Skip to content

Commit f04bd61

Browse files
Merge branch 'release/5.238.0'
2 parents 689fa15 + 590d950 commit f04bd61

File tree

174 files changed

+3120
-1252
lines changed

Some content is hidden

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

174 files changed

+3120
-1252
lines changed

.github/workflows/release_tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ jobs:
8181
api-key: ${{ secrets.ROBIN_API_KEY }}
8282
project-id: ${{ vars.ROBIN_ANDROID_PROJECT_ID }}
8383
timeout: ${{ vars.ROBIN_TIMEOUT_MINUTES }}
84+
app-file: apk/release.apk
8485
android-api-level: 30
8586
workspace: .maestro
8687
include-tags: ${{ github.event.inputs.test-tag }}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ import com.duckduckgo.app.browser.refreshpixels.RefreshPixelSender
127127
import com.duckduckgo.app.browser.remotemessage.RemoteMessagingModel
128128
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionExperiment
129129
import com.duckduckgo.app.browser.session.WebViewSessionStorage
130+
import com.duckduckgo.app.browser.tabs.TabManager
130131
import com.duckduckgo.app.browser.trafficquality.AndroidFeaturesHeaderPlugin.Companion.X_DUCKDUCKGO_ANDROID_HEADER
131132
import com.duckduckgo.app.browser.viewstate.BrowserViewState
132133
import com.duckduckgo.app.browser.viewstate.CtaViewState
@@ -556,6 +557,7 @@ class BrowserTabViewModelTest {
556557
private val mockSiteHttpErrorHandler: HttpCodeSiteErrorHandler = mock()
557558
private val mockSubscriptionsJSHelper: SubscriptionsJSHelper = mock()
558559
private val mockReactivateUsersExperiment: ReactivateUsersExperiment = mock()
560+
private val tabManager: TabManager = mock()
559561

560562
private val fakeOnboardingDesignExperimentToggles: OnboardingDesignExperimentToggles =
561563
FakeFeatureToggleFactory.create(OnboardingDesignExperimentToggles::class.java)
@@ -763,6 +765,7 @@ class BrowserTabViewModelTest {
763765
senseOfProtectionExperiment = mockSenseOfProtectionExperiment,
764766
subscriptionsJSHelper = mockSubscriptionsJSHelper,
765767
onboardingDesignExperimentToggles = fakeOnboardingDesignExperimentToggles,
768+
tabManager = tabManager,
766769
)
767770

768771
testee.loadData("abc", null, false, false)

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ class BrowserWebViewClientTest {
977977
fun whenPageFinishesBeforeStartingThenPixelIsNotFired() {
978978
val mockWebView = getImmediatelyInvokedMockWebView()
979979
testee.onPageFinished(mockWebView, EXAMPLE_URL)
980-
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any())
980+
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any())
981981
}
982982

983983
@Test
@@ -991,7 +991,7 @@ class BrowserWebViewClientTest {
991991
testee.onPageFinished(mockWebView, EXAMPLE_URL)
992992
val startArgumentCaptor = argumentCaptor<Long>()
993993
val endArgumentCaptor = argumentCaptor<Long>()
994-
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture())
994+
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture(), any())
995995
assertEquals(0L, startArgumentCaptor.firstValue)
996996
assertEquals(10L, endArgumentCaptor.firstValue)
997997
}
@@ -1004,7 +1004,7 @@ class BrowserWebViewClientTest {
10041004
whenever(mockWebView.settings).thenReturn(mock())
10051005
testee.onPageStarted(mockWebView, "about:blank", null)
10061006
testee.onPageFinished(mockWebView, "about:blank")
1007-
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any())
1007+
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any())
10081008
}
10091009

10101010
@Test
@@ -1013,7 +1013,7 @@ class BrowserWebViewClientTest {
10131013
whenever(mockWebView.settings).thenReturn(mock())
10141014
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
10151015
testee.onPageFinished(mockWebView, EXAMPLE_URL)
1016-
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any())
1016+
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any())
10171017
}
10181018

10191019
@Test
@@ -1046,7 +1046,7 @@ class BrowserWebViewClientTest {
10461046

10471047
val startArgumentCaptor = argumentCaptor<Long>()
10481048
val endArgumentCaptor = argumentCaptor<Long>()
1049-
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture())
1049+
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture(), any())
10501050
assertEquals(0L, startArgumentCaptor.firstValue)
10511051
assertEquals(10L, endArgumentCaptor.firstValue)
10521052
}
@@ -1068,7 +1068,7 @@ class BrowserWebViewClientTest {
10681068
testee.onPageFinished(mockWebView, EXAMPLE_URL)
10691069
val startArgumentCaptor = argumentCaptor<Long>()
10701070
val endArgumentCaptor = argumentCaptor<Long>()
1071-
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture())
1071+
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture(), any())
10721072
assertEquals(5L, startArgumentCaptor.firstValue)
10731073
assertEquals(10L, endArgumentCaptor.firstValue)
10741074
}

