Skip to content

Commit c8bb558

Browse files
committed
Merge branch 'release/5.205.0' into main
2 parents 0281ac3 + 18f70f1 commit c8bb558

File tree

64 files changed

+518
-423
lines changed

Some content is hidden

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

64 files changed

+518
-423
lines changed

ad-click/ad-click-impl/src/main/java/com/duckduckgo/adclick/impl/DuckDuckGoAdClickData.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,14 @@ interface AdClickData {
3838
fun remove(tabId: String)
3939
fun removeAll()
4040
fun removeAllExpired()
41+
fun setCurrentPage(currentPageUrl: String)
42+
fun getCurrentPage(): String
4143
}
4244

4345
@ContributesBinding(AppScope::class)
4446
class DuckDuckGoAdClickData @Inject constructor() : AdClickData {
4547

48+
private var currentPageUrl = ""
4649
private var activeTabId = ""
4750
private val tabAdDomains = mutableMapOf<String, String>() // tabId -> adDomain or empty
4851
private val tabExemptions = mutableMapOf<String, Exemption>() // tabId -> exemption
@@ -128,4 +131,12 @@ class DuckDuckGoAdClickData @Inject constructor() : AdClickData {
128131
}
129132
Timber.d("Removed all expired data. Tab exemptions: $tabExemptions")
130133
}
134+
135+
override fun setCurrentPage(currentPageUrl: String) {
136+
this.currentPageUrl = currentPageUrl
137+
}
138+
139+
override fun getCurrentPage(): String {
140+
return currentPageUrl
141+
}
131142
}

ad-click/ad-click-impl/src/main/java/com/duckduckgo/adclick/impl/DuckDuckGoAdClickManager.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class DuckDuckGoAdClickManager @Inject constructor(
6464
}
6565

6666
val savedAdDomainTldPlusOne = adClickData.getAdDomainTldPlusOne()
67-
addNewExemption(savedAdDomainTldPlusOne, urlAdDomainTldPlusOne)
67+
addNewExemption(savedAdDomainTldPlusOne, urlAdDomainTldPlusOne, url)
6868

6969
adClickData.removeAdDomain()
7070
}
@@ -96,8 +96,10 @@ class DuckDuckGoAdClickManager @Inject constructor(
9696
// return false
9797

9898
val documentUrlHost = UriString.host(documentUrl)?.takeIf { it != DUCKDUCKGO_HOST } ?: return false
99+
val documentUrlTlDPlusOne = toTldPlusOne(documentUrl) ?: return false
99100

100-
if (!adClickData.isHostExempted(documentUrlHost)) {
101+
val hostExempted = adClickData.isHostExempted(documentUrlHost) || adClickData.isHostExempted(documentUrlTlDPlusOne)
102+
if (!hostExempted) {
101103
return false
102104
}
103105

@@ -111,6 +113,10 @@ class DuckDuckGoAdClickManager @Inject constructor(
111113
if (adClickAttribution.isAllowed(url)) {
112114
Timber.d("isExemption: Url $url MATCHES the allow list")
113115
val exemption = adClickData.getExemption()
116+
if (adClickData.getCurrentPage().isNotEmpty()) {
117+
adClickData.setCurrentPage("")
118+
adClickPixels.updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
119+
}
114120
val pixelFired = adClickPixels.fireAdClickActivePixel(exemption)
115121
if (pixelFired && exemption != null) {
116122
adClickData.addExemption(exemption.copy(adClickActivePixelFired = true))
@@ -173,7 +179,7 @@ class DuckDuckGoAdClickManager @Inject constructor(
173179
// - ad detection happens on the shopping vertical tab
174180
// - the advertiser landing page loads in a new tab
175181
val sourceTabAdDomainTldPLusOne = adClickData.getAdDomainTldPlusOne(sourceTabId)
176-
addNewExemption(sourceTabAdDomainTldPLusOne, hostTldPlusOne)
182+
addNewExemption(sourceTabAdDomainTldPLusOne, hostTldPlusOne, url)
177183
adClickData.removeAdDomain(sourceTabId)
178184
return
179185
}
@@ -191,7 +197,6 @@ class DuckDuckGoAdClickManager @Inject constructor(
191197
adClickActivePixelFired = false,
192198
),
193199
)
194-
adClickPixels.updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
195200
}
196201
} else {
197202
// propagate exemption with timeout since it's a different host
@@ -204,11 +209,12 @@ class DuckDuckGoAdClickManager @Inject constructor(
204209
adClickActivePixelFired = false,
205210
),
206211
)
207-
adClickPixels.updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
208212
}
209213
}
210214

