Skip to content

Commit 5c9123b

Browse files
Merge branch 'release/5.250.0'
2 parents 0cdbbaf + 2c8ca23 commit 5c9123b

File tree

664 files changed

+3476
-1309
lines changed

Some content is hidden

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

664 files changed

+3476
-1309
lines changed

.maestro/duckplayer/common/load_youtube_video.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ appId: com.duckduckgo.mobile.android
77
- pressKey: Enter
88
- runFlow: handle_youtube_cookies.yaml
99
- tapOn:
10-
text: "DuckDuckGo vs Google: 5 Reasons You Should Switch.*"
10+
text: "DuckDuckGo vs Google.*"

anrs/anrs-internal/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ dependencies {
3131
anvil project(':anvil-compiler')
3232
implementation project(':anvil-annotations')
3333
implementation project(':di')
34-
implementation project(':common-ui')
34+
implementation project(':design-system')
3535
implementation project(':common-utils')
3636
implementation project(':navigation-api')
3737
implementation project(':statistics-api')

app-tracking-protection/vpn-impl/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ dependencies {
5555
implementation project(':browser-api')
5656
implementation project(':di')
5757
implementation project(':common-utils')
58-
implementation project(':common-ui')
58+
implementation project(':design-system')
5959
implementation project(':statistics-api')
6060
implementation project(':app-build-config-api')
6161
implementation project(':feature-toggles-api')

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/TrackerBlockingVpnService.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -710,12 +710,17 @@ class TrackerBlockingVpnService : VpnService(), CoroutineScope by MainScope(), V
710710
}
711711
}
712712

713-
ServiceCompat.startForeground(
714-
this,
715-
VPN_FOREGROUND_SERVICE_ID,
716-
VpnEnabledNotificationBuilder.buildVpnEnabledNotification(applicationContext, vpnNotification),
717-
FOREGROUND_SERVICE_TYPE_SPECIAL_USE,
718-
)
713+
try {
714+
ServiceCompat.startForeground(
715+
this,
716+
VPN_FOREGROUND_SERVICE_ID,
717+
VpnEnabledNotificationBuilder.buildVpnEnabledNotification(applicationContext, vpnNotification),
718+
FOREGROUND_SERVICE_TYPE_SPECIAL_USE,
719+
)
720+
} catch (_: Throwable) {
721+
// signal the error
722+
return false
723+
}
719724

720725
return vpnNotification != emptyNotification
721726
}

app-tracking-protection/vpn-impl/src/main/res/values/donottranslate.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@
3939

4040
<!-- New Tab -->
4141
<string name="vpn_NewTabSectionSettingsTitle">App Tracking Protection Status</string>
42+
<string name="vpnMenuTitle">VPN</string>
4243

4344
</resources>

