Skip to content

Commit 0211e63

Browse files
committed
Merge branch 'release/5.73.0'
2 parents aafc58f + f2e428e commit 0211e63

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1512
-1118
lines changed

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import com.duckduckgo.app.browser.downloader.FileDownloader
4848
import com.duckduckgo.app.browser.favicon.FaviconManager
4949
import com.duckduckgo.app.browser.logindetection.LoginDetected
5050
import com.duckduckgo.app.browser.logindetection.NavigationAwareLoginDetector
51+
import com.duckduckgo.app.browser.logindetection.NavigationEvent
5152
import com.duckduckgo.app.browser.logindetection.NavigationEvent.LoginAttempt
5253
import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials
5354
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
@@ -71,6 +72,9 @@ import com.duckduckgo.app.global.model.SiteFactory
7172
import com.duckduckgo.app.global.useourapp.UseOurAppDetector
7273
import com.duckduckgo.app.global.useourapp.UseOurAppDetector.Companion.USE_OUR_APP_DOMAIN
7374
import com.duckduckgo.app.global.useourapp.UseOurAppDetector.Companion.USE_OUR_APP_SHORTCUT_URL
75+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlManager
76+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlManager.Companion.GPC_HEADER
77+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlManager.Companion.GPC_HEADER_VALUE
7478
import com.duckduckgo.app.location.GeoLocationPermissions
7579
import com.duckduckgo.app.location.data.LocationPermissionEntity
7680
import com.duckduckgo.app.location.data.LocationPermissionType
@@ -324,7 +328,8 @@ class BrowserTabViewModelTest {
324328
notificationDao = mockNotificationDao,
325329
useOurAppDetector = UseOurAppDetector(mockUserEventsStore),
326330
variantManager = mockVariantManager,
327-
fileDownloader = mockFileDownloader
331+
fileDownloader = mockFileDownloader,
332+
globalPrivacyControl = GlobalPrivacyControlManager(mockSettingsStore)
328333
)
329334

330335
testee.loadData("abc", null, false)
@@ -2940,7 +2945,7 @@ class BrowserTabViewModelTest {
29402945
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
29412946

29422947
val command = commandCaptor.lastValue as Navigate
2943-
assertEquals(BrowserTabViewModel.GPC_HEADER_VALUE, command.headers[BrowserTabViewModel.GPC_HEADER])
2948+
assertEquals(GPC_HEADER_VALUE, command.headers[GPC_HEADER])
29442949
}
29452950

29462951
@Test
@@ -2964,7 +2969,7 @@ class BrowserTabViewModelTest {
29642969
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
29652970

29662971
val command = commandCaptor.lastValue as Navigate
2967-
assertEquals(BrowserTabViewModel.GPC_HEADER_VALUE, command.headers[BrowserTabViewModel.GPC_HEADER])
2972+
assertEquals(GPC_HEADER_VALUE, command.headers[GPC_HEADER])
29682973
}
29692974

29702975
@Test
@@ -2988,7 +2993,7 @@ class BrowserTabViewModelTest {
29882993
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
29892994

29902995
val command = commandCaptor.lastValue as Command.HandleExternalAppLink
2991-
assertEquals(BrowserTabViewModel.GPC_HEADER_VALUE, command.headers[BrowserTabViewModel.GPC_HEADER])
2996+
assertEquals(GPC_HEADER_VALUE, command.headers[GPC_HEADER])
29922997
}
29932998

29942999
@Test
@@ -3016,6 +3021,12 @@ class BrowserTabViewModelTest {
30163021
verify(mockDismissedCtaDao).insert(DismissedCta(CtaId.DAX_FIRE_BUTTON_PULSE))
30173022
}
30183023