app/src/androidTest/java/com/duckduckgo/app/browser/pageloadpixel/PageLoadedHandlerTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ class PageLoadedHandlerTest {
5151

5252
@Test
5353
fun whenInvokingWithValidUrlThenPixelIsAdded() {
54-
testee.onPageLoaded(VALID_URL, "title", 0L, 10L)
54+
testee.onPageLoaded(VALID_URL, "title", 0L, 10L, true)
5555
val argumentCaptor = argumentCaptor<PageLoadedPixelEntity>()
5656
verify(pageLoadedPixelDao).add(argumentCaptor.capture())
5757
Assert.assertEquals(10L, argumentCaptor.firstValue.elapsedTime)
5858
}
5959

6060
@Test
6161
fun whenInvokingWithInvalidUrlThenPixelIsAdded() {
62-
testee.onPageLoaded(INVALID_URL, "title", 0L, 10L)
62+
testee.onPageLoaded(INVALID_URL, "title", 0L, 10L, true)
6363
verify(pageLoadedPixelDao, never()).add(any())
6464
}
6565
}

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import androidx.activity.result.contract.ActivityResultContracts
3535
import androidx.annotation.VisibleForTesting
3636
import androidx.core.view.isVisible
3737
import androidx.core.view.postDelayed
38-
import androidx.fragment.app.Fragment
3938
import androidx.lifecycle.Lifecycle.State.STARTED
4039
import androidx.lifecycle.lifecycleScope
4140
import androidx.lifecycle.repeatOnLifecycle
@@ -103,6 +102,8 @@ import com.duckduckgo.duckchat.api.DuckChat
103102
import com.duckduckgo.navigation.api.GlobalActivityStarter
104103
import com.duckduckgo.savedsites.impl.bookmarks.BookmarksActivity.Companion.SAVED_SITE_URL_EXTRA
105104
import com.duckduckgo.site.permissions.impl.ui.SitePermissionScreenNoParams
105+
import com.duckduckgo.sync.api.SyncActivityFromSetupUrl
106+
import com.duckduckgo.sync.api.setup.SyncUrlIdentifier
106107
import javax.inject.Inject
107108
import kotlinx.coroutines.CoroutineScope
108109
import kotlinx.coroutines.Job
@@ -177,6 +178,9 @@ open class BrowserActivity : DuckDuckGoActivity() {
177178
@Inject
178179
lateinit var duckChat: DuckChat
179180

181+
@Inject
182+
lateinit var syncUrlIdentifier: SyncUrlIdentifier
183+
180184
@Inject
181185
lateinit var visualDesignExperimentDataStore: VisualDesignExperimentDataStore
182186

@@ -219,10 +223,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
219223
}
220224

221225
private val tabPagerAdapter by lazy {
222-
TabPagerAdapter(
223-
activity = this,
224-
swipingTabsFeature = swipingTabsFeature,
225-
)
226+
TabPagerAdapter(activity = this)
226227
}
227228

228229
private lateinit var toolbarMockupBinding: IncludeOmnibarToolbarMockupBinding
@@ -523,6 +524,14 @@ open class BrowserActivity : DuckDuckGoActivity() {
523524
return
524525
}
525526

527+
intent.intentText?.let {
528+
if (syncUrlIdentifier.shouldDelegateToSyncSetup(it)) {
529+
globalActivityStarter.start(this, SyncActivityFromSetupUrl(it))
530+
logcat { "Sync setup link was consumed, so don't allow it to open in a new tab" }
531+
return
532+
}
533+
}
534+
526535
// the BrowserActivity will automatically clear its stack of activities when being brought to the foreground, so this can no longer be true
527536
currentTab?.inContextEmailProtectionShowing = false
528537

@@ -1000,6 +1009,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
10001009

10011010
private fun onMoveToTabRequested(index: Int) {
10021011
tabPager.post {
1012+
tabPagerAdapter.currentTabIndex = index
10031013
tabPager.setCurrentItem(index, false)
10041014
}
10051015
}
@@ -1020,7 +1030,11 @@ open class BrowserActivity : DuckDuckGoActivity() {
10201030
tabPagerAdapter.onTabsUpdated(updatedTabIds)
10211031
}
10221032

