Skip to content

Commit 562c4da

Browse files
authored
Live content updates for Privacy Dashboard
* Add live content updates to the Privacy Dashboard * Refactor tracking event to include network information and remove repeated lookups which are slow * Update outdated gradle dependencies
1 parent e15cd46 commit 562c4da

24 files changed

+334
-269
lines changed

app/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ android {
7474
}
7575

7676
ext {
77-
supportLibrary = "27.0.1"
77+
supportLibrary = "27.0.2"
7878
architectureComponents = "1.0.0"
7979
dagger = "2.13"
8080
retrofit = "2.3.0"
@@ -103,14 +103,14 @@ dependencies {
103103
kapt "com.google.dagger:dagger-android-processor:$dagger"
104104
kapt "com.google.dagger:dagger-compiler:$dagger"
105105

106-
testImplementation "org.mockito:mockito-core:2.12.0"
106+
testImplementation "org.mockito:mockito-core:2.13.0"
107107
testImplementation "com.nhaarman:mockito-kotlin-kt1.1:1.5.0"
108108
testImplementation "junit:junit:4.12"
109109
testImplementation "android.arch.core:core-testing:$architectureComponents"
110110

111111
androidTestImplementation "com.android.support.test:runner:1.0.1"
112112
androidTestImplementation "com.android.support.test.espresso:espresso-core:3.0.1"
113-
androidTestImplementation "org.mockito:mockito-android:2.12.0"
113+
androidTestImplementation "org.mockito:mockito-android:2.13.0"
114114
androidTestImplementation "com.nhaarman:mockito-kotlin-kt1.1:1.5.0"
115115
androidTestImplementation "android.arch.core:core-testing:$architectureComponents"
116116
}

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserViewModelTest.kt

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@ import android.net.Uri
2222
import com.duckduckgo.app.browser.BrowserViewModel.NavigationCommand
2323
import com.duckduckgo.app.browser.BrowserViewModel.ViewState
2424
import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter
25-
import com.duckduckgo.app.trackerdetection.model.NetworkTrackers
25+
import com.duckduckgo.app.privacymonitor.store.PrivacyMonitorRepository
2626
import com.nhaarman.mockito_kotlin.mock
2727
import org.junit.After
2828
import org.junit.Assert.*
2929
import org.junit.Before
3030
import org.junit.Rule
3131
import org.junit.Test
3232
import org.mockito.ArgumentMatchers
33-
import org.mockito.Mock
3433
import org.mockito.Mockito.never
3534
import org.mockito.Mockito.verify
3635

@@ -40,26 +39,23 @@ class BrowserViewModelTest {
4039
@Suppress("unused")
4140
var instantTaskExecutorRule = InstantTaskExecutorRule()
4241

43-
@Mock
44-
private val viewStateObserver: Observer<ViewState> = mock()
45-
46-
@Mock
47-
private val queryObserver: Observer<String> = mock()
48-
49-
@Mock
50-
private val navigationObserver: Observer<NavigationCommand> = mock()
42+
private lateinit var viewStateObserver: Observer<ViewState>
43+
private lateinit var queryObserver: Observer<String>
44+
private lateinit var navigationObserver: Observer<NavigationCommand>
45+
private lateinit var testee: BrowserViewModel
5146

5247
private val testOmnibarConverter: OmnibarEntryConverter = object : OmnibarEntryConverter {
5348
override fun convertUri(input: String): String = "duckduckgo.com"
5449
override fun isWebUrl(inputQuery: String): Boolean = true
5550
override fun convertQueryToUri(inputQuery: String): Uri = Uri.parse("duckduckgo.com")
5651
}
5752

58-
private lateinit var testee: BrowserViewModel
59-
6053
@Before
6154
fun before() {
62-
testee = BrowserViewModel(testOmnibarConverter, DuckDuckGoUrlDetector(), NetworkTrackers())
55+
viewStateObserver = mock()
56+
queryObserver = mock()
57+
navigationObserver = mock()
58+
testee = BrowserViewModel(testOmnibarConverter, DuckDuckGoUrlDetector(), PrivacyMonitorRepository())
6359
testee.query.observeForever(queryObserver)
6460
testee.viewState.observeForever(viewStateObserver)
6561
testee.navigation.observeForever(navigationObserver)

app/src/androidTest/java/com/duckduckgo/app/privacydashboard/PrivacyDashboardViewModelTest.kt

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,21 @@ import org.junit.Assert.assertEquals
2929
import org.junit.Before
3030
import org.junit.Rule
3131
import org.junit.Test
32-
import org.mockito.Mock
3332

3433
class PrivacyDashboardViewModelTest {
3534

3635
@get:Rule
3736
@Suppress("unused")
3837
var instantTaskExecutorRule = InstantTaskExecutorRule()
3938

40-
@Mock
41-
private val viewStateObserver: Observer<PrivacyDashboardViewModel.ViewState> = mock()
42-
43-
@Mock
44-
private val monitor: PrivacyMonitor = mock()
45-
39+
private lateinit var viewStateObserver: Observer<PrivacyDashboardViewModel.ViewState>
40+
private lateinit var monitor: PrivacyMonitor
4641
private lateinit var testee: PrivacyDashboardViewModel
4742

4843
@Before
4944
fun before() {
45+
viewStateObserver = mock()
46+
monitor = mock()
5047
testee = PrivacyDashboardViewModel(InstrumentationRegistry.getTargetContext())
5148
testee.viewState.observeForever(viewStateObserver)
5249
whenever(monitor.https).thenReturn(HttpsStatus.SECURE)
@@ -60,52 +57,52 @@ class PrivacyDashboardViewModelTest {
6057
@Test
6158
fun whenHttpsStatusIsSecureThenTextAndIconReflectSame() {
6259
whenever(monitor.https).thenReturn(HttpsStatus.SECURE)
63-
testee.updatePrivacyMonitor(monitor)
60+
testee.onPrivacyMonitorChanged(monitor)
6461
assertEquals(getStringResource(R.string.httpsGood), testee.viewState.value?.httpsText)
6562
assertEquals(R.drawable.dashboard_https_good, testee.viewState.value?.httpsIcon)
6663
}
6764

6865
@Test
6966
fun whenHttpsStatusIsMixedThenTextAndIconReflectSame() {
7067
whenever(monitor.https).thenReturn(HttpsStatus.MIXED)
71-
testee.updatePrivacyMonitor(monitor)
68+
testee.onPrivacyMonitorChanged(monitor)
7269
assertEquals(getStringResource(R.string.httpsMixed), testee.viewState.value?.httpsText)
7370
assertEquals(R.drawable.dashboard_https_neutral, testee.viewState.value?.httpsIcon)
7471
}
7572

7673
@Test
7774
fun whenHttpsStatusIsNoneThenTextAndIconReflectSame() {
7875
whenever(monitor.https).thenReturn(HttpsStatus.NONE)
79-
testee.updatePrivacyMonitor(monitor)
76+
testee.onPrivacyMonitorChanged(monitor)
8077
assertEquals(getStringResource(R.string.httpsBad), testee.viewState.value?.httpsText)
8178
assertEquals(R.drawable.dashboard_https_bad, testee.viewState.value?.httpsIcon)
8279
}
8380

8481
@Test
8582
fun whenNoTrackersNetworksThenNetworkTextShowsZero() {
8683
whenever(monitor.networkCount).thenReturn(0)
87-
testee.updatePrivacyMonitor(monitor)
84+
testee.onPrivacyMonitorChanged(monitor)
8885
assertEquals("0 Tracker Networks Blocked", testee.viewState.value?.networksText)
8986
}
9087

9188
@Test
9289
fun whenTenTrackersNetworksThenNetworkTextShowsTen() {
9390
whenever(monitor.networkCount).thenReturn(10)
94-
testee.updatePrivacyMonitor(monitor)
91+
testee.onPrivacyMonitorChanged(monitor)
9592
assertEquals("10 Tracker Networks Blocked", testee.viewState.value?.networksText)
9693
}
9794

9895
@Test
9996
fun whenNoMajorTrackersNetworksThenMajorNetworkTextShowsZero() {
10097
whenever(monitor.majorNetworkCount).thenReturn(0)
101-
testee.updatePrivacyMonitor(monitor)
98+
testee.onPrivacyMonitorChanged(monitor)
10299
assertEquals("0 Major Tracker Networks Blocked", testee.viewState.value?.majorNetworksText)
103100
}
104101

105102
@Test
106103
fun whenTenMajorTrackersNetworksThenMajorNetworkTextShowsTen() {
107104
whenever(monitor.majorNetworkCount).thenReturn(10)
108-
testee.updatePrivacyMonitor(monitor)
105+
testee.onPrivacyMonitorChanged(monitor)
109106
assertEquals("10 Major Tracker Networks Blocked", testee.viewState.value?.majorNetworksText)
110107
}
111108

app/src/androidTest/java/com/duckduckgo/app/privacymonitor/SiteMonitorInstrumentationTests.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.duckduckgo.app.privacymonitor
1818

19-
import com.duckduckgo.app.trackerdetection.model.NetworkTrackers
2019
import org.junit.Assert.assertEquals
2120
import org.junit.Test
2221

@@ -30,26 +29,26 @@ class SiteMonitorInstrumentationTests {
3029

3130
@Test
3231
fun whenUrlIsHttpsThenHttpsStatusIsSecure() {
33-
val testee = SiteMonitor(httpsDocument, NetworkTrackers())
32+
val testee = SiteMonitor(httpsDocument)
3433
assertEquals(HttpsStatus.SECURE, testee.https)
3534
}
3635

3736
@Test
3837
fun whenUrlIsHttpThenHttpsStatusIsNone() {
39-
val testee = SiteMonitor(httpDocument, NetworkTrackers())
38+
val testee = SiteMonitor(httpDocument)
4039
assertEquals(HttpsStatus.NONE, testee.https)
4140
}
4241

4342
@Test
4443
fun whenUrlIsHttpsWithHttpResourcesThenHttpsStatusIsMixed() {
45-
val testee = SiteMonitor(httpsDocument, NetworkTrackers())
44+
val testee = SiteMonitor(httpsDocument)
4645
testee.hasHttpResources = true
4746
assertEquals(HttpsStatus.MIXED, testee.https)
4847
}
4948

5049
@Test
5150
fun whenUrlIsMalformedThenHttpsStatusIsNone() {
52-
val testee = SiteMonitor(malformesDocument, NetworkTrackers())
51+
val testee = SiteMonitor(malformesDocument)
5352
assertEquals(HttpsStatus.NONE, testee.https)
5453
}
5554
}

app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TrackerDetectorInstrumentationTest.kt

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,19 @@
1616

1717
package com.duckduckgo.app.trackerdetection
1818

19-
import com.duckduckgo.app.trackerdetection.model.DisconnectTracker
20-
import com.duckduckgo.app.trackerdetection.model.NetworkTrackers
21-
import com.duckduckgo.app.trackerdetection.model.ResourceType
19+
import com.duckduckgo.app.trackerdetection.model.*
2220
import com.nhaarman.mockito_kotlin.any
2321
import com.nhaarman.mockito_kotlin.mock
2422
import com.nhaarman.mockito_kotlin.whenever
25-
import org.junit.Assert.assertFalse
26-
import org.junit.Assert.assertTrue
23+
import org.junit.Assert.assertEquals
24+
import org.junit.Assert.assertNull
2725
import org.junit.Test
2826
import org.mockito.ArgumentMatchers.anyString
29-
import java.util.*
3027

3128

3229
class TrackerDetectorInstrumentationTest {
3330

34-
private val networkTrackers = NetworkTrackers()
31+
private val networkTrackers = TrackerNetworks()
3532
private val trackerDetector = TrackerDetector(networkTrackers)
3633

3734
companion object {
@@ -40,71 +37,89 @@ class TrackerDetectorInstrumentationTest {
4037
}
4138

4239
@Test
43-
fun whenThereAreNoClientsThenShouldBlockIsFalse() {
44-
assertFalse(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
40+
fun whenThereAreNoClientsThenEvaluateReturnsNull() {
41+
assertNull(trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
4542
}
4643

4744
@Test
48-
fun whenAllClientsFailToMatchThenShouldBlockIsFalse() {
45+
fun whenAllClientsFailToMatchThenEvaluateReturnsNull() {
4946
trackerDetector.addClient(neverMatchingClient())
5047
trackerDetector.addClient(neverMatchingClient())
51-
assertFalse(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
48+
assertNull(trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
5249
}
5350

5451
@Test
55-
fun whenAllClientsMatchThenShouldBlockIsTrue() {
52+
fun whenAllClientsMatchThenEvaluateReturnsTrackingEvent() {
5653
trackerDetector.addClient(alwaysMatchingClient())
5754
trackerDetector.addClient(alwaysMatchingClient())
58-
assertTrue(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
55+
val expected = TrackingEvent("http://example.com/index.com", "http://thirdparty.com/update.js", null, true)
56+
val actual = trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType)
57+
assertEquals(expected, actual)
5958
}
6059

6160
@Test
62-
fun whenSomeClientsMatchThenShouldBlockIsTrue() {
61+
fun whenSomeClientsMatchThenEvaluateReturnsTrackingEvent() {
6362
trackerDetector.addClient(neverMatchingClient())
6463
trackerDetector.addClient(alwaysMatchingClient())
65-
assertTrue(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
64+
val expected = TrackingEvent("http://example.com/index.com", "http://thirdparty.com/update.js", null, true)
65+
val actual = trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType)
66+
assertEquals(expected, actual)
6667
}
6768

6869
@Test
69-
fun whenUrlHasSameDomainAsDocumentThenShouldBlockIsFalse() {
70+
fun whenTrackerIsPartOfNetworkThenEvaluateReturnsTrackingEventWithNetwork() {
71+
val networks = arrayListOf(
72+
DisconnectTracker("thirdparty.com", "", network, "http://network.com")
73+
)
74+
networkTrackers.updateData(networks)
75+
trackerDetector.addClient(alwaysMatchingClient())
76+
77+
val network = TrackerNetwork(network, "http://network.com")
78+
val expected = TrackingEvent("http://example.com/index.com", "http://thirdparty.com/update.js", network, true)
79+
val actual = trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType)
80+
assertEquals(expected, actual)
81+
}
82+
83+
@Test
84+
fun whenUrlHasSameDomainAsDocumentThenEvaluateReturnsNull() {
7085
trackerDetector.addClient(alwaysMatchingClient())
71-
assertFalse(trackerDetector.shouldBlock("http://example.com/update.js", "http://example.com/index.com", resourceType))
86+
assertNull(trackerDetector.evaluate("http://example.com/update.js", "http://example.com/index.com", resourceType))
7287
}
7388

7489
@Test
75-
fun whenUrlIsSubdomainOfDocumentThenShouldBlockIsFalse() {
90+
fun whenUrlIsSubdomainOfDocumentThenEvaluateReturnsNull() {
7691
trackerDetector.addClient(alwaysMatchingClient())
77-
assertFalse(trackerDetector.shouldBlock("http://mobile.example.com/update.js", "http://example.com/index.com", resourceType))
92+
assertNull(trackerDetector.evaluate("http://mobile.example.com/update.js", "http://example.com/index.com", resourceType))
7893
}
7994

8095
@Test
81-
fun whenUrlIsParentOfDocumentThenShouldBlockIsFalse() {
96+
fun whenUrlIsParentOfDocumentThenEvaluateReturnsNull() {
8297
trackerDetector.addClient(alwaysMatchingClient())
83-
assertFalse(trackerDetector.shouldBlock("http://example.com/update.js", "http://mobile.example.com/index.com", resourceType))
98+
assertNull(trackerDetector.evaluate("http://example.com/update.js", "http://mobile.example.com/index.com", resourceType))
8499
}
85100

86101
@Test
87-
fun whenUrlIsNetworkOfDocumentThenShouldBlockIsFalse() {
88-
val networks = Arrays.asList(DisconnectTracker("example.com", "", network, "http://thirdparty.com/"))
102+
fun whenUrlIsNetworkOfDocumentThenEvaluateReturnsNull() {
103+
val networks = arrayListOf(DisconnectTracker("example.com", "", network, "http://thirdparty.com/"))
89104
networkTrackers.updateData(networks)
90-
assertFalse(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
105+
assertNull(trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
91106
}
92107

93108
@Test
94-
fun whenDocumentIsNetworkOfUrlThenShouldBlockIsFalse() {
95-
val networks = Arrays.asList(DisconnectTracker("thirdparty.com", "", network, "http://example.com"))
109+
fun whenDocumentIsNetworkOfUrlThenEvaluateReturnsNull() {
110+
val networks = arrayListOf(DisconnectTracker("thirdparty.com", "", network, "http://example.com"))
96111
networkTrackers.updateData(networks)
97-
assertFalse(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
112+
assertNull(trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
98113
}
99114

100115
@Test
101-
fun whenUrlSharesSameNetworkAsDocumentThenShouldBlockIsFalse() {
102-
val networks = Arrays.asList(
116+
fun whenUrlSharesSameNetworkAsDocumentThenEvaluateReturnsNull() {
117+
val networks = arrayListOf(
103118
DisconnectTracker("thirdparty.com", "", network, "http://network.com"),
104119
DisconnectTracker("example.com", "", network, "http://network.com")
105120
)
106121
networkTrackers.updateData(networks)
107-
assertFalse(trackerDetector.shouldBlock("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
122+
assertNull(trackerDetector.evaluate("http://thirdparty.com/update.js", "http://example.com/index.com", resourceType))
108123
}
109124

110125
private fun alwaysMatchingClient(): Client {

app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TrackerDetectorListInstrumentationTest.kt

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ package com.duckduckgo.app.trackerdetection
2020
import android.support.test.runner.AndroidJUnit4
2121
import com.duckduckgo.app.trackerdetection.Client.ClientName.EASYLIST
2222
import com.duckduckgo.app.trackerdetection.Client.ClientName.EASYPRIVACY
23-
import com.duckduckgo.app.trackerdetection.model.NetworkTrackers
2423
import com.duckduckgo.app.trackerdetection.model.ResourceType
25-
import org.junit.Assert.assertFalse
26-
import org.junit.Assert.assertTrue
24+
import com.duckduckgo.app.trackerdetection.model.TrackerNetworks
25+
import com.duckduckgo.app.trackerdetection.model.TrackingEvent
26+
import org.junit.Assert.assertEquals
27+
import org.junit.Assert.assertNull
2728
import org.junit.Before
2829
import org.junit.Test
2930
import org.junit.runner.RunWith
@@ -43,27 +44,29 @@ class TrackerDetectorListInstrumentationTest {
4344
fun before() {
4445
val easylistAdblock = adblockClient(EASYLIST, "binary/easylist_sample")
4546
val easyprivacyAdblock = adblockClient(EASYPRIVACY, "binary/easyprivacy_sample")
46-
testee = TrackerDetector(NetworkTrackers())
47+
testee = TrackerDetector(TrackerNetworks())
4748
testee.addClient(easyprivacyAdblock)
4849
testee.addClient(easylistAdblock)
4950
}
5051

5152
@Test
52-
fun whenUrlIsInEasyListThenShouldBlockIsTrue() {
53+
fun whenUrlIsInEasyListThenEvaluateReturnsTrackingEvent() {
5354
val url = "http://imasdk.googleapis.com/js/sdkloader/ima3.js"
54-
assertTrue(testee.shouldBlock(url, documentUrl, resourceType))
55+
val expected = TrackingEvent(documentUrl, url, null, true)
56+
assertEquals(expected, testee.evaluate(url, documentUrl, resourceType))
5557
}
5658

5759
@Test
58-
fun whenUrlIsInEasyPrivacyListThenShouldBlockIsTrue() {
60+
fun whenUrlIsInEasyPrivacyListThenEvaluateReturnsTrackingEvent() {
5961
val url = "http://cdn.tagcommander.com/1705/tc_catalog.css"
60-
assertTrue(testee.shouldBlock(url, documentUrl, resourceType))
62+
val expected = TrackingEvent(documentUrl, url, null, true)
63+
assertEquals(expected, testee.evaluate(url, documentUrl, resourceType))
6164
}
6265

6366
@Test
64-
fun whenUrlIsNotInAnyTrackerListsThenShouldBlockIsFalse() {
67+
fun whenUrlIsNotInAnyTrackerListsThenEvaluateReturnsNull() {
6568
val url = "https://duckduckgo.com/index.html"
66-
assertFalse(testee.shouldBlock(url, documentUrl, resourceType))
69+
assertNull(testee.evaluate(url, documentUrl, resourceType))
6770
}
6871

6972
private fun adblockClient(name: Client.ClientName, dataFile: String): Client {

0 commit comments

Comments
 (0)