211-
private fun addNewExemption(savedAdDomain: String?, urlAdDomain: String) {
215+
private fun addNewExemption(savedAdDomain: String?, urlAdDomain: String, url: String) {
216+
adClickData.setCurrentPage(url)
217+
212218
if (savedAdDomain != null) {
213219
adClickData.addExemption(
214220
Exemption(
@@ -223,7 +229,6 @@ class DuckDuckGoAdClickManager @Inject constructor(
223229
heuristicEnabled = adClickAttribution.isHeuristicDetectionEnabled(),
224230
domainEnabled = adClickAttribution.isDomainDetectionEnabled(),
225231
)
226-
adClickPixels.updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
227232
}
228233
}
229234

ad-click/ad-click-impl/src/test/java/com/duckduckgo/adclick/impl/DuckDuckGoAdClickManagerTest.kt

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.junit.runner.RunWith
2929
import org.mockito.kotlin.any
3030
import org.mockito.kotlin.mock
3131
import org.mockito.kotlin.never
32+
import org.mockito.kotlin.times
3233
import org.mockito.kotlin.verify
3334
import org.mockito.kotlin.verifyNoInteractions
3435
import org.mockito.kotlin.whenever
@@ -154,7 +155,6 @@ class DuckDuckGoAdClickManagerTest {
154155

155156
verify(mockAdClickData).setActiveTab(tabId)
156157
verify(mockAdClickData).addExemption(tabId = any(), exemption = any())
157-
verify(mockAdClickPixels).updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
158158
}
159159

160160
@Test
@@ -170,7 +170,6 @@ class DuckDuckGoAdClickManagerTest {
170170

171171
verify(mockAdClickData).setActiveTab(tabId)
172172
verify(mockAdClickData, never()).addExemption(tabId = any(), exemption = any())
173-
verify(mockAdClickPixels, never()).updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
174173
}
175174

176175
@Test
@@ -328,6 +327,7 @@ class DuckDuckGoAdClickManagerTest {
328327

329328
val result = testee.isExemption(documentUrl = documentUrl, url = url)
330329
verify(mockAdClickPixels, never()).fireAdClickActivePixel(any())
330+
verify(mockAdClickPixels, never()).updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
331331
assertFalse(result)
332332
}
333333

@@ -344,6 +344,7 @@ class DuckDuckGoAdClickManagerTest {
344344

345345
verify(mockAdClickData).removeExemption()
346346
verify(mockAdClickPixels, never()).fireAdClickActivePixel(any())
347+
verify(mockAdClickPixels, never()).updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
347348
assertFalse(result)
348349
}
349350

@@ -361,6 +362,7 @@ class DuckDuckGoAdClickManagerTest {
361362

362363
verify(mockAdClickData, never()).removeExemption()
363364
verify(mockAdClickPixels, never()).fireAdClickActivePixel(any())
365+
verify(mockAdClickPixels, never()).updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
364366
assertFalse(result)
365367
}
366368

@@ -372,6 +374,29 @@ class DuckDuckGoAdClickManagerTest {
372374

373375
whenever(mockAdClickData.isHostExempted(documentUrlHost)).thenReturn(true)
374376
whenever(mockAdClickData.getExemption()).thenReturn(notExpired(documentUrlHost))
377+
whenever(mockAdClickData.getCurrentPage()).thenReturn(documentUrl)
378+
whenever(mockAdClickAttribution.isAllowed(url)).thenReturn(true)
379+
testee.detectAdDomain(url = "https://asos.com/")
380+
381+
val result = testee.isExemption(documentUrl = documentUrl, url = url)
382+
383+
verify(mockAdClickData, never()).removeExemption()
384+
verify(mockAdClickPixels).fireAdClickActivePixel(any())
385+
verify(mockAdClickPixels, times(1)).updateCountPixel(AdClickPixelName.AD_CLICK_PAGELOADS_WITH_AD_ATTRIBUTION)
386+
assertTrue(result)
387+
}
388+
389+
@Test
390+
fun whenIsExemptionCalledWithETldPlusOneExemptedAndMatchingTrackerThenSendPixelAndReturnTrue() {
391+
val documentUrl = "https://uk.asos.com"
392+
val documentUrlHost = "uk.asos.com" // notice the host: uk.asos.com
393+
val documentUrlTlDPlusOne = "asos.com" // notice the eTLD+1: asos.com
394+
val url = "https://bat.bing.com"
395+
396+
whenever(mockAdClickData.isHostExempted(documentUrlHost)).thenReturn(false)
397+
whenever(mockAdClickData.isHostExempted(documentUrlTlDPlusOne)).thenReturn(true)
398+
whenever(mockAdClickData.getExemption()).thenReturn(notExpired(documentUrlTlDPlusOne))
399+
whenever(mockAdClickData.getCurrentPage()).thenReturn(documentUrl)
375400
whenever(mockAdClickAttribution.isAllowed(url)).thenReturn(true)
376401

377402
val result = testee.isExemption(documentUrl = documentUrl, url = url)

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

Lines changed: 13 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,11 @@ class BrowserTabViewModelTest {
621621
subscriptions = subscriptions,
622622
sslCertificatesFeature = mockSSLCertificatesFeature,
623623
bypassedSSLCertificatesRepository = mockBypassedSSLCertificatesRepository,
624-
extendedOnboardingFeatureToggles = mockExtendedOnboardingFeatureToggles,
625624
userBrowserProperties = mockUserBrowserProperties,
626625
history = mockNavigationHistory,
627626
)
628627

629-
testee.loadData("abc", null, false, false)
628+
testee.loadData("abc", null, false)
630629
testee.command.observeForever(mockCommandObserver)
631630
}
632631

@@ -811,24 +810,21 @@ class BrowserTabViewModelTest {
811810
}
812811

813812
@Test
814-
fun whenBrowsingAndUrlPresentThenAddBookmarkFavoriteButtonsEnabled() {
813+
fun whenBrowsingAndUrlPresentThenAddBookmarkButtonEnabled() {
815814
loadUrl("https://www.example.com", isBrowserShowing = true)
816815
assertTrue(browserViewState().canSaveSite)
817-
assertTrue(browserViewState().addFavorite.isEnabled())
818816
}
819817

820818
@Test
821-
fun whenBrowsingAndNoUrlThenAddBookmarkFavoriteButtonsDisabled() {
819+
fun whenBrowsingAndNoUrlThenAddBookmarkButtonDisabled() {
822820
loadUrl(null, isBrowserShowing = true)
823821
assertFalse(browserViewState().canSaveSite)
824-
assertFalse(browserViewState().addFavorite.isEnabled())
825822
}
826823

827824
@Test
828-
fun whenNotBrowsingAndUrlPresentThenAddBookmarkFavoriteButtonsDisabled() {
825+
fun whenNotBrowsingAndUrlPresentThenAddBookmarkButtonDisabled() {
829826
loadUrl("https://www.example.com", isBrowserShowing = false)
830827
assertFalse(browserViewState().canSaveSite)
831-
assertFalse(browserViewState().addFavorite.isEnabled())
832828
}
833829

834830
@Test
@@ -2056,64 +2052,25 @@ class BrowserTabViewModelTest {
20562052

20572053
@Test
20582054
fun whenUrlNullThenSetBrowserNotShowing() = runTest {
2059-
testee.loadData("id", null, false, false)
2055+
testee.loadData("id", null, false)
20602056
testee.determineShowBrowser()
20612057
assertEquals(false, testee.browserViewState.value?.browserShowing)
20622058
}
20632059

20642060
@Test
20652061
fun whenUrlBlankThenSetBrowserNotShowing() = runTest {
2066-
testee.loadData("id", " ", false, false)
2062+
testee.loadData("id", " ", false)
20672063
testee.determineShowBrowser()
20682064
assertEquals(false, testee.browserViewState.value?.browserShowing)
20692065
}
20702066

20712067
@Test
20722068
fun whenUrlPresentThenSetBrowserShowing() = runTest {
2073-
testee.loadData("id", "https://example.com", false, false)
2069+
testee.loadData("id", "https://example.com", false)
20742070
testee.determineShowBrowser()
20752071
assertEquals(true, testee.browserViewState.value?.browserShowing)
20762072
}
20772073

2078-
@Test
2079-
fun whenFavoritesOnboardingAndSiteLoadedThenHighglightMenuButton() = runTest {
2080-
testee.loadData("id", "https://example.com", false, true)
2081-
testee.determineShowBrowser()
2082-
assertEquals(true, testee.browserViewState.value?.showMenuButton?.isHighlighted())
2083-
}
2084-
2085-
@Test
2086-
fun whenFavoritesOnboardingAndUserOpensOptionsMenuThenHighglightAddFavoriteOption() = runTest {
2087-
testee.loadData("id", "https://example.com", false, true)
2088-
testee.determineShowBrowser()
2089-
2090-
testee.onBrowserMenuClicked()
2091-
2092-
assertEquals(true, testee.browserViewState.value?.addFavorite?.isHighlighted())
2093-
}
2094-
2095-
@Test
2096-
fun whenFavoritesOnboardingAndUserClosesOptionsMenuThenMenuButtonNotHighlighted() = runTest {
2097-
testee.loadData("id", "https://example.com", false, true)
2098-
testee.determineShowBrowser()
2099-
2100-
testee.onBrowserMenuClosed()
2101-
2102-
assertEquals(false, testee.browserViewState.value?.addFavorite?.isHighlighted())
2103-
}
2104-
2105-
@Test
2106-
fun whenFavoritesOnboardingAndUserClosesOptionsMenuThenLoadingNewSiteDoesNotHighlightMenuOption() = runTest {
2107-
testee.loadData("id", "https://example.com", false, true)
2108-
testee.determineShowBrowser()
2109-
testee.onBrowserMenuClicked()
2110-
testee.onBrowserMenuClosed()
2111-
2112-
testee.determineShowBrowser()
2113-
2114-
assertEquals(false, testee.browserViewState.value?.addFavorite?.isHighlighted())
2115-
}
2116-
21172074
@Test
21182075
fun whenRecoveringFromProcessGoneThenShowErrorWithAction() {
21192076
testee.recoverFromRenderProcessGone()
@@ -2809,11 +2766,10 @@ class BrowserTabViewModelTest {
28092766
}
28102767

28112768
@Test
2812-
fun whenUserBrowsingPressesBackThenCannotAddBookmarkOrFavorite() {
2769+
fun whenUserBrowsingPressesBackThenCannotAddBookmark() {
28132770
setupNavigation(skipHome = false, isBrowsing = true, canGoBack = false)
28142771
assertTrue(testee.onUserPressedBack())
28152772
assertFalse(browserViewState().canSaveSite)
2816-
assertFalse(browserViewState().addFavorite.isEnabled())
28172773
}
28182774

28192775
@Test
@@ -2873,12 +2829,11 @@ class BrowserTabViewModelTest {
28732829
}
28742830

28752831
@Test
2876-
fun whenUserBrowsingPressesBackAndForwardThenCanAddBookmarkOrFavorite() {
2832+
fun whenUserBrowsingPressesBackAndForwardThenCanAddBookmark() {
28772833
setupNavigation(skipHome = false, isBrowsing = true, canGoBack = false)
28782834
testee.onUserPressedBack()
28792835
testee.onUserPressedForward()
28802836
assertTrue(browserViewState().canSaveSite)
2881-
assertTrue(browserViewState().addFavorite.isEnabled())
28822837
}
28832838

28842839
@Test
@@ -5500,6 +5455,7 @@ class BrowserTabViewModelTest {
55005455
}
55015456

55025457
private suspend fun givenFireButtonPulsing() {
5458+
whenever(mockExtendedOnboardingFeatureToggles.noBrowserCtas()).thenReturn(mockEnabledToggle)
55035459
whenever(mockUserStageStore.getUserAppStage()).thenReturn(AppStage.DAX_ONBOARDING)
55045460
dismissedCtaDaoChannel.send(listOf(DismissedCta(CtaId.DAX_DIALOG_TRACKERS_FOUND)))
55055461
}
@@ -5587,7 +5543,7 @@ class BrowserTabViewModelTest {
55875543

55885544
private fun givenOneActiveTabSelected() {
55895545
selectedTabLiveData.value = TabEntity("TAB_ID", "https://example.com", "", skipHome = false, viewed = true, position = 0)
5590-
testee.loadData("TAB_ID", "https://example.com", false, false)
5546+
testee.loadData("TAB_ID", "https://example.com", false)
55915547
}
55925548

55935549
private fun givenFireproofWebsiteDomain(vararg fireproofWebsitesDomain: String) {
@@ -5606,7 +5562,7 @@ class BrowserTabViewModelTest {
56065562
val siteLiveData = MutableLiveData<Site>()
56075563
siteLiveData.value = site
56085564
whenever(mockTabRepository.retrieveSiteData("TAB_ID")).thenReturn(siteLiveData)
5609-
testee.loadData("TAB_ID", domain, false, false)
5565+
testee.loadData("TAB_ID", domain, false)
56105566

56115567
return site
56125568
}
@@ -5638,7 +5594,7 @@ class BrowserTabViewModelTest {
56385594
}
56395595

56405596
private fun loadTabWithId(tabId: String) {
5641-
testee.loadData(tabId, initialUrl = null, skipHome = false, favoritesOnboarding = false)
5597+
testee.loadData(tabId, initialUrl = null, skipHome = false)
56425598
}
56435599

56445600
private fun loadUrl(

0 commit comments

Comments
 (0)