1023-
fun launchNewTab(query: String? = null, sourceTabId: String? = null, skipHome: Boolean = false) {
1033+
fun launchNewTab(
1034+
query: String? = null,
1035+
sourceTabId: String? = null,
1036+
skipHome: Boolean = false,
1037+
) {
10241038
lifecycleScope.launch {
10251039
if (swipingTabsFeature.isEnabled) {
10261040
tabManager.openNewTab(query, sourceTabId, skipHome)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ import com.duckduckgo.app.browser.omnibar.model.OmnibarPosition.TOP
205205
import com.duckduckgo.app.browser.refreshpixels.RefreshPixelSender
206206
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionExperiment
207207
import com.duckduckgo.app.browser.session.WebViewSessionStorage
208+
import com.duckduckgo.app.browser.tabs.TabManager
208209
import com.duckduckgo.app.browser.urlextraction.UrlExtractionListener
209210
import com.duckduckgo.app.browser.viewstate.AccessibilityViewState
210211
import com.duckduckgo.app.browser.viewstate.AutoCompleteViewState
@@ -465,6 +466,7 @@ class BrowserTabViewModel @Inject constructor(
465466
private val senseOfProtectionExperiment: SenseOfProtectionExperiment,
466467
private val subscriptionsJSHelper: SubscriptionsJSHelper,
467468
private val onboardingDesignExperimentToggles: OnboardingDesignExperimentToggles,
469+
private val tabManager: TabManager,
468470
) : WebViewClientListener,
469471
EditSavedSiteListener,
470472
DeleteBookmarkListener,
@@ -1242,6 +1244,14 @@ class BrowserTabViewModel @Inject constructor(
12421244

12431245
override fun isDesktopSiteEnabled(): Boolean = currentBrowserViewState().isDesktopBrowsingMode
12441246

1247+
override fun isTabInForeground(): Boolean {
1248+
return if (swipingTabsFeature.isEnabled) {
1249+
tabId == tabManager.getSelectedTabId()
1250+
} else {
1251+
true
1252+
}
1253+
}
1254+
12451255
override fun closeCurrentTab() {
12461256
viewModelScope.launch {
12471257
removeCurrentTabFromRepository()
@@ -2970,6 +2980,7 @@ class BrowserTabViewModel @Inject constructor(
29702980
}
29712981

29722982
override fun openMessageInNewTab(message: Message) {
2983+
command.value = GenerateWebViewPreviewImage
29732984
command.value = OpenMessageInNewTab(message, tabId)
29742985
}
29752986

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,13 @@ class BrowserWebViewClient @Inject constructor(
479479
if (url != ABOUT_BLANK) {
480480
start?.let { safeStart ->
481481
// TODO (cbarreiro - 22/05/2024): Extract to plugins
482-
pageLoadedHandler.onPageLoaded(it, navigationList.currentItem?.title, safeStart, currentTimeProvider.elapsedRealtime())
482+
pageLoadedHandler.onPageLoaded(
483+
url = it,
484+
title = navigationList.currentItem?.title,
485+
start = safeStart,
486+
end = currentTimeProvider.elapsedRealtime(),
487+
isTabInForeground = webViewClientListener?.isTabInForeground() ?: true,
488+
)
483489
shouldSendPagePaintedPixel(webView = webView, url = it)
484490
appCoroutineScope.launch(dispatcherProvider.io()) {
485491
if (duckPlayer.getDuckPlayerState() == ENABLED && duckPlayer.isSimulatedYoutubeNoCookie(uri)) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ interface WebViewClientListener {
8282
fun surrogateDetected(surrogate: SurrogateResponse)
8383
fun isDesktopSiteEnabled(): Boolean
8484

85+
fun isTabInForeground(): Boolean
86+
8587
fun loginDetected()
8688
fun dosAttackDetected()
8789
fun iconReceived(

app/src/main/java/com/duckduckgo/app/browser/pageloadpixel/PageLoadedHandler.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ import com.squareup.anvil.annotations.ContributesBinding
2929
import javax.inject.Inject
3030
import kotlinx.coroutines.CoroutineScope
3131
import kotlinx.coroutines.launch
32+
import logcat.logcat
3233

3334
interface PageLoadedHandler {
34-
fun onPageLoaded(url: String, title: String?, start: Long, end: Long)
35+
fun onPageLoaded(url: String, title: String?, start: Long, end: Long, isTabInForeground: Boolean)
3536
}
3637

3738
@ContributesBinding(AppScope::class)
@@ -45,7 +46,7 @@ class RealPageLoadedHandler @Inject constructor(
4546
private val optimizeTrackerEvaluationRCWrapper: OptimizeTrackerEvaluationRCWrapper,
4647
) : PageLoadedHandler {
4748

48-
override fun onPageLoaded(url: String, title: String?, start: Long, end: Long) {
49+
override fun onPageLoaded(url: String, title: String?, start: Long, end: Long, isTabInForeground: Boolean) {
4950
appCoroutineScope.launch(dispatcherProvider.io()) {
5051
if (sites.any { UriString.sameOrSubdomain(url, it) }) {
5152
pageLoadedPixelDao.add(
@@ -58,6 +59,7 @@ class RealPageLoadedHandler @Inject constructor(
5859
),
5960
)
6061
}
62+
logcat { "$$$: Page load time: ${end - start}, foreground: $isTabInForeground" }
6163
}
6264
}
6365
}

app/src/main/java/com/duckduckgo/app/browser/tabs/DefaultTabManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.duckduckgo.app.tabs.model.TabRepository
2424
import com.duckduckgo.common.utils.DispatcherProvider
2525
import com.duckduckgo.di.scopes.ActivityScope
2626
import com.squareup.anvil.annotations.ContributesBinding
27+
import dagger.SingleInstanceIn
2728
import javax.inject.Inject
2829
import kotlinx.coroutines.withContext
2930
import logcat.LogPriority.INFO
@@ -50,6 +51,7 @@ interface TabManager {
5051
)
5152
}
5253

54+
@SingleInstanceIn(ActivityScope::class)
5355
@ContributesBinding(ActivityScope::class)
5456
class DefaultTabManager @Inject constructor(
5557
private val tabRepository: TabRepository,

0 commit comments

Comments
 (0)