app-tracking-protection/vpn-internal/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ dependencies {
4343
implementation project(':app-tracking-api')
4444
implementation project(':di')
4545
implementation project(':common-utils')
46-
implementation project(':common-ui')
46+
implementation project(':design-system')
4747
implementation project(':app-build-config-api')
4848
implementation project(':feature-toggles-api')
4949
implementation project(':internal-features-api')

app/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,7 @@ dependencies {
264264
implementation project(':experiments-impl')
265265
implementation project(':common-utils')
266266
implementation project(':app-store')
267-
implementation project(':common-ui')
268-
internalImplementation project(':common-ui-internal')
267+
implementation project(':design-system')
269268
implementation project(':di')
270269
implementation project(':app-tracking-api')
271270
implementation project(':vpn-impl')

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

Lines changed: 6 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import android.net.http.SslError
2626
import android.os.Build
2727
import android.print.PrintAttributes
2828
import android.view.MenuItem
29-
import android.view.MotionEvent
3029
import android.view.View
3130
import android.webkit.HttpAuthHandler
3231
import android.webkit.PermissionRequest
@@ -107,6 +106,7 @@ import com.duckduckgo.app.browser.logindetection.LoginDetected
107106
import com.duckduckgo.app.browser.logindetection.NavigationAwareLoginDetector
108107
import com.duckduckgo.app.browser.logindetection.NavigationEvent
109108
import com.duckduckgo.app.browser.logindetection.NavigationEvent.LoginAttempt
109+
import com.duckduckgo.app.browser.menu.VpnMenuStateProvider
110110
import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials
111111
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
112112
import com.duckduckgo.app.browser.model.LongPressTarget
@@ -128,6 +128,7 @@ import com.duckduckgo.app.browser.viewstate.FindInPageViewState
128128
import com.duckduckgo.app.browser.viewstate.GlobalLayoutViewState
129129
import com.duckduckgo.app.browser.viewstate.HighlightableButton
130130
import com.duckduckgo.app.browser.viewstate.LoadingViewState
131+
import com.duckduckgo.app.browser.viewstate.VpnMenuState
131132
import com.duckduckgo.app.browser.webview.MaliciousSiteBlockedWarningLayout.Action.LearnMore
132133
import com.duckduckgo.app.browser.webview.MaliciousSiteBlockedWarningLayout.Action.LeaveSite
133134
import com.duckduckgo.app.browser.webview.MaliciousSiteBlockedWarningLayout.Action.ReportError
@@ -450,6 +451,8 @@ class BrowserTabViewModelTest {
450451

451452
private val mockExternalIntentProcessingState: ExternalIntentProcessingState = mock()
452453

454+
private val mockVpnMenuStateProvider: VpnMenuStateProvider = mock()
455+
453456
private val mockHasPendingTabLaunchFlow = MutableStateFlow(false)
454457

455458
private val mockHasPendingDuckAiOpenFlow = MutableStateFlow(false)
@@ -660,6 +663,7 @@ class BrowserTabViewModelTest {
660663
whenever(mockDuckAiFeatureState.showInputScreenAutomaticallyOnNewTab).thenReturn(mockDuckAiFeatureStateInputScreenOpenAutomaticallyFlow)
661664
whenever(mockExternalIntentProcessingState.hasPendingTabLaunch).thenReturn(mockHasPendingTabLaunchFlow)
662665
whenever(mockExternalIntentProcessingState.hasPendingDuckAiOpen).thenReturn(mockHasPendingDuckAiOpenFlow)
666+
whenever(mockVpnMenuStateProvider.getVpnMenuState()).thenReturn(flowOf(VpnMenuState.Hidden))
663667
whenever(mockOnboardingDesignExperimentManager.isModifiedControlEnrolledAndEnabled()).thenReturn(false)
664668
whenever(mockOnboardingDesignExperimentManager.isBuckEnrolledAndEnabled()).thenReturn(false)
665669
whenever(mockOnboardingDesignExperimentManager.isBbEnrolledAndEnabled()).thenReturn(false)
@@ -810,6 +814,7 @@ class BrowserTabViewModelTest {
810814
serpEasterEggLogosToggles = mockSerpEasterEggLogoToggles,
811815
nonHttpAppLinkChecker = nonHttpAppLinkChecker,
812816
externalIntentProcessingState = mockExternalIntentProcessingState,
817+
vpnMenuStateProvider = mockVpnMenuStateProvider,
813818
)
814819

815820
testee.loadData("abc", null, false, false)
@@ -5610,110 +5615,6 @@ class BrowserTabViewModelTest {
56105615
verify(mockPixel).fire(AppPixelName.TAB_MANAGER_CLICKED_DAILY, params, emptyMap(), Daily())
56115616
}
56125617

5613-
@Test
5614-
fun whenOnUserTouchedOmnibarTextInputWithEmptyTextAndActionUpThenPixelFired() {
5615-
testee.onUserTouchedOmnibarTextInput(MotionEvent.ACTION_UP)
5616-
5617-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_NEW_TAB_PAGE_CLICKED)
5618-
}
5619-
5620-
@Test
5621-
fun whenOnUserTouchedOmnibarTextInputWithUrlAndActionUpThenPixelFired() {
5622-
loadUrl("https://example.com")
5623-
testee.onUserTouchedOmnibarTextInput(MotionEvent.ACTION_UP)
5624-
5625-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_WEBSITE_CLICKED)
5626-
}
5627-
5628-
@Test
5629-
fun whenOnUserTouchedOmnibarTextInputWithQueryAndActionUpThenPixelFired() {
5630-
loadUrl("https://duckduckgo.com/?q=example")
5631-
testee.onUserTouchedOmnibarTextInput(MotionEvent.ACTION_UP)
5632-
5633-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_SERP_CLICKED)
5634-
}
5635-
5636-
@Test
5637-
fun whenOnUserTouchedOmnibarTextInputWithAnyTextAndOtherActionThenPixelNotFired() {
5638-
loadUrl("https://duckduckgo.com/?q=example")
5639-
testee.onUserTouchedOmnibarTextInput(MotionEvent.ACTION_DOWN)
5640-
5641-
verify(mockPixel, never()).fire(AppPixelName.ADDRESS_BAR_NEW_TAB_PAGE_CLICKED)
5642-
verify(mockPixel, never()).fire(AppPixelName.ADDRESS_BAR_WEBSITE_CLICKED)
5643-
verify(mockPixel, never()).fire(AppPixelName.ADDRESS_BAR_SERP_CLICKED)
5644-
}
5645-
5646-
@Test
5647-
fun whenOnClearOmnibarTextInputWithEmptyTextThenPixelFired() {
5648-
testee.onClearOmnibarTextInput()
5649-
5650-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_NEW_TAB_PAGE_ENTRY_CLEARED)
5651-
}
5652-
5653-
@Test
5654-
fun whenOnClearOmnibarTextInputWithUrlThenPixelFired() {
5655-
loadUrl("https://example.com")
5656-
testee.onClearOmnibarTextInput()
5657-
5658-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_WEBSITE_ENTRY_CLEARED)
5659-
}
5660-
5661-
@Test
5662-
fun whenOnClearOmnibarTextInputWithQueryUrlThenPixelFired() {
5663-
loadUrl("https://duckduckgo.com/?q=example")
5664-
testee.onClearOmnibarTextInput()
5665-
5666-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_SERP_ENTRY_CLEARED)
5667-
}
5668-
5669-
@Test
5670-
fun whenSendPixelsOnBackKeyPressedWithEmptyTextThenPixelFired() {
5671-
testee.sendPixelsOnBackKeyPressed()
5672-
5673-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_NEW_TAB_PAGE_CANCELLED)
5674-
}
5675-
5676-
@Test
5677-
fun whenSendPixelsOnBackKeyPressedWithUrlThenPixelFired() {
5678-
loadUrl("https://example.com")
5679-
testee.sendPixelsOnBackKeyPressed()
5680-
5681-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_WEBSITE_CANCELLED)
5682-
}
5683-
5684-
@Test
5685-
fun whenSendPixelsOnBackKeyPressedWithQueryUrlThenPixelFired() {
5686-
loadUrl("https://duckduckgo.com/?q=example")
5687-
5688-
testee.sendPixelsOnBackKeyPressed()
5689-
5690-
verify(mockPixel).fire(AppPixelName.ADDRESS_BAR_SERP_CANCELLED)
5691-
}
5692-
5693-
@Test
5694-
fun whenSendPixelsOnEnterKeyPressedWithEmptyTextThenPixelFired() {
5695-
testee.sendPixelsOnEnterKeyPressed()
5696-
5697-
verify(mockPixel).fire(AppPixelName.KEYBOARD_GO_NEW_TAB_CLICKED)
5698-
}
5699-
5700-
@Test
5701-
fun whenSendPixelsOnEnterKeyPressedWithUrlThenPixelFired() {
5702-
loadUrl("https://example.com")
5703-
testee.sendPixelsOnEnterKeyPressed()
5704-
5705-
verify(mockPixel).fire(AppPixelName.KEYBOARD_GO_WEBSITE_CLICKED)
5706-
}
5707-
5708-
@Test
5709-
fun whenSendPixelsOnEnterKeyPressedWithQueryUrlThenPixelFired() {
5710-
loadUrl("https://duckduckgo.com/?q=example")
5711-
5712-
testee.sendPixelsOnEnterKeyPressed()
5713-
5714-
verify(mockPixel).fire(AppPixelName.KEYBOARD_GO_SERP_CLICKED)
5715-
}
5716-
57175618
@Test
57185619
fun whenNewTabShownThenPixelIsFired() {
57195620
testee.onNewTabShown()

app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ import com.duckduckgo.app.browser.history.NavigationHistorySheet.NavigationHisto
138138
import com.duckduckgo.app.browser.httpauth.WebViewHttpAuthStore
139139
import com.duckduckgo.app.browser.logindetection.DOMLoginDetector
140140
import com.duckduckgo.app.browser.menu.BrowserPopupMenu
141+
import com.duckduckgo.app.browser.menu.VpnMenuStore
141142
import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials
142143
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
143144
import com.duckduckgo.app.browser.model.LongPressTarget
@@ -173,6 +174,7 @@ import com.duckduckgo.app.browser.viewstate.LoadingViewState
173174
import com.duckduckgo.app.browser.viewstate.OmnibarViewState
174175
import com.duckduckgo.app.browser.viewstate.PrivacyShieldViewState
175176
import com.duckduckgo.app.browser.viewstate.SavedSiteChangedViewState
177+
import com.duckduckgo.app.browser.viewstate.VpnMenuState
176178
import com.duckduckgo.app.browser.webauthn.WebViewPasskeyInitializer
177179
import com.duckduckgo.app.browser.webshare.WebShareChooser
178180
import com.duckduckgo.app.browser.webshare.WebViewCompatWebShareChooser
@@ -307,6 +309,7 @@ import com.duckduckgo.mobile.android.R as CommonR
307309
import com.duckduckgo.mobile.android.app.tracking.ui.AppTrackingProtectionScreens.AppTrackerOnboardingActivityWithEmptyParamsParams
308310
import com.duckduckgo.navigation.api.GlobalActivityStarter
309311
import com.duckduckgo.navigation.api.GlobalActivityStarter.DeeplinkActivityParams
312+
import com.duckduckgo.networkprotection.api.NetworkProtectionScreens.NetworkProtectionManagementScreenNoParams
310313
import com.duckduckgo.privacy.dashboard.api.ui.DashboardOpener
311314
import com.duckduckgo.privacy.dashboard.api.ui.PrivacyDashboardHybridScreenParams.BrokenSiteForm
312315
import com.duckduckgo.privacy.dashboard.api.ui.PrivacyDashboardHybridScreenParams.BrokenSiteForm.BrokenSiteFormReportFlow
@@ -407,6 +410,9 @@ class BrowserTabFragment :
407410
@Inject
408411
lateinit var pixel: Pixel
409412

413+
@Inject
414+
lateinit var vpnMenuStore: VpnMenuStore
415+
410416
@Inject
411417
lateinit var ctaViewModel: CtaViewModel
412418

@@ -1346,6 +1352,10 @@ class BrowserTabFragment :
13461352
pixel.fire(CustomTabPixelNames.CUSTOM_TABS_OPEN_IN_DDG)
13471353
}
13481354
}
1355+
1356+
onMenuItemClicked(vpnMenuItem) {
1357+
viewModel.onVpnMenuClicked()
1358+
}
13491359
}
13501360
}
13511361