3024+
@Test
3025+
fun whenRedirectTriggeredByGpcThenGpcRedirectEventSent() {
3026+
testee.redirectTriggeredByGpc()
3027+
verify(mockNavigationAwareLoginDetector).onEvent(NavigationEvent.GpcRedirect)
3028+
}
3029+
30193030
private suspend fun givenFireButtonPulsing() {
30203031
whenever(mockUserStageStore.getUserAppStage()).thenReturn(AppStage.DAX_ONBOARDING)
30213032
dismissedCtaDaoChannel.send(listOf(DismissedCta(CtaId.DAX_DIALOG_TRACKERS_FOUND)))

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import com.duckduckgo.app.browser.logindetection.DOMLoginDetector
2828
import com.duckduckgo.app.browser.logindetection.WebNavigationEvent
2929
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
3030
import com.duckduckgo.app.global.exception.UncaughtExceptionRepository
31-
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlInjector
31+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControl
3232
import com.duckduckgo.app.runBlocking
3333
import com.duckduckgo.app.statistics.store.OfflinePixelCountDataStore
3434
import com.nhaarman.mockitokotlin2.*
@@ -55,7 +55,7 @@ class BrowserWebViewClientTest {
5555
private val offlinePixelCountDataStore: OfflinePixelCountDataStore = mock()
5656
private val uncaughtExceptionRepository: UncaughtExceptionRepository = mock()
5757
private val dosDetector: DosDetector = DosDetector()
58-
private val globalPrivacyControlInjector: GlobalPrivacyControlInjector = mock()
58+
private val globalPrivacyControl: GlobalPrivacyControl = mock()
5959
private val trustedCertificateStore: TrustedCertificateStore = mock()
6060

6161
@UiThreadTest
@@ -72,7 +72,7 @@ class BrowserWebViewClientTest {
7272
cookieManager,
7373
loginDetector,
7474
dosDetector,
75-
globalPrivacyControlInjector
75+
globalPrivacyControl
7676
)
7777
testee.webViewClientListener = listener
7878
}
@@ -111,7 +111,7 @@ class BrowserWebViewClientTest {
111111
@Test
112112
fun whenOnPageStartedCalledThenInjectDoNotSellToDom() = coroutinesTestRule.runBlocking {
113113
testee.onPageStarted(webView, EXAMPLE_URL, null)
114-
verify(globalPrivacyControlInjector).injectDoNotSellToDom(webView)
114+
verify(globalPrivacyControl).injectDoNotSellToDom(webView)
115115
}
116116

117117
@UiThreadTest

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

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@
1919
package com.duckduckgo.app.browser
2020

2121
import android.net.Uri
22+
import android.webkit.WebBackForwardList
23+
import android.webkit.WebHistoryItem
2224
import android.webkit.WebResourceRequest
2325
import android.webkit.WebResourceResponse
2426
import android.webkit.WebView
2527
import androidx.test.annotation.UiThreadTest
2628
import com.duckduckgo.app.CoroutineTestRule
29+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControl
30+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlManager
2731
import com.duckduckgo.app.httpsupgrade.HttpsUpgrader
2832
import com.duckduckgo.app.privacy.db.PrivacyProtectionCountDao
2933
import com.duckduckgo.app.surrogates.ResourceSurrogates
@@ -53,19 +57,22 @@ class WebViewRequestInterceptorTest {
5357
private var mockResourceSurrogates: ResourceSurrogates = mock()
5458
private var mockRequest: WebResourceRequest = mock()
5559
private val mockPrivacyProtectionCountDao: PrivacyProtectionCountDao = mock()
60+
private val mockGlobalPrivacyControl: GlobalPrivacyControl = mock()
61+
private val mockWebBackForwardList: WebBackForwardList = mock()
5662

5763
private var webView: WebView = mock()
5864

5965
@UiThreadTest
6066
@Before
6167
fun setup() {
62-
MockitoAnnotations.initMocks(this)
68+
MockitoAnnotations.openMocks(this)
6369

6470
testee = WebViewRequestInterceptor(
6571
trackerDetector = mockTrackerDetector,
6672
httpsUpgrader = mockHttpsUpgrader,
6773
resourceSurrogates = mockResourceSurrogates,
68-
privacyProtectionCountDao = mockPrivacyProtectionCountDao
74+
privacyProtectionCountDao = mockPrivacyProtectionCountDao,
75+
globalPrivacyControl = mockGlobalPrivacyControl
6976
)
7077
}
7178

@@ -333,6 +340,106 @@ class WebViewRequestInterceptorTest {
333340
verify(mockWebViewClientListener).upgradedToHttps()
334341
}
335342

343+
@Test
344+
fun whenUrlShouldBeUpgradedAndGcpActiveThenLoadUrlWithGpcHeaders() = runBlocking<Unit> {
345+
configureShouldUpgrade()
346+
configureShouldAddGpcHeader()
347+
val mockWebViewClientListener: WebViewClientListener = mock()
348+
349+
testee.shouldIntercept(
350+
request = mockRequest,
351+
documentUrl = null,
352+
webView = webView,
353+
webViewClientListener = mockWebViewClientListener
354+
)
355+
356+
verify(webView).loadUrl(validHttpsUri().toString(), mockGlobalPrivacyControl.getHeaders())
357+
}
358+
359+
@Test
360+
fun whenRequestShouldAddGcpHeadersThenRedirectTriggeredByGpcCalled() = runBlocking<Unit> {
361+
configureShouldNotUpgrade()
362+
configureShouldAddGpcHeader()
363+
configureUrlDoesNotExistInTheStack()
364+
val mockWebViewClientListener: WebViewClientListener = mock()
365+
366+
testee.shouldIntercept(
367+
request = mockRequest,
368+
documentUrl = null,
369+
webView = webView,
370+
webViewClientListener = mockWebViewClientListener
371+
)
372+
373+
verify(mockWebViewClientListener).redirectTriggeredByGpc()
374+
}
375+
376+
@Test
377+
fun whenRequestShouldAddGcpHeadersThenLoadUrlWithGpcHeaders() = runBlocking<Unit> {
378+
configureShouldNotUpgrade()
379+
configureShouldAddGpcHeader()
380+
configureUrlDoesNotExistInTheStack()
381+
val mockWebViewClientListener: WebViewClientListener = mock()
382+
383+
testee.shouldIntercept(
384+
request = mockRequest,
385+
documentUrl = null,
386+
webView = webView,
387+
webViewClientListener = mockWebViewClientListener
388+
)
389+
390+
verify(webView).loadUrl(validUri().toString(), mockGlobalPrivacyControl.getHeaders())
391+
}
392+
393+
@Test
394+
fun whenRequestShouldAddGcpHeadersButUrlExistsInTheStackThenLoadUrlNotCalled() = runBlocking<Unit> {
395+
configureShouldNotUpgrade()
396+
configureShouldAddGpcHeader()
397+
configureUrlExistsInTheStack()
398+
val mockWebViewClientListener: WebViewClientListener = mock()
399+
400+
testee.shouldIntercept(
401+
request = mockRequest,
402+
documentUrl = null,
403+
webView = webView,
404+
webViewClientListener = mockWebViewClientListener
405+
)
406+
407+
verify(webView, never()).loadUrl(any())
408+
}
409+
410+
@Test
411+
fun whenRequestShouldAddGcpHeadersButAlreadyContainsHeadersThenLoadUrlNotCalled() = runBlocking<Unit> {
412+
configureShouldNotUpgrade()
413+
configureRequestContainsGcpHeader()
414+
415+
val mockWebViewClientListener: WebViewClientListener = mock()
416+
417+
testee.shouldIntercept(
418+
request = mockRequest,
419+
documentUrl = null,
420+
webView = webView,
421+
webViewClientListener = mockWebViewClientListener
422+
)
423+
424+
verify(webView, never()).loadUrl(any(), any())
425+
}
426+
427+
@Test
428+
fun whenRequestShouldNotAddGcpHeadersThenLoadUrlNotCalled() = runBlocking<Unit> {
429+
configureShouldNotUpgrade()
430+
configureShouldNotAddGpcHeader()
431+
val mockWebViewClientListener: WebViewClientListener = mock()
432+
433+
testee.shouldIntercept(
434+
request = mockRequest,
435+
documentUrl = null,
436+
webView = webView,
437+
webViewClientListener = mockWebViewClientListener
438+
)
439+
440+
verify(webView, never()).loadUrl(any(), any())
441+
}
442+
336443
private fun assertRequestCanContinueToLoad(response: WebResourceResponse?) {
337444
assertNull(response)
338445
}
@@ -349,6 +456,41 @@ class WebViewRequestInterceptorTest {
349456
whenever(mockTrackerDetector.evaluate(any(), any())).thenReturn(blockTrackingEvent)
350457
}
351458

459+
private fun configureUrlExistsInTheStack() {
460+
val mockWebHistoryItem: WebHistoryItem = mock()
461+
whenever(mockWebHistoryItem.url).thenReturn(validUri().toString())
462+
whenever(mockWebBackForwardList.currentItem).thenReturn(mockWebHistoryItem)
463+
whenever(webView.copyBackForwardList()).thenReturn(mockWebBackForwardList)
464+
}
465+
466+
private fun configureUrlDoesNotExistInTheStack() {
467+
val mockWebHistoryItem: WebHistoryItem = mock()
468+
whenever(mockWebHistoryItem.url).thenReturn("www.test.com")
469+
whenever(mockWebBackForwardList.currentItem).thenReturn(mockWebHistoryItem)
470+
whenever(webView.copyBackForwardList()).thenReturn(mockWebBackForwardList)
471+
}
472+
473+
private fun configureRequestContainsGcpHeader() = runBlocking<Unit> {
474+
whenever(mockGlobalPrivacyControl.isGpcActive()).thenReturn(true)
475+
whenever(mockRequest.method).thenReturn("GET")
476+
whenever(mockRequest.requestHeaders).thenReturn(mapOf(GlobalPrivacyControlManager.GPC_HEADER to "test"))
477+
478+
}
479+
480+
private fun configureShouldAddGpcHeader() = runBlocking<Unit> {
481+
whenever(mockGlobalPrivacyControl.isGpcActive()).thenReturn(true)
482+
whenever(mockGlobalPrivacyControl.getHeaders()).thenReturn(mapOf("test" to "test"))
483+
whenever(mockGlobalPrivacyControl.shouldAddHeaders(any())).thenReturn(true)
484+
whenever(mockRequest.method).thenReturn("GET")
485+
}
486+
487+
private fun configureShouldNotAddGpcHeader() = runBlocking<Unit> {
488+
whenever(mockGlobalPrivacyControl.isGpcActive()).thenReturn(false)
489+
whenever(mockGlobalPrivacyControl.getHeaders()).thenReturn(mapOf("test" to "test"))
490+
whenever(mockGlobalPrivacyControl.shouldAddHeaders(any())).thenReturn(false)
491+
whenever(mockRequest.method).thenReturn("GET")
492+
}
493+
352494
private fun configureShouldUpgrade() = runBlocking<Unit> {
353495
whenever(mockHttpsUpgrader.shouldUpgrade(any())).thenReturn(true)
354496
whenever(mockHttpsUpgrader.upgrade(any())).thenReturn(validHttpsUri())
Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,32 @@
1717
package com.duckduckgo.app.globalprivacycontrol
1818

1919
import android.webkit.WebView
20+
import androidx.core.net.toUri
2021
import androidx.test.annotation.UiThreadTest
2122
import androidx.test.platform.app.InstrumentationRegistry
2223
import com.duckduckgo.app.browser.R
24+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlManager.Companion.GPC_HEADER
25+
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControlManager.Companion.GPC_HEADER_VALUE
2326
import com.duckduckgo.app.settings.db.SettingsDataStore
2427
import com.nhaarman.mockitokotlin2.mock
2528
import com.nhaarman.mockitokotlin2.never
2629
import com.nhaarman.mockitokotlin2.spy
2730
import com.nhaarman.mockitokotlin2.verify
2831
import com.nhaarman.mockitokotlin2.whenever
32+
import org.junit.Assert.assertEquals
33+
import org.junit.Assert.assertFalse
34+
import org.junit.Assert.assertTrue
2935
import org.junit.Before
3036
import org.junit.Test
3137

32-
class GlobalPrivacyControlInjectorJsTest {
38+
class GlobalPrivacyControlManagerTest {
3339

3440
private val mockSettingsStore: SettingsDataStore = mock()
35-
lateinit var testee: GlobalPrivacyControlInjectorJs
41+
lateinit var testee: GlobalPrivacyControlManager
3642

3743
@Before
3844
fun setup() {
39-
testee = GlobalPrivacyControlInjectorJs(mockSettingsStore)
45+
testee = GlobalPrivacyControlManager(mockSettingsStore)
4046
}
4147

4248
@UiThreadTest
@@ -63,6 +69,48 @@ class GlobalPrivacyControlInjectorJsTest {
6369
verify(webView, never()).evaluateJavascript(jsToEvaluate, null)
6470
}
6571

72+
@Test
73+
fun whenIsGpcActiveAndSettingEnabledThenReturnTrue() {
74+
whenever(mockSettingsStore.globalPrivacyControlEnabled).thenReturn(true)
75+
76+
assertTrue(testee.isGpcActive())
77+
}
78+
79+
@Test
80+
fun whenIsGpcActiveAndSettingDisabledThenReturnFalse() {
81+
whenever(mockSettingsStore.globalPrivacyControlEnabled).thenReturn(false)
82+
83+
assertFalse(testee.isGpcActive())
84+
}
85+
86+
@Test
87+
fun whenGetHeadersIfGpcIsEnabledThenReturnHeaders() {
88+
whenever(mockSettingsStore.globalPrivacyControlEnabled).thenReturn(true)
89+
90+
val headers = testee.getHeaders()
91+
92+
assertEquals(GPC_HEADER_VALUE, headers[GPC_HEADER])
93+
}
94+
95+
@Test
96+
fun whenGetHeadersIfGpcIsDisabledThenReturnEmptyMap() {
97+
whenever(mockSettingsStore.globalPrivacyControlEnabled).thenReturn(false)
98+
99+
val headers = testee.getHeaders()
100+
101+
assertTrue(headers.isEmpty())
102+
}
103+
104+
@Test
105+
fun whenShouldAddHeadersAndUrlIsFromTheHeadersConsumersListThenReturnTrue() {
106+
assertTrue(testee.shouldAddHeaders("http://nytimes.com".toUri()))
107+
}
108+
109+
@Test
110+
fun whenShouldAddHeadersAndUrlIsNotFromTheHeadersConsumersListThenReturnFalse() {
111+
assertFalse(testee.shouldAddHeaders("http://example.com".toUri()))
112+
}
113+
66114
private fun getJsToEvaluate(): String {
67115
val js = InstrumentationRegistry.getInstrumentation().targetContext.resources.openRawResource(R.raw.donotsell)
68116
.bufferedReader()

0 commit comments

Comments
 (0)