summaryrefslogtreecommitdiffstats
path: root/mobile/android/android-components/components/browser/engine-system/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:50 +0000
commitdef92d1b8e9d373e2f6f27c366d578d97d8960c6 (patch)
tree2ef34b9ad8bb9a9220e05d60352558b15f513894 /mobile/android/android-components/components/browser/engine-system/src
parentAdding debian version 125.0.3-1. (diff)
downloadfirefox-def92d1b8e9d373e2f6f27c366d578d97d8960c6.tar.xz
firefox-def92d1b8e9d373e2f6f27c366d578d97d8960c6.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/android-components/components/browser/engine-system/src')
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/androidTest/java/mozilla/components/browser/engine/system/VersionTest.kt28
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/androidTest/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/NestedWebView.kt170
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngine.kt152
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSession.kt636
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSessionState.kt95
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt835
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/ReversibleString.kt98
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Safelist.kt176
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Trie.kt114
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/UrlMatcher.kt323
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequest.kt41
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/window/SystemWindowRequest.kt52
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json11046
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json12347
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-am/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-an/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ann/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ar/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ast/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-az/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-azb/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ban/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-be/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-bg/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-bn/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-br/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-bs/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ca/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-cak/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ceb/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ckb/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-co/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-cs/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-cy/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-da/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-de/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-dsb/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-el/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rCA/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rGB/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-eo/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rCL/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rES/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rMX/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-es/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-et/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-eu/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-fa/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ff/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-fi/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-fr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-fur/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-fy-rNL/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ga-rIE/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-gd/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-gl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-gn/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-gu-rIN/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-hi-rIN/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-hil/strings.xml5
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-hr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-hsb/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-hu/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-hy-rAM/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ia/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-in/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-is/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-it/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-iw/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ja/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ka/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-kaa/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-kab/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-kk/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-kmr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-kn/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ko/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-kw/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-lij/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-lo/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-lt/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-mix/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ml/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-mr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-my/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-nb-rNO/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ne-rNP/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-nl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-nn-rNO/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-nv/strings.xml5
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-oc/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-or/strings.xml5
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rPK/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-pl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ppl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rBR/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rPT/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-rm/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ro/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ru/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sat/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sc/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-si/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sk/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-skr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sq/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-su/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-sv-rSE/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-szl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ta/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-te/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-tg/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-th/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-tl/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-tok/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-tr/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-trs/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-tt/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-tzm/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ug/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-uk/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-ur/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-uz/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-vec/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-vi/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-yo/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rCN/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rTW/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/values/strings.xml13
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/NestedWebViewTest.kt165
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionStateTest.kt138
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionTest.kt1238
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineTest.kt105
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt1654
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/ReversibleStringTest.kt122
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/SafelistTest.kt126
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/TrieTest.kt46
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/UrlMatcherTest.kt296
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequestTest.kt99
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/window/SystemWindowRequestTest.kt76
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/test/resources/robolectric.properties1
148 files changed, 31365 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/browser/engine-system/src/androidTest/java/mozilla/components/browser/engine/system/VersionTest.kt b/mobile/android/android-components/components/browser/engine-system/src/androidTest/java/mozilla/components/browser/engine/system/VersionTest.kt
new file mode 100644
index 0000000000..dca1cead0c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/androidTest/java/mozilla/components/browser/engine/system/VersionTest.kt
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class VersionTest {
+ @Test
+ fun testParsingOfActualWebViewVersion() {
+ runBlocking(Dispatchers.Main) {
+ val context: Context = ApplicationProvider.getApplicationContext()
+ val engine = SystemEngine(context)
+ val version = engine.version
+
+ assertTrue(version.major > 60)
+
+ // 60.0.3112 was released 2017-07-31.
+ assertTrue(version.isAtLeast(60, 0, 3113))
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/androidTest/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/browser/engine-system/src/androidTest/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/androidTest/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/browser/engine-system/src/main/AndroidManifest.xml b/mobile/android/android-components/components/browser/engine-system/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/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/engine-system/src/main/java/mozilla/components/browser/engine/system/NestedWebView.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/NestedWebView.kt
new file mode 100644
index 0000000000..74b3479b11
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/NestedWebView.kt
@@ -0,0 +1,170 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.browser.engine.system
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_CANCEL
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_UP
+import android.view.MotionEvent.obtain
+import android.webkit.WebView
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.NestedScrollingChild
+import androidx.core.view.NestedScrollingChildHelper
+import androidx.core.view.ViewCompat
+import mozilla.components.concept.engine.INPUT_HANDLED
+import mozilla.components.concept.engine.INPUT_UNHANDLED
+import mozilla.components.concept.engine.InputResultDetail
+
+/**
+ * WebView that supports nested scrolls (for using in a CoordinatorLayout).
+ *
+ * This code is a simplified version of the NestedScrollView implementation
+ * which can be found in the support library:
+ * [android.support.v4.widget.NestedScrollView]
+ *
+ * Based on:
+ * https://github.com/takahirom/webview-in-coordinatorlayout
+ */
+class NestedWebView(context: Context) : WebView(context), NestedScrollingChild {
+
+ @VisibleForTesting
+ internal var lastY: Int = 0
+
+ @VisibleForTesting
+ internal val scrollOffset = IntArray(2)
+
+ private val scrollConsumed = IntArray(2)
+
+ @VisibleForTesting
+ internal var nestedOffsetY: Int = 0
+
+ @VisibleForTesting
+ internal var childHelper: NestedScrollingChildHelper = NestedScrollingChildHelper(this)
+
+ /**
+ * How user's MotionEvent will be handled.
+ *
+ * @see InputResultDetail
+ */
+ internal var inputResultDetail = InputResultDetail.newInstance()
+
+ init {
+ isNestedScrollingEnabled = true
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onTouchEvent(ev: MotionEvent): Boolean {
+ val event = obtain(ev)
+ val action = ev.actionMasked
+
+ if (action == ACTION_DOWN) {
+ nestedOffsetY = 0
+ }
+
+ val eventY = event.y.toInt()
+ event.offsetLocation(0f, nestedOffsetY.toFloat())
+
+ when (action) {
+ ACTION_MOVE -> {
+ var deltaY = lastY - eventY
+
+ if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
+ deltaY -= scrollConsumed[1]
+ event.offsetLocation(0f, (-scrollOffset[1]).toFloat())
+ nestedOffsetY += scrollOffset[1]
+ }
+
+ lastY = eventY - scrollOffset[1]
+
+ if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) {
+ lastY -= scrollOffset[1]
+ event.offsetLocation(0f, scrollOffset[1].toFloat())
+ nestedOffsetY += scrollOffset[1]
+ }
+ }
+
+ ACTION_DOWN -> {
+ lastY = eventY
+ startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
+ }
+
+ // We don't care about other touch events
+ ACTION_UP, ACTION_CANCEL -> stopNestedScroll()
+ }
+
+ // Execute event handler from parent class in all cases
+ val eventHandled = callSuperOnTouchEvent(event)
+ updateInputResult(eventHandled)
+
+ // Recycle previously obtained event
+ event.recycle()
+
+ return eventHandled
+ }
+
+ @VisibleForTesting
+ internal fun callSuperOnTouchEvent(event: MotionEvent): Boolean {
+ return super.onTouchEvent(event)
+ }
+
+ // NestedScrollingChild
+
+ override fun setNestedScrollingEnabled(enabled: Boolean) {
+ childHelper.isNestedScrollingEnabled = enabled
+ }
+
+ override fun isNestedScrollingEnabled(): Boolean {
+ return childHelper.isNestedScrollingEnabled
+ }
+
+ override fun startNestedScroll(axes: Int): Boolean {
+ return childHelper.startNestedScroll(axes)
+ }
+
+ override fun stopNestedScroll() {
+ childHelper.stopNestedScroll()
+ }
+
+ override fun hasNestedScrollingParent(): Boolean {
+ return childHelper.hasNestedScrollingParent()
+ }
+
+ override fun dispatchNestedScroll(
+ dxConsumed: Int,
+ dyConsumed: Int,
+ dxUnconsumed: Int,
+ dyUnconsumed: Int,
+ offsetInWindow: IntArray?,
+ ): Boolean {
+ return childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
+ }
+
+ override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?): Boolean {
+ return childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
+ }
+
+ override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean): Boolean {
+ return childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
+ }
+
+ override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
+ return childHelper.dispatchNestedPreFling(velocityX, velocityY)
+ }
+
+ @VisibleForTesting
+ internal fun updateInputResult(eventHandled: Boolean) {
+ inputResultDetail = inputResultDetail.copy(
+ if (eventHandled) {
+ INPUT_HANDLED
+ } else {
+ INPUT_UNHANDLED
+ },
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngine.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngine.kt
new file mode 100644
index 0000000000..0117b53014
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngine.kt
@@ -0,0 +1,152 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.content.Context
+import android.util.AttributeSet
+import android.util.JsonReader
+import android.webkit.WebSettings
+import android.webkit.WebView
+import androidx.annotation.VisibleForTesting
+import mozilla.components.concept.base.profiler.Profiler
+import mozilla.components.concept.engine.DefaultSettings
+import mozilla.components.concept.engine.Engine
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
+import mozilla.components.concept.engine.EngineSessionState
+import mozilla.components.concept.engine.EngineView
+import mozilla.components.concept.engine.Settings
+import mozilla.components.concept.engine.history.HistoryTrackingDelegate
+import mozilla.components.concept.engine.utils.EngineVersion
+import org.json.JSONObject
+import java.lang.IllegalStateException
+
+/**
+ * WebView-based implementation of the Engine interface.
+ */
+class SystemEngine(
+ private val context: Context,
+ private val defaultSettings: Settings = DefaultSettings(),
+) : Engine {
+ init {
+ initDefaultUserAgent(context)
+ }
+
+ /**
+ * Creates a new WebView-based EngineView implementation.
+ */
+ override fun createView(context: Context, attrs: AttributeSet?): EngineView {
+ return SystemEngineView(context, attrs)
+ }
+
+ /**
+ * Creates a new WebView-based EngineSession implementation.
+ */
+ override fun createSession(private: Boolean, contextId: String?): EngineSession {
+ if (private) {
+ // TODO Implement private browsing: https://github.com/mozilla-mobile/android-components/issues/649
+ throw UnsupportedOperationException("Private browsing is not supported in ${this::class.java.simpleName}")
+ } else if (contextId != null) {
+ throw UnsupportedOperationException(
+ "Contextual identities are not supported in ${this::class.java.simpleName}",
+ )
+ }
+
+ return SystemEngineSession(context, defaultSettings)
+ }
+
+ /**
+ * Opens a speculative connection to the host of [url].
+ *
+ * Note: This implementation is a no-op.
+ */
+ override fun speculativeConnect(url: String) = Unit
+
+ /**
+ * See [Engine.profiler].
+ */
+ override val profiler: Profiler? = null
+
+ /**
+ * See [Engine.name]
+ */
+ override fun name(): String = "System"
+
+ @Suppress("TooGenericExceptionCaught")
+ override val version: EngineVersion
+ get() {
+ val userAgent = WebSettings.getDefaultUserAgent(context)
+ val version = try {
+ "Chrome/([^ ]+)".toRegex().find(userAgent)?.groups?.get(1)?.value
+ ?: throw IllegalStateException("Could not get version from user agent: $userAgent")
+ } catch (e: IllegalStateException) {
+ throw IllegalStateException("Could not get version from user agent: $userAgent")
+ } catch (e: IndexOutOfBoundsException) {
+ throw IllegalStateException("Could not get version from user agent: $userAgent")
+ }
+
+ return EngineVersion.parse(version)
+ ?: throw IllegalStateException("Could not determine engine version: $version")
+ }
+
+ override fun createSessionState(json: JSONObject): EngineSessionState {
+ return SystemEngineSessionState.fromJSON(json)
+ }
+
+ override fun createSessionStateFrom(reader: JsonReader): EngineSessionState {
+ return SystemEngineSessionState.from(reader)
+ }
+
+ /**
+ * See [Engine.settings]
+ */
+ override val settings: Settings = object : Settings() {
+ private var internalRemoteDebuggingEnabled = false
+ override var remoteDebuggingEnabled: Boolean
+ get() = internalRemoteDebuggingEnabled
+ set(value) {
+ WebView.setWebContentsDebuggingEnabled(value)
+ internalRemoteDebuggingEnabled = value
+ }
+
+ override var userAgentString: String?
+ get() = defaultSettings.userAgentString
+ set(value) {
+ defaultSettings.userAgentString = value
+ }
+
+ override var trackingProtectionPolicy: TrackingProtectionPolicy?
+ get() = defaultSettings.trackingProtectionPolicy
+ set(value) {
+ defaultSettings.trackingProtectionPolicy = value
+ }
+
+ override var historyTrackingDelegate: HistoryTrackingDelegate?
+ get() = defaultSettings.historyTrackingDelegate
+ set(value) {
+ defaultSettings.historyTrackingDelegate = value
+ }
+ }.apply {
+ this.remoteDebuggingEnabled = defaultSettings.remoteDebuggingEnabled
+ this.trackingProtectionPolicy = defaultSettings.trackingProtectionPolicy
+ if (defaultSettings.userAgentString == null) {
+ defaultSettings.userAgentString = defaultUserAgent
+ }
+ }
+
+ companion object {
+ // In Robolectric tests we can't call WebSettings.getDefaultUserAgent(context)
+ // as this would result in a NPE. So, we expose this field to circumvent the call.
+ @VisibleForTesting
+ var defaultUserAgent: String? = null
+
+ private fun initDefaultUserAgent(context: Context): String {
+ if (defaultUserAgent == null) {
+ defaultUserAgent = WebSettings.getDefaultUserAgent(context)
+ }
+ return defaultUserAgent as String
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSession.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSession.kt
new file mode 100644
index 0000000000..aaf2ec1634
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSession.kt
@@ -0,0 +1,636 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.content.Context
+import android.webkit.CookieManager
+import android.webkit.WebChromeClient
+import android.webkit.WebSettings
+import android.webkit.WebSettings.LOAD_NO_CACHE
+import android.webkit.WebStorage
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.webkit.WebViewDatabase
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import mozilla.components.browser.errorpages.ErrorType
+import mozilla.components.concept.engine.Engine.BrowsingData
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.EngineSessionState
+import mozilla.components.concept.engine.Settings
+import mozilla.components.concept.engine.history.HistoryTrackingDelegate
+import mozilla.components.concept.engine.request.RequestInterceptor
+import mozilla.components.concept.engine.shopping.ProductAnalysis
+import mozilla.components.concept.engine.shopping.ProductAnalysisStatus
+import mozilla.components.concept.engine.shopping.ProductRecommendation
+import mozilla.components.concept.engine.translate.TranslationOptions
+import kotlin.reflect.KProperty
+
+internal val xRequestHeader = mapOf(
+ // For every request WebView sends a "X-requested-with" header with the package name of the
+ // application. We can't really prevent that but we can at least send an empty value.
+ // Unfortunately the additional headers will not be propagated to subsequent requests
+ // (e.g. redirects). See issue #696.
+ "X-Requested-With" to "",
+)
+
+/**
+ * WebView-based EngineSession implementation.
+ */
+@Suppress("LargeClass", "TooManyFunctions")
+class SystemEngineSession(
+ context: Context,
+ private val defaultSettings: Settings? = null,
+) : EngineSession() {
+ private val resources = context.resources
+
+ @Volatile internal lateinit var internalSettings: Settings
+
+ @Volatile internal var historyTrackingDelegate: HistoryTrackingDelegate? = null
+
+ @Volatile internal var trackingProtectionPolicy: TrackingProtectionPolicy? = null
+
+ @Volatile internal var webFontsEnabled = true
+
+ @Volatile internal var currentUrl = ""
+
+ @Volatile internal var useWideViewPort: Boolean? = null // See [toggleDesktopMode]
+
+ @Volatile internal var fullScreenCallback: WebChromeClient.CustomViewCallback? = null
+
+ // This is public for FFTV which needs access to the WebView instance. We can mark it internal once
+ // https://github.com/mozilla-mobile/android-components/issues/1616 is resolved.
+ @Volatile var webView: WebView = NestedWebView(context)
+ set(value) {
+ field = value
+ initSettings()
+ }
+
+ init {
+ initSettings()
+ }
+
+ /**
+ * See [EngineSession.loadUrl]. Note that [LoadUrlFlags] are ignored in this engine
+ * implementation.
+ */
+ override fun loadUrl(
+ url: String,
+ parent: EngineSession?,
+ flags: LoadUrlFlags,
+ additionalHeaders: Map<String, String>?,
+ ) {
+ notifyObservers { onLoadUrl() }
+
+ val headers =
+ if (additionalHeaders == null) {
+ xRequestHeader
+ } else {
+ xRequestHeader + additionalHeaders
+ }
+
+ if (!url.isEmpty()) {
+ currentUrl = url
+ webView.loadUrl(url, headers)
+ }
+ }
+
+ /**
+ * See [EngineSession.loadData]
+ */
+ override fun loadData(data: String, mimeType: String, encoding: String) {
+ webView.loadData(data, mimeType, encoding)
+ notifyObservers { onLoadData() }
+ }
+
+ override fun requestPdfToDownload() {
+ throw UnsupportedOperationException("PDF support is not available in this engine")
+ }
+
+ override fun requestPrintContent() {
+ throw UnsupportedOperationException("Print support is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.stopLoading]
+ */
+ override fun stopLoading() {
+ webView.stopLoading()
+ }
+
+ /**
+ * See [EngineSession.reload]
+ * @param flags currently not supported in `SystemEngineSession`.
+ */
+ override fun reload(flags: LoadUrlFlags) {
+ webView.reload()
+ }
+
+ /**
+ * See [EngineSession.goBack]
+ */
+ override fun goBack(userInteraction: Boolean) {
+ webView.goBack()
+ if (webView.canGoBack()) {
+ notifyObservers { onNavigateBack() }
+ }
+ }
+
+ /**
+ * See [EngineSession.goForward]
+ */
+ override fun goForward(userInteraction: Boolean) {
+ webView.goForward()
+ if (webView.canGoForward()) {
+ notifyObservers { onNavigateForward() }
+ }
+ }
+
+ /**
+ * See [EngineSession.goToHistoryIndex]
+ */
+ override fun goToHistoryIndex(index: Int) {
+ val historyList = webView.copyBackForwardList()
+ webView.goBackOrForward(index - historyList.currentIndex)
+ notifyObservers { onGotoHistoryIndex() }
+ }
+
+ /**
+ * See [EngineSession.restoreState]
+ */
+ override fun restoreState(state: EngineSessionState): Boolean {
+ if (state !is SystemEngineSessionState) {
+ throw IllegalArgumentException("Can only restore from SystemEngineSessionState")
+ }
+
+ return state.bundle?.let { webView.restoreState(it) } != null
+ }
+
+ /**
+ * See [EngineSession.updateTrackingProtection]
+ */
+ override fun updateTrackingProtection(policy: TrackingProtectionPolicy) {
+ // Make sure Url matcher is preloaded now that tracking protection is enabled
+ CoroutineScope(Dispatchers.IO).launch {
+ SystemEngineView.getOrCreateUrlMatcher(resources, policy)
+ }
+
+ // TODO check if policy should be applied for this session type
+ // (regular|private) once we support private browsing in system engine:
+ // https://github.com/mozilla-mobile/android-components/issues/649
+ trackingProtectionPolicy = policy
+ notifyObservers { onTrackerBlockingEnabledChange(true) }
+ }
+
+ @VisibleForTesting
+ internal fun disableTrackingProtection() {
+ trackingProtectionPolicy = null
+ notifyObservers { onTrackerBlockingEnabledChange(false) }
+ }
+
+ /**
+ * See [EngineSession.close]
+ */
+ override fun close() {
+ super.close()
+ // The WebView instance must remain useable for the duration of this session.
+ // We can only destroy it once we're sure this session will not be used
+ // again which is why destroy happens here are not part of regular (activity)
+ // lifecycle event.
+ webView.destroy()
+ }
+
+ /**
+ * See [EngineSession.clearData]
+ */
+ @Suppress("TooGenericExceptionCaught")
+ override fun clearData(data: BrowsingData, host: String?, onSuccess: () -> Unit, onError: (Throwable) -> Unit) {
+ webView.apply {
+ try {
+ if (data.contains(BrowsingData.DOM_STORAGES)) {
+ webStorage().deleteAllData()
+ }
+ if (data.contains(BrowsingData.IMAGE_CACHE) || data.contains(BrowsingData.NETWORK_CACHE)) {
+ clearCache(true)
+ }
+ if (data.contains(BrowsingData.COOKIES)) {
+ CookieManager.getInstance().removeAllCookies(null)
+ }
+ if (data.contains(BrowsingData.AUTH_SESSIONS)) {
+ webViewDatabase(context).clearHttpAuthUsernamePassword()
+ }
+ if (data.contains(BrowsingData.ALL)) {
+ clearSslPreferences()
+ clearFormData()
+ clearMatches()
+ clearHistory()
+ }
+ onSuccess()
+ } catch (e: Throwable) {
+ onError(e)
+ }
+ }
+ }
+
+ /**
+ * See [EngineSession.findAll]
+ */
+ override fun findAll(text: String) {
+ notifyObservers { onFind(text) }
+ webView.findAllAsync(text)
+ }
+
+ /**
+ * See [EngineSession.findNext]
+ */
+ override fun findNext(forward: Boolean) {
+ webView.findNext(forward)
+ }
+
+ /**
+ * See [EngineSession.clearFindMatches]
+ */
+ override fun clearFindMatches() {
+ webView.clearMatches()
+ }
+
+ /**
+ * Clears the internal back/forward list.
+ */
+ override fun purgeHistory() {
+ webView.clearHistory()
+ }
+
+ /**
+ * See [EngineSession.settings]
+ */
+ override val settings: Settings
+ get() = internalSettings
+
+ class WebSetting<T>(private val get: () -> T, private val set: (T) -> Unit) {
+ operator fun getValue(thisRef: Any?, property: KProperty<*>): T = get()
+ operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = set(value)
+ }
+
+ @VisibleForTesting
+ internal fun initSettings() {
+ webView.settings.apply {
+ // Explicitly set global defaults.
+
+ cacheMode = LOAD_NO_CACHE
+ databaseEnabled = false
+
+ setDeprecatedWebSettings(this)
+
+ // We currently don't implement the callback to support turning this on.
+ setGeolocationEnabled(false)
+
+ // webViewSettings built-in zoom controls are the only supported ones,
+ // so they should be turned on but hidden.
+ builtInZoomControls = true
+ displayZoomControls = false
+
+ initSettings(webView, this)
+ }
+ }
+
+ @Suppress("DEPRECATION")
+ private fun setDeprecatedWebSettings(webSettings: WebSettings) {
+ // Since API26 an autofill platform feature is used instead of WebView's form data. This
+ // has no effect. Form data is supported on pre-26 API versions.
+ webSettings.saveFormData = false
+ // Deprecated in API18.
+ webSettings.savePassword = false
+ }
+
+ private fun setUseWideViewPort(settings: WebSettings, useWideViewPort: Boolean?) {
+ this.useWideViewPort = useWideViewPort
+ useWideViewPort?.let { settings.useWideViewPort = it }
+ }
+
+ private fun initSettings(webView: WebView, s: WebSettings) {
+ internalSettings = object : Settings() {
+ override var javascriptEnabled by WebSetting(s::getJavaScriptEnabled, s::setJavaScriptEnabled)
+ override var domStorageEnabled by WebSetting(s::getDomStorageEnabled, s::setDomStorageEnabled)
+ override var allowFileAccess by WebSetting(s::getAllowFileAccess, s::setAllowFileAccess)
+ override var allowContentAccess by WebSetting(s::getAllowContentAccess, s::setAllowContentAccess)
+ override var userAgentString by WebSetting(s::getUserAgentString, s::setUserAgentString)
+ override var displayZoomControls by WebSetting(s::getDisplayZoomControls, s::setDisplayZoomControls)
+ override var loadWithOverviewMode by WebSetting(s::getLoadWithOverviewMode, s::setLoadWithOverviewMode)
+ override var useWideViewPort: Boolean?
+ get() = this@SystemEngineSession.useWideViewPort
+ set(value) = setUseWideViewPort(s, value)
+ override var supportMultipleWindows by WebSetting(s::supportMultipleWindows, s::setSupportMultipleWindows)
+
+ @Suppress("DEPRECATION")
+ // Deprecation will be handled in https://github.com/mozilla-mobile/android-components/issues/8513
+ override var allowFileAccessFromFileURLs by WebSetting(
+ s::getAllowFileAccessFromFileURLs,
+ s::setAllowFileAccessFromFileURLs,
+ )
+
+ @Suppress("DEPRECATION")
+ // Deprecation will be handled in https://github.com/mozilla-mobile/android-components/issues/8514
+ override var allowUniversalAccessFromFileURLs by WebSetting(
+ s::getAllowUniversalAccessFromFileURLs,
+ s::setAllowUniversalAccessFromFileURLs,
+ )
+
+ override var mediaPlaybackRequiresUserGesture by WebSetting(
+ s::getMediaPlaybackRequiresUserGesture,
+ s::setMediaPlaybackRequiresUserGesture,
+ )
+ override var javaScriptCanOpenWindowsAutomatically by WebSetting(
+ s::getJavaScriptCanOpenWindowsAutomatically,
+ s::setJavaScriptCanOpenWindowsAutomatically,
+ )
+
+ override var verticalScrollBarEnabled
+ get() = webView.isVerticalScrollBarEnabled
+ set(value) { webView.isVerticalScrollBarEnabled = value }
+
+ override var horizontalScrollBarEnabled
+ get() = webView.isHorizontalScrollBarEnabled
+ set(value) { webView.isHorizontalScrollBarEnabled = value }
+
+ override var webFontsEnabled
+ get() = this@SystemEngineSession.webFontsEnabled
+ set(value) { this@SystemEngineSession.webFontsEnabled = value }
+
+ override var trackingProtectionPolicy: TrackingProtectionPolicy?
+ get() = this@SystemEngineSession.trackingProtectionPolicy
+ set(value) = value?.let { updateTrackingProtection(it) } ?: disableTrackingProtection()
+
+ override var historyTrackingDelegate: HistoryTrackingDelegate?
+ get() = this@SystemEngineSession.historyTrackingDelegate
+ set(value) { this@SystemEngineSession.historyTrackingDelegate = value }
+
+ override var requestInterceptor: RequestInterceptor? = null
+ }.apply {
+ defaultSettings?.let {
+ javascriptEnabled = it.javascriptEnabled
+ domStorageEnabled = it.domStorageEnabled
+ webFontsEnabled = it.webFontsEnabled
+ displayZoomControls = it.displayZoomControls
+ loadWithOverviewMode = it.loadWithOverviewMode
+ useWideViewPort = it.useWideViewPort
+ trackingProtectionPolicy = it.trackingProtectionPolicy
+ historyTrackingDelegate = it.historyTrackingDelegate
+ requestInterceptor = it.requestInterceptor
+ mediaPlaybackRequiresUserGesture = it.mediaPlaybackRequiresUserGesture
+ javaScriptCanOpenWindowsAutomatically = it.javaScriptCanOpenWindowsAutomatically
+ allowFileAccess = it.allowFileAccess
+ allowContentAccess = it.allowContentAccess
+ allowUniversalAccessFromFileURLs = it.allowUniversalAccessFromFileURLs
+ allowFileAccessFromFileURLs = it.allowFileAccessFromFileURLs
+ verticalScrollBarEnabled = it.verticalScrollBarEnabled
+ horizontalScrollBarEnabled = it.horizontalScrollBarEnabled
+ userAgentString = it.userAgentString
+ supportMultipleWindows = it.supportMultipleWindows
+ }
+ }
+ }
+
+ /**
+ * See [EngineSession.toggleDesktopMode]
+ *
+ * Precondition:
+ * If settings.useWideViewPort = true, then webSettings.useWideViewPort is always on
+ * If settings.useWideViewPort = false or null, then webSettings.useWideViewPort can be on/off
+ */
+ override fun toggleDesktopMode(enable: Boolean, reload: Boolean) {
+ val webSettings = webView.settings
+ webSettings.userAgentString = toggleDesktopUA(webSettings.userAgentString, enable)
+ webSettings.useWideViewPort = if (settings.useWideViewPort == true) true else enable
+
+ notifyObservers { onDesktopModeChange(enable) }
+
+ if (reload) {
+ webView.reload()
+ }
+ }
+
+ /**
+ * Checks for if PDF Viewer is used.
+ */
+ override fun checkForPdfViewer(
+ onResult: (Boolean) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Checking for PDF viewer is not available in this engine")
+ }
+
+ /**
+ * /**
+ * See [EngineSession.requestProductRecommendations]
+ */
+ */
+ override fun requestProductRecommendations(
+ url: String,
+ onResult: (List<ProductRecommendation>) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Analysis of product reviews for shopping is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.requestProductAnalysis]
+ */
+ override fun requestProductAnalysis(
+ url: String,
+ onResult: (ProductAnalysis) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Analysis of product reviews for shopping is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.reanalyzeProduct]
+ */
+ override fun reanalyzeProduct(
+ url: String,
+ onResult: (String) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Reanalyzing product reviews for shopping is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.requestAnalysisStatus]
+ */
+ override fun requestAnalysisStatus(
+ url: String,
+ onResult: (ProductAnalysisStatus) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Requesting product analysis status is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.sendClickAttributionEvent]
+ */
+ override fun sendClickAttributionEvent(
+ aid: String,
+ onResult: (Boolean) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Sending click attribution event is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.sendImpressionAttributionEvent]
+ */
+ override fun sendImpressionAttributionEvent(
+ aid: String,
+ onResult: (Boolean) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Sending impression attribution event is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.sendPlacementAttributionEvent]
+ */
+ override fun sendPlacementAttributionEvent(
+ aid: String,
+ onResult: (Boolean) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Sending placement attribution event is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.reportBackInStock]
+ */
+ override fun reportBackInStock(
+ url: String,
+ onResult: (String) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Reporting back in stock is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.requestTranslate]
+ */
+ override fun requestTranslate(
+ fromLanguage: String,
+ toLanguage: String,
+ options: TranslationOptions?,
+ ) {
+ throw UnsupportedOperationException("Translate support is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.requestTranslationRestore]
+ */
+ override fun requestTranslationRestore() {
+ throw UnsupportedOperationException("Translate restore support is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.getNeverTranslateSiteSetting]
+ */
+ override fun getNeverTranslateSiteSetting(
+ onResult: (Boolean) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Getting the site's translate setting is not available in this engine.")
+ }
+
+ /**
+ * See [EngineSession.setNeverTranslateSiteSetting]
+ */
+ override fun setNeverTranslateSiteSetting(
+ setting: Boolean,
+ onResult: () -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Setting the site's translate setting is not available in this engine")
+ }
+
+ override fun hasCookieBannerRuleForSession(
+ onResult: (Boolean) -> Unit,
+ onException: (Throwable) -> Unit,
+ ) {
+ throw UnsupportedOperationException("Cookie Banner handling is not available in this engine")
+ }
+
+ /**
+ * See [EngineSession.exitFullScreenMode]
+ */
+ override fun exitFullScreenMode() {
+ fullScreenCallback?.onCustomViewHidden()
+ }
+
+ internal fun toggleDesktopUA(userAgent: String, requestDesktop: Boolean): String {
+ return if (requestDesktop) {
+ userAgent.replace("Mobile", "eliboM").replace("Android", "diordnA")
+ } else {
+ userAgent.replace("eliboM", "Mobile").replace("diordnA", "Android")
+ }
+ }
+
+ internal fun webStorage(): WebStorage = WebStorage.getInstance()
+
+ internal fun webViewDatabase(context: Context) = WebViewDatabase.getInstance(context)
+
+ /**
+ * Helper method to notify observers from other classes in this package. This is needed as
+ * almost everything is implemented by WebView and its listeners. There is no actual concept of
+ * a session when using WebView.
+ */
+ internal fun internalNotifyObservers(block: Observer.() -> Unit) {
+ super.notifyObservers(block)
+ }
+
+ companion object {
+ /**
+ * Provides an ErrorType corresponding to the error code provided.
+ *
+ * Chromium's mapping (internal error code, to Android WebView error code) is described at:
+ * https://goo.gl/vspwct (ErrorCodeConversionHelper.java)
+ */
+ internal fun webViewErrorToErrorType(errorCode: Int) =
+ when (errorCode) {
+ WebViewClient.ERROR_UNKNOWN -> ErrorType.UNKNOWN
+
+ // This is probably the most commonly shown error. If there's no network, we inevitably
+ // show this.
+ WebViewClient.ERROR_HOST_LOOKUP -> ErrorType.ERROR_UNKNOWN_HOST
+
+ WebViewClient.ERROR_CONNECT -> ErrorType.ERROR_CONNECTION_REFUSED
+
+ // It's unclear what this actually means - it's not well documented. Based on looking at
+ // ErrorCodeConversionHelper this could happen if networking is disabled during load, in which
+ // case the generic error is good enough:
+ WebViewClient.ERROR_IO -> ErrorType.ERROR_CONNECTION_REFUSED
+
+ WebViewClient.ERROR_TIMEOUT -> ErrorType.ERROR_NET_TIMEOUT
+
+ WebViewClient.ERROR_REDIRECT_LOOP -> ErrorType.ERROR_REDIRECT_LOOP
+
+ WebViewClient.ERROR_UNSUPPORTED_SCHEME -> ErrorType.ERROR_UNKNOWN_PROTOCOL
+
+ WebViewClient.ERROR_FAILED_SSL_HANDSHAKE -> ErrorType.ERROR_SECURITY_SSL
+
+ WebViewClient.ERROR_BAD_URL -> ErrorType.ERROR_MALFORMED_URI
+
+ // Seems to be an indication of OOM, insufficient resources, or too many queued DNS queries
+ WebViewClient.ERROR_TOO_MANY_REQUESTS -> ErrorType.UNKNOWN
+
+ WebViewClient.ERROR_FILE_NOT_FOUND -> ErrorType.ERROR_FILE_NOT_FOUND
+
+ // There's no mapping for the following errors yet. At the time this library was
+ // extracted from Focus we didn't use any of those errors.
+ // WebViewClient.ERROR_UNSUPPORTED_AUTH_SCHEME
+ // WebViewClient.ERROR_AUTHENTICATION
+ // WebViewClient.ERROR_FILE
+ else -> ErrorType.UNKNOWN
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSessionState.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSessionState.kt
new file mode 100644
index 0000000000..198fc9a303
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineSessionState.kt
@@ -0,0 +1,95 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.os.Bundle
+import android.util.JsonReader
+import android.util.JsonToken
+import android.util.JsonWriter
+import mozilla.components.concept.engine.EngineSessionState
+import org.json.JSONObject
+
+class SystemEngineSessionState(
+ internal val bundle: Bundle?,
+) : EngineSessionState {
+ override fun writeTo(writer: JsonWriter) {
+ writer.beginObject()
+
+ bundle?.keySet()?.forEach { key ->
+ when (
+ @Suppress("DEPRECATION")
+ val value = bundle[key]
+ ) {
+ is Number -> writer.name(key).value(value)
+ is String -> writer.name(key).value(value)
+ is Boolean -> writer.name(key).value(value)
+ }
+ }
+
+ writer.endObject()
+ writer.flush()
+ }
+
+ companion object {
+ fun fromJSON(json: JSONObject): SystemEngineSessionState {
+ return SystemEngineSessionState(json.toBundle())
+ }
+
+ /**
+ * Creates a [SystemEngineSessionState] from the given [JsonReader].
+ */
+ fun from(reader: JsonReader): SystemEngineSessionState {
+ return SystemEngineSessionState(reader.toBundle())
+ }
+ }
+}
+
+private fun JsonReader.toBundle(): Bundle {
+ beginObject()
+
+ val bundle = Bundle()
+
+ while (peek() != JsonToken.END_OBJECT) {
+ val name = nextName()
+
+ when (peek()) {
+ JsonToken.NULL -> nextNull()
+ JsonToken.BOOLEAN -> bundle.putBoolean(name, nextBoolean())
+ JsonToken.STRING -> bundle.putString(name, nextString())
+ JsonToken.NUMBER -> bundle.putDouble(name, nextDouble())
+ JsonToken.BEGIN_OBJECT -> bundle.putBundle(name, toBundle())
+ else -> skipValue()
+ }
+ }
+
+ endObject()
+
+ return bundle
+}
+
+private fun JSONObject.toBundle(): Bundle {
+ val bundle = Bundle()
+
+ keys().forEach { key ->
+ val value = get(key)
+ bundle.put(key, value)
+ }
+
+ return bundle
+}
+
+private fun Bundle.put(key: String, value: Any) {
+ when (value) {
+ is Int -> putInt(key, value)
+ is Double -> putDouble(key, value)
+ is Long -> putLong(key, value)
+ is Float -> putFloat(key, value)
+ is Char -> putChar(key, value)
+ is Short -> putShort(key, value)
+ is Byte -> putByte(key, value)
+ is String -> putString(key, value)
+ is Boolean -> putBoolean(key, value)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt
new file mode 100644
index 0000000000..d0a5a6af8e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt
@@ -0,0 +1,835 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.annotation.TargetApi
+import android.app.Activity
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.net.Uri
+import android.net.http.SslError
+import android.os.Build
+import android.os.Build.VERSION.SDK_INT
+import android.os.Handler
+import android.os.Message
+import android.util.AttributeSet
+import android.view.PixelCopy
+import android.view.View
+import android.webkit.CookieManager
+import android.webkit.DownloadListener
+import android.webkit.HttpAuthHandler
+import android.webkit.JsPromptResult
+import android.webkit.JsResult
+import android.webkit.PermissionRequest
+import android.webkit.SslErrorHandler
+import android.webkit.ValueCallback
+import android.webkit.WebChromeClient
+import android.webkit.WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE
+import android.webkit.WebResourceError
+import android.webkit.WebResourceRequest
+import android.webkit.WebResourceResponse
+import android.webkit.WebView
+import android.webkit.WebView.HitTestResult.EMAIL_TYPE
+import android.webkit.WebView.HitTestResult.GEO_TYPE
+import android.webkit.WebView.HitTestResult.IMAGE_TYPE
+import android.webkit.WebView.HitTestResult.PHONE_TYPE
+import android.webkit.WebView.HitTestResult.SRC_ANCHOR_TYPE
+import android.webkit.WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
+import android.webkit.WebViewClient
+import android.widget.FrameLayout
+import androidx.annotation.VisibleForTesting
+import androidx.annotation.VisibleForTesting.Companion.PRIVATE
+import androidx.core.net.toUri
+import kotlinx.coroutines.runBlocking
+import mozilla.components.browser.engine.system.matcher.UrlMatcher
+import mozilla.components.browser.engine.system.permission.SystemPermissionRequest
+import mozilla.components.browser.engine.system.window.SystemWindowRequest
+import mozilla.components.browser.errorpages.ErrorType
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
+import mozilla.components.concept.engine.EngineView
+import mozilla.components.concept.engine.HitResult
+import mozilla.components.concept.engine.InputResultDetail
+import mozilla.components.concept.engine.content.blocking.Tracker
+import mozilla.components.concept.engine.prompt.PromptRequest
+import mozilla.components.concept.engine.request.RequestInterceptor.InterceptionResponse
+import mozilla.components.concept.engine.selection.SelectionActionDelegate
+import mozilla.components.concept.engine.window.WindowRequest
+import mozilla.components.concept.storage.PageVisit
+import mozilla.components.concept.storage.VisitType
+import mozilla.components.support.ktx.android.view.getRectWithViewLocation
+import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl
+import mozilla.components.support.utils.DownloadUtils
+
+/**
+ * WebView-based implementation of EngineView.
+ */
+@Suppress("TooManyFunctions")
+class SystemEngineView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : FrameLayout(context, attrs, defStyleAttr), EngineView, View.OnLongClickListener {
+ @VisibleForTesting(otherwise = PRIVATE)
+ internal var session: SystemEngineSession? = null
+
+ override var selectionActionDelegate: SelectionActionDelegate? = null
+
+ /**
+ * Render the content of the given session.
+ */
+ override fun render(session: EngineSession) {
+ removeAllViews()
+
+ this.session = session as SystemEngineSession
+ (session.webView.parent as? SystemEngineView)?.removeView(session.webView)
+ addView(initWebView(session.webView))
+ }
+
+ override fun release() {
+ this.session = null
+
+ removeAllViews()
+ }
+
+ override fun onLongClick(view: View?): Boolean {
+ val result = session?.webView?.hitTestResult
+ return result?.let { handleLongClick(result.type, result.extra ?: "") } ?: false
+ }
+
+ override fun onPause() {
+ session?.apply {
+ webView.onPause()
+ webView.pauseTimers()
+ }
+ }
+
+ override fun onResume() {
+ session?.apply {
+ webView.onResume()
+ webView.resumeTimers()
+ }
+ }
+
+ override fun onDestroy() {
+ session?.apply {
+ // The WebView instance is long-lived, as it's referenced in the
+ // engine session. We can't destroy it here since the session
+ // might be used with a different engine view instance later.
+
+ // Further, when this engine view gets destroyed, we need to
+ // remove/detach the WebView so that engine view's activity context
+ // can properly be destroyed and gc'ed. The WebView instances are
+ // created with the context provided to the engine (application
+ // context) and reference their parent (this engine view). Since
+ // we're keeping the engine session (and their WebView) instances
+ // in the SessionManager until closed we'd otherwise prevent
+ // this engine view and its context from getting gc'ed.
+ (webView.parent as? SystemEngineView)?.removeView(webView)
+ }
+ }
+
+ internal fun initWebView(webView: WebView): WebView {
+ webView.tag = "mozac_system_engine_webview"
+ webView.webViewClient = createWebViewClient()
+ webView.webChromeClient = createWebChromeClient()
+ webView.setDownloadListener(createDownloadListener())
+ webView.setFindListener(createFindListener())
+ return webView
+ }
+
+ @Suppress("ComplexMethod", "NestedBlockDepth")
+ private fun createWebViewClient() = object : WebViewClient() {
+ override fun doUpdateVisitedHistory(view: WebView, url: String, isReload: Boolean) {
+ // TODO private browsing not supported for SystemEngine
+ // https://github.com/mozilla-mobile/android-components/issues/649
+ // Check if the delegate wants this type of url.
+ val delegate = session?.settings?.historyTrackingDelegate ?: return
+
+ if (!delegate.shouldStoreUri(url)) {
+ return
+ }
+
+ val visitType = when (isReload) {
+ true -> VisitType.RELOAD
+ false -> VisitType.LINK
+ }
+
+ runBlocking {
+ session?.settings?.historyTrackingDelegate?.onVisited(url, PageVisit(visitType))
+ }
+ }
+
+ override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
+ url?.let {
+ session?.currentUrl = url
+ session?.internalNotifyObservers {
+ onLoadingStateChange(true)
+ onLocationChange(it, false)
+ onNavigationStateChange(view.canGoBack(), view.canGoForward())
+ }
+ }
+ }
+
+ override fun onPageFinished(view: WebView?, url: String?) {
+ url?.let {
+ val cert = view?.certificate
+ session?.internalNotifyObservers {
+ onLocationChange(it, false)
+ onLoadingStateChange(false)
+ onSecurityChange(
+ secure = cert != null,
+ host = cert?.let { Uri.parse(url).host },
+ issuer = cert?.issuedBy?.oName,
+ )
+ }
+ }
+ }
+
+ @Suppress("ReturnCount", "NestedBlockDepth", "LongMethod")
+ override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
+ if (session?.webFontsEnabled == false && UrlMatcher.isWebFont(request.url)) {
+ return WebResourceResponse(null, null, null)
+ }
+
+ session?.trackingProtectionPolicy?.let {
+ val resourceUri = request.url
+ val scheme = resourceUri.scheme
+ val path = resourceUri.path
+
+ if (!request.isForMainFrame && scheme != "http" && scheme != "https") {
+ // Block any malformed non-http(s) URIs. WebView will already ignore things like market: URLs,
+ // but not in all cases (malformed market: URIs, such as market:://... will still end up here).
+ // (Note: data: URIs are automatically handled by WebView, and won't end up here either.)
+ // file:// URIs are disabled separately by setting WebSettings.setAllowFileAccess()
+ return WebResourceResponse(null, null, null)
+ }
+
+ // WebView always requests a favicon, even though it won't be used anywhere. This check
+ // isn't able to block all favicons (some of them will be loaded using <link rel="shortcut icon">
+ // with a custom URL which we can't match or detect), but reduces the amount of unnecessary
+ // favicon loading that's performed.
+ if (path != null && path.endsWith("/favicon.ico")) {
+ return WebResourceResponse(null, null, null)
+ }
+
+ val (matches, stringCategory) = getOrCreateUrlMatcher(resources, it).matches(
+ resourceUri,
+ Uri.parse(session?.currentUrl),
+ )
+
+ if (!request.isForMainFrame && matches) {
+ session?.internalNotifyObservers {
+ val matchedCategories = stringCategory.toTrackingProtectionCategories()
+ onTrackerBlocked(
+ Tracker(
+ resourceUri.toString(),
+ matchedCategories,
+ ),
+ )
+ }
+ return WebResourceResponse(null, null, null)
+ }
+ }
+
+ val isRedirect = if (SDK_INT >= Build.VERSION_CODES.N) {
+ request.isRedirect
+ } else {
+ false
+ }
+
+ session?.let { session ->
+ session.settings.requestInterceptor?.let { interceptor ->
+ interceptor.onLoadRequest(
+ session,
+ request.url.toString(),
+ session.currentUrl,
+ request.hasGesture(),
+ session.currentUrl.tryGetHostFromUrl() == request.url.host,
+ isRedirect,
+ false,
+ request.isForMainFrame,
+ )?.apply {
+ return when (this) {
+ is InterceptionResponse.Content ->
+ WebResourceResponse(mimeType, encoding, data.byteInputStream())
+ is InterceptionResponse.Url -> {
+ view.post { view.loadUrl(url) }
+ super.shouldInterceptRequest(view, request)
+ }
+ is InterceptionResponse.AppIntent -> {
+ if (request.isForMainFrame) {
+ session.notifyObservers {
+ onLaunchIntentRequest(url = url, appIntent = appIntent)
+ }
+ }
+
+ super.shouldInterceptRequest(view, request)
+ }
+
+ is InterceptionResponse.Deny -> super.shouldInterceptRequest(view, request)
+ }
+ }
+ }
+ }
+
+ if (request.isForMainFrame) {
+ session?.let {
+ it.notifyObservers {
+ onLoadRequest(request.url.toString(), request.hasGesture(), true)
+ }
+ }
+ }
+
+ return super.shouldInterceptRequest(view, request)
+ }
+
+ override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
+ handler.cancel()
+ session?.let { session ->
+ session.settings.requestInterceptor?.onErrorRequest(
+ session,
+ ErrorType.ERROR_SECURITY_SSL,
+ error.url,
+ )?.apply {
+ view.loadUrl(this.uri)
+ }
+ }
+ }
+
+ @Deprecated("Deprecated in Java")
+ override fun onReceivedError(view: WebView, errorCode: Int, description: String?, failingUrl: String?) {
+ session?.let { session ->
+ val errorType = SystemEngineSession.webViewErrorToErrorType(errorCode)
+ session.settings.requestInterceptor?.onErrorRequest(
+ session,
+ errorType,
+ failingUrl,
+ )?.apply {
+ view.loadUrl(this.uri)
+ }
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
+ session?.let { session ->
+ if (!request.isForMainFrame) {
+ return
+ }
+ val errorType = SystemEngineSession.webViewErrorToErrorType(error.errorCode)
+ session.settings.requestInterceptor?.onErrorRequest(
+ session,
+ errorType,
+ request.url.toString(),
+ )?.apply {
+ view.loadUrl(this.uri)
+ }
+ }
+ }
+
+ override fun onReceivedHttpAuthRequest(view: WebView, handler: HttpAuthHandler, host: String, realm: String) {
+ val session = session ?: return handler.cancel()
+
+ val formattedUrl = session.currentUrl.toUri().let { uri ->
+ "${uri.scheme ?: "http"}://${uri.host ?: host}"
+ }
+
+ // Trim obnoxiously long realms.
+ val trimmedRealm = if (realm.length > MAX_REALM_LENGTH) {
+ realm.substring(0, MAX_REALM_LENGTH) + "\u2026"
+ } else {
+ realm
+ }
+
+ val message = if (trimmedRealm.isEmpty()) {
+ context.getString(R.string.mozac_browser_engine_system_auth_no_realm_message, formattedUrl)
+ } else {
+ context.getString(R.string.mozac_browser_engine_system_auth_message, trimmedRealm, formattedUrl)
+ }
+
+ val credentials = view.getAuthCredentials(host, realm)
+ val userName = credentials.first
+ val password = credentials.second
+
+ session.notifyObservers {
+ onPromptRequest(
+ PromptRequest.Authentication(
+ formattedUrl,
+ "",
+ message,
+ userName,
+ password,
+ PromptRequest.Authentication.Method.HOST,
+ PromptRequest.Authentication.Level.NONE,
+ onConfirm = { user, pass -> handler.proceed(user, pass) },
+ onDismiss = { handler.cancel() },
+ ),
+ )
+ }
+ }
+ }
+
+ @Suppress("ComplexMethod")
+ private fun createWebChromeClient() = object : WebChromeClient() {
+ override fun getVisitedHistory(callback: ValueCallback<Array<String>>) {
+ // TODO private browsing not supported for SystemEngine
+ // https://github.com/mozilla-mobile/android-components/issues/649
+ session?.settings?.historyTrackingDelegate?.let {
+ runBlocking {
+ callback.onReceiveValue(it.getVisited().toTypedArray())
+ }
+ }
+ }
+
+ override fun onProgressChanged(view: WebView?, newProgress: Int) {
+ session?.internalNotifyObservers { onProgress(newProgress) }
+ }
+
+ override fun onReceivedTitle(view: WebView, title: String?) {
+ val titleOrEmpty = title ?: ""
+ // TODO private browsing not supported for SystemEngine
+ // https://github.com/mozilla-mobile/android-components/issues/649
+ session?.currentUrl?.takeIf { it.isNotEmpty() }?.let { url ->
+ session?.settings?.historyTrackingDelegate?.let { delegate ->
+ runBlocking {
+ delegate.onTitleChanged(url, titleOrEmpty)
+ }
+ }
+ }
+ session?.internalNotifyObservers {
+ onTitleChange(titleOrEmpty)
+ onNavigationStateChange(view.canGoBack(), view.canGoForward())
+ }
+ }
+
+ override fun onShowCustomView(view: View, callback: CustomViewCallback) {
+ addFullScreenView(view, callback)
+ session?.internalNotifyObservers { onFullScreenChange(true) }
+ }
+
+ override fun onHideCustomView() {
+ removeFullScreenView()
+ session?.internalNotifyObservers { onFullScreenChange(false) }
+ }
+
+ override fun onPermissionRequestCanceled(request: PermissionRequest) {
+ session?.internalNotifyObservers { onCancelContentPermissionRequest(SystemPermissionRequest(request)) }
+ }
+
+ override fun onPermissionRequest(request: PermissionRequest) {
+ session?.internalNotifyObservers { onContentPermissionRequest(SystemPermissionRequest(request)) }
+ }
+
+ override fun onJsAlert(view: WebView, url: String?, message: String?, result: JsResult): Boolean {
+ val session = session ?: return applyDefaultJsDialogBehavior(result)
+
+ // When an alert is triggered from a iframe, url is equals to about:blank, using currentUrl as a fallback.
+ val safeUrl = if (url.isNullOrBlank()) {
+ session.currentUrl
+ } else {
+ if (url.contains("about")) session.currentUrl else url
+ }
+
+ val title = context.getString(R.string.mozac_browser_engine_system_alert_title, safeUrl)
+
+ val onDismiss: () -> Unit = {
+ result.cancel()
+ }
+
+ val onConfirm: (Boolean) -> Unit = { _ -> result.confirm() }
+
+ session.notifyObservers {
+ onPromptRequest(
+ PromptRequest.Alert(
+ title,
+ message ?: "",
+ false,
+ onConfirm,
+ onDismiss,
+ ),
+ )
+ }
+ return true
+ }
+
+ override fun onJsPrompt(
+ view: WebView?,
+ url: String?,
+ message: String?,
+ defaultValue: String?,
+ result: JsPromptResult,
+ ): Boolean {
+ val session = session ?: return applyDefaultJsDialogBehavior(result)
+
+ val title = context.getString(R.string.mozac_browser_engine_system_alert_title, url ?: session.currentUrl)
+
+ val onDismiss: () -> Unit = {
+ result.cancel()
+ }
+
+ val onConfirm: (Boolean, String) -> Unit = { _, valueInput ->
+ result.confirm(valueInput)
+ }
+
+ session.notifyObservers {
+ onPromptRequest(
+ PromptRequest.TextPrompt(
+ title,
+ message ?: "",
+ defaultValue ?: "",
+ false,
+ onConfirm,
+ onDismiss,
+ ),
+ )
+ }
+ return true
+ }
+
+ override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult): Boolean {
+ val session = session ?: return applyDefaultJsDialogBehavior(result)
+ val title = context.getString(R.string.mozac_browser_engine_system_alert_title, url ?: session.currentUrl)
+
+ val onDismiss: () -> Unit = {
+ result.cancel()
+ }
+
+ val onConfirmPositiveButton: (Boolean) -> Unit = { _ ->
+ result.confirm()
+ }
+
+ val onConfirmNegativeButton: (Boolean) -> Unit = { _ ->
+ result.cancel()
+ }
+
+ session.notifyObservers {
+ onPromptRequest(
+ PromptRequest.Confirm(
+ title,
+ message ?: "",
+ false,
+ "",
+ "",
+ "",
+ onConfirmPositiveButton,
+ onConfirmNegativeButton,
+ {},
+ onDismiss,
+ ),
+ )
+ }
+ return true
+ }
+
+ override fun onShowFileChooser(
+ webView: WebView?,
+ filePathCallback: ValueCallback<Array<Uri>>?,
+ fileChooserParams: FileChooserParams?,
+ ): Boolean {
+ var mimeTypes = fileChooserParams?.acceptTypes ?: arrayOf()
+
+ if (mimeTypes.isNotEmpty() && mimeTypes.first().isNullOrEmpty()) {
+ mimeTypes = arrayOf()
+ }
+
+ val isMultipleFilesSelection = fileChooserParams?.mode == MODE_OPEN_MULTIPLE
+
+ val captureMode = if (fileChooserParams?.isCaptureEnabled == true) {
+ PromptRequest.File.FacingMode.ANY
+ } else {
+ PromptRequest.File.FacingMode.NONE
+ }
+
+ val onSelectMultiple: (Context, Array<Uri>) -> Unit = { _, uris ->
+ filePathCallback?.onReceiveValue(uris)
+ }
+
+ val onSelectSingle: (Context, Uri) -> Unit = { _, uri ->
+ filePathCallback?.onReceiveValue(arrayOf(uri))
+ }
+
+ val onDismiss: () -> Unit = {
+ filePathCallback?.onReceiveValue(null)
+ }
+
+ session?.notifyObservers {
+ onPromptRequest(
+ PromptRequest.File(
+ mimeTypes,
+ isMultipleFilesSelection,
+ captureMode,
+ onSelectSingle,
+ onSelectMultiple,
+ onDismiss,
+ ),
+ )
+ }
+
+ return true
+ }
+
+ override fun onCreateWindow(
+ view: WebView,
+ isDialog: Boolean,
+ isUserGesture: Boolean,
+ resultMsg: Message?,
+ ): Boolean {
+ session?.internalNotifyObservers {
+ val newEngineSession = SystemEngineSession(context, session?.settings)
+ onWindowRequest(
+ SystemWindowRequest(
+ view,
+ newEngineSession,
+ NestedWebView(context),
+ isDialog,
+ isUserGesture,
+ resultMsg,
+ ),
+ )
+ }
+ return true
+ }
+
+ override fun onCloseWindow(window: WebView) {
+ session?.internalNotifyObservers {
+ onWindowRequest(SystemWindowRequest(window, type = WindowRequest.Type.CLOSE))
+ }
+ }
+ }
+
+ internal fun createDownloadListener(): DownloadListener {
+ return DownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
+ session?.internalNotifyObservers {
+ val fileName = DownloadUtils.guessFileName(contentDisposition, null, url, mimetype)
+ val cookie = CookieManager.getInstance().getCookie(url)
+ onExternalResource(url, fileName, contentLength, mimetype, cookie, userAgent)
+ }
+ }
+ }
+
+ internal fun createFindListener(): WebView.FindListener {
+ return WebView.FindListener { activeMatchOrdinal: Int, numberOfMatches: Int, isDoneCounting: Boolean ->
+ session?.internalNotifyObservers {
+ onFindResult(activeMatchOrdinal, numberOfMatches, isDoneCounting)
+ }
+ }
+ }
+
+ internal fun handleLongClick(type: Int, extra: String): Boolean {
+ val result: HitResult? = when (type) {
+ EMAIL_TYPE -> {
+ HitResult.EMAIL(extra)
+ }
+ GEO_TYPE -> {
+ HitResult.GEO(extra)
+ }
+ PHONE_TYPE -> {
+ HitResult.PHONE(extra)
+ }
+ IMAGE_TYPE -> {
+ HitResult.IMAGE(extra)
+ }
+ SRC_ANCHOR_TYPE -> {
+ HitResult.UNKNOWN(extra)
+ }
+ SRC_IMAGE_ANCHOR_TYPE -> {
+ // HitTestResult.getExtra() contains only the image URL, and not the link
+ // URL. Internally, WebView's HitTestData contains both, but they only
+ // make it available via requestFocusNodeHref...
+ val message = Message()
+ message.target = ImageHandler(session)
+ session?.webView?.requestFocusNodeHref(message)
+ null
+ }
+ else -> null
+ }
+ result?.let {
+ session?.internalNotifyObservers { onLongPress(it) }
+ return true
+ }
+ return false
+ }
+
+ internal fun addFullScreenView(view: View, callback: WebChromeClient.CustomViewCallback) {
+ val webView = findViewWithTag<WebView>("mozac_system_engine_webview")
+ val layoutParams = FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ )
+ webView?.apply { this.visibility = View.INVISIBLE }
+
+ session?.fullScreenCallback = callback
+
+ view.tag = "mozac_system_engine_fullscreen"
+ addView(view, layoutParams)
+ }
+
+ internal fun removeFullScreenView() {
+ val view = findViewWithTag<View>("mozac_system_engine_fullscreen")
+ val webView = findViewWithTag<WebView>("mozac_system_engine_webview")
+ view?.let {
+ webView?.apply { this.visibility = View.VISIBLE }
+ removeView(view)
+ }
+ }
+
+ // Deprecation will be handled in https://github.com/mozilla-mobile/android-components/issues/8514
+ @Suppress("DEPRECATION")
+ class ImageHandler(val session: SystemEngineSession?) : Handler() {
+ override fun handleMessage(msg: Message) {
+ val url = msg.data.getString("url")
+ val src = msg.data.getString("src")
+
+ if (url == null || src == null) {
+ throw IllegalStateException("WebView did not supply url or src for image link")
+ }
+
+ session?.internalNotifyObservers { onLongPress(HitResult.IMAGE_SRC(src, url)) }
+ }
+ }
+
+ override fun setVerticalClipping(clippingHeight: Int) {
+ // no-op
+ }
+
+ override fun setDynamicToolbarMaxHeight(height: Int) {
+ // no-op
+ }
+
+ override fun setActivityContext(context: Context?) {
+ // no-op
+ }
+
+ override fun canScrollVerticallyUp() = session?.webView?.canScrollVertically(-1) ?: false
+
+ override fun canScrollVerticallyDown() = session?.webView?.canScrollVertically(1) ?: false
+
+ override fun getInputResultDetail(): InputResultDetail {
+ return (session?.webView as? NestedWebView)?.inputResultDetail
+ ?: InputResultDetail.newInstance()
+ }
+
+ override fun captureThumbnail(onFinish: (Bitmap?) -> Unit) {
+ val webView = session?.webView
+ if (webView == null) {
+ onFinish(null)
+ return
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ createThumbnailUsingDrawingView(webView, onFinish)
+ } else {
+ createThumbnailUsingPixelCopy(webView, onFinish)
+ }
+ }
+
+ override fun clearSelection() {
+ // no-op
+ }
+
+ private fun createThumbnailUsingDrawingView(view: View, onFinish: (Bitmap?) -> Unit) {
+ val outBitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
+ val canvas = Canvas(outBitmap)
+ view.draw(canvas)
+ onFinish(outBitmap)
+ }
+
+ @TargetApi(Build.VERSION_CODES.O)
+ private fun createThumbnailUsingPixelCopy(view: View, onFinish: (Bitmap?) -> Unit) {
+ val out = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
+ val viewRect = view.getRectWithViewLocation()
+ val window = (context as Activity).window
+
+ PixelCopy.request(
+ window,
+ viewRect,
+ out,
+ { copyResult ->
+ val result = if (copyResult == PixelCopy.SUCCESS) out else null
+ onFinish(result)
+ },
+ handler,
+ )
+ }
+
+ private fun applyDefaultJsDialogBehavior(result: JsResult?): Boolean {
+ result?.cancel()
+ return true
+ }
+
+ @Suppress("Deprecation")
+ private fun WebView.getAuthCredentials(host: String, realm: String): Pair<String, String> {
+ val credentials = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ session?.webViewDatabase(context)?.getHttpAuthUsernamePassword(host, realm)
+ } else {
+ this.getHttpAuthUsernamePassword(host, realm)
+ }
+
+ var credentialsPair = "" to ""
+
+ if (!credentials.isNullOrEmpty() && credentials.size == 2) {
+ val user = credentials[0] ?: ""
+ val pass = credentials[1] ?: ""
+
+ credentialsPair = user to pass
+ }
+ return credentialsPair
+ }
+
+ companion object {
+
+ // Maximum number of successive dialogs before we prompt users to disable dialogs.
+ internal const val MAX_SUCCESSIVE_DIALOG_COUNT: Int = 2
+
+ // Minimum time required between dialogs in seconds before enabling the stop dialog.
+ internal const val MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT: Int = 3
+
+ // Maximum realm length to be shown in authentication dialog.
+ internal const val MAX_REALM_LENGTH: Int = 50
+
+ // Number of milliseconds in 1 second.
+ internal const val SECOND_MS: Int = 1000
+
+ @Volatile
+ internal var URL_MATCHER: UrlMatcher? = null
+
+ private val urlMatcherCategoryMap = mapOf(
+ UrlMatcher.ADVERTISING to TrackingProtectionPolicy.TrackingCategory.AD,
+ UrlMatcher.ANALYTICS to TrackingProtectionPolicy.TrackingCategory.ANALYTICS,
+ UrlMatcher.CONTENT to TrackingProtectionPolicy.TrackingCategory.CONTENT,
+ UrlMatcher.SOCIAL to TrackingProtectionPolicy.TrackingCategory.SOCIAL,
+ UrlMatcher.CRYPTOMINING to TrackingProtectionPolicy.TrackingCategory.CRYPTOMINING,
+ UrlMatcher.FINGERPRINTING to TrackingProtectionPolicy.TrackingCategory.FINGERPRINTING,
+ )
+
+ private fun String?.toTrackingProtectionCategories(): List<TrackingProtectionPolicy.TrackingCategory> {
+ val category = urlMatcherCategoryMap[this]
+ return if (category != null) {
+ listOf(category)
+ } else {
+ emptyList()
+ }
+ }
+
+ @Synchronized
+ internal fun getOrCreateUrlMatcher(resources: Resources, policy: TrackingProtectionPolicy): UrlMatcher {
+ val categories = urlMatcherCategoryMap.filterValues { policy.contains(it) }.keys
+
+ URL_MATCHER?.setCategoriesEnabled(categories) ?: run {
+ URL_MATCHER = UrlMatcher.createMatcher(
+ resources,
+ R.raw.domain_blocklist,
+ R.raw.domain_safelist,
+ categories,
+ )
+ }
+
+ return URL_MATCHER as UrlMatcher
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/ReversibleString.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/ReversibleString.kt
new file mode 100644
index 0000000000..5625fda9f3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/ReversibleString.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.browser.engine.system.matcher
+
+/**
+ * A String wrapper utility that allows for efficient string reversal. We
+ * regularly need to reverse strings. The standard way of doing this in Java
+ * would be to copy the string to reverse (e.g. using StringBuffer.reverse()).
+ * This seems wasteful when we only read our Strings character by character,
+ * in which case can just transpose positions as needed.
+ */
+abstract class ReversibleString private constructor(
+ protected val string: String,
+ protected val offsetStart: Int,
+ protected val offsetEnd: Int,
+) {
+ abstract val isReversed: Boolean
+ abstract fun charAt(position: Int): Char
+ abstract fun substring(startIndex: Int): ReversibleString
+
+ init {
+ if (offsetStart > offsetEnd || offsetStart < 0 || offsetEnd < 0) {
+ throw StringIndexOutOfBoundsException("Cannot create negative-length String")
+ }
+ }
+
+ /**
+ * Returns the length of this string.
+ */
+ fun length(): Int = offsetEnd - offsetStart
+
+ /**
+ * Reverses this string.
+ */
+ fun reverse(): ReversibleString =
+ if (isReversed) {
+ ForwardString(string, offsetStart, offsetEnd)
+ } else {
+ ReverseString(string, offsetStart, offsetEnd)
+ }
+
+ private class ForwardString(
+ string: String,
+ offsetStart: Int,
+ offsetEnd: Int,
+ ) : ReversibleString(string, offsetStart, offsetEnd) {
+ override val isReversed: Boolean = false
+
+ override fun charAt(position: Int): Char {
+ if (position > length()) {
+ throw StringIndexOutOfBoundsException()
+ }
+ return string[position + offsetStart]
+ }
+
+ override fun substring(startIndex: Int): ReversibleString {
+ return ForwardString(string, offsetStart + startIndex, offsetEnd)
+ }
+ }
+
+ private class ReverseString(
+ string: String,
+ offsetStart: Int,
+ offsetEnd: Int,
+ ) : ReversibleString(string, offsetStart, offsetEnd) {
+ override val isReversed: Boolean = true
+
+ override fun charAt(position: Int): Char {
+ if (position > length()) {
+ throw StringIndexOutOfBoundsException()
+ }
+ return string[length() - 1 - position + offsetStart]
+ }
+
+ override fun substring(startIndex: Int): ReversibleString {
+ return ReverseString(string, offsetStart, offsetEnd - startIndex)
+ }
+ }
+
+ companion object {
+ /**
+ * Create a [ReversibleString] for the provided [String].
+ */
+ fun create(string: String): ReversibleString {
+ return ForwardString(string, 0, string.length)
+ }
+ }
+}
+
+fun String.reversible(): ReversibleString {
+ return ReversibleString.create(this)
+}
+
+fun String.reverse(): ReversibleString {
+ return this.reversible().reverse()
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Safelist.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Safelist.kt
new file mode 100644
index 0000000000..d75d9966ec
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Safelist.kt
@@ -0,0 +1,176 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.matcher
+
+import android.net.Uri
+import android.text.TextUtils
+import android.util.JsonReader
+import java.util.ArrayList
+
+/**
+ * Stores safe-listed URIs for individual hosts.
+ */
+internal class Safelist {
+ private val rootNode: SafelistTrie = SafelistTrie.createRootNode()
+
+ /**
+ * Adds the provided safelist for the provided host.
+ *
+ * @param host the reversed host URI ("foo.com".reverse())
+ * @param safelist a [Trie] representing the safe-listed URIs
+ */
+ fun put(host: ReversibleString, safelist: Trie) {
+ rootNode.putSafelist(host, safelist)
+ }
+
+ /**
+ * Checks if the given resource is safe-listed for the given host.
+ *
+ * @param host the host URI as string ("foo.com")
+ * @param host the resources URI as string ("bar.com")
+ */
+ fun contains(host: String, resource: String): Boolean {
+ return contains(Uri.parse(host), Uri.parse(resource))
+ }
+
+ /**
+ * Checks if the given resource is safe-listed for the given host.
+ *
+ * @param hostUri the host URI
+ * @param resource the resources URI
+ */
+ fun contains(hostUri: Uri, resource: Uri): Boolean {
+ return if (TextUtils.isEmpty(hostUri.host) || TextUtils.isEmpty(resource.host) || hostUri.scheme == "data") {
+ false
+ } else if (resource.scheme?.isPermittedResourceProtocol() == true &&
+ hostUri.scheme?.isSupportedProtocol() == true
+ ) {
+ contains(hostUri.host!!.reverse(), resource.host!!.reverse(), rootNode)
+ } else {
+ false
+ }
+ }
+
+ private fun contains(site: ReversibleString, resource: ReversibleString, revHostTrie: Trie): Boolean {
+ val next = revHostTrie.children.get(site.charAt(0).code) as? SafelistTrie ?: return false
+
+ if (next.safelist?.findNode(resource) != null) {
+ return true
+ }
+
+ return if (site.length() == 1) false else contains(site.substring(1), resource, next)
+ }
+
+ /**
+ * Check if this String is a valid resource protocol.
+ */
+ private fun String.isPermittedResourceProtocol(): Boolean {
+ return this.startsWith("http") ||
+ this.startsWith("https") ||
+ this.startsWith("file") ||
+ this.startsWith("data") ||
+ this.startsWith("javascript") ||
+ this.startsWith("about")
+ }
+
+ /**
+ * Check if this String is a supported protocol.
+ */
+ private fun String.isSupportedProtocol(): Boolean {
+ return this.isPermittedResourceProtocol() || this.startsWith("error")
+ }
+
+ companion object {
+ /**
+ * Parses json for safe-listed URIs.
+ *
+ * @param reader a JsonReader
+ * @return the safe list.
+ */
+ @Suppress("NestedBlockDepth")
+ fun fromJson(reader: JsonReader): Safelist {
+ val safelist = Safelist()
+ reader.beginObject()
+
+ while (reader.hasNext()) {
+ reader.skipValue()
+ reader.beginObject()
+
+ val safelistTrie = Trie.createRootNode()
+ val propertyList = ArrayList<String>()
+ while (reader.hasNext()) {
+ val itemName = reader.nextName()
+ if (itemName == "properties") {
+ reader.beginArray()
+ while (reader.hasNext()) {
+ propertyList.add(reader.nextString())
+ }
+ reader.endArray()
+ } else if (itemName == "resources") {
+ reader.beginArray()
+ while (reader.hasNext()) {
+ safelistTrie.put(reader.nextString().reverse())
+ }
+ reader.endArray()
+ }
+ }
+ propertyList.forEach { safelist.put(it.reverse(), safelistTrie) }
+ reader.endObject()
+ }
+ reader.endObject()
+ return safelist
+ }
+ }
+}
+
+/**
+ * A [Trie] implementation which stores a safe list (another [Trie]).
+ */
+internal class SafelistTrie private constructor(character: Char, parent: SafelistTrie?) : Trie(character, parent) {
+ var safelist: Trie? = null
+
+ override fun createNode(character: Char, parent: Trie): Trie {
+ return SafelistTrie(character, parent as SafelistTrie)
+ }
+
+ /**
+ * Adds new nodes (recursively) for all chars in the provided string and stores
+ * the provide safelist Trie.
+ *
+ * @param string the string for which a node should be added.
+ * @param safelist the safelist to store.
+ * @return the newly created node or the existing one.
+ */
+ fun putSafelist(string: String, safelist: Trie) {
+ this.putSafelist(string.reversible(), safelist)
+ }
+
+ /**
+ * Adds new nodes (recursively) for all chars in the provided string and stores
+ * the provide safelist Trie.
+ *
+ * @param string the string for which a node should be added.
+ * @param safelist the safelist to store.
+ * @return the newly created node or the existing one.
+ */
+ fun putSafelist(string: ReversibleString, safelist: Trie) {
+ val node = super.put(string) as SafelistTrie
+
+ if (node.safelist != null) {
+ throw IllegalStateException("Safelist already set for node $string")
+ }
+
+ node.safelist = safelist
+ }
+
+ companion object {
+ /**
+ * Creates a new root node.
+ */
+ fun createRootNode(): SafelistTrie {
+ return SafelistTrie(Character.MIN_VALUE, null)
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Trie.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Trie.kt
new file mode 100644
index 0000000000..2a46ba1381
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/Trie.kt
@@ -0,0 +1,114 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.matcher
+
+import android.util.SparseArray
+
+/**
+ * Simple implementation of a Trie, used for indexing URLs.
+ */
+open class Trie constructor(character: Char, parent: Trie?) {
+ val children = SparseArray<Trie>()
+ private var terminator = false
+
+ init {
+ parent?.children?.put(character.code, this)
+ }
+
+ /**
+ * Finds the node corresponding to the provided string.
+ *
+ * @param string the string to search.
+ * @return the corresponding node if found, otherwise null.
+ */
+ fun findNode(string: String): Trie? {
+ return this.findNode(string.reversible())
+ }
+
+ /**
+ * Finds the node corresponding to the provided string.
+ *
+ * @param string the string to search.
+ * @return the corresponding node if found, otherwise null.
+ */
+ fun findNode(string: ReversibleString): Trie? {
+ var match: Trie? = null
+ if (terminator && (string.length() == 0 || string.charAt(0) == '.')) {
+ // Match found and we're at a domain boundary. This is important, because
+ // we don't want to return on partial domain matches. If the trie node is bar.com,
+ // and the search string is foo-bar.com, we shouldn't match, but
+ // foo.bar.com should match.)
+ match = this
+ } else if (string.length() != 0) {
+ val next = children.get(string.charAt(0).code)
+ match = next?.findNode(string.substring(1))
+ }
+ return match
+ }
+
+ /**
+ * Adds new nodes (recursively) for all chars in the provided string.
+ *
+ * @param string the string for which a node should be added.
+ * @return the newly created node or the existing one.
+ */
+ fun put(string: String): Trie {
+ return this.put(string.reversible())
+ }
+
+ /**
+ * Adds new nodes (recursively) for all chars in the provided string.
+ *
+ * @param string the string for which a node should be added.
+ * @return the newly created node or the existing one.
+ */
+ fun put(string: ReversibleString): Trie {
+ if (string.length() == 0) {
+ terminator = true
+ return this
+ }
+
+ val character = string.charAt(0)
+ val child = put(character)
+ return child.put(string.substring(1))
+ }
+
+ /**
+ * Adds a new node for the provided character if none exists.
+ *
+ * @param character the character for which a node should be added.
+ * @return the newly created node or the existing one.
+ */
+ fun put(character: Char): Trie {
+ val existingChild = children.get(character.code)
+
+ if (existingChild != null) {
+ return existingChild
+ }
+
+ val newChild = createNode(character, this)
+ children.put(character.code, newChild)
+ return newChild
+ }
+
+ /**
+ * Creates a new node for the provided character and parent node.
+ *
+ * @param character the character this node represents
+ * @param parent the parent of this node
+ */
+ open fun createNode(character: Char, parent: Trie): Trie {
+ return Trie(character, parent)
+ }
+
+ companion object {
+ /**
+ * Creates a new root node.
+ */
+ fun createRootNode(): Trie {
+ return Trie(Character.MIN_VALUE, null)
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/UrlMatcher.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/UrlMatcher.kt
new file mode 100644
index 0000000000..b496cca756
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/matcher/UrlMatcher.kt
@@ -0,0 +1,323 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.matcher
+
+import android.content.Context
+import android.content.res.Resources
+import android.net.Uri
+import android.util.JsonReader
+import androidx.annotation.RawRes
+import java.io.InputStreamReader
+import java.io.Reader
+import java.nio.charset.StandardCharsets.UTF_8
+import java.util.LinkedList
+
+/**
+ * Provides functionality to process categorized URL block/safe lists and match
+ * URLs against these lists.
+ */
+class UrlMatcher {
+ private val categories: MutableMap<String, Trie>
+ internal val enabledCategories = HashSet<String>()
+
+ private val safelist: Safelist?
+ private val previouslyMatched = HashSet<String>()
+ private val previouslyUnmatched = HashSet<String>()
+
+ constructor(patterns: Array<String>) {
+ categories = HashMap()
+ safelist = null
+
+ val defaultCategory = Trie.createRootNode()
+ patterns.forEach { defaultCategory.put(it.reverse()) }
+ categories[DEFAULT] = defaultCategory
+ enabledCategories.add(DEFAULT)
+ }
+
+ internal constructor(
+ enabledCategories: Set<String>,
+ supportedCategories: Set<String>,
+ categoryMap: MutableMap<String, Trie>,
+ safelist: Safelist? = null,
+ ) {
+ this.safelist = safelist
+ this.categories = categoryMap
+
+ for ((key) in categoryMap) {
+ if (!supportedCategories.contains(key)) {
+ throw IllegalArgumentException("$key categoryMap contains undeclared category")
+ }
+ }
+
+ enabledCategories.forEach { setCategoryEnabled(it, true) }
+ }
+
+ /**
+ * Enables the provided categories.
+ *
+ * @param categories set of categories to enable.
+ */
+ fun setCategoriesEnabled(categories: Set<String>) {
+ if (enabledCategories != categories) {
+ enabledCategories.removeAll { it != DEFAULT }
+ categories.forEach { setCategoryEnabled(it, true) }
+ }
+ }
+
+ internal fun setCategoryEnabled(category: String, enabled: Boolean) {
+ if (enabled) {
+ if (enabledCategories.contains(category)) {
+ return
+ } else {
+ enabledCategories.add(category)
+ previouslyUnmatched.clear()
+ }
+ } else {
+ if (!enabledCategories.contains(category)) {
+ return
+ } else {
+ enabledCategories.remove(category)
+ previouslyMatched.clear()
+ }
+ }
+ }
+
+ /**
+ * Checks if the given page URI is blocklisted for the given resource URI.
+ * Returns true if the site (page URI) is allowed to access
+ * the resource URI, otherwise false.
+ *
+ * @param resourceURI URI of a resource to be loaded by the page
+ * @param pageURI URI of the page
+ * @return a [Pair] of <Boolean, String?> the first indicates, if the URI matches and the second
+ * indicates the category of the match if available otherwise null.
+ */
+ fun matches(resourceURI: String, pageURI: String): Pair<Boolean, String?> {
+ return matches(Uri.parse(resourceURI), Uri.parse(pageURI))
+ }
+
+ /**
+ * Checks if the given page URI is blocklisted for the given resource URI.
+ * Returns true if the site (page URI) is allowed to access
+ * the resource URI, otherwise false.
+ *
+ * @param resourceURI URI of a resource to be loaded by the page
+ * @param pageURI URI of the page
+ * @return a [Pair] of <Boolean, String?> the first indicates, if the URI matches and the second
+ * indicates the category of the match if available otherwise null.
+ */
+ @Suppress("ReturnCount", "ComplexMethod")
+ fun matches(resourceURI: Uri, pageURI: Uri): Pair<Boolean, String?> {
+ val resourceURLString = resourceURI.toString()
+ val resourceHost = resourceURI.host
+ val pageHost = pageURI.host
+ val notMatchesFound = false to null
+
+ if (previouslyUnmatched.contains(resourceURLString)) {
+ return notMatchesFound
+ }
+
+ if (safelist?.contains(pageURI, resourceURI) == true) {
+ return notMatchesFound
+ }
+
+ if (pageHost != null && pageHost == resourceHost) {
+ return notMatchesFound
+ }
+
+ if (previouslyMatched.contains(resourceURLString)) {
+ return true to null
+ }
+
+ if (resourceHost == null) {
+ return notMatchesFound
+ }
+
+ for ((key, value) in categories) {
+ if (enabledCategories.contains(key) && value.findNode(resourceHost.reverse()) != null) {
+ previouslyMatched.add(resourceURLString)
+ return true to key
+ }
+ }
+
+ previouslyUnmatched.add(resourceURLString)
+ return notMatchesFound
+ }
+
+ companion object {
+ const val ADVERTISING = "Advertising"
+ const val ANALYTICS = "Analytics"
+ const val CONTENT = "Content"
+ const val SOCIAL = "Social"
+ const val DEFAULT = "default"
+ const val CRYPTOMINING = "Cryptomining"
+ const val FINGERPRINTING = "Fingerprinting"
+
+ private val ignoredCategories = setOf("Legacy Disconnect", "Legacy Content")
+ private val webfontExtensions = arrayOf(".woff2", ".woff", ".eot", ".ttf", ".otf")
+ private val supportedCategories = setOf(
+ ADVERTISING,
+ ANALYTICS,
+ SOCIAL,
+ CONTENT,
+ CRYPTOMINING,
+ FINGERPRINTING,
+ )
+
+ /**
+ * Creates a new matcher instance for the provided URL lists.
+ *
+ * @deprecated Pass resources directly
+ * @param blocklistFile resource ID to a JSON file containing the block list
+ * @param safelistFile resource ID to a JSON file containing the safe list
+ */
+ fun createMatcher(
+ context: Context,
+ @RawRes blocklistFile: Int,
+ @RawRes safelistFile: Int,
+ enabledCategories: Set<String> = supportedCategories,
+ ): UrlMatcher =
+ createMatcher(context.resources, blocklistFile, safelistFile, enabledCategories)
+
+ /**
+ * Creates a new matcher instance for the provided URL lists.
+ *
+ * @param blocklistFile resource ID to a JSON file containing the block list
+ * @param safelistFile resource ID to a JSON file containing the safe list
+ */
+ fun createMatcher(
+ resources: Resources,
+ @RawRes blocklistFile: Int,
+ @RawRes safelistFile: Int,
+ enabledCategories: Set<String> = supportedCategories,
+ ): UrlMatcher {
+ val blocklistReader = InputStreamReader(resources.openRawResource(blocklistFile), UTF_8)
+ val safelistReader = InputStreamReader(resources.openRawResource(safelistFile), UTF_8)
+ return createMatcher(blocklistReader, safelistReader, enabledCategories)
+ }
+
+ /**
+ * Creates a new matcher instance for the provided URL lists.
+ *
+ * @param block reader containing the block list
+ * @param safe resource ID to a JSON file containing the safe list
+ */
+ fun createMatcher(
+ block: Reader,
+ safe: Reader,
+ enabledCategories: Set<String> = supportedCategories,
+ ): UrlMatcher {
+ val categoryMap = HashMap<String, Trie>()
+
+ JsonReader(block).use {
+ jsonReader ->
+ loadCategories(jsonReader, categoryMap)
+ }
+
+ var safelist: Safelist?
+ JsonReader(safe).use { jsonReader -> safelist = Safelist.fromJson(jsonReader) }
+ return UrlMatcher(enabledCategories, supportedCategories, categoryMap, safelist)
+ }
+
+ /**
+ * Checks if the given URI points to a Web font.
+ * @param uri the URI to check.
+ *
+ * @return true if the URI is a Web font, otherwise false.
+ */
+ fun isWebFont(uri: Uri): Boolean {
+ val path = uri.path ?: return false
+ return webfontExtensions.find { path.endsWith(it) } != null
+ }
+
+ private fun loadCategories(
+ reader: JsonReader,
+ categoryMap: MutableMap<String, Trie>,
+ override: Boolean = false,
+ ): Map<String, Trie> {
+ reader.beginObject()
+
+ while (reader.hasNext()) {
+ val name = reader.nextName()
+ if (name == "categories") {
+ extractCategories(reader, categoryMap, override)
+ } else {
+ reader.skipValue()
+ }
+ }
+
+ reader.endObject()
+ return categoryMap
+ }
+
+ @Suppress("ThrowsCount", "ComplexMethod", "NestedBlockDepth")
+ private fun extractCategories(reader: JsonReader, categoryMap: MutableMap<String, Trie>, override: Boolean) {
+ reader.beginObject()
+
+ val socialOverrides = LinkedList<String>()
+ while (reader.hasNext()) {
+ val categoryName = reader.nextName()
+ when {
+ ignoredCategories.contains(categoryName) -> reader.skipValue()
+ else -> {
+ val categoryTrie: Trie?
+ if (!override) {
+ if (categoryMap.containsKey(categoryName)) {
+ throw IllegalStateException("Cannot insert already loaded category")
+ }
+ categoryTrie = Trie.createRootNode()
+ categoryMap[categoryName] = categoryTrie
+ } else {
+ categoryTrie = categoryMap[categoryName]
+ if (categoryTrie == null) {
+ throw IllegalStateException("Cannot add override items to nonexistent category")
+ }
+ }
+ extractCategory(reader) { url, _ -> categoryTrie.put(url.reverse()) }
+ }
+ }
+ }
+
+ val socialTrie = categoryMap[SOCIAL]
+ if (socialTrie == null && !override) {
+ throw IllegalStateException("Expected social list to exist")
+ }
+ socialOverrides.forEach { socialTrie?.put(it.reverse()) }
+ reader.endObject()
+ }
+
+ private fun extractCategory(reader: JsonReader, callback: (String, String) -> Unit) {
+ reader.beginArray()
+ while (reader.hasNext()) {
+ extractSite(reader, callback)
+ }
+ reader.endArray()
+ }
+
+ private fun extractSite(reader: JsonReader, callback: (String, String) -> Unit) {
+ reader.beginObject()
+ val siteOwner = reader.nextName()
+
+ reader.beginObject()
+ while (reader.hasNext()) {
+ reader.skipValue()
+ val nextToken = reader.peek()
+ if (nextToken.name == "STRING") {
+ // Sometimes there's a "dnt" entry, with unspecified purpose.
+ reader.skipValue()
+ } else {
+ reader.beginArray()
+ while (reader.hasNext()) {
+ callback(reader.nextString(), siteOwner)
+ }
+ reader.endArray()
+ }
+ }
+ reader.endObject()
+
+ reader.endObject()
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequest.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequest.kt
new file mode 100644
index 0000000000..0579b359e1
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequest.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.browser.engine.system.permission
+
+import android.webkit.PermissionRequest.RESOURCE_AUDIO_CAPTURE
+import android.webkit.PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID
+import android.webkit.PermissionRequest.RESOURCE_VIDEO_CAPTURE
+import mozilla.components.concept.engine.permission.Permission
+import mozilla.components.concept.engine.permission.PermissionRequest
+
+/**
+ * WebView-based implementation of [PermissionRequest].
+ *
+ * @property nativeRequest the underlying WebView permission request.
+ */
+class SystemPermissionRequest(private val nativeRequest: android.webkit.PermissionRequest) : PermissionRequest {
+ override val uri: String = nativeRequest.origin.toString()
+ override val id: String = java.util.UUID.randomUUID().toString()
+
+ override val permissions = nativeRequest.resources.map { resource ->
+ permissionsMap.getOrElse(resource) { Permission.Generic(resource) }
+ }
+
+ override fun grant(permissions: List<Permission>) {
+ nativeRequest.grant(permissions.map { it.id }.toTypedArray())
+ }
+
+ override fun reject() {
+ nativeRequest.deny()
+ }
+
+ companion object {
+ val permissionsMap = mapOf(
+ RESOURCE_AUDIO_CAPTURE to Permission.ContentAudioCapture(RESOURCE_AUDIO_CAPTURE),
+ RESOURCE_VIDEO_CAPTURE to Permission.ContentVideoCapture(RESOURCE_VIDEO_CAPTURE),
+ RESOURCE_PROTECTED_MEDIA_ID to Permission.ContentProtectedMediaId(RESOURCE_PROTECTED_MEDIA_ID),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/window/SystemWindowRequest.kt b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/window/SystemWindowRequest.kt
new file mode 100644
index 0000000000..38fd33284b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/window/SystemWindowRequest.kt
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.browser.engine.system.window
+
+import android.os.Message
+import android.webkit.WebView
+import mozilla.components.browser.engine.system.SystemEngineSession
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.window.WindowRequest
+
+/**
+ * WebView-based implementation of [WindowRequest].
+ *
+ * @property webView the WebView from which the request originated.
+ * @property newWebView the WebView to use for opening a new window, may be null for close requests.
+ * @property newEngineSession the new [EngineSession] to handle this request.
+ * @property openAsDialog whether or not the window should be opened as a dialog, defaults to false.
+ * @property triggeredByUser whether or not the request was triggered by the user, defaults to false.
+ * @property resultMsg the message to send to the new WebView, may be null.
+ */
+class SystemWindowRequest(
+ private val webView: WebView,
+ private val newEngineSession: EngineSession? = null,
+ private val newWebView: WebView? = null,
+ val openAsDialog: Boolean = false,
+ val triggeredByUser: Boolean = false,
+ private val resultMsg: Message? = null,
+ override val type: WindowRequest.Type = WindowRequest.Type.OPEN,
+) : WindowRequest {
+
+ override val url: String = ""
+
+ override fun prepare(): EngineSession {
+ requireNotNull(newEngineSession)
+
+ newWebView?.let {
+ (newEngineSession as SystemEngineSession).webView = it
+ }
+ return newEngineSession
+ }
+
+ override fun start() {
+ val message = resultMsg
+ val transport = message?.obj as? WebView.WebViewTransport
+ transport?.let {
+ it.webView = newWebView
+ message.sendToTarget()
+ }
+ }
+}
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
new file mode 100644
index 0000000000..845571cfa0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json
@@ -0,0 +1,11046 @@
+{
+ "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
new file mode 100644
index 0000000000..a2c80176b6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json
@@ -0,0 +1,12347 @@
+{
+ "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/engine-system/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..e52c54b1a8
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-am/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">በ%1$s ላይ ያለው ገጽ እንዲህ ይላል፡-</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s የእርስዎን የተጠቃሚ ስም እና የይለፍ ቃል እየጠየቀ ነው። ድረ-ገፁ እንዲህ ይላል፡- &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s የእርስዎን የተጠቃሚ ስም እና የይለፍ ቃል እየጠየቀ ነው።</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-an/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-an/strings.xml
new file mode 100644
index 0000000000..676854b02c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-an/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La pachina en %1$s diz:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s te ye pedindo lo tuyo nombre d’usuario y clau. Lo puesto diz: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s te ye pedindo lo tuyo nombre d’usuario y clau.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ann/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ann/strings.xml
new file mode 100644
index 0000000000..96cb729e73
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ann/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Akpọk òkup me %1$s ìbe:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ìkido erieen̄ òsikwaan̄ kwun̄ mè ikọ-atafia. Akpatan̄ ya ìbe: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ìkido erieen̄ òsikwaan̄ kwun̄ mè ikọ-atafia.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..7b36637be6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ar/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">تقول الصفحة في %1$s:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">يطلب الوسيط %2$s اسم مستخدم و كلمة سر. يقول الموقع: ”%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">يطلب %1$s اسم المستخدم و كلمة السر.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..5cf994aa8e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ast/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La páxina de «%1$s» diz:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">«%2$s» solicita un nome d\'usuariu y una contraseña. El sitiu diz «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">«%1$s» solicita un nome d\'usuariu y una contraseña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-az/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-az/strings.xml
new file mode 100644
index 0000000000..0f445744de
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-az/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s səhifəsi deyir ki:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s istifadəçi adı və parolunuzu istəyir. Sayt deyir ki: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s istifadəçi adı və parolunuzu istəyir.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..2c64a4e2ba
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-azb/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s یارپاغیندا دئییلیر:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s قوللانیجی آدینیزی و رمزینیزی ایستییر. سایت‌دا دئییلیر: ”%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s قوللانیجی آدینیزی و رمزینیزی ایستییر.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ban/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ban/strings.xml
new file mode 100644
index 0000000000..ed2eb2520d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ban/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Kaca ring %1$s mapikobet:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ngidih aran sang anganggé miwah kruna sandi Ragané. Situs nyuratang: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ngidih aran sang anganggé miwah sandi Ragané.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..d29e4e6dfa
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-be/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Старонка на %1$s паведамляе:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s запытвае імя карыстальніка і пароль. Сайт паведамляе: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s запытвае імя карыстальніка і пароль.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..e8b1b76299
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bg/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Страницата на %1$s казва:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s пита за вашето потребителско име и парола. Сайтът казва: „%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s пита за вашето потребителско име и парола.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bn/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bn/strings.xml
new file mode 100644
index 0000000000..7cc8bde2c2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bn/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s পাতায় বলা হয়েছে:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s আপনার ব্যবহারকারী নাম এবং পাসওয়ার্ডের জন্য অনুরোধ করছে। সাইটটি বলছে: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s আপনার ব্যবহারকারী নাম এবং পাসওয়ার্ড অনুরোধ করছে।</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..882b2fbab0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-br/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ar bajenn war %1$s a lâr:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Emañ ar proksi %2$s ocʼh azgoulenn un anv arveriad hag ur ger-tremen. Emañ al lecʼhienn o lavarout: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Emañ ar proksi %1$s ocʼh azgoulenn un anv arveriad hag ur ger-tremen.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..3d65bfb52b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-bs/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Stranica pri %1$s kaže:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s zahtijeva korisničko ime i lozinku. Stranica vraća odgovor: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s zahtijeva tvoje korisničko ime i lozinku.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..488d0cf419
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ca/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La pàgina a %1$s diu:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s sol·licita el vostre nom d’usuari i contrasenya. El lloc diu: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s sol·licita el vostre nom d’usuari i contrasenya.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..2054981f69
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cak/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ri ruxaq %1$s nub\'ij:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s nuk\'utuj rub\'i\' winäq chuqa\' jun ewan tzij. Ri ruxaq k\'amaya\'l nub\'ij: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s nuk\'utuj ri rub\'i\' ataqoya\'l chuqa\' ewan atzij.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ceb/strings.xml
new file mode 100644
index 0000000000..33ffd2b3d7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ceb/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ang page sa %1$s ingon:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s nangayo sa imong username ug password. Ang site ingon: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s nangayo sa imong username ug password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..baa85b12a8
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">پەڕە لە %1$s دەڵێت:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s داوای ناوی بەکارهێنەر و وشەی تێپەڕبوون دەکات. ماڵپەڕەکە دەڵێت: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s داوای ناوی بەکارهێنەر و ووشەی تێپەڕبوون دەکات.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..26e36461c0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-co/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Annunziamentu di a pagina %1$s :find in page</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">U situ %2$s richiede u vostru nome d’utilizatore è a vostra parolla d’intesa. U site indica : « %1$s »</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">U situ %1$s richiede u vostru nome d’utilizatore è a vostra parolla d’intesa.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..bc5b5608f0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cs/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Sdělení stránky %1$s:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s požaduje vaše uživatelské jméno a heslo. Sdělení serveru: „%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s požaduje vaše uživatelské jméno a heslo.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..0ab3645f16
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-cy/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Mae tudalen yn %1$s yn dweud:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Mae %2$s yn gofyn am enw defnyddiwr a chyfrinair. Mae’r wefan yn dweud: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Mae %1$s yn gofyn am eich enw defnyddiwr a chyfrinair.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..2e5451caef
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-da/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Siden på %1$s siger:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s beder om dit brugernavn og din adgangskode. Webstedet siger: &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s beder om dit brugernavn og din adgangskode.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..0fcf258a76
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-de/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Die Seite mit der Adresse %1$s meldet:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s verlangt einen Benutzernamen und ein Passwort. Ausgabe der Website: „%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s verlangt einen Benutzernamen und ein Passwort.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..187703d7c9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Bok na %1$s groni:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s pomina wužywarske mě a gronidło. Sedło groni: &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s pomina wašo wužywarske mě a gronidło.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..7376515b82
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-el/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Η σελίδα στο %1$s δηλώνει:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Το %2$s ζητά όνομα χρήστη και κωδικό πρόσβασής. Ο ιστότοπος δηλώνει: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Το %1$s ζητά το όνομα χρήστη και τον κωδικό πρόσβασής σας.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..b70ef57248
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">The page at %1$s says:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s is requesting your username and password. The site says: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s is requesting your username and password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..b70ef57248
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">The page at %1$s says:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s is requesting your username and password. The site says: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s is requesting your username and password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..aaeb343bab
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-eo/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La paĝo ĉe %1$s diras:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s petas vian nomon de uzanto kaj pasvorton. La retejo diras &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s petas vian nomon de uzanto kaj pasvorton.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..8f0dde846d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La página en %1$s dice:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s está pidiendo tu nombre de usuario y contraseña. El sitio dice: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s te está pidiendo tu nombre de usuario y contraseña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..f679763411
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La página en %1$s dice:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s está solicitando tu usuario y contraseña. El sitio dice: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s está solicitando tu usuario y contraseña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..a9ccba99c5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La página en %1$s dice:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s te está pidiendo tu nombre de usuario y contraseña. El sitio dice: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s te está pidiendo tu nombre de usuario y contraseña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..6c3bd9f23c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La página en %1$s dice:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s está solicitando tu nombre de usuario y contraseña. El sitio dice: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s está solicitando tu nombre de usuario y contraseña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..a9ccba99c5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-es/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La página en %1$s dice:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s te está pidiendo tu nombre de usuario y contraseña. El sitio dice: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s te está pidiendo tu nombre de usuario y contraseña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..2efd14bd0d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-et/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Veebileht aadressil %1$s ütleb:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Sait aadressil %2$s nõuab kasutajanime ja parooli. Teade saidilt: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s nõuab kasutajanime ja parooli.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..23cf8239d3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-eu/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s helbideko orriak hau dio:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s guneak erabiltzaile-izen eta pasahitza eskatzen ditu. Guneak hau dio: &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s guneak erabiltzaile-izen eta pasahitza eskatzen ditu.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..ce4b29bd0e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fa/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">صفحهٔ %1$s می‌گوید:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s درخواست نام کاربری و گذرواژهٔ شما را دارد. این پایگاه می‌گوید: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s درخواست نام کاربری و گذرواژهٔ شما را دارد.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ff/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ff/strings.xml
new file mode 100644
index 0000000000..206ab42aa6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ff/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Hello wonngo to %1$s wiyi:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ena naamnii innde kuutoro maa e finnde. Lowre ndee wiyi: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ena naamnii innde kuutoro maa e finnde.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..af33a323c4
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fi/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Sivu osoitteessa %1$s sanoo:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s pyytää käyttäjätunnusta ja salasanaa. Sivusto sanoo: ”%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s pyytää käyttäjätunnusta ja salasanaa.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..d4f313637b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Annonce de la page %1$s :</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Le site %2$s demande votre nom d’utilisateur et votre mot de passe. Le site indique : « %1$s »</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s demande votre nom d’utilisateur et votre mot de passe.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..96aef64c14
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fur/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La pagjine su %1$s e dîs:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s al domande il to non utent e la password. Il sît al dîs: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s al domande il to non utent e la password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..3350940938
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">De side op %1$s meldt:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s freget om jo brûkersnamme en wachtwurd. De website meldt: ‘%1$s’</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s freget om jo brûkersnamme en wachtwurd.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ga-rIE/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ga-rIE/strings.xml
new file mode 100644
index 0000000000..5ff5ac4408
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ga-rIE/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Deir an leathanach ag %1$s:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Tá %2$s ag iarraidh ainm úsáideora agus focal faire uait. Deir an suíomh: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Tá %1$s ag iarraidh ainm úsáideora agus focal faire uait.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..00304632ce
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gd/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Tha an duilleag aig %1$s ag ràdh:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Tha am progsaidh %2$s ag iarraidh ainm-cleachdaiche is facal-faire. Tha an làrach ag ràdh: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Tha %1$s ag iarraidh an ainm-chleachdaiche is an fhacail-fhaire agad.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..2f63376db4
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">A páxina en %1$s di:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s solicita o seu nome de usuario e o contrasinal. O sitio di: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s solicita o seu nome de usuario e o contrasinal.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..0445a456da
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gn/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Pe kuatiarogue %1$s pegua he’i:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ojerure poruhára réra ha avei ñe’ẽñemi. Pe tenda he’i: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ojerure nde poruhára réra ha ñe’ẽñemi.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gu-rIN/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000000..73ee5f15b2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-gu-rIN/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s આગળનું પાનું આમ કહે છે:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s તમારું વપરાશકર્તા નામ અને પાસવર્ડની વિનંતી કરી રહ્યું છે. આ સાઇટ કહે છે: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s તમારા વપરાશકર્તા નામ અને પાસવર્ડની વિનંતી કરી રહ્યું છે.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hi-rIN/strings.xml
new file mode 100644
index 0000000000..99d77afaaa
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hi-rIN/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s पर मौजूद पृष्ठ का कहना है:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s आपके उपयोगकर्ता नाम और पासवर्ड का अनुरोध कर रहा है। साइट का कहना है: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s आपके उपयोगकर्ता नाम और पासवर्ड का अनुरोध कर रहा है।</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hil/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hil/strings.xml
new file mode 100644
index 0000000000..fc19280ac9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hil/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ang pahina sa %1$s nagasiling:</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..3d65bfb52b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Stranica pri %1$s kaže:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s zahtijeva korisničko ime i lozinku. Stranica vraća odgovor: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s zahtijeva tvoje korisničko ime i lozinku.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..9886d5a970
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Strona na %1$s praji:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s žada sej waše wužiwarske mjeno a hesło. Sydło praji: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s sej waše wužiwarske mjeno a hesło žada.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..61f9314eb1
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hu/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Az oldal a(z) %1$s helyen azt mondja:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">A(z) %2$s felhasználónevet és jelszót kér. A webhely üzenete: „%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">A(z) %1$s felhasználónevet és jelszót kér.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..3f5ca0b268
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title"> %1$s-ից էջը հաղորդում է`</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s-ը պահանջում է օգտվողի անուն և գաղտնաբառ: Կայքը հաղորդում է` &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s-ը հարցնում է օգտվողի Ձեր անունը և գաղտնաբառը</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..6b1d1e8d3b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ia/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Le pagina sur %1$s dice:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s requesta tu nomine de usator e contrasigno. Le sito dice: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s requesta tu nomine de usator e contrasigno.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..589964cfea
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-in/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Laman dari %1$s menjelaskan:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s meminta nama pengguna dan sandi anda. Situs ini berkata: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s meminta nama pengguna dan sandi anda.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..afc6c1bccc
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-is/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Síðan %1$s segir:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s er að biðja um notandanafnið þitt og lykilorð. Tilkynningin frá vefsvæðinu er: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s er að biðja um notandanafnið þitt og lykilorð.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..2bb6759963
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-it/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La pagina sul server %1$s riporta:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s richiede un nome utente e una password. Il sito riporta: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s richiede un nome utente e una password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..c07e1eb199
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-iw/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">הדף %1$s אומר:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">השרת %2$s מבקש את שם המשתמש והססמה שלך. מהאתר נמסר: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">השרת %1$s מבקש את שם המשתמש והססמה שלך.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..f04da64533
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ja/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s のページから:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s がユーザー名とパスワードを要求しています。サイトからのメッセージ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s がユーザー名とパスワードを要求しています。</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..b428118f78
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ka/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">გვერდი %1$s გამცნობთ:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ითხოვს მომხმარებლის სახელსა და პაროლს. საიტი გამცნობთ: „%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ითხოვს მომხმარებლის სახელსა და პაროლს.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..bca1aa650f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s betinde aytılıwınsha:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s paydalanıwshı atın hám parolin sorap atır. Sayt aytıwınsha: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s paydalanıwshı atın hám parolin sorap atır.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..92b5287629
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kab/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Asebter deg %1$s yeqqar-d:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s yessutur isem-ik n useqdac akked wawal-ik uffir. Asmel yaqqar: &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s yessutur isem-ik n useqdac akked wawal-ik uffir.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..8776c5afc5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kk/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s адресіндегі бет хабарлайды:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s сайты сіздің пайдаланушы атын мен паролін сұрайды. Сайт айтады: &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s сіздің пайдаланушы атын және паролін сұрап тұр.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..7009b2f611
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Rûpela %1$s’ê dibêje:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s navê bikarhêner û pêborîna te dixwaze. Malper dibêje: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s navê bikarhêner û pêborîna te dixwaze.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kn/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kn/strings.xml
new file mode 100644
index 0000000000..f787624f46
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kn/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s ನಲ್ಲಿರುವ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ಎಂಬ ಪ್ರಾಕ್ಸಿಯು ಒಂದು ಬಳಕೆದಾರ ಪದ ಹಾಗು ಗುಪ್ತಪದಕ್ಕಾಗಿ ಮನವಿ ಸಲ್ಲಿಸಿದೆ. ತಾಣವು ಹೀಗೆ ಹೇಳುತ್ತದೆ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ನಿಮ್ಮ ಬಳಕೆದಾರನ ಹೆಸರು ಮತ್ತು ಪ್ರವೇಶ ಪದ ಕೇಳುತ್ತಿದೆ.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..a7fa3f43ba
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ko/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s 페이지의 메세지:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s가 사용자 이름과 비밀번호를 요청하고 있습니다. 사이트 메시지: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s가 사용자 이름과 비밀번호를 요청하고 있습니다.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kw/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kw/strings.xml
new file mode 100644
index 0000000000..533de3e828
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-kw/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">An folen orth %1$s a lever:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s a bys a\'th hanow devnydhyer ha ger tremena. An wiasva a lever: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s a bys a\'th hanow devnydhyer ha ger tremena.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lij/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lij/strings.xml
new file mode 100644
index 0000000000..60d8ae087c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lij/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">A pagina in %1$s a dixe:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s o domanda o teu nomme utente e paròlla segreta. O scito o dixe: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s o domanda o teu nomme utente e paròlla segreta.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..f6703c74e8
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lo/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">ຫນ້າເວັບທີ່ %1$s ລະບຸວ່າ:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ຕ້ອງການຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານຂອງທ່ານ. ເວັບໄຊທລະບຸວ່າ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ຕ້ອງການຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານຂອງທ່ານ.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..f17c191cdc
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-lt/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Tinklalapis %1$s praneša:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s reikalauja jūsų vardo ir slaptažodžio. Svetainės pranešimas: „%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s reikalauja jūsų vardo iš slaptažodžio.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-mix/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-mix/strings.xml
new file mode 100644
index 0000000000..372b02ea26
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-mix/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Página nu %1$s katyi:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s tsiki sivi tsi tu un se e. Ndaka tu in: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s tsiki sivi tsi tu un se e.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ml/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ml/strings.xml
new file mode 100644
index 0000000000..0728f4572a
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ml/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s ൽ ഉള്ള പേജ് പറയുന്നത്:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ന് നിങ്ങളുടെ ഉപയോക്തൃനാമവും രഹസ്യവാക്കും ആവശ്യമാണ് . സൈറ്റ് പറയുന്നത് : “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s നിങ്ങളുടെ ഉപയോക്തൃനാമവും രഹസ്യവാക്കും ആവശ്യപെടുന്നു.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000000..c7cc6930a9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-mr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s वरील पृष्ठ म्हणते:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s वापरकर्तानाव व पासवर्डसाठी विनंती करत आहे. स्थळ असे म्हणते: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s आपल्या वापरकर्तानाव आणि पासवर्डसाठी विनंती करत आहे.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000000..9d9a02f29c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-my/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s ရှိစာမျက်နှာက -</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s သည်သင်၏သုံးစွဲသူအမည်နှင့်စကားဝှက်ကိုတောင်းနေသည်။ ဆိုဒ်တွင်“%1$s” ဆိုထားသည်။</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s သည်သင်၏သုံးစွဲသူအမည်နှင့်စကားဝှက်ကိုတောင်းနေသည်။</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..ac3004ffc6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Nettsiden på %1$s sier:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ber om brukernavn og passord. Nettstedet sier: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s krever brukernavn og passord.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000000..56135b2712
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ne-rNP/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title"> %1$s मा रहेको पृष्ठले भन्छ:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message"> %2$s ले प्रयोगकर्ता नाम र पासवर्ड अनुरोध गरिरहेको छ। साइट भन्छ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message"> %1$s ले तपाईँको प्रयोगकर्ता नाम र पासवर्ड अनुरोध गरेको छ।</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..71b2ddf0b2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">De pagina op %1$s zegt:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s vraagt om uw gebruikersnaam en wachtwoord. De website zegt: ‘%1$s’</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s vraagt om uw gebruikersnaam en wachtwoord.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..7763857a1f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Nettsida på %1$s seier:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ber om brukarnamn og passord. Nettstaden seier: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s krev brukarnamn og passord.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nv/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nv/strings.xml
new file mode 100644
index 0000000000..e305ee9534
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-nv/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Níłch’i naaltsoos -gi ’ání %1$s:</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..cdf223c0f7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-oc/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Anóncia de la pagina %1$s :</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s demanda un nom d’utilizaire e un senhal. Lo site indica : « %1$s »</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s demanda vòstres nom d’utilizaire e senhal.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-or/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-or/strings.xml
new file mode 100644
index 0000000000..e93ac76cf2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-or/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s ରେ ଥିବା ପୃଷ୍ଠା କହେ:</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..8a6d8fac81
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s ਉੱਤੇ ਸਫ਼ਾ ਦਰਸਾਉਂਦਾ ਹੈ:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਦੀ ਮੰਗ ਕਰ ਰਹੀ ਹੈ। ਸਾਈਟ ਕਹਿੰਦੀ ਹੈ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਦੀ ਮੰਗ ਕਰ ਰਹੀ ਹੈ। </string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..acabc7da8e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">پتے %1$s دے صفحے توں سنیہا:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s تہاڈے ورتنوالے دا ناں تے پاس‌ورڈ دی منگ کر رہی اے۔ ایتھوں سنیہا اے – ”%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s تہاڈے ورتنوالے دا ناں تے پاس‌ورڈ دی منگ کر رہی اے۔</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..8a242ccbd4
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Komunikat ze strony %1$s:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s prosi o podanie nazwy użytkownika i hasła. Komunikat witryny: „%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s prosi o podanie nazwy użytkownika i hasła.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ppl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ppl/strings.xml
new file mode 100644
index 0000000000..8ed3d80af8
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ppl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ne iswat tik %1$s ina:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s metztajtanilia muusuariojtukay wan muichtakataketzalis. Ne sitioj ina: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s metztajtanilia muusuariojtukay wan muichtakataketzalis.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..0378158e27
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">A página em %1$s diz:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s está solicitando seu nome de usuário e senha. O site diz: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s está solicitando seu nome de usuário e senha.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..abac1094bb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">A página %1$s diz:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s está a solicitar o seu nome de utilizador e a palavra-passe. O site diz: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s está a solicitar o seu nome de utilizador e a palavra-passe.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..af664e1e22
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-rm/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">La pagina cun l\'adressa %1$s di:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s dumonda tes num d\'utilisader e pled-clav. La pagina di: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s dumonda tes num d\'utilisader e pled-clav.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ro/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000000..1dfac786f0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ro/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Pagina de la %1$s spune:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s solicită numele de utilizator și parola. Site-ul spune: „%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s solicită numele de utilizator și parola.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..04b5fe508a
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ru/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Страница на %1$s сообщает:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s запрашивает имя пользователя и пароль. Сайт сообщает: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s запрашивает имя пользователя и пароль.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..e16abb8a6d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sat/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s ᱴᱷᱮᱱ ᱢᱮᱱᱟᱜ ᱥᱟᱦᱴᱟ ᱢᱮᱱᱮᱜᱼᱟᱭ:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ᱫᱚ ᱟᱢᱟᱜ ᱭᱩᱡᱟᱹᱨᱱᱮᱢ ᱟᱨ ᱯᱟᱥᱥᱣᱟᱹᱨᱰ ᱠᱷᱚᱡ ᱠᱟᱱᱟᱭ ᱾ ᱥᱟᱭᱴ ᱮ ᱢᱮᱱᱮᱜᱼᱟᱭ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ᱫᱚ ᱟᱢᱟᱜ ᱭᱩᱡᱟᱹᱨᱱᱮᱢ ᱟᱨ ᱯᱟᱥᱣᱟᱹᱨᱰ ᱠᱷᱚᱡ ᱠᱟᱱᱟᱭ ᱾</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..8088687053
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sc/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Sa pàgina in %1$s narat:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s rechedet su nòmine tuo e sa crae. Su situ narat: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s rechedet su nòmine tuo e sa crae.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..2cdf4bed5e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-si/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s හි පිටුව මෙසේ පවසයි:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ඔබගේ පරිශීලක නාමය සහ මුරපදය ඉල්ලා සිටියි. අඩවිය පවසන්නේ: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ඔබගේ පරිශීලක නාමය සහ මුරපදය ඉල්ලා සිටියි.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..df5bf93d16
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sk/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Oznámenie stránky %1$s:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s požaduje zadanie vášho používateľského mena a hesla. Oznámenie stránky: „%1$s“</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s požaduje zadanie vášho používateľského mena a hesla.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..f5b21bf699
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-skr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s تے ورقہ آہدے:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ورتݨ ناں تے پاسورڈ دی ارداس کریندا پئے۔ سائٹ آہدی ہے: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s تہاݙے ورتݨ ناں تے پاسورڈ دی ارداس کریندا پئے۔</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..8e839b6f40
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Stran na %1$s sporoča:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s zahteva uporabniško ime in geslo. Sporočilo strani: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s zahteva uporabniško ime in geslo.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..ba788eb520
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sq/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Faqja te %1$s thotë:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s po kërkon emrin tuaj të përdoruesit dhe fjalëkalimin. Sajti thotë: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s po kërkon emrin tuaj të përdoruesit dhe fjalëkalimin.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..f79607c7c3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Порука са странице %1$s гласи:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s захтева ваше корисничко име и лозинку. Страница поручује: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s захтева ваше корисничко име и лозинку.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..f3256f67c6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-su/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Kaca di %1$s nyebutkeun:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ménta sandiasma jeung kecap konci anjeun. Situsna nyebutkeun: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ménta sandiasma jeung kecap konci anjeun.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..f95ae52bd7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Sidan på %1$s säger:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s efterfrågar ditt användarnamn och lösenord. Webbplatsen säger: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s efterfrågar ditt användarnamn och lösenord.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-szl/strings.xml
new file mode 100644
index 0000000000..8d445f4a01
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-szl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Strōna %1$s dowo znać:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s prosi ô twoje miano używocza i hasło. Kōmunikat strōny: „%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s prosi ô twoje miano używocza i hasło.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000000..a9878f95c9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ta/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">பக்கம் %1$s இல் சொல்வது:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s உங்கள் பயனர்பெயர் மற்றும் கடவுச்சொல்லைக் கோருகிறது. தளம் கூறுகிறது: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s உங்கள் பயனர்பெயர் மற்றும் கடவுச்சொல்லைக் கோருகிறது.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-te/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000000..387402a8ba
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-te/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s వద్ద పేజీ అంటోంది:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s మీ వాడుకరి పేరును, సంకేతపదాన్ని అడుగుతోంది. సైటు ఇలా అంటుోంది: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s మీ వాడుకరి పేరును, సంకేతపదాన్ని అడుగుతోంది.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..4d5d623a07
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tg/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Саҳифа дар %1$s хабар медиҳад:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s номи корбар ва ниҳонвожаи шуморо дархост мекунад. Сомона хабар медиҳад: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s номи корбар ва ниҳонвожаи шуморо дархост мекунад.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..96dfa57c15
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-th/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">หน้าที่ %1$s ระบุว่า:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s กำลังขอชื่อผู้ใช้และรหัสผ่านของคุณ ไซต์ระบุว่า: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s กำลังขอชื่อผู้ใช้และรหัสผ่านของคุณ</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..520af991f2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tl/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ang pahina sa %1$s ay nagsasabi ng:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ay humihingi ng iyong username at password. Ang sabi ng site ay: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Hinihingi ng %1$s ang iyong username at password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tok/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tok/strings.xml
new file mode 100644
index 0000000000..3c3cc21d77
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tok/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">lipu %1$s li toki:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s li wile e nimi sina e nimi open sina. lipu li toki e ni: &quot;%1$s&quot;</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s li wile e nimi sina e nimi open sina.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..e5011323c2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tr/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s sayfası diyor ki:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s kullanıcı adı ve parolanızı istiyor. Site diyor ki: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s kullanıcı adı ve parolanızı istiyor.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..93075f89dd
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-trs/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Pajinâ nū riña %1$s taj:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s nachin\' man si yuguît ngà da\'nga\' huì arâj sunt. Sa tāj sitiô nan huin: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s nachin\' man si yuguît ngà da\'nga\' huì arâj sunt.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..8abc7cdffc
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tt/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s сәхифәсеннән хәбәр:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s кулланучы исемен һәм серсүзен сорый. Сайт хәбәре: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s кулланучы исемен һәм серсүзен сорый.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tzm/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tzm/strings.xml
new file mode 100644
index 0000000000..6400a304ee
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-tzm/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Da tettini tasna g %1$s:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">Issutur-ak %2$s ism d tguri n uzray-nnek. Da ittini usit: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">Issutur-ak %1$s isem d tguri n uzray-nnek.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..67daade49d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ug/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">بەت %1$s تە دېيىلگىنى:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ئىشلەتكۈچى ئىسمى بىلەن ئىمنى تەلەپ قىلىۋاتىدۇ. تور بېكەتتە دېيىلگىنى: «%1$s»</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ئىشلەتكۈچى ئىسمى بىلەن ئىمنى تەلەپ قىلىۋاتىدۇ.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..876a66cc03
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-uk/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Сторінка на %1$s повідомляє:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s запитує ваше ім’я користувача і пароль. Повідомлення сайту: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s запитує ім’я користувача і пароль.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000000..4af1973108
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-ur/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s پر صفحہ کہتا ہے:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s صارف کا نام اور پاسورڈ کی درخواست کر رہا ہے۔ سائٹ کہتی ہے: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s صارف کا نام اور پاسورڈ کی درخواست کر رہا ہے۔</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..0e3c13ca2c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-uz/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s sahifasi xabari:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s login va parolingizni soʻrayapti. Sayt xabari: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s login va parolingizni soʻrayapti.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-vec/strings.xml
new file mode 100644
index 0000000000..9f85621706
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-vec/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ƚa pàgina so’l server %1$s ƚa riporta:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s el dimanda on nòme utente e na password. El sito el riporta: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s dimanda on nòme utente e na password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..573499c584
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-vi/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Trang %1$s cho biết:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s yêu cầu tên người dùng và mật khẩu của bạn. Trang web thông báo: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s yêu cầu tên người dùng và mật khẩu của bạn.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-yo/strings.xml
new file mode 100644
index 0000000000..5676053cd2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-yo/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">Ojú-ìwé %1$s sọ pé:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s ń béèrè orúkọ ìṣàmúlò àti kóòdù rẹ. Ìkànnì náà sọ pé: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s ń béère orúkọ ìwọlé àti pásíwọọ̀dù </string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..52a4d15cfb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">域名为 %1$s 的页面提示:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s 要求您输入用户名和密码。该网站提示:“%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s 要求您输入用户名和密码。</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..3c2573af95
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">%1$s 這一頁說:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the realm, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s 要求您輸入帳號密碼。此網站說:「%1$s」</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s 要求您輸入帳號與密碼。</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/values/strings.xml b/mobile/android/android-components/components/browser/engine-system/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..7e80343142
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/values/strings.xml
@@ -0,0 +1,13 @@
+<?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>
+ <!-- Text for the title of an alert dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_alert_title">The page at %1$s says:</string>
+ <!-- Text for the message of an auth dialog displayed by a web page.
+ %1$s will be replaced by the hostname or a description of the protected area/site, %2$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_message">%2$s is requesting your username and password. The site says: “%1$s”</string>
+ <!-- Text for the message of an auth dialog displayed by a web page. %1$s will be replaced with the URL of the current page (displaying the dialog). -->
+ <string name="mozac_browser_engine_system_auth_no_realm_message">%1$s is requesting your username and password.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/NestedWebViewTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/NestedWebViewTest.kt
new file mode 100644
index 0000000000..e822084cb3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/NestedWebViewTest.kt
@@ -0,0 +1,165 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.view.MotionEvent.ACTION_CANCEL
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_UP
+import androidx.core.view.NestedScrollingChildHelper
+import androidx.core.view.ViewCompat.SCROLL_AXIS_VERTICAL
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.mockMotionEvent
+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.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class NestedWebViewTest {
+
+ @Test
+ fun `NestedWebView must delegate NestedScrollingChild implementation to childHelper`() {
+ val nestedWebView = NestedWebView(testContext)
+ val mockChildHelper: NestedScrollingChildHelper = mock()
+ nestedWebView.childHelper = mockChildHelper
+
+ doReturn(true).`when`(mockChildHelper).isNestedScrollingEnabled
+ doReturn(true).`when`(mockChildHelper).hasNestedScrollingParent()
+
+ nestedWebView.isNestedScrollingEnabled = true
+ verify(mockChildHelper).isNestedScrollingEnabled = true
+
+ assertTrue(nestedWebView.isNestedScrollingEnabled)
+ verify(mockChildHelper).isNestedScrollingEnabled
+
+ nestedWebView.startNestedScroll(1)
+ verify(mockChildHelper).startNestedScroll(1)
+
+ nestedWebView.stopNestedScroll()
+ verify(mockChildHelper).stopNestedScroll()
+
+ assertTrue(nestedWebView.hasNestedScrollingParent())
+ verify(mockChildHelper).hasNestedScrollingParent()
+
+ nestedWebView.dispatchNestedScroll(0, 0, 0, 0, null)
+ verify(mockChildHelper).dispatchNestedScroll(0, 0, 0, 0, null)
+
+ nestedWebView.dispatchNestedPreScroll(0, 0, null, null)
+ verify(mockChildHelper).dispatchNestedPreScroll(0, 0, null, null)
+
+ nestedWebView.dispatchNestedFling(0f, 0f, true)
+ verify(mockChildHelper).dispatchNestedFling(0f, 0f, true)
+
+ nestedWebView.dispatchNestedPreFling(0f, 0f)
+ verify(mockChildHelper).dispatchNestedPreFling(0f, 0f)
+ }
+
+ @Test
+ fun `verify onTouchEvent when ACTION_DOWN`() {
+ val nestedWebView = NestedWebView(testContext)
+ val mockChildHelper: NestedScrollingChildHelper = mock()
+ nestedWebView.childHelper = mockChildHelper
+
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_DOWN))
+ verify(mockChildHelper).startNestedScroll(SCROLL_AXIS_VERTICAL)
+ }
+
+ @Test
+ fun `verify onTouchEvent when ACTION_MOVE`() {
+ val nestedWebView = NestedWebView(testContext)
+ val mockChildHelper: NestedScrollingChildHelper = mock()
+ nestedWebView.childHelper = mockChildHelper
+
+ doReturn(true).`when`(mockChildHelper).dispatchNestedPreScroll(
+ anyInt(),
+ anyInt(),
+ any(),
+ any(),
+ )
+
+ nestedWebView.scrollOffset[0] = 1
+ nestedWebView.scrollOffset[1] = 2
+
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_MOVE, y = 10f))
+ assertEquals(nestedWebView.nestedOffsetY, 2)
+ assertEquals(nestedWebView.lastY, 8)
+
+ doReturn(true).`when`(mockChildHelper).dispatchNestedScroll(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ any(),
+ )
+
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_MOVE, y = 10f))
+ assertEquals(nestedWebView.nestedOffsetY, 6)
+ assertEquals(nestedWebView.lastY, 6)
+ }
+
+ @Test
+ fun `verify onTouchEvent when ACTION_UP or ACTION_CANCEL`() {
+ val nestedWebView = NestedWebView(testContext)
+ val mockChildHelper: NestedScrollingChildHelper = mock()
+ nestedWebView.childHelper = mockChildHelper
+
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_UP))
+ verify(mockChildHelper).stopNestedScroll()
+
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_CANCEL))
+ verify(mockChildHelper, times(2)).stopNestedScroll()
+ }
+
+ @Test
+ fun `GIVEN NestedWebView WHEN a new instance is created THEN a properly configured InputResultDetail is created`() {
+ val nestedWebView = NestedWebView(testContext)
+
+ assertTrue(nestedWebView.inputResultDetail.isTouchHandlingUnknown())
+ assertFalse(nestedWebView.inputResultDetail.canScrollToLeft())
+ assertFalse(nestedWebView.inputResultDetail.canScrollToTop())
+ assertFalse(nestedWebView.inputResultDetail.canScrollToRight())
+ assertFalse(nestedWebView.inputResultDetail.canScrollToBottom())
+ assertFalse(nestedWebView.inputResultDetail.canOverscrollLeft())
+ assertFalse(nestedWebView.inputResultDetail.canOverscrollTop())
+ assertFalse(nestedWebView.inputResultDetail.canOverscrollRight())
+ assertFalse(nestedWebView.inputResultDetail.canOverscrollBottom())
+ }
+
+ @Test
+ fun `GIVEN NestedWebView WHEN onTouchEvent is called THEN updateInputResult is called with the result of whether the touch is handled or not`() {
+ val nestedWebView = spy(NestedWebView(testContext))
+
+ doReturn(true).`when`(nestedWebView).callSuperOnTouchEvent(any())
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_DOWN))
+ verify(nestedWebView).updateInputResult(true)
+
+ doReturn(false).`when`(nestedWebView).callSuperOnTouchEvent(any())
+ nestedWebView.onTouchEvent(mockMotionEvent(ACTION_DOWN))
+ verify(nestedWebView).updateInputResult(false)
+ }
+
+ @Test
+ fun `GIVEN an instance of InputResultDetail WHEN updateInputResult called THEN it sets whether the touch was handled`() {
+ val nestedWebView = NestedWebView(testContext)
+
+ assertTrue(nestedWebView.inputResultDetail.isTouchHandlingUnknown())
+
+ nestedWebView.updateInputResult(true)
+ assertTrue(nestedWebView.inputResultDetail.isTouchHandledByBrowser())
+
+ nestedWebView.updateInputResult(false)
+ assertTrue(nestedWebView.inputResultDetail.isTouchUnhandled())
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionStateTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionStateTest.kt
new file mode 100644
index 0000000000..a3aafae50e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionStateTest.kt
@@ -0,0 +1,138 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.os.Bundle
+import android.util.JsonReader
+import android.util.JsonWriter
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.json.JSONArray
+import org.json.JSONObject
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.ByteArrayOutputStream
+
+@RunWith(AndroidJUnit4::class)
+class SystemEngineSessionStateTest {
+ @Test
+ fun fromJSON() {
+ val json = JSONObject().apply {
+ put("k0", "v0")
+ put("k1", 1)
+ put("k2", true)
+ put("k3", 5.0)
+ put("k4", 1.0f)
+ put("k5", JSONArray(listOf(1, 2, 3)))
+ }
+
+ val state = SystemEngineSessionState.fromJSON(json)
+ val bundle = state.bundle!!
+
+ assertEquals(5, bundle.size())
+
+ assertTrue(bundle.containsKey("k0"))
+ assertTrue(bundle.containsKey("k1"))
+ assertTrue(bundle.containsKey("k2"))
+ assertTrue(bundle.containsKey("k3"))
+ assertTrue(bundle.containsKey("k4"))
+
+ assertEquals("v0", bundle.getString("k0"))
+ assertEquals(1, bundle.getInt("k1"))
+ assertEquals(true, bundle.getBoolean("k2"))
+ assertEquals(5.0, bundle.getDouble("k3"), 0.0)
+ assertEquals(1.0f, bundle.getFloat("k4"))
+ }
+
+ @Test
+ fun writeToAndFromJSON() {
+ val state = SystemEngineSessionState(
+ Bundle().apply {
+ putString("k0", "v0")
+ putInt("k1", 1)
+ putBoolean("k2", true)
+ putStringArrayList("k3", ArrayList<String>(listOf("Hello", "World")))
+ putDouble("k4", 5.0)
+ putFloat("k5", 1.0f)
+ putFloat("k6", 42.25f)
+ putDouble("k7", 23.23)
+ },
+ )
+
+ val outputStream = ByteArrayOutputStream()
+ state.writeTo(JsonWriter(outputStream.writer()))
+
+ val bundle = SystemEngineSessionState.fromJSON(
+ JSONObject(outputStream.toString()),
+ ).bundle
+
+ assertNotNull(bundle!!)
+
+ assertEquals(7, bundle.size())
+
+ assertTrue(bundle.containsKey("k0"))
+ assertTrue(bundle.containsKey("k1"))
+ assertTrue(bundle.containsKey("k2"))
+ assertFalse(bundle.containsKey("k3"))
+ assertTrue(bundle.containsKey("k4"))
+ assertTrue(bundle.containsKey("k5"))
+ assertTrue(bundle.containsKey("k6"))
+ assertTrue(bundle.containsKey("k7"))
+
+ assertEquals("v0", bundle.getString("k0"))
+ assertEquals(1, bundle.getInt("k1"))
+ assertEquals(true, bundle.getBoolean("k2"))
+ assertEquals(5.0, bundle.getDouble("k4"), 0.0)
+ assertEquals(1.0, bundle.getDouble("k5"), 0.0)
+ assertEquals(42.25, bundle.getDouble("k6"), 0.0)
+ assertEquals(23.23, bundle.getDouble("k7"), 0.0)
+ }
+
+ @Test
+ fun writeToAndReadFrom() {
+ val state = SystemEngineSessionState(
+ Bundle().apply {
+ putString("k0", "v0")
+ putInt("k1", 1)
+ putBoolean("k2", true)
+ putStringArrayList("k3", ArrayList<String>(listOf("Hello", "World")))
+ putDouble("k4", 5.0)
+ putFloat("k5", 1.0f)
+ putFloat("k6", 42.25f)
+ putDouble("k7", 23.23)
+ },
+ )
+
+ val outputStream = ByteArrayOutputStream()
+ state.writeTo(JsonWriter(outputStream.writer()))
+
+ val reader = JsonReader(outputStream.toString().reader())
+ val bundle = SystemEngineSessionState.from(reader).bundle
+
+ assertNotNull(bundle!!)
+
+ assertEquals(7, bundle.size())
+
+ assertTrue(bundle.containsKey("k0"))
+ assertTrue(bundle.containsKey("k1"))
+ assertTrue(bundle.containsKey("k2"))
+ assertFalse(bundle.containsKey("k3"))
+ assertTrue(bundle.containsKey("k4"))
+ assertTrue(bundle.containsKey("k5"))
+ assertTrue(bundle.containsKey("k6"))
+ assertTrue(bundle.containsKey("k7"))
+
+ assertEquals("v0", bundle.getString("k0"))
+ assertEquals(1.0, bundle.getDouble("k1"), 0.0) // We only see token "number", so we have to read a double and can't know that this was an int.
+ assertEquals(true, bundle.getBoolean("k2"))
+ assertEquals(5.0, bundle.getDouble("k4"), 0.0)
+ assertEquals(1.0, bundle.getDouble("k5"), 0.0)
+ assertEquals(42.25, bundle.getDouble("k6"), 0.0)
+ assertEquals(23.23, bundle.getDouble("k7"), 0.0)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionTest.kt
new file mode 100644
index 0000000000..4f56d9c467
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineSessionTest.kt
@@ -0,0 +1,1238 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.content.Context
+import android.net.Uri
+import android.os.Bundle
+import android.webkit.WebChromeClient
+import android.webkit.WebResourceRequest
+import android.webkit.WebSettings
+import android.webkit.WebStorage
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.webkit.WebViewDatabase
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import mozilla.components.browser.engine.system.matcher.UrlMatcher
+import mozilla.components.browser.errorpages.ErrorType
+import mozilla.components.concept.engine.DefaultSettings
+import mozilla.components.concept.engine.Engine.BrowsingData
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.request.RequestInterceptor
+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 mozilla.components.support.test.whenever
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mockito
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.doThrow
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.robolectric.Shadows.shadowOf
+import org.robolectric.annotation.LooperMode
+import java.lang.reflect.Modifier
+import org.mockito.ArgumentMatchers.any as mockitoAny
+
+@Suppress("DEPRECATION") // Suppress deprecation for LooperMode.Mode.LEGACY
+@RunWith(AndroidJUnit4::class)
+@LooperMode(LooperMode.Mode.LEGACY)
+class SystemEngineSessionTest {
+
+ @Test
+ fun webChromeClientNotifiesObservers() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observedProgress = 0
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onProgress(progress: Int) { observedProgress = progress }
+ },
+ )
+
+ engineSession.webView.webChromeClient!!.onProgressChanged(null, 100)
+ assertEquals(100, observedProgress)
+ }
+
+ @Test
+ fun loadUrl() {
+ var loadedUrl: String? = null
+ var loadHeaders: Map<String, String>? = null
+
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = spy(
+ object : WebView(testContext) {
+ override fun loadUrl(url: String, additionalHttpHeaders: MutableMap<String, String>) {
+ loadedUrl = url
+ loadHeaders = additionalHttpHeaders
+ }
+ },
+ )
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.webView = webView
+
+ engineSession.loadUrl("")
+ verify(webView, never()).loadUrl(anyString())
+
+ engineSession.loadUrl("http://mozilla.org")
+ verify(webView).loadUrl(eq("http://mozilla.org"), any())
+
+ assertEquals("http://mozilla.org", loadedUrl)
+
+ assertNotNull(loadHeaders)
+ assertEquals(1, loadHeaders!!.size)
+ assertTrue(loadHeaders!!.containsKey("X-Requested-With"))
+ assertEquals("", loadHeaders!!["X-Requested-With"])
+
+ val extraHeaders = mapOf("X-Extra-Header" to "true")
+ engineSession.loadUrl("http://mozilla.org", additionalHeaders = extraHeaders)
+ assertNotNull(loadHeaders)
+ assertEquals(2, loadHeaders!!.size)
+ assertTrue(loadHeaders!!.containsKey("X-Extra-Header"))
+ assertEquals("true", loadHeaders!!["X-Extra-Header"])
+ }
+
+ @Test
+ fun `WHEN URL is loaded THEN URL load observer is notified`() {
+ var onLoadUrlTriggered = false
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onLoadUrl() {
+ onLoadUrlTriggered = true
+ }
+ },
+ )
+ engineSession.webView = webView
+
+ engineSession.loadUrl("http://mozilla.org")
+
+ assertTrue(onLoadUrlTriggered)
+ }
+
+ @Test
+ fun loadData() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.loadData("<html><body>Hello!</body></html>")
+ verify(webView, never()).loadData(anyString(), eq("text/html"), eq("UTF-8"))
+
+ engineSession.webView = webView
+
+ engineSession.loadData("<html><body>Hello!</body></html>")
+ verify(webView).loadData(eq("<html><body>Hello!</body></html>"), eq("text/html"), eq("UTF-8"))
+
+ engineSession.loadData("Hello!", "text/plain", "UTF-8")
+ verify(webView).loadData(eq("Hello!"), eq("text/plain"), eq("UTF-8"))
+
+ engineSession.loadData("ahr0cdovl21vemlsbgeub3jn==", "text/plain", "base64")
+ verify(webView).loadData(eq("ahr0cdovl21vemlsbgeub3jn=="), eq("text/plain"), eq("base64"))
+ }
+
+ @Test
+ fun `WHEN data is loaded THEN data load observer is notified`() {
+ var onLoadDataTriggered = false
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onLoadData() {
+ onLoadDataTriggered = true
+ }
+ },
+ )
+ engineSession.webView = webView
+
+ engineSession.loadData("<html><body/></html>")
+
+ assertTrue(onLoadDataTriggered)
+ }
+
+ @Test
+ fun stopLoading() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.stopLoading()
+ verify(webView, never()).stopLoading()
+
+ engineSession.webView = webView
+
+ engineSession.stopLoading()
+ verify(webView).stopLoading()
+ }
+
+ @Test
+ fun reload() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ engineSession.reload()
+ verify(webView, never()).reload()
+
+ engineSession.webView = webView
+
+ engineSession.reload()
+ verify(webView).reload()
+ }
+
+ @Test
+ fun goBack() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.goBack()
+ verify(webView, never()).goBack()
+
+ engineSession.webView = webView
+
+ engineSession.goBack()
+ verify(webView).goBack()
+ }
+
+ @Test
+ fun goForward() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.goForward()
+ verify(webView, never()).goForward()
+
+ engineSession.webView = webView
+
+ engineSession.goForward()
+ verify(webView).goForward()
+ }
+
+ @Test
+ fun `GIVEN forward navigation is possible WHEN navigating forward THEN forward navigation observer is notified`() {
+ var observedOnNavigateForward = false
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ whenever(webView.canGoForward()).thenReturn(true)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onNavigateForward() {
+ observedOnNavigateForward = true
+ }
+ },
+ )
+ engineSession.webView = webView
+
+ engineSession.goForward()
+
+ assertTrue(observedOnNavigateForward)
+ }
+
+ @Test
+ fun `GIVEN forward navigation is not possible WHEN navigating forward THEN forward navigation observer is not notified`() {
+ var observedOnNavigateForward = false
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ whenever(webView.canGoForward()).thenReturn(false)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onNavigateForward() {
+ observedOnNavigateForward = true
+ }
+ },
+ )
+ engineSession.webView = webView
+
+ engineSession.goForward()
+
+ assertFalse(observedOnNavigateForward)
+ }
+
+ @Test
+ fun goToHistoryIndex() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ whenever(webView.copyBackForwardList()).thenReturn(mock())
+ engineSession.goToHistoryIndex(0)
+ verify(webView, never()).goBackOrForward(0)
+
+ engineSession.webView = webView
+
+ engineSession.goToHistoryIndex(0)
+ verify(webView).goBackOrForward(0)
+ }
+
+ @Test
+ fun `WHEN navigating to history index THEN the observer is notified`() {
+ var onGotoHistoryIndexTriggered = false
+ val engineSession = spy(SystemEngineSession(testContext))
+ val settings = mock<WebSettings>()
+ val webView = mock<WebView>() {
+ whenever(this.settings).thenReturn(settings)
+ whenever(copyBackForwardList()).thenReturn(mock())
+ }
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onGotoHistoryIndex() {
+ onGotoHistoryIndexTriggered = true
+ }
+ },
+ )
+ engineSession.webView = webView
+
+ engineSession.goToHistoryIndex(0)
+
+ assertTrue(onGotoHistoryIndexTriggered)
+ }
+
+ @Test
+ fun restoreState() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = spy(WebView(testContext))
+
+ try {
+ engineSession.restoreState(mock())
+ fail("Expected IllegalArgumentException")
+ } catch (e: IllegalArgumentException) {}
+ assertFalse(engineSession.restoreState(SystemEngineSessionState(Bundle())))
+ verify(webView, never()).restoreState(mockitoAny(Bundle::class.java))
+
+ engineSession.webView = webView
+ engineSession.webView.loadUrl("http://example.com")
+
+ // update the WebView's history async.
+ shadowOf(webView).pushEntryToHistory("http://example.com")
+
+ val bundle = Bundle()
+ webView.saveState(bundle)
+ val state = SystemEngineSessionState(bundle)
+
+ assertTrue(engineSession.restoreState(state))
+ verify(webView).restoreState(bundle)
+ }
+
+ @ExperimentalCoroutinesApi
+ @Test
+ fun enableTrackingProtection() = runTest {
+ SystemEngineView.URL_MATCHER = UrlMatcher(arrayOf(""))
+
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+
+ whenever(webView.settings).thenReturn(settings)
+ whenever(webView.context).thenReturn(testContext)
+
+ engineSession.webView = webView
+
+ var enabledObserved: Boolean? = null
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onTrackerBlockingEnabledChange(enabled: Boolean) {
+ enabledObserved = enabled
+ }
+ },
+ )
+
+ assertNull(engineSession.trackingProtectionPolicy)
+ engineSession.updateTrackingProtection()
+ assertEquals(
+ EngineSession.TrackingProtectionPolicy.strict(),
+ engineSession.trackingProtectionPolicy,
+ )
+ assertNotNull(enabledObserved)
+ assertTrue(enabledObserved as Boolean)
+ }
+
+ @Test
+ fun disableTrackingProtection() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ var enabledObserved: Boolean? = null
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onTrackerBlockingEnabledChange(enabled: Boolean) {
+ enabledObserved = enabled
+ }
+ },
+ )
+
+ engineSession.trackingProtectionPolicy = EngineSession.TrackingProtectionPolicy.strict()
+
+ engineSession.disableTrackingProtection()
+ assertNull(engineSession.trackingProtectionPolicy)
+ assertNotNull(enabledObserved)
+ assertFalse(enabledObserved as Boolean)
+ }
+
+ @Test
+ fun initSettings() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ assertNotNull(engineSession.internalSettings)
+
+ val webViewSettings = mock<WebSettings>()
+ whenever(webViewSettings.displayZoomControls).thenReturn(true)
+ whenever(webViewSettings.allowContentAccess).thenReturn(true)
+ whenever(webViewSettings.allowFileAccess).thenReturn(true)
+ whenever(webViewSettings.mediaPlaybackRequiresUserGesture).thenReturn(true)
+ whenever(webViewSettings.supportMultipleWindows()).thenReturn(false)
+
+ val webView = mock<WebView>()
+ whenever(webView.context).thenReturn(testContext)
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webView.isVerticalScrollBarEnabled).thenReturn(true)
+ whenever(webView.isHorizontalScrollBarEnabled).thenReturn(true)
+ engineSession.webView = webView
+
+ assertFalse(engineSession.settings.javascriptEnabled)
+ engineSession.settings.javascriptEnabled = true
+ verify(webViewSettings).javaScriptEnabled = true
+
+ assertFalse(engineSession.settings.domStorageEnabled)
+ engineSession.settings.domStorageEnabled = true
+ verify(webViewSettings).domStorageEnabled = true
+
+ assertNull(engineSession.settings.userAgentString)
+ engineSession.settings.userAgentString = "userAgent"
+ verify(webViewSettings).userAgentString = "userAgent"
+
+ assertTrue(engineSession.settings.mediaPlaybackRequiresUserGesture)
+ engineSession.settings.mediaPlaybackRequiresUserGesture = false
+ verify(webViewSettings).mediaPlaybackRequiresUserGesture = false
+
+ assertFalse(engineSession.settings.javaScriptCanOpenWindowsAutomatically)
+ engineSession.settings.javaScriptCanOpenWindowsAutomatically = true
+ verify(webViewSettings).javaScriptCanOpenWindowsAutomatically = true
+
+ assertTrue(engineSession.settings.displayZoomControls)
+ engineSession.settings.javaScriptCanOpenWindowsAutomatically = false
+ verify(webViewSettings).javaScriptCanOpenWindowsAutomatically = false
+
+ assertFalse(engineSession.settings.loadWithOverviewMode)
+ engineSession.settings.loadWithOverviewMode = true
+ verify(webViewSettings).loadWithOverviewMode = true
+
+ assertNull(engineSession.settings.useWideViewPort)
+ engineSession.settings.useWideViewPort = false
+ verify(webViewSettings).useWideViewPort = false
+
+ assertTrue(engineSession.settings.allowContentAccess)
+ engineSession.settings.allowContentAccess = false
+ verify(webViewSettings).allowContentAccess = false
+
+ assertTrue(engineSession.settings.allowFileAccess)
+ engineSession.settings.allowFileAccess = false
+ verify(webViewSettings).allowFileAccess = false
+
+ assertFalse(engineSession.settings.allowUniversalAccessFromFileURLs)
+ engineSession.settings.allowUniversalAccessFromFileURLs = true
+ verify(webViewSettings).allowUniversalAccessFromFileURLs = true
+
+ assertFalse(engineSession.settings.allowFileAccessFromFileURLs)
+ engineSession.settings.allowFileAccessFromFileURLs = true
+ verify(webViewSettings).allowFileAccessFromFileURLs = true
+
+ assertTrue(engineSession.settings.verticalScrollBarEnabled)
+ engineSession.settings.verticalScrollBarEnabled = false
+ verify(webView).isVerticalScrollBarEnabled = false
+
+ assertTrue(engineSession.settings.horizontalScrollBarEnabled)
+ engineSession.settings.horizontalScrollBarEnabled = false
+ verify(webView).isHorizontalScrollBarEnabled = false
+
+ assertFalse(engineSession.settings.supportMultipleWindows)
+ engineSession.settings.supportMultipleWindows = true
+ verify(webViewSettings).setSupportMultipleWindows(true)
+
+ assertTrue(engineSession.webFontsEnabled)
+ assertTrue(engineSession.settings.webFontsEnabled)
+ engineSession.settings.webFontsEnabled = false
+ assertFalse(engineSession.webFontsEnabled)
+ assertFalse(engineSession.settings.webFontsEnabled)
+
+ assertNull(engineSession.settings.trackingProtectionPolicy)
+ engineSession.settings.trackingProtectionPolicy =
+ EngineSession.TrackingProtectionPolicy.strict()
+ verify(engineSession).updateTrackingProtection(EngineSession.TrackingProtectionPolicy.strict())
+
+ engineSession.settings.trackingProtectionPolicy = null
+ verify(engineSession).disableTrackingProtection()
+
+ verify(webViewSettings).cacheMode = WebSettings.LOAD_NO_CACHE
+ verify(webViewSettings).setGeolocationEnabled(false)
+ verify(webViewSettings).databaseEnabled = false
+ verify(webViewSettings).savePassword = false
+ verify(webViewSettings).saveFormData = false
+ verify(webViewSettings).builtInZoomControls = true
+ verify(webViewSettings).displayZoomControls = false
+ }
+
+ @Test
+ fun withProvidedDefaultSettings() {
+ val defaultSettings = DefaultSettings(
+ javascriptEnabled = false,
+ domStorageEnabled = false,
+ webFontsEnabled = false,
+ trackingProtectionPolicy = EngineSession.TrackingProtectionPolicy.strict(),
+ userAgentString = "userAgent",
+ mediaPlaybackRequiresUserGesture = false,
+ javaScriptCanOpenWindowsAutomatically = true,
+ displayZoomControls = true,
+ loadWithOverviewMode = true,
+ useWideViewPort = true,
+ supportMultipleWindows = true,
+ )
+ val engineSession = spy(SystemEngineSession(testContext, defaultSettings))
+
+ val webView = mock<WebView>()
+ whenever(webView.context).thenReturn(testContext)
+
+ val webViewSettings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(webViewSettings)
+
+ engineSession.webView = webView
+
+ verify(webViewSettings).domStorageEnabled = false
+ verify(webViewSettings).javaScriptEnabled = false
+ verify(webViewSettings).userAgentString = "userAgent"
+ verify(webViewSettings).mediaPlaybackRequiresUserGesture = false
+ verify(webViewSettings).javaScriptCanOpenWindowsAutomatically = true
+ verify(webViewSettings).displayZoomControls = true
+ verify(webViewSettings).loadWithOverviewMode = true
+ verify(webViewSettings).useWideViewPort = true
+ verify(webViewSettings).setSupportMultipleWindows(true)
+ verify(engineSession).updateTrackingProtection(EngineSession.TrackingProtectionPolicy.strict())
+ assertFalse(engineSession.webFontsEnabled)
+ }
+
+ @Test
+ fun sharedFieldsAreVolatile() {
+ val internalSettings = SystemEngineSession::class.java.getDeclaredField("internalSettings")
+ val webFontsEnabledField = SystemEngineSession::class.java.getDeclaredField("webFontsEnabled")
+ val trackingProtectionField = SystemEngineSession::class.java.getDeclaredField("trackingProtectionPolicy")
+ val historyTrackingDelegate = SystemEngineSession::class.java.getDeclaredField("historyTrackingDelegate")
+ val fullScreenCallback = SystemEngineSession::class.java.getDeclaredField("fullScreenCallback")
+ val currentUrl = SystemEngineSession::class.java.getDeclaredField("currentUrl")
+ val webView = SystemEngineSession::class.java.getDeclaredField("webView")
+
+ assertTrue(Modifier.isVolatile(internalSettings.modifiers))
+ assertTrue(Modifier.isVolatile(webFontsEnabledField.modifiers))
+ assertTrue(Modifier.isVolatile(trackingProtectionField.modifiers))
+ assertTrue(Modifier.isVolatile(historyTrackingDelegate.modifiers))
+ assertTrue(Modifier.isVolatile(fullScreenCallback.modifiers))
+ assertTrue(Modifier.isVolatile(currentUrl.modifiers))
+ assertTrue(Modifier.isVolatile(webView.modifiers))
+ }
+
+ @Test
+ fun settingInterceptorToProvideAlternativeContent() {
+ var interceptorCalledWithUri: String? = null
+
+ val interceptor = object : RequestInterceptor {
+ override fun onLoadRequest(
+ engineSession: EngineSession,
+ uri: String,
+ lastUri: String?,
+ hasUserGesture: Boolean,
+ isSameDomain: Boolean,
+ isRedirect: Boolean,
+ isDirectNavigation: Boolean,
+ isSubframeRequest: Boolean,
+ ): RequestInterceptor.InterceptionResponse? {
+ interceptorCalledWithUri = uri
+ return RequestInterceptor.InterceptionResponse.Content("<h1>Hello World</h1>")
+ }
+ }
+
+ val defaultSettings = DefaultSettings(requestInterceptor = interceptor)
+
+ val engineSession = SystemEngineSession(testContext, defaultSettings)
+ engineSession.webView = spy(engineSession.webView)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val request: WebResourceRequest = mock()
+ doReturn(Uri.parse("sample:about")).`when`(request).url
+
+ val response = engineSession.webView.webViewClient.shouldInterceptRequest(
+ engineSession.webView,
+ request,
+ )
+
+ assertEquals("sample:about", interceptorCalledWithUri)
+
+ assertNotNull(response)
+
+ assertEquals("<h1>Hello World</h1>", response!!.data.bufferedReader().use { it.readText() })
+ assertEquals("text/html", response.mimeType)
+ assertEquals("UTF-8", response.encoding)
+ }
+
+ @Test
+ fun `shouldInterceptRequest notifies observers if request was not intercepted`() {
+ val url = "sample:about"
+ val request: WebResourceRequest = mock()
+ doReturn(true).`when`(request).isForMainFrame
+ doReturn(true).`when`(request).hasGesture()
+ doReturn(Uri.parse(url)).`when`(request).url
+
+ val engineSession = SystemEngineSession(testContext)
+ engineSession.webView = spy(engineSession.webView)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val observer: EngineSession.Observer = mock()
+ engineSession.register(observer)
+
+ engineSession.webView.webViewClient.shouldInterceptRequest(engineSession.webView, request)
+
+ verify(observer).onLoadRequest(anyString(), eq(true), eq(true))
+
+ val redirect: WebResourceRequest = mock()
+ doReturn(true).`when`(redirect).isForMainFrame
+ doReturn(false).`when`(redirect).hasGesture()
+ doReturn(Uri.parse("sample:about")).`when`(redirect).url
+
+ engineSession.webView.webViewClient.shouldInterceptRequest(engineSession.webView, redirect)
+
+ verify(observer).onLoadRequest(anyString(), eq(true), eq(true))
+ }
+
+ @Test
+ fun `shouldInterceptRequest does not notify observers if request was intercepted`() {
+ val request: WebResourceRequest = mock()
+ doReturn(true).`when`(request).isForMainFrame
+ doReturn(true).`when`(request).hasGesture()
+ doReturn(Uri.parse("sample:about")).`when`(request).url
+
+ val interceptor = object : RequestInterceptor {
+ override fun onLoadRequest(
+ engineSession: EngineSession,
+ uri: String,
+ lastUri: String?,
+ hasUserGesture: Boolean,
+ isSameDomain: Boolean,
+ isRedirect: Boolean,
+ isDirectNavigation: Boolean,
+ isSubframeRequest: Boolean,
+ ): RequestInterceptor.InterceptionResponse? {
+ return RequestInterceptor.InterceptionResponse.Content("<h1>Hello World</h1>")
+ }
+ }
+
+ val defaultSettings = DefaultSettings(requestInterceptor = interceptor)
+
+ val engineSession = SystemEngineSession(testContext, defaultSettings)
+ engineSession.webView = spy(engineSession.webView)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val observer: EngineSession.Observer = mock()
+ engineSession.register(observer)
+
+ engineSession.webView.webViewClient.shouldInterceptRequest(
+ engineSession.webView,
+ request,
+ )
+
+ verify(observer, never()).onLoadRequest(anyString(), anyBoolean(), anyBoolean())
+ }
+
+ @Test
+ fun settingInterceptorToProvideAlternativeUrl() {
+ var interceptorCalledWithUri: String? = null
+
+ val interceptor = object : RequestInterceptor {
+ override fun onLoadRequest(
+ engineSession: EngineSession,
+ uri: String,
+ lastUri: String?,
+ hasUserGesture: Boolean,
+ isSameDomain: Boolean,
+ isRedirect: Boolean,
+ isDirectNavigation: Boolean,
+ isSubframeRequest: Boolean,
+ ): RequestInterceptor.InterceptionResponse? {
+ interceptorCalledWithUri = uri
+ return RequestInterceptor.InterceptionResponse.Url("https://mozilla.org")
+ }
+ }
+
+ val defaultSettings = DefaultSettings(requestInterceptor = interceptor)
+
+ val engineSession = SystemEngineSession(testContext, defaultSettings)
+ engineSession.webView = spy(engineSession.webView)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val request: WebResourceRequest = mock()
+ doReturn(Uri.parse("sample:about")).`when`(request).url
+
+ val response = engineSession.webView.webViewClient.shouldInterceptRequest(
+ engineSession.webView,
+ request,
+ )
+
+ assertNull(response)
+ assertEquals("sample:about", interceptorCalledWithUri)
+ assertEquals("https://mozilla.org", engineSession.webView.url)
+ }
+
+ @Test
+ fun onLoadRequestWithoutInterceptor() {
+ val defaultSettings = DefaultSettings()
+
+ val engineSession = SystemEngineSession(testContext, defaultSettings)
+ engineSession.webView = spy(engineSession.webView)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val request: WebResourceRequest = mock()
+ doReturn(Uri.parse("sample:about")).`when`(request).url
+
+ val response = engineSession.webView.webViewClient.shouldInterceptRequest(
+ engineSession.webView,
+ request,
+ )
+
+ assertNull(response)
+ }
+
+ @Test
+ fun onLoadRequestWithInterceptorThatDoesNotIntercept() {
+ var interceptorCalledWithUri: String? = null
+
+ val interceptor = object : RequestInterceptor {
+ override fun onLoadRequest(
+ engineSession: EngineSession,
+ uri: String,
+ lastUri: String?,
+ hasUserGesture: Boolean,
+ isSameDomain: Boolean,
+ isRedirect: Boolean,
+ isDirectNavigation: Boolean,
+ isSubframeRequest: Boolean,
+ ): RequestInterceptor.InterceptionResponse? {
+ interceptorCalledWithUri = uri
+ return null
+ }
+ }
+
+ val defaultSettings = DefaultSettings(requestInterceptor = interceptor)
+
+ val engineSession = SystemEngineSession(testContext, defaultSettings)
+ engineSession.webView = spy(engineSession.webView)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val request: WebResourceRequest = mock()
+ doReturn(Uri.parse("sample:about")).`when`(request).url
+
+ val response = engineSession.webView.webViewClient.shouldInterceptRequest(
+ engineSession.webView,
+ request,
+ )
+
+ assertEquals("sample:about", interceptorCalledWithUri)
+ assertNull(response)
+ }
+
+ @Test
+ fun webViewErrorMappingToErrorType() {
+ assertEquals(
+ ErrorType.ERROR_UNKNOWN_HOST,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_HOST_LOOKUP),
+ )
+ assertEquals(
+ ErrorType.ERROR_CONNECTION_REFUSED,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_CONNECT),
+ )
+ assertEquals(
+ ErrorType.ERROR_CONNECTION_REFUSED,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_IO),
+ )
+ assertEquals(
+ ErrorType.ERROR_NET_TIMEOUT,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_TIMEOUT),
+ )
+ assertEquals(
+ ErrorType.ERROR_REDIRECT_LOOP,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_REDIRECT_LOOP),
+ )
+ assertEquals(
+ ErrorType.ERROR_UNKNOWN_PROTOCOL,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_UNSUPPORTED_SCHEME),
+ )
+ assertEquals(
+ ErrorType.ERROR_SECURITY_SSL,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_FAILED_SSL_HANDSHAKE),
+ )
+ assertEquals(
+ ErrorType.ERROR_MALFORMED_URI,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_BAD_URL),
+ )
+ assertEquals(
+ ErrorType.UNKNOWN,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_TOO_MANY_REQUESTS),
+ )
+ assertEquals(
+ ErrorType.ERROR_FILE_NOT_FOUND,
+ SystemEngineSession.webViewErrorToErrorType(WebViewClient.ERROR_FILE_NOT_FOUND),
+ )
+ assertEquals(
+ ErrorType.UNKNOWN,
+ SystemEngineSession.webViewErrorToErrorType(-500),
+ )
+ }
+
+ @Test
+ fun desktopMode() {
+ val userAgentMobile = "Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 Mobile Safari/537.36"
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val webViewSettings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(webViewSettings)
+
+ var desktopMode = false
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onDesktopModeChange(enabled: Boolean) {
+ desktopMode = enabled
+ }
+ },
+ )
+
+ engineSession.webView = webView
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ engineSession.toggleDesktopMode(true)
+ verify(webViewSettings).useWideViewPort = true
+ verify(engineSession).toggleDesktopUA(userAgentMobile, true)
+ assertTrue(desktopMode)
+
+ engineSession.toggleDesktopMode(true)
+ verify(webView, never()).reload()
+
+ engineSession.toggleDesktopMode(true, true)
+ verify(webView).reload()
+ }
+
+ @Test
+ fun desktopModeWithProvidedTrueWideViewPort() {
+ val userAgentMobile = "Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 Mobile Safari/537.36"
+ val defaultSettings = DefaultSettings(useWideViewPort = true)
+ val engineSession = spy(SystemEngineSession(testContext, defaultSettings))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ val webViewSettings = mock<WebSettings>()
+ var desktopMode = false
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onDesktopModeChange(enabled: Boolean) {
+ desktopMode = enabled
+ }
+ },
+ )
+
+ engineSession.webView = webView
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ engineSession.toggleDesktopMode(true)
+ verify(webViewSettings).useWideViewPort = true
+ verify(engineSession).toggleDesktopUA(userAgentMobile, true)
+ assertTrue(desktopMode)
+ }
+
+ @Test
+ fun desktopModeWithProvidedFalseWideViewPort() {
+ val userAgentMobile = "Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 Mobile Safari/537.36"
+ val defaultSettings = DefaultSettings(useWideViewPort = false)
+ val engineSession = spy(SystemEngineSession(testContext, defaultSettings))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ val webViewSettings = mock<WebSettings>()
+ var desktopMode = false
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onDesktopModeChange(enabled: Boolean) {
+ desktopMode = enabled
+ }
+ },
+ )
+
+ engineSession.webView = webView
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ engineSession.toggleDesktopMode(true)
+ verify(webViewSettings).useWideViewPort = true
+ verify(engineSession).toggleDesktopUA(userAgentMobile, true)
+ assertTrue(desktopMode)
+
+ engineSession.toggleDesktopMode(false)
+ verify(webViewSettings).useWideViewPort = false
+ verify(engineSession).toggleDesktopUA(userAgentMobile, false)
+ assertFalse(desktopMode)
+ }
+
+ @Test
+ fun desktopModeToggleTrueWithNoProvidedDefault() {
+ val userAgentMobile = "Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 Mobile Safari/537.36"
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+
+ val webViewSettings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ var desktopMode = false
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onDesktopModeChange(enabled: Boolean) {
+ desktopMode = enabled
+ }
+ },
+ )
+
+ engineSession.webView = webView
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ engineSession.toggleDesktopMode(true)
+ verify(webViewSettings).useWideViewPort = true
+ verify(engineSession).toggleDesktopUA(userAgentMobile, true)
+ assertTrue(desktopMode)
+ }
+
+ @Test
+ fun desktopModeToggleFalseWithNoProvidedDefault() {
+ val userAgentMobile = "Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 Mobile Safari/537.36"
+ val engineSession = spy(SystemEngineSession(testContext))
+
+ val webView = mock<WebView>()
+
+ val webViewSettings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ var desktopMode = false
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onDesktopModeChange(enabled: Boolean) {
+ desktopMode = enabled
+ }
+ },
+ )
+
+ engineSession.webView = webView
+ whenever(webView.settings).thenReturn(webViewSettings)
+ whenever(webViewSettings.userAgentString).thenReturn(userAgentMobile)
+
+ engineSession.toggleDesktopMode(false)
+ verify(webViewSettings).useWideViewPort = false
+ verify(engineSession).toggleDesktopUA(userAgentMobile, false)
+ assertFalse(desktopMode)
+ }
+
+ @Test
+ fun desktopModeUA() {
+ val userAgentMobile = "Mozilla/5.0 (Linux; Android 9) AppleWebKit/537.36 Mobile Safari/537.36"
+ val userAgentDesktop = "Mozilla/5.0 (Linux; diordnA 9) AppleWebKit/537.36 eliboM Safari/537.36"
+ val engineSession = spy(SystemEngineSession(testContext))
+
+ assertEquals(engineSession.toggleDesktopUA(userAgentMobile, false), userAgentMobile)
+ assertEquals(engineSession.toggleDesktopUA(userAgentMobile, true), userAgentDesktop)
+ }
+
+ @Test
+ fun findAll() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ engineSession.findAll("mozilla")
+ verify(webView, never()).findAllAsync(anyString())
+
+ engineSession.webView = webView
+ var findObserved: String? = null
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onFind(text: String) {
+ findObserved = text
+ }
+ },
+ )
+ engineSession.findAll("mozilla")
+ verify(webView).findAllAsync("mozilla")
+ assertEquals("mozilla", findObserved)
+ }
+
+ @Test
+ fun findNext() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.findNext(true)
+ verify(webView, never()).findNext(mockitoAny(Boolean::class.java))
+
+ engineSession.webView = webView
+ engineSession.findNext(true)
+ verify(webView).findNext(true)
+ }
+
+ @Test
+ fun clearFindMatches() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.clearFindMatches()
+ verify(webView, never()).clearMatches()
+
+ engineSession.webView = webView
+ engineSession.clearFindMatches()
+ verify(webView).clearMatches()
+ }
+
+ @Test
+ fun clearDataMakingExpectedCalls() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ val webStorage: WebStorage = mock()
+ val webViewDatabase: WebViewDatabase = mock()
+ val context: Context = testContext
+
+ doReturn(webStorage).`when`(engineSession).webStorage()
+ doReturn(webViewDatabase).`when`(engineSession).webViewDatabase(context)
+ whenever(webView.context).thenReturn(context)
+ engineSession.webView = webView
+
+ // clear all data by default
+ engineSession.clearData()
+ verify(webView).clearFormData()
+ verify(webView).clearHistory()
+ verify(webView).clearMatches()
+ verify(webView).clearSslPreferences()
+ verify(webView).clearCache(true)
+ verify(webStorage).deleteAllData()
+ verify(webViewDatabase).clearHttpAuthUsernamePassword()
+
+ // clear storages
+ engineSession.clearData(BrowsingData.select(BrowsingData.DOM_STORAGES))
+ verify(webStorage, times(2)).deleteAllData()
+ verify(webView, times(1)).clearCache(true)
+ verify(webView, times(1)).clearFormData()
+ verify(webView, times(1)).clearMatches()
+ verify(webView, times(1)).clearHistory()
+ verify(webView, times(1)).clearSslPreferences()
+ verify(webViewDatabase, times(1)).clearHttpAuthUsernamePassword()
+
+ // clear auth info
+ engineSession.clearData(BrowsingData.select(BrowsingData.AUTH_SESSIONS))
+ verify(webViewDatabase, times(2)).clearHttpAuthUsernamePassword()
+ verify(webStorage, times(2)).deleteAllData()
+ verify(webView, times(1)).clearCache(true)
+ verify(webView, times(1)).clearFormData()
+ verify(webView, times(1)).clearMatches()
+ verify(webView, times(1)).clearHistory()
+ verify(webView, times(1)).clearSslPreferences()
+
+ // clear cookies
+ engineSession.clearData(BrowsingData.select(BrowsingData.COOKIES))
+ verify(webViewDatabase, times(2)).clearHttpAuthUsernamePassword()
+ verify(webStorage, times(2)).deleteAllData()
+ verify(webView, times(1)).clearCache(true)
+ verify(webView, times(1)).clearFormData()
+ verify(webView, times(1)).clearMatches()
+ verify(webView, times(1)).clearHistory()
+ verify(webView, times(1)).clearSslPreferences()
+
+ // clear image cache
+ engineSession.clearData(BrowsingData.select(BrowsingData.IMAGE_CACHE))
+ verify(webView, times(2)).clearCache(true)
+ verify(webViewDatabase, times(2)).clearHttpAuthUsernamePassword()
+ verify(webStorage, times(2)).deleteAllData()
+ verify(webView, times(1)).clearFormData()
+ verify(webView, times(1)).clearMatches()
+ verify(webView, times(1)).clearHistory()
+ verify(webView, times(1)).clearSslPreferences()
+
+ // clear network cache
+ engineSession.clearData(BrowsingData.select(BrowsingData.NETWORK_CACHE))
+ verify(webView, times(3)).clearCache(true)
+ verify(webViewDatabase, times(2)).clearHttpAuthUsernamePassword()
+ verify(webStorage, times(2)).deleteAllData()
+ verify(webView, times(1)).clearFormData()
+ verify(webView, times(1)).clearMatches()
+ verify(webView, times(1)).clearHistory()
+ verify(webView, times(1)).clearSslPreferences()
+
+ // clear all caches
+ engineSession.clearData(BrowsingData.allCaches())
+ verify(webView, times(4)).clearCache(true)
+ verify(webViewDatabase, times(2)).clearHttpAuthUsernamePassword()
+ verify(webStorage, times(2)).deleteAllData()
+ verify(webView, times(1)).clearFormData()
+ verify(webView, times(1)).clearMatches()
+ verify(webView, times(1)).clearHistory()
+ verify(webView, times(1)).clearSslPreferences()
+ }
+
+ @Test
+ fun clearDataInvokesSuccessCallback() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ val webStorage: WebStorage = mock()
+ val webViewDatabase: WebViewDatabase = mock()
+ val context: Context = testContext
+ var onSuccessCalled = false
+
+ doReturn(webStorage).`when`(engineSession).webStorage()
+ doReturn(webViewDatabase).`when`(engineSession).webViewDatabase(context)
+ whenever(webView.context).thenReturn(context)
+ engineSession.webView = webView
+
+ engineSession.clearData(onSuccess = { onSuccessCalled = true })
+ assertTrue(onSuccessCalled)
+ }
+
+ @Test
+ fun clearDataInvokesErrorCallback() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ val webViewDatabase: WebViewDatabase = mock()
+ val context: Context = testContext
+ var onErrorCalled = false
+
+ val exception = RuntimeException()
+ doThrow(exception).`when`(engineSession).webStorage()
+ doReturn(webViewDatabase).`when`(engineSession).webViewDatabase(context)
+ whenever(webView.context).thenReturn(context)
+ engineSession.webView = webView
+
+ engineSession.clearData(
+ onError = {
+ onErrorCalled = true
+ assertSame(it, exception)
+ },
+ )
+ assertTrue(onErrorCalled)
+ }
+
+ @Test
+ fun testExitFullscreenModeWithWebViewAndCallBack() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ val customViewCallback = mock<WebChromeClient.CustomViewCallback>()
+
+ engineView.render(engineSession)
+ engineSession.exitFullScreenMode()
+ verify(customViewCallback, never()).onCustomViewHidden()
+
+ engineSession.fullScreenCallback = customViewCallback
+ engineSession.exitFullScreenMode()
+ verify(customViewCallback).onCustomViewHidden()
+ }
+
+ @Test
+ fun closeDestroysWebView() {
+ val engineSession = SystemEngineSession(testContext)
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+ engineSession.webView = webView
+
+ engineSession.close()
+ verify(webView).destroy()
+ }
+
+ @Test
+ fun `purgeHistory delegates to clearHistory`() {
+ val engineSession = SystemEngineSession(testContext)
+
+ val webView: WebView = mock()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.webView = webView
+
+ engineSession.purgeHistory()
+ verify(webView).clearHistory()
+ }
+
+ @Test
+ fun `GIVEN webView_canGoBack() true WHEN goBack() is called THEN verify EngineObserver onNavigateBack() is triggered`() {
+ var observedOnNavigateBack = false
+
+ val engineSession = SystemEngineSession(testContext)
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.webView = webView
+ Mockito.`when`(webView.canGoBack()).thenReturn(true)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onNavigateBack() {
+ observedOnNavigateBack = true
+ }
+ },
+ )
+
+ engineSession.goBack()
+ assertTrue(observedOnNavigateBack)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineTest.kt
new file mode 100644
index 0000000000..596157111b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineTest.kt
@@ -0,0 +1,105 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.browser.engine.system
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.concept.engine.DefaultSettings
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.UnsupportedSettingException
+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.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SystemEngineTest {
+
+ @Before
+ fun setup() {
+ // This is setting a internal field just for testing purposes as
+ // WebSettings.getDefaultUserAgent isn't mocked by Roboelectric
+ SystemEngine.defaultUserAgent = "test-ua-string"
+ }
+
+ @Test
+ fun createView() {
+ val engine = SystemEngine(testContext)
+ assertTrue(engine.createView(testContext) is SystemEngineView)
+ }
+
+ @Test
+ fun createSession() {
+ val engine = SystemEngine(testContext)
+ assertTrue(engine.createSession() is SystemEngineSession)
+
+ try {
+ engine.createSession(true)
+ // Private browsing not yet supported
+ fail("Expected UnsupportedOperationException")
+ } catch (e: UnsupportedOperationException) { }
+
+ try {
+ engine.createSession(false, "1")
+ // Contextual identities not yet supported
+ fail("Expected UnsupportedOperationException")
+ } catch (e: UnsupportedOperationException) { }
+ }
+
+ @Test
+ fun name() {
+ val engine = SystemEngine(testContext)
+ assertEquals("System", engine.name())
+ }
+
+ @Test
+ fun settings() {
+ val engine = SystemEngine(
+ testContext,
+ DefaultSettings(
+ remoteDebuggingEnabled = true,
+ trackingProtectionPolicy = EngineSession.TrackingProtectionPolicy.strict(),
+ ),
+ )
+
+ assertTrue(engine.settings.remoteDebuggingEnabled)
+ engine.settings.remoteDebuggingEnabled = false
+ assertFalse(engine.settings.remoteDebuggingEnabled)
+
+ assertEquals(
+ engine.settings.trackingProtectionPolicy,
+ EngineSession.TrackingProtectionPolicy.strict(),
+ )
+ engine.settings.trackingProtectionPolicy = EngineSession.TrackingProtectionPolicy.none()
+ assertEquals(engine.settings.trackingProtectionPolicy, EngineSession.TrackingProtectionPolicy.none())
+
+ // Specifying no ua-string default should result in WebView default
+ // It should be possible to read and set a new default
+ assertEquals("test-ua-string", engine.settings.userAgentString)
+ engine.settings.userAgentString = engine.settings.userAgentString + "-test"
+ assertEquals("test-ua-string-test", engine.settings.userAgentString)
+
+ // It should be possible to specify a custom ua-string default
+ assertEquals("foo", SystemEngine(testContext, DefaultSettings(userAgentString = "foo")).settings.userAgentString)
+ }
+
+ // This feature will be covered on this issue
+ // https://github.com/mozilla-mobile/android-components/issues/4206
+ @Test(expected = UnsupportedSettingException::class)
+ fun safeBrowsingIsNotSupportedYet() {
+ val engine = SystemEngine(
+ testContext,
+ DefaultSettings(
+ remoteDebuggingEnabled = true,
+ trackingProtectionPolicy = EngineSession.TrackingProtectionPolicy.strict(),
+ ),
+ )
+
+ engine.settings.safeBrowsingPolicy
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt
new file mode 100644
index 0000000000..95cfbd2253
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt
@@ -0,0 +1,1654 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.net.Uri
+import android.net.http.SslCertificate
+import android.net.http.SslError
+import android.os.Build
+import android.os.Bundle
+import android.os.Message
+import android.view.PixelCopy
+import android.view.View
+import android.webkit.HttpAuthHandler
+import android.webkit.JsPromptResult
+import android.webkit.JsResult
+import android.webkit.SslErrorHandler
+import android.webkit.ValueCallback
+import android.webkit.WebChromeClient
+import android.webkit.WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE
+import android.webkit.WebResourceError
+import android.webkit.WebResourceRequest
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebView.HitTestResult
+import android.webkit.WebViewClient
+import android.webkit.WebViewDatabase
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import mozilla.components.browser.engine.system.matcher.UrlMatcher
+import mozilla.components.browser.errorpages.ErrorType
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
+import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory
+import mozilla.components.concept.engine.HitResult
+import mozilla.components.concept.engine.InputResultDetail
+import mozilla.components.concept.engine.content.blocking.Tracker
+import mozilla.components.concept.engine.history.HistoryTrackingDelegate
+import mozilla.components.concept.engine.permission.PermissionRequest
+import mozilla.components.concept.engine.prompt.PromptRequest
+import mozilla.components.concept.engine.request.RequestInterceptor
+import mozilla.components.concept.engine.window.WindowRequest
+import mozilla.components.concept.fetch.Response
+import mozilla.components.concept.storage.PageVisit
+import mozilla.components.concept.storage.VisitType
+import mozilla.components.support.test.any
+import mozilla.components.support.test.argumentCaptor
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.shadow.PixelCopyShadow
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.support.test.whenever
+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.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoInteractions
+import org.robolectric.Robolectric
+import org.robolectric.annotation.Config
+import java.io.StringReader
+
+@ExperimentalCoroutinesApi // for runTest
+@RunWith(AndroidJUnit4::class)
+class SystemEngineViewTest {
+
+ @Test
+ fun `EngineView initialization`() {
+ val engineView = SystemEngineView(testContext)
+ val webView = WebView(testContext)
+
+ engineView.initWebView(webView)
+ assertNotNull(webView.webChromeClient)
+ assertNotNull(webView.webViewClient)
+ }
+
+ @Test
+ fun `EngineView renders WebView`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+
+ engineView.render(engineSession)
+ assertEquals(engineSession.webView, engineView.getChildAt(0))
+ }
+
+ @Test
+ fun `WebViewClient notifies observers`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observedUrl = ""
+ var observedUserGesture = true
+ var observedLoadingState = false
+ var observedSecurityChange: Triple<Boolean, String?, String?> = Triple(false, null, null)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onLoadingStateChange(loading: Boolean) { observedLoadingState = loading }
+ override fun onLocationChange(url: String, hasUserGesture: Boolean) {
+ observedUrl = url
+ observedUserGesture = hasUserGesture
+ }
+ override fun onSecurityChange(secure: Boolean, host: String?, issuer: String?) {
+ observedSecurityChange = Triple(secure, host, issuer)
+ }
+ },
+ )
+
+ engineSession.webView.webViewClient.onPageStarted(mock(), "https://wiki.mozilla.org/", null)
+ assertEquals(true, observedLoadingState)
+ assertEquals(observedUrl, "https://wiki.mozilla.org/")
+
+ observedLoadingState = true
+ engineSession.webView.webViewClient.onPageFinished(null, "http://mozilla.org")
+ assertEquals("http://mozilla.org", observedUrl)
+ assertEquals(false, observedUserGesture)
+ assertFalse(observedLoadingState)
+ assertEquals(Triple(false, null, null), observedSecurityChange)
+
+ val view = mock<WebView>()
+ engineSession.webView.webViewClient.onPageFinished(view, "http://mozilla.org")
+ assertEquals(Triple(false, null, null), observedSecurityChange)
+
+ val certificate = mock<SslCertificate>()
+ val dName = mock<SslCertificate.DName>()
+ doReturn("testCA").`when`(dName).oName
+ doReturn(certificate).`when`(view).certificate
+ engineSession.webView.webViewClient.onPageFinished(view, "http://mozilla.org")
+
+ doReturn("testCA").`when`(dName).oName
+ doReturn(dName).`when`(certificate).issuedBy
+ doReturn(certificate).`when`(view).certificate
+ engineSession.webView.webViewClient.onPageFinished(view, "http://mozilla.org")
+ assertEquals(Triple(true, "mozilla.org", "testCA"), observedSecurityChange)
+ }
+
+ @Test
+ fun `HitResult type handling`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var hitTestResult: HitResult = HitResult.UNKNOWN("")
+ engineView.render(engineSession)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onLongPress(hitResult: HitResult) {
+ hitTestResult = hitResult
+ }
+ },
+ )
+
+ engineView.handleLongClick(HitTestResult.EMAIL_TYPE, "mailto:asa@mozilla.com")
+ assertTrue(hitTestResult is HitResult.EMAIL)
+ assertEquals("mailto:asa@mozilla.com", hitTestResult.src)
+
+ engineView.handleLongClick(HitTestResult.GEO_TYPE, "geo:1,-1")
+ assertTrue(hitTestResult is HitResult.GEO)
+ assertEquals("geo:1,-1", hitTestResult.src)
+
+ engineView.handleLongClick(HitTestResult.PHONE_TYPE, "tel:+123456789")
+ assertTrue(hitTestResult is HitResult.PHONE)
+ assertEquals("tel:+123456789", hitTestResult.src)
+
+ engineView.handleLongClick(HitTestResult.IMAGE_TYPE, "image.png")
+ assertTrue(hitTestResult is HitResult.IMAGE)
+ assertEquals("image.png", hitTestResult.src)
+
+ engineView.handleLongClick(HitTestResult.SRC_ANCHOR_TYPE, "https://mozilla.org")
+ assertTrue(hitTestResult is HitResult.UNKNOWN)
+ assertEquals("https://mozilla.org", hitTestResult.src)
+
+ var result = engineView.handleLongClick(HitTestResult.SRC_IMAGE_ANCHOR_TYPE, "image.png")
+ assertFalse(result) // Intentional for image links; see ImageHandler tests.
+
+ result = engineView.handleLongClick(HitTestResult.EDIT_TEXT_TYPE, "https://mozilla.org")
+ assertFalse(result)
+ }
+
+ @Test
+ fun `ImageHandler notifies observers`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ val handler = SystemEngineView.ImageHandler(engineSession)
+ val message = mock<Message>()
+ val bundle = mock<Bundle>()
+ var observerNotified = false
+
+ whenever(message.data).thenReturn(bundle)
+ whenever(message.data.getString("url")).thenReturn("https://mozilla.org")
+ whenever(message.data.getString("src")).thenReturn("file.png")
+
+ engineView.render(engineSession)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onLongPress(hitResult: HitResult) {
+ observerNotified = true
+ }
+ },
+ )
+
+ handler.handleMessage(message)
+ assertTrue(observerNotified)
+
+ observerNotified = false
+ val nullHandler = SystemEngineView.ImageHandler(null)
+ nullHandler.handleMessage(message)
+ assertFalse(observerNotified)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun `null image src`() {
+ val engineSession = SystemEngineSession(testContext)
+ val handler = SystemEngineView.ImageHandler(engineSession)
+ val message = mock<Message>()
+ val bundle = mock<Bundle>()
+
+ whenever(message.data).thenReturn(bundle)
+ whenever(message.data.getString("url")).thenReturn("https://mozilla.org")
+
+ handler.handleMessage(message)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun `null image url`() {
+ val engineSession = SystemEngineSession(testContext)
+ val handler = SystemEngineView.ImageHandler(engineSession)
+ val message = mock<Message>()
+ val bundle = mock<Bundle>()
+
+ whenever(message.data).thenReturn(bundle)
+ whenever(message.data.getString("src")).thenReturn("file.png")
+
+ handler.handleMessage(message)
+ }
+
+ @Test
+ fun `WebChromeClient notifies observers`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observedProgress = 0
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onProgress(progress: Int) { observedProgress = progress }
+ },
+ )
+
+ engineSession.webView.webChromeClient!!.onProgressChanged(null, 100)
+ assertEquals(100, observedProgress)
+ }
+
+ @Test
+ fun `SystemEngineView updates current session url via onPageStart events`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ assertEquals("", engineSession.currentUrl)
+ engineSession.webView.webViewClient.onPageStarted(engineSession.webView, "https://www.mozilla.org/", null)
+ assertEquals("https://www.mozilla.org/", engineSession.currentUrl)
+
+ engineSession.webView.webViewClient.onPageStarted(engineSession.webView, "https://www.firefox.com/", null)
+ assertEquals("https://www.firefox.com/", engineSession.currentUrl)
+ }
+
+ @Test
+ fun `WebView client notifies navigation state changes`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+
+ val observer: EngineSession.Observer = mock()
+ val webView: WebView = mock()
+ whenever(webView.canGoBack()).thenReturn(true)
+ whenever(webView.canGoForward()).thenReturn(true)
+
+ engineSession.register(observer)
+ verify(observer, never()).onNavigationStateChange(true, true)
+
+ engineView.render(engineSession)
+ engineSession.webView.webViewClient.onPageStarted(webView, "https://www.mozilla.org/", null)
+ verify(observer).onNavigationStateChange(true, true)
+ }
+
+ @Test
+ fun `WebView client notifies configured history delegate of url visits`() = runTest {
+ val engineSession = SystemEngineSession(testContext)
+
+ val engineView = SystemEngineView(testContext)
+ val webView: WebView = mock()
+ val historyDelegate: HistoryTrackingDelegate = mock()
+
+ engineView.render(engineSession)
+
+ // Nothing breaks if delegate isn't set.
+ engineSession.webView.webViewClient.doUpdateVisitedHistory(webView, "https://www.mozilla.com", false)
+
+ engineSession.settings.historyTrackingDelegate = historyDelegate
+ whenever(historyDelegate.shouldStoreUri(any())).thenReturn(true)
+
+ engineSession.webView.webViewClient.doUpdateVisitedHistory(webView, "https://www.mozilla.com", false)
+ verify(historyDelegate).onVisited(eq("https://www.mozilla.com"), eq(PageVisit(VisitType.LINK)))
+
+ engineSession.webView.webViewClient.doUpdateVisitedHistory(webView, "https://www.mozilla.com", true)
+ verify(historyDelegate).onVisited(eq("https://www.mozilla.com"), eq(PageVisit(VisitType.RELOAD)))
+ }
+
+ @Test
+ fun `WebView client checks with the delegate if the URI visit should be recorded`() = runTest {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ val webView: WebView = mock()
+ engineView.render(engineSession)
+
+ val historyDelegate: HistoryTrackingDelegate = mock()
+ engineSession.settings.historyTrackingDelegate = historyDelegate
+
+ whenever(historyDelegate.shouldStoreUri("https://www.mozilla.com")).thenReturn(true)
+
+ // Verify that engine session asked delegate if uri should be stored.
+ engineSession.webView.webViewClient.doUpdateVisitedHistory(webView, "https://www.mozilla.com", false)
+ verify(historyDelegate).onVisited(eq("https://www.mozilla.com"), eq(PageVisit(VisitType.LINK)))
+ verify(historyDelegate).shouldStoreUri("https://www.mozilla.com")
+
+ // Verify that engine won't try to store a uri that delegate doesn't want.
+ engineSession.webView.webViewClient.doUpdateVisitedHistory(webView, "https://www.mozilla.com/not-allowed", false)
+ verify(historyDelegate, never()).onVisited(eq("https://www.mozilla.com/not-allowed"), any())
+ verify(historyDelegate).shouldStoreUri("https://www.mozilla.com/not-allowed")
+ Unit
+ }
+
+ @Test
+ fun `WebView client requests history from configured history delegate`() = runTest {
+ val engineSession = SystemEngineSession(testContext)
+
+ val engineView = SystemEngineView(testContext)
+ val historyDelegate = object : HistoryTrackingDelegate {
+ override suspend fun onVisited(uri: String, visit: PageVisit) {
+ fail()
+ }
+
+ override fun shouldStoreUri(uri: String): Boolean {
+ return true
+ }
+
+ override suspend fun onTitleChanged(uri: String, title: String) {
+ fail()
+ }
+
+ override suspend fun onPreviewImageChange(uri: String, previewImageUrl: String) {
+ fail()
+ }
+
+ override suspend fun getVisited(uris: List<String>): List<Boolean> {
+ fail()
+ return emptyList()
+ }
+
+ override suspend fun getVisited(): List<String> {
+ return listOf("https://www.mozilla.com")
+ }
+ }
+
+ engineView.render(engineSession)
+
+ // Nothing breaks if delegate isn't set.
+ engineSession.webView.webChromeClient!!.getVisitedHistory(mock())
+
+ engineSession.settings.historyTrackingDelegate = historyDelegate
+
+ val historyValueCallback: ValueCallback<Array<String>> = mock()
+ engineSession.webView.webChromeClient!!.getVisitedHistory(historyValueCallback)
+ verify(historyValueCallback).onReceiveValue(arrayOf("https://www.mozilla.com"))
+ }
+
+ @Test
+ fun `WebView client notifies configured history delegate of title changes`() = runTest {
+ val engineSession = SystemEngineSession(testContext)
+
+ val engineView = SystemEngineView(testContext)
+ val webView: WebView = mock()
+ val historyDelegate: HistoryTrackingDelegate = mock()
+
+ engineView.render(engineSession)
+
+ // Nothing breaks if delegate isn't set.
+ engineSession.webView.webChromeClient!!.onReceivedTitle(webView, "New title!")
+
+ // We can now set the delegate. Were it set before the render call,
+ // it'll get overwritten during settings initialization.
+ engineSession.settings.historyTrackingDelegate = historyDelegate
+
+ // Delegate not notified if, somehow, there's no currentUrl present in the view.
+ engineSession.webView.webChromeClient!!.onReceivedTitle(webView, "New title!")
+ verify(historyDelegate, never()).onTitleChanged(eq(""), eq("New title!"))
+
+ // This sets the currentUrl.
+ engineSession.webView.webViewClient.onPageStarted(webView, "https://www.mozilla.org/", null)
+
+ engineSession.webView.webChromeClient!!.onReceivedTitle(webView, "New title!")
+ verify(historyDelegate).onTitleChanged(eq("https://www.mozilla.org/"), eq("New title!"))
+
+ reset(historyDelegate)
+
+ // Empty title when none provided
+ engineSession.webView.webChromeClient!!.onReceivedTitle(webView, null)
+ verify(historyDelegate).onTitleChanged(eq("https://www.mozilla.org/"), eq(""))
+ }
+
+ @Test
+ fun `WebView client notifies observers about title changes`() {
+ val engineSession = SystemEngineSession(testContext)
+
+ val engineView = SystemEngineView(testContext)
+ val observer: EngineSession.Observer = mock()
+ val webView: WebView = mock()
+ whenever(webView.canGoBack()).thenReturn(true)
+ whenever(webView.canGoForward()).thenReturn(true)
+
+ engineSession.register(observer)
+ engineView.render(engineSession)
+ engineSession.webView.webChromeClient!!.onReceivedTitle(webView, "Hello World!")
+ verify(observer).onTitleChange(eq("Hello World!"))
+ verify(observer).onNavigationStateChange(true, true)
+
+ reset(observer)
+
+ // Empty title when none provided.
+ engineSession.webView.webChromeClient!!.onReceivedTitle(webView, null)
+ verify(observer).onTitleChange(eq(""))
+ verify(observer).onNavigationStateChange(true, true)
+ }
+
+ @Test
+ fun `download listener notifies observers`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observerNotified = false
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onExternalResource(
+ url: String,
+ fileName: String?,
+ contentLength: Long?,
+ contentType: String?,
+ cookie: String?,
+ userAgent: String?,
+ isPrivate: Boolean,
+ skipConfirmation: Boolean,
+ openInApp: Boolean,
+ response: Response?,
+ ) {
+ assertEquals("https://download.mozilla.org", url)
+ assertEquals("image.png", fileName)
+ assertEquals(1337L, contentLength)
+ assertNull(cookie)
+ assertEquals("Components/1.0", userAgent)
+
+ observerNotified = true
+ }
+ },
+ )
+
+ val listener = engineView.createDownloadListener()
+ listener.onDownloadStart(
+ "https://download.mozilla.org",
+ "Components/1.0",
+ "attachment; filename=\"image.png\"",
+ "image/png",
+ 1337,
+ )
+
+ assertTrue(observerNotified)
+ }
+
+ @Test
+ fun `WebView client tracking protection`() {
+ SystemEngineView.URL_MATCHER = UrlMatcher(arrayOf("blocked.random"))
+
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val webViewClient = engineSession.webView.webViewClient
+ val invalidRequest = mock<WebResourceRequest>()
+ whenever(invalidRequest.isForMainFrame).thenReturn(false)
+ whenever(invalidRequest.url).thenReturn(Uri.parse("market://foo.bar/"))
+
+ var response = webViewClient.shouldInterceptRequest(engineSession.webView, invalidRequest)
+ assertNull(response)
+
+ engineSession.trackingProtectionPolicy = TrackingProtectionPolicy.strict()
+ response = webViewClient.shouldInterceptRequest(engineSession.webView, invalidRequest)
+ assertNotNull(response)
+ assertNull(response!!.data)
+ assertNull(response.encoding)
+ assertNull(response.mimeType)
+
+ val faviconRequest = mock<WebResourceRequest>()
+ whenever(faviconRequest.isForMainFrame).thenReturn(false)
+ whenever(faviconRequest.url).thenReturn(Uri.parse("http://foo/favicon.ico"))
+ response = webViewClient.shouldInterceptRequest(engineSession.webView, faviconRequest)
+ assertNotNull(response)
+ assertNull(response!!.data)
+ assertNull(response.encoding)
+ assertNull(response.mimeType)
+
+ val blockedRequest = mock<WebResourceRequest>()
+ whenever(blockedRequest.isForMainFrame).thenReturn(false)
+ whenever(blockedRequest.url).thenReturn(Uri.parse("http://blocked.random"))
+
+ var trackerBlocked: Tracker? = null
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onTrackerBlocked(tracker: Tracker) {
+ trackerBlocked = tracker
+ }
+ },
+ )
+
+ response = webViewClient.shouldInterceptRequest(engineSession.webView, blockedRequest)
+ assertNotNull(response)
+ assertNull(response!!.data)
+ assertNull(response.encoding)
+ assertNull(response.mimeType)
+ assertTrue(trackerBlocked!!.trackingCategories.isEmpty())
+ }
+
+ @Test
+ fun `blocked trackers are reported with correct categories`() {
+ val BLOCK_LIST = """{
+ "license": "test-license",
+ "categories": {
+ "Advertising": [
+ {
+ "AdTest1": {
+ "http://www.adtest1.com/": [
+ "adtest1.com"
+ ]
+ }
+ }
+ ],
+ "Analytics": [
+ {
+ "AnalyticsTest": {
+ "http://analyticsTest1.com/": [
+ "analyticsTest1.com"
+ ]
+ }
+ }
+ ],
+ "Content": [
+ {
+ "ContentTest1": {
+ "http://contenttest1.com/": [
+ "contenttest1.com"
+ ]
+ }
+ }
+ ],
+ "Social": [
+ {
+ "SocialTest1": {
+ "http://www.socialtest1.com/": [
+ "socialtest1.com"
+ ]
+ }
+ }
+ ]
+ }
+ }
+ """
+ SystemEngineView.URL_MATCHER = UrlMatcher.createMatcher(
+ StringReader(BLOCK_LIST),
+ StringReader("{}"),
+ )
+
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var trackerBlocked: Tracker? = null
+
+ engineView.render(engineSession)
+ val webViewClient = engineSession.webView.webViewClient
+
+ engineSession.trackingProtectionPolicy = TrackingProtectionPolicy.strict()
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onTrackerBlocked(tracker: Tracker) {
+ trackerBlocked = tracker
+ }
+ },
+ )
+
+ val blockedRequest = mock<WebResourceRequest>()
+ whenever(blockedRequest.isForMainFrame).thenReturn(false)
+
+ whenever(blockedRequest.url).thenReturn(Uri.parse("http://www.adtest1.com/"))
+ webViewClient.shouldInterceptRequest(engineSession.webView, blockedRequest)
+
+ assertTrue(trackerBlocked!!.trackingCategories.first() == TrackingCategory.AD)
+
+ whenever(blockedRequest.url).thenReturn(Uri.parse("http://analyticsTest1.com/"))
+ webViewClient.shouldInterceptRequest(engineSession.webView, blockedRequest)
+
+ assertTrue(trackerBlocked!!.trackingCategories.first() == TrackingCategory.ANALYTICS)
+
+ whenever(blockedRequest.url).thenReturn(Uri.parse("http://www.socialtest1.com/"))
+ webViewClient.shouldInterceptRequest(engineSession.webView, blockedRequest)
+
+ assertTrue(trackerBlocked!!.trackingCategories.first() == TrackingCategory.SOCIAL)
+
+ SystemEngineView.URL_MATCHER = null
+ }
+
+ @Test
+ @Suppress("Deprecation")
+ fun `WebViewClient calls interceptor from deprecated onReceivedError API`() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+ doNothing().`when`(engineSession).initSettings()
+
+ val requestInterceptor: RequestInterceptor = mock()
+ val webViewClient = engineSession.webView.webViewClient
+
+ // No session or interceptor attached.
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verifyNoInteractions(requestInterceptor)
+
+ // Session attached, but not interceptor.
+ engineView.render(engineSession)
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verifyNoInteractions(requestInterceptor)
+
+ // Session and interceptor.
+ engineSession.settings.requestInterceptor = requestInterceptor
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verify(requestInterceptor).onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random")
+
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.webView = webView
+ val errorResponse = RequestInterceptor.ErrorResponse("about:fail")
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verify(webView, never()).loadUrl(ArgumentMatchers.anyString())
+
+ whenever(requestInterceptor.onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random"))
+ .thenReturn(errorResponse)
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verify(webView).loadUrl("about:fail")
+
+ val errorResponse2 = RequestInterceptor.ErrorResponse("about:fail2")
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verify(webView, never()).loadUrl("about:fail2")
+
+ whenever(requestInterceptor.onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random"))
+ .thenReturn(errorResponse2)
+ webViewClient.onReceivedError(
+ engineSession.webView,
+ WebViewClient.ERROR_UNKNOWN,
+ null,
+ "http://failed.random",
+ )
+ verify(webView).loadUrl("about:fail2")
+ }
+
+ @Test
+ fun `WebViewClient calls interceptor from new onReceivedError API`() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+ doNothing().`when`(engineSession).initSettings()
+
+ val requestInterceptor: RequestInterceptor = mock()
+ val webViewClient = engineSession.webView.webViewClient
+ val webRequest: WebResourceRequest = mock()
+ val webError: WebResourceError = mock()
+ val url: Uri = mock()
+
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verifyNoInteractions(requestInterceptor)
+
+ engineView.render(engineSession)
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verifyNoInteractions(requestInterceptor)
+
+ whenever(webError.errorCode).thenReturn(WebViewClient.ERROR_UNKNOWN)
+ whenever(webRequest.url).thenReturn(url)
+ whenever(url.toString()).thenReturn("http://failed.random")
+ engineSession.settings.requestInterceptor = requestInterceptor
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verify(requestInterceptor, never()).onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random")
+
+ whenever(webRequest.isForMainFrame).thenReturn(true)
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verify(requestInterceptor).onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random")
+
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.webView = webView
+ val errorResponse = RequestInterceptor.ErrorResponse("about:fail")
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verify(webView, never()).loadUrl(ArgumentMatchers.anyString())
+
+ whenever(requestInterceptor.onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random"))
+ .thenReturn(errorResponse)
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verify(webView).loadUrl("about:fail")
+
+ val errorResponse2 = RequestInterceptor.ErrorResponse("about:fail2")
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verify(webView, never()).loadUrl("about:fail2")
+
+ whenever(requestInterceptor.onErrorRequest(engineSession, ErrorType.UNKNOWN, "http://failed.random"))
+ .thenReturn(errorResponse2)
+ webViewClient.onReceivedError(engineSession.webView, webRequest, webError)
+ verify(webView).loadUrl("about:fail2")
+ }
+
+ @Test
+ fun `WebViewClient calls interceptor when onReceivedSslError`() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+ doNothing().`when`(engineSession).initSettings()
+
+ val requestInterceptor: RequestInterceptor = mock()
+ val webViewClient = engineSession.webView.webViewClient
+ val handler: SslErrorHandler = mock()
+ val error: SslError = mock()
+
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verifyNoInteractions(requestInterceptor)
+
+ engineView.render(engineSession)
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verifyNoInteractions(requestInterceptor)
+
+ whenever(error.primaryError).thenReturn(SslError.SSL_EXPIRED)
+ whenever(error.url).thenReturn("http://failed.random")
+ engineSession.settings.requestInterceptor = requestInterceptor
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verify(requestInterceptor).onErrorRequest(engineSession, ErrorType.ERROR_SECURITY_SSL, "http://failed.random")
+ verify(handler, times(3)).cancel()
+
+ val webView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(webView.settings).thenReturn(settings)
+
+ engineSession.webView = webView
+ val errorResponse = RequestInterceptor.ErrorResponse("about:fail")
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verify(webView, never()).loadUrl(ArgumentMatchers.anyString())
+
+ whenever(
+ requestInterceptor.onErrorRequest(
+ engineSession,
+ ErrorType.ERROR_SECURITY_SSL,
+ "http://failed.random",
+ ),
+ ).thenReturn(errorResponse)
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verify(webView).loadUrl("about:fail")
+
+ val errorResponse2 = RequestInterceptor.ErrorResponse("about:fail2")
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verify(webView, never()).loadUrl("about:fail2")
+
+ whenever(requestInterceptor.onErrorRequest(engineSession, ErrorType.ERROR_SECURITY_SSL, "http://failed.random"))
+ .thenReturn(errorResponse2)
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verify(webView).loadUrl("about:fail2")
+
+ whenever(requestInterceptor.onErrorRequest(engineSession, ErrorType.ERROR_SECURITY_SSL, "http://failed.random"))
+ .thenReturn(RequestInterceptor.ErrorResponse("http://failed.random"))
+ webViewClient.onReceivedSslError(engineSession.webView, handler, error)
+ verify(webView).loadUrl("http://failed.random")
+ }
+
+ @Test
+ fun `WebViewClient blocks WebFonts`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val webViewClient = engineSession.webView.webViewClient
+ val webFontRequest = mock<WebResourceRequest>()
+ whenever(webFontRequest.url).thenReturn(Uri.parse("/fonts/test.woff"))
+ assertNull(webViewClient.shouldInterceptRequest(engineSession.webView, webFontRequest))
+
+ engineView.render(engineSession)
+ assertNull(webViewClient.shouldInterceptRequest(engineSession.webView, webFontRequest))
+
+ engineSession.settings.webFontsEnabled = false
+
+ val request = mock<WebResourceRequest>()
+ whenever(request.url).thenReturn(Uri.parse("http://mozilla.org"))
+ assertNull(webViewClient.shouldInterceptRequest(engineSession.webView, request))
+
+ val response = webViewClient.shouldInterceptRequest(engineSession.webView, webFontRequest)
+ assertNotNull(response)
+ assertNull(response!!.data)
+ assertNull(response.encoding)
+ assertNull(response.mimeType)
+ }
+
+ @Test
+ fun `FindListener notifies observers`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observerNotified = false
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onFindResult(activeMatchOrdinal: Int, numberOfMatches: Int, isDoneCounting: Boolean) {
+ assertEquals(0, activeMatchOrdinal)
+ assertEquals(1, numberOfMatches)
+ assertTrue(isDoneCounting)
+ observerNotified = true
+ }
+ },
+ )
+
+ val listener = engineView.createFindListener()
+ listener.onFindResultReceived(0, 1, true)
+ assertTrue(observerNotified)
+ }
+
+ @Test
+ fun `lifecycle methods are invoked`() {
+ val mockWebView = mock<WebView>()
+ val settings = mock<WebSettings>()
+ whenever(mockWebView.settings).thenReturn(settings)
+
+ val engineSession1 = SystemEngineSession(testContext)
+ val engineSession2 = SystemEngineSession(testContext)
+
+ val engineView = SystemEngineView(testContext)
+ engineView.onPause()
+ engineView.onResume()
+ engineView.onDestroy()
+
+ engineSession1.webView = mockWebView
+ engineView.render(engineSession1)
+ engineView.onDestroy()
+
+ engineView.render(engineSession2)
+ assertNotNull(engineSession2.webView.parent)
+
+ engineView.onDestroy()
+ assertNull(engineSession2.webView.parent)
+
+ engineView.render(engineSession1)
+ engineView.onPause()
+ verify(mockWebView, times(1)).onPause()
+ verify(mockWebView, times(1)).pauseTimers()
+
+ engineView.onResume()
+ verify(mockWebView, times(1)).onResume()
+ verify(mockWebView, times(1)).resumeTimers()
+
+ engineView.onDestroy()
+ }
+
+ @Test
+ fun `showCustomView notifies fullscreen mode observers and execs callback`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val observer: EngineSession.Observer = mock()
+ engineSession.register(observer)
+
+ val view = mock<View>()
+ val customViewCallback = mock<WebChromeClient.CustomViewCallback>()
+ engineSession.webView.webChromeClient!!.onShowCustomView(view, customViewCallback)
+
+ verify(observer).onFullScreenChange(true)
+ }
+
+ @Test
+ fun `addFullScreenView execs callback and removeView`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val view = View(ApplicationProvider.getApplicationContext())
+ val customViewCallback = mock<WebChromeClient.CustomViewCallback>()
+
+ assertNull(engineSession.fullScreenCallback)
+
+ engineSession.webView.webChromeClient!!.onShowCustomView(view, customViewCallback)
+
+ assertNotNull(engineSession.fullScreenCallback)
+ assertEquals(customViewCallback, engineSession.fullScreenCallback)
+ assertEquals("mozac_system_engine_fullscreen", view.tag)
+
+ engineSession.webView.webChromeClient!!.onHideCustomView()
+ assertEquals(View.VISIBLE, engineSession.webView.visibility)
+ }
+
+ @Test
+ fun `addFullScreenView with no matching webView`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val view = View(ApplicationProvider.getApplicationContext())
+ val customViewCallback = mock<WebChromeClient.CustomViewCallback>()
+
+ engineSession.webView.tag = "not_webview"
+ engineSession.webView.webChromeClient!!.onShowCustomView(view, customViewCallback)
+
+ assertNotEquals(View.INVISIBLE, engineSession.webView.visibility)
+ }
+
+ @Test
+ fun `removeFullScreenView with no matching views`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ val view = View(ApplicationProvider.getApplicationContext())
+ val customViewCallback = mock<WebChromeClient.CustomViewCallback>()
+
+ // When the fullscreen view isn't available
+ engineSession.webView.webChromeClient!!.onShowCustomView(view, customViewCallback)
+ engineView.findViewWithTag<View>("mozac_system_engine_fullscreen").tag = "not_fullscreen"
+
+ engineSession.webView.webChromeClient!!.onHideCustomView()
+
+ assertNotNull(engineSession.fullScreenCallback)
+ verify(engineSession.fullScreenCallback, never())?.onCustomViewHidden()
+ assertEquals(View.INVISIBLE, engineSession.webView.visibility)
+
+ // When fullscreen view is available, but WebView isn't.
+ engineView.findViewWithTag<View>("not_fullscreen").tag = "mozac_system_engine_fullscreen"
+ engineSession.webView.tag = "not_webView"
+
+ engineSession.webView.webChromeClient!!.onHideCustomView()
+
+ assertEquals(View.INVISIBLE, engineSession.webView.visibility)
+ }
+
+ @Test
+ fun `fullscreenCallback is null`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ engineSession.webView.webChromeClient!!.onHideCustomView()
+ assertNull(engineSession.fullScreenCallback)
+ }
+
+ @Test
+ fun `onPageFinished handles invalid URL`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observedUrl = ""
+ var observedLoadingState = true
+ var observedSecurityChange: Triple<Boolean, String?, String?> = Triple(false, null, null)
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onLoadingStateChange(loading: Boolean) { observedLoadingState = loading }
+ override fun onLocationChange(url: String, hasUserGesture: Boolean) { observedUrl = url }
+ override fun onSecurityChange(secure: Boolean, host: String?, issuer: String?) {
+ observedSecurityChange = Triple(secure, host, issuer)
+ }
+ },
+ )
+
+ // We need a certificate to trigger parsing the potentially invalid URL for
+ // the host parameter in onSecurityChange
+ val view = mock<WebView>()
+ val certificate = mock<SslCertificate>()
+ val dName = mock<SslCertificate.DName>()
+ doReturn("testCA").`when`(dName).oName
+ doReturn(dName).`when`(certificate).issuedBy
+ doReturn(certificate).`when`(view).certificate
+
+ engineSession.webView.webViewClient.onPageFinished(view, "invalid:")
+ assertEquals("invalid:", observedUrl)
+ assertFalse(observedLoadingState)
+ assertEquals(Triple(true, null, "testCA"), observedSecurityChange)
+ }
+
+ @Test
+ fun `URL matcher categories can be changed`() {
+ SystemEngineView.URL_MATCHER = null
+ val resources = testContext.resources
+
+ var urlMatcher = SystemEngineView.getOrCreateUrlMatcher(
+ resources,
+ TrackingProtectionPolicy.select(
+ arrayOf(
+ TrackingCategory.AD,
+ TrackingCategory.ANALYTICS,
+ ),
+ ),
+ )
+ assertEquals(setOf(UrlMatcher.ADVERTISING, UrlMatcher.ANALYTICS), urlMatcher.enabledCategories)
+
+ urlMatcher = SystemEngineView.getOrCreateUrlMatcher(
+ resources,
+ TrackingProtectionPolicy.select(
+ arrayOf(
+ TrackingCategory.AD,
+ TrackingCategory.SOCIAL,
+ ),
+ ),
+ )
+ assertEquals(setOf(UrlMatcher.ADVERTISING, UrlMatcher.SOCIAL), urlMatcher.enabledCategories)
+ }
+
+ @Test
+ fun `URL matcher supports compounded categories`() {
+ val recommendedPolicy = TrackingProtectionPolicy.recommended()
+ val strictPolicy = TrackingProtectionPolicy.strict()
+ val resources = testContext.resources
+ val recommendedCategories = setOf(
+ UrlMatcher.ADVERTISING,
+ UrlMatcher.ANALYTICS,
+ UrlMatcher.SOCIAL,
+ UrlMatcher.FINGERPRINTING,
+ UrlMatcher.CRYPTOMINING,
+ )
+ val strictCategories = setOf(
+ UrlMatcher.ADVERTISING,
+ UrlMatcher.ANALYTICS,
+ UrlMatcher.SOCIAL,
+ UrlMatcher.FINGERPRINTING,
+ UrlMatcher.CRYPTOMINING,
+ )
+
+ var urlMatcher = SystemEngineView.getOrCreateUrlMatcher(resources, recommendedPolicy)
+
+ assertEquals(recommendedCategories, urlMatcher.enabledCategories)
+
+ urlMatcher = SystemEngineView.getOrCreateUrlMatcher(resources, strictPolicy)
+
+ assertEquals(strictCategories, urlMatcher.enabledCategories)
+ }
+
+ @Test
+ fun `permission requests are forwarded to observers`() {
+ val permissionRequest: android.webkit.PermissionRequest = mock()
+ whenever(permissionRequest.resources).thenReturn(emptyArray())
+ whenever(permissionRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var observedPermissionRequest: PermissionRequest? = null
+ var cancelledPermissionRequest: PermissionRequest? = null
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onContentPermissionRequest(permissionRequest: PermissionRequest) {
+ observedPermissionRequest = permissionRequest
+ }
+
+ override fun onCancelContentPermissionRequest(permissionRequest: PermissionRequest) {
+ cancelledPermissionRequest = permissionRequest
+ }
+ },
+ )
+
+ engineSession.webView.webChromeClient!!.onPermissionRequest(permissionRequest)
+ assertNotNull(observedPermissionRequest)
+
+ engineSession.webView.webChromeClient!!.onPermissionRequestCanceled(permissionRequest)
+ assertNotNull(cancelledPermissionRequest)
+ }
+
+ @Test
+ fun `window requests are forwarded to observers`() {
+ val permissionRequest: android.webkit.PermissionRequest = mock()
+ whenever(permissionRequest.resources).thenReturn(emptyArray())
+ whenever(permissionRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ engineView.render(engineSession)
+
+ var createWindowRequest: WindowRequest? = null
+ var closeWindowRequest: WindowRequest? = null
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onWindowRequest(windowRequest: WindowRequest) {
+ if (windowRequest.type == WindowRequest.Type.OPEN) {
+ createWindowRequest = windowRequest
+ } else {
+ closeWindowRequest = windowRequest
+ }
+ }
+ },
+ )
+
+ engineSession.webView.webChromeClient!!.onCreateWindow(mock(), false, false, null)
+ assertNotNull(createWindowRequest)
+ assertNull(closeWindowRequest)
+
+ engineSession.webView.webChromeClient!!.onCloseWindow(mock())
+ assertNotNull(closeWindowRequest)
+ }
+
+ @Test
+ fun `Calling onShowFileChooser must provide a FilePicker PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var onSingleFileSelectedWasCalled = false
+ var onMultipleFilesSelectedWasCalled = false
+ var onDismissWasCalled = false
+ var request: PromptRequest? = null
+
+ val callback = ValueCallback<Array<Uri>> {
+ if (it == null) {
+ onDismissWasCalled = true
+ } else {
+ if (it.size == 1) {
+ onSingleFileSelectedWasCalled = true
+ } else {
+ onMultipleFilesSelectedWasCalled = true
+ }
+ }
+ }
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+
+ engineView.render(engineSession)
+
+ val mockFileChooserParams = mock<WebChromeClient.FileChooserParams>()
+
+ doReturn(MODE_OPEN_MULTIPLE).`when`(mockFileChooserParams).mode
+
+ engineSession.webView.webChromeClient!!.onShowFileChooser(null, callback, mockFileChooserParams)
+
+ val filePickerRequest = request as PromptRequest.File
+ assertTrue(request is PromptRequest.File)
+
+ filePickerRequest.onSingleFileSelected(mock(), mock())
+ assertTrue(onSingleFileSelectedWasCalled)
+
+ filePickerRequest.onMultipleFilesSelected(mock(), arrayOf(mock(), mock()))
+ assertTrue(onMultipleFilesSelectedWasCalled)
+
+ filePickerRequest.onDismiss()
+ assertTrue(onDismissWasCalled)
+
+ assertTrue(filePickerRequest.mimeTypes.isEmpty())
+ assertTrue(filePickerRequest.isMultipleFilesSelection)
+
+ doReturn(arrayOf("")).`when`(mockFileChooserParams).acceptTypes
+ engineSession.webView.webChromeClient!!.onShowFileChooser(null, callback, mockFileChooserParams)
+ assertTrue(filePickerRequest.mimeTypes.isEmpty())
+ }
+
+ @Test
+ fun `canScrollVerticallyDown can be called without session`() {
+ val engineView = SystemEngineView(testContext)
+ assertFalse(engineView.canScrollVerticallyDown())
+
+ engineView.render(SystemEngineSession(testContext))
+ assertFalse(engineView.canScrollVerticallyDown())
+ }
+
+ @Test
+ fun `onLongClick can be called without session`() {
+ val engineView = SystemEngineView(testContext)
+ assertFalse(engineView.onLongClick(null))
+
+ engineView.render(SystemEngineSession(testContext))
+ assertFalse(engineView.onLongClick(null))
+ }
+
+ @Test
+ fun `Calling onJsAlert must provide an Alert PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+
+ engineView.render(engineSession)
+
+ val mockJSResult = mock<JsResult>()
+
+ engineSession.webView.webChromeClient!!.onJsAlert(mock(), "http://www.mozilla.org", "message", mockJSResult)
+
+ val alertRequest = request as PromptRequest.Alert
+ assertTrue(request is PromptRequest.Alert)
+
+ assertTrue(alertRequest.title.contains("mozilla.org"))
+ assertEquals(alertRequest.message, "message")
+
+ alertRequest.onConfirm(true)
+ verify(mockJSResult).confirm()
+
+ alertRequest.onDismiss()
+ verify(mockJSResult).cancel()
+ }
+
+ @Test
+ fun `calling onJsPrompt must provide a TextPrompt PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+
+ engineView.render(engineSession)
+
+ val mockJSPromptResult = mock<JsPromptResult>()
+
+ engineSession.webView.webChromeClient!!.onJsPrompt(
+ mock(),
+ "http://www.mozilla.org",
+ "message",
+ "defaultValue",
+ mockJSPromptResult,
+ )
+
+ val textPromptRequest = request as PromptRequest.TextPrompt
+ assertTrue(request is PromptRequest.TextPrompt)
+
+ assertTrue(textPromptRequest.title.contains("mozilla.org"))
+ assertEquals(textPromptRequest.hasShownManyDialogs, false)
+ assertEquals(textPromptRequest.inputLabel, "message")
+ assertEquals(textPromptRequest.inputValue, "defaultValue")
+
+ textPromptRequest.onConfirm(true, "value")
+ verify(mockJSPromptResult).confirm("value")
+
+ textPromptRequest.onDismiss()
+ verify(mockJSPromptResult).cancel()
+
+ textPromptRequest.onConfirm(true, "value")
+ }
+
+ @Test
+ fun `calling onJsPrompt with a null session must not provide a TextPrompt PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+
+ engineView.render(engineSession)
+
+ val mockJSPromptResult = mock<JsPromptResult>()
+ engineView.session = null
+
+ val wasTheDialogHandled = engineSession.webView.webChromeClient!!.onJsPrompt(
+ mock(),
+ "http://www.mozilla.org",
+ "message",
+ "defaultValue",
+ mockJSPromptResult,
+ )
+
+ assertTrue(wasTheDialogHandled)
+ assertNull(request)
+ verify(mockJSPromptResult).cancel()
+ }
+
+ @Test
+ fun `calling onJsConfirm must provide a Confirm PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+
+ engineView.render(engineSession)
+
+ val mockJSPromptResult = mock<JsResult>()
+
+ engineSession.webView.webChromeClient!!.onJsConfirm(
+ mock(),
+ "http://www.mozilla.org",
+ "message",
+ mockJSPromptResult,
+ )
+
+ val confirmPromptRequest = request as PromptRequest.Confirm
+ assertTrue(request is PromptRequest.Confirm)
+
+ assertTrue(confirmPromptRequest.title.contains("mozilla.org"))
+ assertEquals(confirmPromptRequest.hasShownManyDialogs, false)
+ assertEquals(confirmPromptRequest.message, "message")
+
+ confirmPromptRequest.onConfirmPositiveButton(true)
+ verify(mockJSPromptResult).confirm()
+
+ confirmPromptRequest.onDismiss()
+ verify(mockJSPromptResult).cancel()
+
+ confirmPromptRequest.onConfirmNegativeButton(true)
+ verify(mockJSPromptResult, times(2)).cancel()
+ }
+
+ @Test
+ @Config(sdk = [Build.VERSION_CODES.N])
+ fun captureThumbnailOnPreO() {
+ val activity = Robolectric.buildActivity(Activity::class.java).setup().get()
+ val engineView = SystemEngineView(activity)
+ val webView = mock<WebView>()
+
+ whenever(webView.width).thenReturn(100)
+ whenever(webView.height).thenReturn(200)
+
+ engineView.session = mock()
+
+ whenever(engineView.session!!.webView).thenReturn(webView)
+
+ var thumbnail: Bitmap? = null
+
+ engineView.captureThumbnail {
+ thumbnail = it
+ }
+ verify(webView).draw(any())
+ assertNotNull(thumbnail)
+
+ engineView.session = null
+ engineView.captureThumbnail {
+ thumbnail = it
+ }
+
+ assertNull(thumbnail)
+ }
+
+ @Test
+ @Config(sdk = [Build.VERSION_CODES.O], shadows = [PixelCopyShadow::class])
+ fun captureThumbnailOnPostO() {
+ val activity = Robolectric.buildActivity(Activity::class.java).setup().get()
+ val engineView = SystemEngineView(activity)
+ val webView = mock<WebView>()
+ whenever(webView.width).thenReturn(100)
+ whenever(webView.height).thenReturn(200)
+
+ var thumbnail: Bitmap? = null
+
+ engineView.session = null
+ engineView.captureThumbnail {
+ thumbnail = it
+ }
+ assertNull(thumbnail)
+
+ engineView.session = mock()
+ whenever(engineView.session!!.webView).thenReturn(webView)
+
+ PixelCopyShadow.copyResult = PixelCopy.ERROR_UNKNOWN
+ engineView.captureThumbnail {
+ thumbnail = it
+ }
+ assertNull(thumbnail)
+
+ PixelCopyShadow.copyResult = PixelCopy.SUCCESS
+ engineView.captureThumbnail {
+ thumbnail = it
+ }
+ assertNotNull(thumbnail)
+ }
+
+ @Test
+ fun `calling onReceivedHttpAuthRequest must provide an Authentication PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+ engineView.render(engineSession)
+
+ val authHandler = mock<HttpAuthHandler>()
+ val host = "mozilla.org"
+ val realm = "realm"
+
+ engineSession.webView.webViewClient.onReceivedHttpAuthRequest(engineSession.webView, authHandler, host, realm)
+
+ val authRequest = request as PromptRequest.Authentication
+ assertTrue(request is PromptRequest.Authentication)
+
+ assertEquals(authRequest.title, "")
+
+ authRequest.onConfirm("u", "p")
+ verify(authHandler).proceed("u", "p")
+
+ authRequest.onDismiss()
+ verify(authHandler).cancel()
+ }
+
+ @Test
+ fun `calling onReceivedHttpAuthRequest with a null session must not provide an Authentication PromptRequest`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+ engineView.render(engineSession)
+
+ val authHandler = mock<HttpAuthHandler>()
+ engineView.session = null
+
+ engineSession.webView.webViewClient.onReceivedHttpAuthRequest(mock(), authHandler, "mozilla.org", "realm")
+
+ assertNull(request)
+ verify(authHandler).cancel()
+ }
+
+ @Test
+ fun `onReceivedHttpAuthRequest correctly handles realm`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+ engineView.render(engineSession)
+
+ val webView = engineSession.webView
+ val authHandler = mock<HttpAuthHandler>()
+ val host = "mozilla.org"
+
+ val longRealm = "Login with a user name of httpwatch and a different password each time"
+ webView.webViewClient.onReceivedHttpAuthRequest(webView, authHandler, host, longRealm)
+ assertTrue((request as PromptRequest.Authentication).message.endsWith("differen…”"))
+
+ val emptyRealm = ""
+ webView.webViewClient.onReceivedHttpAuthRequest(webView, authHandler, host, emptyRealm)
+ val noRealmMessageTail = testContext.getString(R.string.mozac_browser_engine_system_auth_no_realm_message).let {
+ it.substring(it.length - 10)
+ }
+ assertTrue((request as PromptRequest.Authentication).message.endsWith(noRealmMessageTail))
+ }
+
+ @Test
+ @Config(sdk = [Build.VERSION_CODES.N])
+ @Suppress("Deprecation")
+ fun `onReceivedHttpAuthRequest takes credentials from WebView`() {
+ val engineSession = SystemEngineSession(testContext)
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+
+ engineSession.webView = spy(engineSession.webView)
+ engineView.render(engineSession)
+
+ // use captor as getWebViewClient() is available only from Oreo
+ // and this test runs on N to not use WebViewDatabase
+ val captor = argumentCaptor<WebViewClient>()
+ verify(engineSession.webView).webViewClient = captor.capture()
+ val webViewClient = captor.value
+
+ val host = "mozilla.org"
+ val realm = "realm"
+ val userName = "user123"
+ val password = "pass@123"
+
+ val validCredentials = arrayOf(userName, password)
+ whenever(engineSession.webView.getHttpAuthUsernamePassword(host, realm)).thenReturn(validCredentials)
+ webViewClient.onReceivedHttpAuthRequest(engineSession.webView, mock(), host, realm)
+ assertEquals((request as PromptRequest.Authentication).userName, userName)
+ assertEquals((request as PromptRequest.Authentication).password, password)
+
+ val nullCredentials = null
+ whenever(engineSession.webView.getHttpAuthUsernamePassword(host, realm)).thenReturn(nullCredentials)
+ webViewClient.onReceivedHttpAuthRequest(engineSession.webView, mock(), host, realm)
+ assertEquals((request as PromptRequest.Authentication).userName, "")
+ assertEquals((request as PromptRequest.Authentication).password, "")
+
+ val credentialsWithNulls = arrayOf<String?>(null, null)
+ whenever(engineSession.webView.getHttpAuthUsernamePassword(host, realm)).thenReturn(credentialsWithNulls)
+ webViewClient.onReceivedHttpAuthRequest(engineSession.webView, mock(), host, realm)
+ assertEquals((request as PromptRequest.Authentication).userName, "")
+ assertEquals((request as PromptRequest.Authentication).password, "")
+ }
+
+ @Test
+ @Config(sdk = [Build.VERSION_CODES.O])
+ fun `onReceivedHttpAuthRequest uses WebViewDatabase on Oreo+`() {
+ val engineSession = spy(SystemEngineSession(testContext))
+ val engineView = SystemEngineView(testContext)
+ var request: PromptRequest? = null
+
+ engineSession.register(
+ object : EngineSession.Observer {
+ override fun onPromptRequest(promptRequest: PromptRequest) {
+ request = promptRequest
+ }
+ },
+ )
+ engineView.render(engineSession)
+
+ val host = "mozilla.org"
+ val realm = "realm"
+ val userName = "userFromDB"
+ val password = "pass@123FromDB"
+ val webViewDatabase = mock<WebViewDatabase>()
+ whenever(webViewDatabase.getHttpAuthUsernamePassword(host, realm)).thenReturn(arrayOf(userName, password))
+ whenever(engineSession.webViewDatabase(testContext)).thenReturn(webViewDatabase)
+
+ engineSession.webView.webViewClient.onReceivedHttpAuthRequest(engineSession.webView, mock(), host, realm)
+
+ val authRequest = request as PromptRequest.Authentication
+ assertEquals(authRequest.userName, userName)
+ assertEquals(authRequest.password, password)
+ }
+
+ @Test
+ fun `GIVEN SystemEngineView WHEN getInputResultDetail is called THEN it returns the instance from webView`() {
+ val engineView = SystemEngineView(testContext)
+ val engineSession = SystemEngineSession(testContext)
+ val webView = spy(NestedWebView(testContext))
+ engineSession.webView = webView
+ engineView.render(engineSession)
+ val inputResult = InputResultDetail.newInstance()
+ doReturn(inputResult).`when`(webView).inputResultDetail
+
+ assertSame(inputResult, engineView.getInputResultDetail())
+ }
+
+ @Test
+ fun `GIVEN SystemEngineView WHEN getInputResultDetail is called THEN it returns a new default instance if not available from webView`() {
+ val engineView = spy(SystemEngineView(testContext))
+
+ val result = engineView.getInputResultDetail()
+
+ assertNotNull(result)
+ assertTrue(result.isTouchHandlingUnknown())
+ assertFalse(result.canScrollToLeft())
+ assertFalse(result.canScrollToTop())
+ assertFalse(result.canScrollToRight())
+ assertFalse(result.canScrollToBottom())
+ assertFalse(result.canOverscrollLeft())
+ assertFalse(result.canOverscrollTop())
+ assertFalse(result.canOverscrollRight())
+ assertFalse(result.canOverscrollBottom())
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/ReversibleStringTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/ReversibleStringTest.kt
new file mode 100644
index 0000000000..e7c417be45
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/ReversibleStringTest.kt
@@ -0,0 +1,122 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.matcher
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class ReversibleStringTest {
+
+ @Test(expected = StringIndexOutOfBoundsException::class)
+ @Throws(StringIndexOutOfBoundsException::class)
+ fun outOfBounds() {
+ val fullStringRaw = "a"
+ val fullString = ReversibleString.create(fullStringRaw)
+ fullString.charAt(1)
+ }
+
+ @Test(expected = StringIndexOutOfBoundsException::class)
+ @Throws(StringIndexOutOfBoundsException::class)
+ fun outOfBoundsAfterSubstring() {
+ val fullStringRaw = "abcd"
+ val fullString = ReversibleString.create(fullStringRaw)
+
+ val substring = fullString.substring(3)
+ substring.charAt(1)
+ }
+
+ @Test(expected = StringIndexOutOfBoundsException::class)
+ @Throws(StringIndexOutOfBoundsException::class)
+ fun outOfBoundsSubstring() {
+ val fullStringRaw = "abcd"
+ val fullString = ReversibleString.create(fullStringRaw)
+ fullString.substring(5)
+ }
+
+ @Test(expected = StringIndexOutOfBoundsException::class)
+ @Throws(StringIndexOutOfBoundsException::class)
+ fun outOfBoundsSubstringNegative() {
+ val fullStringRaw = "abcd"
+ val fullString = ReversibleString.create(fullStringRaw)
+ fullString.substring(-1)
+ }
+
+ @Test(expected = StringIndexOutOfBoundsException::class)
+ @Throws(StringIndexOutOfBoundsException::class)
+ fun outOfBoundsAfterSubstringEmpty() {
+ val fullStringRaw = "abcd"
+ val fullString = ReversibleString.create(fullStringRaw)
+
+ val substring = fullString.substring(4)
+ substring.charAt(0)
+ }
+
+ @Test
+ fun substringLength() {
+ val fullStringRaw = "a"
+ val fullString = ReversibleString.create(fullStringRaw)
+
+ assertEquals("Length must match input string length", fullStringRaw.length, fullString.length())
+
+ val sameString = fullString.substring(0)
+ assertEquals("substring(0) should equal input String", fullStringRaw.length, sameString.length())
+ assertEquals("substring(0) should equal input String", fullStringRaw[0], sameString.charAt(0))
+
+ val emptyString = fullString.substring(1)
+ assertEquals("Empty substring should be empty", 0, emptyString.length())
+ }
+
+ @Test
+ fun forwardString() {
+ val fullStringRaw = "abcd"
+ val fullString = ReversibleString.create(fullStringRaw)
+
+ assertEquals("Length must match input string length", fullStringRaw.length, fullString.length())
+
+ for (i in 0 until fullStringRaw.length) {
+ assertEquals("Character doesn't match input string character", fullStringRaw[i], fullString.charAt(i))
+ }
+
+ val substringRaw = fullStringRaw.substring(2)
+ val substring = fullString.substring(2)
+
+ for (i in 0 until substringRaw.length) {
+ assertEquals("Character doesn't match input string character", substringRaw[i], substring.charAt(i))
+ }
+ }
+
+ @Test
+ fun reverseString() {
+ val fullUnreversedStringRaw = "abcd"
+ val fullStringRaw = StringBuffer(fullUnreversedStringRaw).reverse().toString()
+ val fullString = ReversibleString.create(fullUnreversedStringRaw).reverse()
+
+ assertEquals("Length must match input string length", fullStringRaw.length, fullString.length())
+
+ for (i in 0 until fullStringRaw.length) {
+ assertEquals("Character doesn't match input string character", fullStringRaw[i], fullString.charAt(i))
+ }
+
+ val substringRaw = fullStringRaw.substring(2)
+ val substring = fullString.substring(2)
+
+ for (i in 0 until substringRaw.length) {
+ assertEquals("Character doesn't match input string character", substringRaw[i], substring.charAt(i))
+ }
+ }
+
+ @Test
+ fun reverseReversedString() {
+ val fullUnreversedStringRaw = "abcd"
+ val fullStringRaw = StringBuffer(fullUnreversedStringRaw).toString()
+ val fullString = ReversibleString.create(fullUnreversedStringRaw).reverse().reverse()
+
+ assertEquals("Length must match input string length", fullStringRaw.length, fullString.length())
+
+ for (i in 0 until fullStringRaw.length) {
+ assertEquals("Character doesn't match input string character", fullStringRaw[i], fullString.charAt(i))
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/SafelistTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/SafelistTest.kt
new file mode 100644
index 0000000000..0fdba4f16f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/SafelistTest.kt
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.browser.engine.system.matcher
+
+import android.util.JsonReader
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.StringReader
+
+@RunWith(AndroidJUnit4::class)
+class SafelistTest {
+
+ /**
+ * Test setup:
+ * mozilla.org: allow foo.com
+ * foo.mozilla.org: additionally allow bar.com
+ *
+ * Test:
+ * mozilla.org can only use foo.com, but foo.mozilla.org can use both foo.com and bar.com
+ */
+ @Test
+ fun safelist() {
+ val mozillaOrg = "mozilla.org"
+ val fooMozillaOrg = "foo.mozilla.org"
+ val fooCom = "foo.com"
+ val barCom = "bar.com"
+
+ val fooComTrie = Trie.createRootNode()
+ fooComTrie.put(fooCom.reverse())
+
+ val barComTrie = Trie.createRootNode()
+ barComTrie.put(barCom.reverse())
+
+ val safelist = Safelist()
+ safelist.put(mozillaOrg.reverse(), fooComTrie)
+ safelist.put(fooMozillaOrg.reverse(), barComTrie)
+
+ assertTrue(safelist.contains("http://$mozillaOrg", "http://$fooCom"))
+ assertFalse(safelist.contains("http://$mozillaOrg", "http://$barCom"))
+ assertTrue(safelist.contains("http://hello.$mozillaOrg", "http://$fooCom"))
+ assertFalse(safelist.contains("http://hello.$mozillaOrg", "http://$barCom"))
+ assertTrue(safelist.contains("http://$mozillaOrg/somewhere", "http://$fooCom/somewhereElse/bla/bla"))
+ assertFalse(safelist.contains("http://$mozillaOrg/another/page.html?u=a", "http://$barCom/hello"))
+
+ assertTrue(safelist.contains("http://$fooMozillaOrg", "http://$fooCom"))
+ assertTrue(safelist.contains("http://$fooMozillaOrg", "http://$barCom"))
+ assertTrue(safelist.contains("http://hello.$fooMozillaOrg", "http://$fooCom"))
+ assertTrue(safelist.contains("http://hello.$fooMozillaOrg", "http://$barCom"))
+ assertTrue(safelist.contains("http://$fooMozillaOrg/somewhere", "http://$fooCom/somewhereElse/bla/bla"))
+ assertTrue(safelist.contains("http://$fooMozillaOrg/another/page.html?u=a", "http://$barCom/hello"))
+
+ // Test some invalid inputs
+ assertFalse(safelist.contains("http://$barCom", "http://$barCom"))
+ assertFalse(safelist.contains("http://$barCom", "http://$mozillaOrg"))
+
+ // Check we don't safelist resources for data:
+ assertFalse(safelist.contains("data:text/html;stuff", "http://$fooCom/somewhereElse/bla/bla"))
+ }
+
+ @Test
+ fun safelistTrie() {
+ val safelist = Trie.createRootNode()
+ safelist.put("abc")
+
+ val trie = SafelistTrie.createRootNode()
+ trie.putSafelist("def", safelist)
+ Assert.assertNull(trie.findNode("abc"))
+
+ val foundSafelist = trie.findNode("def") as SafelistTrie
+ Assert.assertNotNull(foundSafelist)
+ Assert.assertNotNull(foundSafelist.safelist?.findNode("abc"))
+
+ try {
+ trie.putSafelist("def", safelist)
+ fail("Expected IllegalStateException")
+ } catch (e: IllegalStateException) { }
+ }
+
+ val SAFE_LIST_JSON = """{
+ "Host1": {
+ "properties": [
+ "host1.com",
+ "host1.de"
+ ],
+ "resources": [
+ "host1ads.com",
+ "host1ads.de"
+ ]
+ },
+ "Host2": {
+ "properties": [
+ "host2.com",
+ "host2.de"
+ ],
+ "resources": [
+ "host2ads.com",
+ "host2ads.de"
+ ]
+ }
+ }"""
+
+ @Test
+ fun fromJson() {
+ val safelist = Safelist.fromJson(JsonReader(StringReader(SAFE_LIST_JSON)))
+
+ assertTrue(safelist.contains("http://host1.com", "http://host1ads.com"))
+ assertTrue(safelist.contains("https://host1.com", "https://host1ads.de"))
+ assertTrue(safelist.contains("javascript://host1.de", "javascript://host1ads.com"))
+ assertTrue(safelist.contains("file://host1.de", "file://host1ads.de"))
+
+ assertTrue(safelist.contains("http://host2.com", "http://host2ads.com"))
+ assertTrue(safelist.contains("about://host2.com", "about://host2ads.de"))
+ assertTrue(safelist.contains("http://host2.de", "http://host2ads.com"))
+ assertTrue(safelist.contains("http://host2.de", "http://host2ads.de"))
+
+ assertFalse(safelist.contains("data://host2.de", "data://host2ads.de"))
+ assertFalse(safelist.contains("foo://host2.de", "foo://host2ads.de"))
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/TrieTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/TrieTest.kt
new file mode 100644
index 0000000000..38b47761a5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/TrieTest.kt
@@ -0,0 +1,46 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.matcher
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class TrieTest {
+
+ @Test
+ fun findNode() {
+ val trie = Trie.createRootNode()
+
+ assertNull(trie.findNode("hello"))
+ val putNode = trie.put("hello")
+ val foundNode = trie.findNode("hello")
+ assertNotNull(putNode)
+ assertNotNull(foundNode)
+ assertEquals(putNode, foundNode)
+
+ // Substring matching doesn't happen (except for subdomains)
+ assertNull(trie.findNode("hell"))
+ assertNull(trie.findNode("hellop"))
+
+ // Ensure both old and new overlapping strings can still be found
+ trie.put("hellohello")
+ assertNotNull(trie.findNode("hello"))
+ assertNotNull(trie.findNode("hellohello"))
+ assertNull(trie.findNode("hell"))
+ assertNull(trie.findNode("hellop"))
+
+ // Domain and subdomain can be found
+ trie.put("foo.com".reverse())
+ assertNotNull(trie.findNode("foo.com".reverse()))
+ assertNotNull(trie.findNode("bar.foo.com".reverse()))
+ assertNull(trie.findNode("bar-foo.com".reverse()))
+ assertNull(trie.findNode("oo.com".reverse()))
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/UrlMatcherTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/UrlMatcherTest.kt
new file mode 100644
index 0000000000..e01572e130
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/matcher/UrlMatcherTest.kt
@@ -0,0 +1,296 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.matcher
+
+import android.net.Uri
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.engine.system.matcher.UrlMatcher.Companion.ADVERTISING
+import mozilla.components.browser.engine.system.matcher.UrlMatcher.Companion.ANALYTICS
+import mozilla.components.browser.engine.system.matcher.UrlMatcher.Companion.CONTENT
+import mozilla.components.browser.engine.system.matcher.UrlMatcher.Companion.SOCIAL
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import java.io.StringReader
+import java.util.HashMap
+
+@RunWith(AndroidJUnit4::class)
+class UrlMatcherTest {
+
+ @Test
+ fun basicMatching() {
+ val matcher = UrlMatcher(arrayOf("bcd.random"))
+
+ assertTrue(matcher.matches("http://bcd.random/something", "http://mozilla.org").first)
+ assertTrue(matcher.matches("http://bcd.random", "http://mozilla.org").first)
+ assertTrue(matcher.matches("http://www.bcd.random", "http://mozilla.org").first)
+ assertTrue(matcher.matches("http://www.bcd.random/something", "http://mozilla.org").first)
+ assertTrue(matcher.matches("http://foobar.bcd.random", "http://mozilla.org").first)
+ assertTrue(matcher.matches("http://foobar.bcd.random/something", "http://mozilla.org").first)
+
+ assertFalse(matcher.matches("http://other.random", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://other.random/something", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://www.other.random", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://www.other.random/something", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://bcd.specific", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://bcd.specific/something", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://www.bcd.specific", "http://mozilla.org").first)
+ assertFalse(matcher.matches("http://www.bcd.specific/something", "http://mozilla.org").first)
+
+ assertFalse(matcher.matches("http://mozilla.org/resource", "data:text/html;stuff here").first)
+ assertTrue(matcher.matches("http://bcd.random/resource", "data:text/html;stuff here").first)
+ }
+
+ /**
+ * Tests that category enabling/disabling works correctly. We test this by creating
+ * 4 categories, each with only one domain. We then iterate over all permutations of categories,
+ * and test that only the expected domains are actually blocked.
+ */
+ @Test
+ fun enableDisableCategories() {
+ val categories = HashMap<String, Trie>()
+ val suppportedCategories = mutableSetOf<String>()
+ val enabledCategories = mutableSetOf<String>()
+ val categoryCount = 4
+
+ for (i in 0 until categoryCount) {
+ val trie = Trie.createRootNode()
+ trie.put("category$i.com".reverse())
+
+ val categoryName = "category$i"
+ categories[categoryName] = trie
+ enabledCategories.add(categoryName)
+ suppportedCategories.add(categoryName)
+ }
+
+ val matcher = UrlMatcher(suppportedCategories, enabledCategories, categories)
+
+ // We can test every permutation by iterating over every value of a 4-bit integer (each bit
+ // indicates whether a given category is enabled or disabled).
+ // N categories -> N bits == (2^N - 1) == '1111...'
+ // 4 categories -> 4 bits == 15 == 2^N-1 = '1111'
+ val allEnabledPattern = (1 shl categoryCount) - 1
+ for (categoryPattern in 0..allEnabledPattern) {
+ // Ensure all the correct categories enabled
+ for (currentCategory in 0 until categoryCount) {
+ val currentBit = 1 shl currentCategory
+ val enabled = currentBit and categoryPattern == currentBit
+ matcher.setCategoryEnabled("category$currentCategory", enabled)
+
+ // Make sure our category enabling code actually sets the correct
+ // values for a few known combinations (i.e. we're doing a test within the test)
+ if (categoryPattern == 0) {
+ assertFalse("All categories should be disabled for categorypattern==0", enabled)
+ } else if (categoryPattern == allEnabledPattern) {
+ assertTrue("All categories should be enabled for categorypattern=='111....'", enabled)
+ } else if (categoryPattern == Integer.parseInt("1100", 2)) {
+ if (currentCategory < 2) {
+ assertFalse("Categories 0/1 expected to be disabled", enabled)
+ } else {
+ assertTrue("Categories >= 2 expected to be enabled", enabled)
+ }
+ }
+ }
+
+ for (currentCategory in 0 until categoryCount) {
+ val currentBit = 1 shl currentCategory
+ val enabled = currentBit and categoryPattern == currentBit
+ val url = "http://category$currentCategory.com"
+ assertEquals(
+ "Incorrect category matched for combo=$categoryPattern url=$url",
+ enabled,
+ matcher.matches(url, "http://www.mozilla.org").first,
+ )
+ }
+ }
+ }
+
+ val BLOCK_LIST = """{
+ "license": "test-license",
+ "categories": {
+ "Advertising": [
+ {
+ "AdTest1": {
+ "http://www.adtest1.com/": [
+ "adtest1.com",
+ "adtest1.de"
+ ]
+ }
+ },
+ {
+ "AdTest2": {
+ "http://www.adtest2.com/": [
+ "adtest2.com"
+ ]
+ }
+ }
+ ],
+ "Analytics": [
+ {
+ "AnalyticsTest": {
+ "http://analyticsTest1.com/": [
+ "analyticsTest1.com",
+ "analyticsTest1.de"
+ ]
+ }
+ }
+ ],
+ "Content": [
+ {
+ "ContentTest1": {
+ "http://contenttest1.com/": [
+ "contenttest1.com"
+ ]
+ }
+ }
+ ],
+ "Social": [
+ {
+ "SocialTest1": {
+ "http://www.socialtest1.com/": [
+ "socialtest1.com",
+ "socialtest1.de"
+ ]
+ }
+ }
+ ],
+ "Legacy Disconnect": [
+ {
+ "Ignored1": {
+ "http://www.ignored1.com/": [
+ "ignored.de"
+ ]
+ }
+ }
+ ],
+ "Legacy Content": [
+ {
+ "Ignored2": {
+ "http://www.ignored2.com/": [
+ "ignored.de"
+ ]
+ }
+ }
+ ]
+ }
+ }
+ """
+
+ val SAFE_LIST = """{
+ "SocialTest1": {
+ "properties": [
+ "www.socialtest1.com"
+ ],
+ "resources": [
+ "socialtest1.de"
+ ]
+ }
+ }"""
+
+ @Test
+ fun createMatcher() {
+ val matcher = UrlMatcher.createMatcher(
+ StringReader(BLOCK_LIST),
+ StringReader(SAFE_LIST),
+ )
+
+ // Check returns correct category
+ val (matchesAds, categoryAds) = matcher.matches("http://adtest1.com", "http://www.adtest1.com")
+
+ assertTrue(matchesAds)
+ assertEquals(categoryAds, ADVERTISING)
+
+ val (matchesAds2, categoryAd2) = matcher.matches("http://adtest1.de", "http://www.adtest1.com")
+
+ assertTrue(matchesAds2)
+ assertEquals(categoryAd2, ADVERTISING)
+
+ val (matchesSocial, categorySocial) = matcher.matches(
+ "http://socialtest1.com/",
+ "http://www.socialtest1.com/",
+ )
+
+ assertTrue(matchesSocial)
+ assertEquals(categorySocial, SOCIAL)
+
+ val (matchesContent, categoryContent) = matcher.matches(
+ "http://contenttest1.com/",
+ "http://www.contenttest1.com/",
+ )
+
+ assertTrue(matchesContent)
+ assertEquals(categoryContent, CONTENT)
+
+ val (matchesAnalytics, categoryAnalytics) = matcher.matches(
+ "http://analyticsTest1.com/",
+ "http://www.analyticsTest1.com/",
+ )
+
+ assertTrue(matchesAnalytics)
+ assertEquals(categoryAnalytics, ANALYTICS)
+
+ // Check that safe list worked
+ assertTrue(matcher.matches("http://socialtest1.com", "http://www.socialtest1.com").first)
+ assertFalse(matcher.matches("http://socialtest1.de", "http://www.socialtest1.com").first)
+
+ // Check ignored categories
+ assertFalse(matcher.matches("http://ignored1.de", "http://www.ignored1.com").first)
+ assertFalse(matcher.matches("http://ignored2.de", "http://www.ignored2.com").first)
+ }
+
+ @Test
+ fun isWebFont() {
+ assertFalse(UrlMatcher.isWebFont(mock()))
+ assertFalse(UrlMatcher.isWebFont(Uri.parse("mozilla.org")))
+ assertTrue(UrlMatcher.isWebFont(Uri.parse("/fonts/test.woff2")))
+ assertTrue(UrlMatcher.isWebFont(Uri.parse("/fonts/test.woff")))
+ assertTrue(UrlMatcher.isWebFont(Uri.parse("/fonts/test.eot")))
+ assertTrue(UrlMatcher.isWebFont(Uri.parse("/fonts/test.ttf")))
+ assertTrue(UrlMatcher.isWebFont(Uri.parse("/fonts/test.otf")))
+ }
+
+ @Test
+ fun setCategoriesEnabled() {
+ val matcher = spy(
+ UrlMatcher.createMatcher(
+ StringReader(BLOCK_LIST),
+ StringReader(SAFE_LIST),
+ setOf("Advertising", "Analytics"),
+ ),
+ )
+
+ matcher.setCategoriesEnabled(setOf("Advertising", "Analytics"))
+ verify(matcher, never()).setCategoryEnabled(any(), anyBoolean())
+
+ matcher.setCategoriesEnabled(setOf("Advertising", "Analytics", "Content"))
+ verify(matcher).setCategoryEnabled("Advertising", true)
+ verify(matcher).setCategoryEnabled("Analytics", true)
+ verify(matcher).setCategoryEnabled("Content", true)
+ }
+
+ @Test
+ fun webFontsNotBlockedByDefault() {
+ val matcher = UrlMatcher.createMatcher(
+ StringReader(BLOCK_LIST),
+ StringReader(SAFE_LIST),
+ setOf(UrlMatcher.ADVERTISING, UrlMatcher.ANALYTICS, UrlMatcher.SOCIAL, UrlMatcher.CONTENT),
+ )
+
+ assertFalse(
+ matcher.matches(
+ "http://mozilla.org/fonts/test.woff2",
+ "http://mozilla.org",
+ ).first,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequestTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequestTest.kt
new file mode 100644
index 0000000000..bed30887bb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/permission/SystemPermissionRequestTest.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.engine.system.permission
+
+import android.net.Uri
+import android.webkit.PermissionRequest
+import android.webkit.PermissionRequest.RESOURCE_AUDIO_CAPTURE
+import android.webkit.PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID
+import android.webkit.PermissionRequest.RESOURCE_VIDEO_CAPTURE
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.concept.engine.permission.Permission
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.whenever
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class SystemPermissionRequestTest {
+
+ @Test
+ fun `uri is equal to native request origin`() {
+ val nativeRequest: PermissionRequest = mock()
+ whenever(nativeRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+ whenever(nativeRequest.resources).thenReturn(emptyArray())
+ val request = SystemPermissionRequest(nativeRequest)
+ assertEquals(request.uri, "https://mozilla.org")
+ }
+
+ @Test
+ fun `resources are correctly mapped to permissions`() {
+ val nativeRequest: PermissionRequest = mock()
+ whenever(nativeRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+ whenever(nativeRequest.resources).thenReturn(
+ arrayOf(
+ RESOURCE_AUDIO_CAPTURE,
+ RESOURCE_VIDEO_CAPTURE,
+ RESOURCE_PROTECTED_MEDIA_ID,
+ ),
+ )
+
+ val expected = listOf(
+ Permission.ContentAudioCapture(RESOURCE_AUDIO_CAPTURE),
+ Permission.ContentVideoCapture(RESOURCE_VIDEO_CAPTURE),
+ Permission.ContentProtectedMediaId(RESOURCE_PROTECTED_MEDIA_ID),
+ )
+ val request = SystemPermissionRequest(nativeRequest)
+ assertEquals(expected, request.permissions)
+ }
+
+ @Test
+ fun `reject denies native request`() {
+ val nativeRequest: PermissionRequest = mock()
+ whenever(nativeRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+ whenever(nativeRequest.resources).thenReturn(emptyArray())
+
+ val request = SystemPermissionRequest(nativeRequest)
+ request.reject()
+ verify(nativeRequest).deny()
+ }
+
+ @Test
+ fun `grant permission to all native request resources`() {
+ val resources = arrayOf(
+ RESOURCE_AUDIO_CAPTURE,
+ RESOURCE_VIDEO_CAPTURE,
+ RESOURCE_PROTECTED_MEDIA_ID,
+ )
+
+ val nativeRequest: PermissionRequest = mock()
+ whenever(nativeRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+ whenever(nativeRequest.resources).thenReturn(resources)
+
+ val request = SystemPermissionRequest(nativeRequest)
+ request.grant()
+ verify(nativeRequest).grant(eq(resources))
+ }
+
+ @Test
+ fun `grant permission to selected native request resources`() {
+ val resources = arrayOf(
+ RESOURCE_AUDIO_CAPTURE,
+ RESOURCE_VIDEO_CAPTURE,
+ RESOURCE_PROTECTED_MEDIA_ID,
+ )
+
+ val nativeRequest: PermissionRequest = mock()
+ whenever(nativeRequest.origin).thenReturn(Uri.parse("https://mozilla.org"))
+ whenever(nativeRequest.resources).thenReturn(resources)
+
+ val request = SystemPermissionRequest(nativeRequest)
+ request.grant(listOf(Permission.ContentAudioCapture(RESOURCE_AUDIO_CAPTURE)))
+ verify(nativeRequest).grant(eq(arrayOf(RESOURCE_AUDIO_CAPTURE)))
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/window/SystemWindowRequestTest.kt b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/window/SystemWindowRequestTest.kt
new file mode 100644
index 0000000000..37efa78ace
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/window/SystemWindowRequestTest.kt
@@ -0,0 +1,76 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.engine.system.window
+
+import android.os.Message
+import android.webkit.WebSettings
+import android.webkit.WebView
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.engine.system.SystemEngineSession
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.support.test.whenever
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class SystemWindowRequestTest {
+
+ @Test
+ fun `init request`() {
+ val curWebView = mock<WebView>()
+ val newWebView = mock<WebView>()
+ val newEngineSession = mock<SystemEngineSession>()
+ val request = SystemWindowRequest(curWebView, newEngineSession, newWebView, true, true)
+
+ assertTrue(request.openAsDialog)
+ assertTrue(request.triggeredByUser)
+ assertEquals("", request.url)
+ }
+
+ @Test
+ fun `prepare sets webview on engine session`() {
+ val curWebView = mock<WebView>()
+ val newWebView = mock<WebView>()
+ val settings = mock<WebSettings>()
+
+ whenever(curWebView.settings).thenReturn(settings)
+ whenever(newWebView.settings).thenReturn(settings)
+
+ val newEngineSession = SystemEngineSession(testContext)
+ val request = SystemWindowRequest(curWebView, newEngineSession, newWebView)
+
+ val engineSession = request.prepare() as SystemEngineSession
+ assertSame(newWebView, engineSession.webView)
+ }
+
+ @Test
+ fun `start sends message to target`() {
+ val curWebView = mock<WebView>()
+ val newWebView = mock<WebView>()
+ val resultMsg = mock<Message>()
+ val newEngineSession = mock<SystemEngineSession>()
+
+ SystemWindowRequest(curWebView, newEngineSession, newWebView, false, false).start()
+ verify(resultMsg, never()).sendToTarget()
+
+ SystemWindowRequest(curWebView, newEngineSession, newWebView, false, false, resultMsg).start()
+ verify(resultMsg, never()).sendToTarget()
+
+ resultMsg.obj = ""
+ SystemWindowRequest(curWebView, newEngineSession, newWebView, false, false, resultMsg).start()
+ verify(resultMsg, never()).sendToTarget()
+
+ resultMsg.obj = mock<WebView.WebViewTransport>()
+ SystemWindowRequest(curWebView, newEngineSession, newWebView, false, false, resultMsg).start()
+ verify(resultMsg, times(1)).sendToTarget()
+ }
+}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/browser/engine-system/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/engine-system/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/browser/engine-system/src/test/resources/robolectric.properties b/mobile/android/android-components/components/browser/engine-system/src/test/resources/robolectric.properties
new file mode 100644
index 0000000000..932b01b9eb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/engine-system/src/test/resources/robolectric.properties
@@ -0,0 +1 @@
+sdk=28