@@ -1376,6 +1386,15 @@ class BrowserTabFragment :
13761386
// small delay added to let keyboard disappear and avoid jarring transition
13771387
binding.rootView.postDelayed(POPUP_MENU_DELAY) {
13781388
if (isAdded) {
1389+
// Check if VPN menu item will be shown to non-subscribed user and increment count
1390+
val currentViewState = viewModel.browserViewState.value
1391+
if (currentViewState != null) {
1392+
val shouldShowVpnMenuItem = !currentViewState.browserShowing && !isActiveCustomTab()
1393+
if (currentViewState.vpnMenuState == VpnMenuState.NotSubscribed && shouldShowVpnMenuItem) {
1394+
vpnMenuStore.incrementVpnMenuShownCount()
1395+
}
1396+
}
1397+
13791398
popupMenu.show(binding.rootView, omnibar.toolbar)
13801399
viewModel.onPopupMenuLaunched()
13811400
if (isActiveCustomTab()) {
@@ -1993,6 +2012,10 @@ class BrowserTabFragment :
19932012
}
19942013
}
19952014

2015+
is Command.LaunchVpnManagement -> {
2016+
globalActivityStarter.start(requireContext(), NetworkProtectionManagementScreenNoParams)
2017+
}
2018+
19962019
is Command.DialNumber -> {
19972020
val intent = Intent(Intent.ACTION_DIAL)
19982021
intent.data = Uri.parse("tel:${it.telephoneNumber}")

0 commit comments

Comments
 (0)