Skip to content

Commit defd853

Browse files
Merge branch 'release/5.232.0'
2 parents 3acbe52 + 1e0f1ba commit defd853

File tree

235 files changed

+8845
-1466
lines changed

Some content is hidden

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

235 files changed

+8845
-1466
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.duckduckgo.adclick.impl.remoteconfig
1919
import com.duckduckgo.anvil.annotations.ContributesRemoteFeature
2020
import com.duckduckgo.di.scopes.AppScope
2121
import com.duckduckgo.feature.toggles.api.Toggle
22+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
2223

2324
@ContributesRemoteFeature(
2425
scope = AppScope::class,
@@ -33,13 +34,13 @@ interface AdClickAttributionFeature {
3334
* @return `true` when the remote config has the global "adClickAttribution" feature flag enabled
3435
* If the remote feature is not present defaults to `false`
3536
*/
36-
@Toggle.DefaultValue(false)
37+
@Toggle.DefaultValue(DefaultFeatureValue.FALSE)
3738
fun self(): Toggle
3839

3940
/**
4041
* @return `true` when the remote config has the global "persistExemptions" adClickAttribution sub-feature flag enabled
4142
* If the remote feature is not present defaults to `false`
4243
*/
43-
@Toggle.DefaultValue(false)
44+
@Toggle.DefaultValue(DefaultFeatureValue.FALSE)
4445
fun persistExemptions(): Toggle
4546
}

anrs/anrs-impl/src/main/java/com/duckduckgo/app/anr/ndk/NativeCrashFeature.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.duckduckgo.data.store.api.SharedPreferencesProvider
2525
import com.duckduckgo.di.scopes.AppScope
2626
import com.duckduckgo.feature.toggles.api.RemoteFeatureStoreNamed
2727
import com.duckduckgo.feature.toggles.api.Toggle
28+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
2829
import com.duckduckgo.feature.toggles.api.Toggle.State
2930
import com.squareup.anvil.annotations.ContributesBinding
3031
import com.squareup.moshi.JsonAdapter
@@ -41,14 +42,14 @@ import kotlinx.coroutines.launch
4142
toggleStore = NativeCrashFeatureMultiProcessStore::class,
4243
)
4344
interface NativeCrashFeature {
44-
@Toggle.DefaultValue(true)
45+
@Toggle.DefaultValue(DefaultFeatureValue.TRUE)
4546
@Toggle.InternalAlwaysEnabled
4647
fun self(): Toggle
4748

48-
@Toggle.DefaultValue(true)
49+
@Toggle.DefaultValue(DefaultFeatureValue.TRUE)
4950
fun nativeCrashHandling(): Toggle
5051

51-
@Toggle.DefaultValue(true)
52+
@Toggle.DefaultValue(DefaultFeatureValue.TRUE)
5253
fun nativeCrashHandlingSecondaryProcess(): Toggle
5354
}
5455

anvil/anvil-annotations/src/main/java/com/duckduckgo/anvil/annotations/ContributesActivePlugin.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.duckduckgo.anvil.annotations
1818

19+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
1920
import kotlin.reflect.KClass
2021

2122
/**
@@ -50,7 +51,7 @@ annotation class ContributesActivePlugin(
5051
* The default value of remote feature flag.
5152
* Default is true (ie. enabled)
5253
*/
53-
val defaultActiveValue: Boolean = true,
54+
val defaultActiveValue: DefaultFeatureValue = DefaultFeatureValue.TRUE,
5455

5556
/**
5657
* The priority for the plugin.

anvil/anvil-compiler/src/main/java/com/duckduckgo/anvil/compiler/ContributesActivePluginPointCodeGenerator.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.duckduckgo.anvil.annotations.ContributesRemoteFeature
2323
import com.duckduckgo.anvil.annotations.PriorityKey
2424
import com.duckduckgo.feature.toggles.api.RemoteFeatureStoreNamed
2525
import com.duckduckgo.feature.toggles.api.Toggle
26+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
2627
import com.duckduckgo.feature.toggles.api.Toggle.Experiment
2728
import com.duckduckgo.feature.toggles.api.Toggle.InternalAlwaysEnabled
2829
import com.google.auto.service.AutoService
@@ -143,6 +144,10 @@ class ContributesActivePluginPointCodeGenerator : CodeGenerator {
143144
}
144145

145146
val content = FileSpec.buildFile(generatedPackage, pluginPointClassFileName) {
147+
addImport(DefaultFeatureValue::class.fqName.parent().asString(), DefaultFeatureValue::class.fqName.shortName().asString())
148+
addImport(DefaultFeatureValue::class.fqName.asString(), DefaultFeatureValue.TRUE.toString())
149+
addImport(DefaultFeatureValue::class.fqName.asString(), DefaultFeatureValue.FALSE.toString())
150+
addImport(DefaultFeatureValue::class.fqName.asString(), DefaultFeatureValue.INTERNAL.toString())
146151
// This is the normal plugin point
147152
addType(
148153
TypeSpec.interfaceBuilder(pluginPointClassName)
@@ -176,7 +181,7 @@ class ContributesActivePluginPointCodeGenerator : CodeGenerator {
176181
.addModifiers(ABSTRACT)
177182
.addAnnotation(
178183
AnnotationSpec.builder(Toggle.DefaultValue::class)
179-
.addMember("defaultValue = %L", true)
184+
.addMember("defaultValue = %L", "DefaultFeatureValue.TRUE")
180185
.build(),
181186
)
182187
.returns(Toggle::class)
@@ -313,7 +318,7 @@ class ContributesActivePluginPointCodeGenerator : CodeGenerator {
313318
val boundType = vmClass.annotations.firstOrNull { it.fqName == ContributesActivePlugin::class.fqName }?.boundTypeOrNull()!!
314319
val featureDefaultValue = vmClass.annotations.firstOrNull {
315320
it.fqName == ContributesActivePlugin::class.fqName
316-
}?.defaultActiveValueOrNull() ?: true
321+
}?.defaultActiveValueOrNull() ?: DefaultFeatureValue.TRUE
317322
// the parent feature name is taken from the plugin interface name implemented by this class
318323
val parentFeatureName = "pluginPoint${boundType.shortName}"
319324
val featureName = "plugin${vmClass.shortName}"
@@ -346,6 +351,10 @@ class ContributesActivePluginPointCodeGenerator : CodeGenerator {
346351
}
347352

348353
val content = FileSpec.buildFile(generatedPackage, pluginClassName) {
354+
addImport(DefaultFeatureValue::class.fqName.parent().asString(), DefaultFeatureValue::class.fqName.shortName().asString())
355+
addImport(DefaultFeatureValue::class.fqName.asString(), DefaultFeatureValue.TRUE.toString())
356+
addImport(DefaultFeatureValue::class.fqName.asString(), DefaultFeatureValue.FALSE.toString())
357+
addImport(DefaultFeatureValue::class.fqName.asString(), DefaultFeatureValue.INTERNAL.toString())
349358
// First create the class that will contribute the active plugin.
350359
// We do expect that the plugins are define using the "ContributesActivePlugin" annotation but are also injected
351360
// using @Inject in the constructor, as the concrete plugin type is use as delegate.
@@ -416,7 +425,7 @@ class ContributesActivePluginPointCodeGenerator : CodeGenerator {
416425
.addAnnotation(
417426
AnnotationSpec.builder(Toggle.DefaultValue::class)
418427
// The parent feature toggle is the one guarding the plugin point, for convention is default enabled.
419-
.addMember("defaultValue = %L", true)
428+
.addMember("defaultValue = %L", "DefaultFeatureValue.TRUE")
420429
.build(),
421430
)
422431
.returns(Toggle::class)
@@ -604,7 +613,15 @@ class ContributesActivePluginPointCodeGenerator : CodeGenerator {
604613
}
605614

606615
@OptIn(ExperimentalAnvilApi::class)
607-
private fun AnnotationReference.defaultActiveValueOrNull(): Boolean? = argumentAt("defaultActiveValue", 2)?.value()
616+
private fun AnnotationReference.defaultActiveValueOrNull(): DefaultFeatureValue? {
617+
val rawValue = argumentAt("defaultActiveValue", 2)?.value() as FqName? ?: return null
618+
619+
return if (rawValue.parent() == DefaultFeatureValue::class.fqName) {
620+
DefaultFeatureValue.valueOf(rawValue.shortName().toString())
621+
} else {
622+
null
623+
}
624+
}
608625

609626
@OptIn(ExperimentalAnvilApi::class)
610627
private fun AnnotationReference.priorityOrNull(): Int? = argumentAt("priority", 3)?.value()

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.duckduckgo.mobile.android.vpn.feature
1919
import com.duckduckgo.anvil.annotations.ContributesRemoteFeature
2020
import com.duckduckgo.di.scopes.AppScope
2121
import com.duckduckgo.feature.toggles.api.Toggle
22+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
2223

2324
/**
2425
* Local feature/settings - they will never be in remote config
@@ -28,9 +29,9 @@ import com.duckduckgo.feature.toggles.api.Toggle
2829
featureName = "appTpLocalFeature",
2930
)
3031
interface AppTpLocalFeature {
31-
@Toggle.DefaultValue(false)
32+
@Toggle.DefaultValue(DefaultFeatureValue.FALSE)
3233
fun self(): Toggle
3334

34-
@Toggle.DefaultValue(false)
35+
@Toggle.DefaultValue(DefaultFeatureValue.FALSE)
3536
fun verboseLogging(): Toggle
3637
}

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.duckduckgo.feature.toggles.api.MetricsPixel
3131
import com.duckduckgo.feature.toggles.api.MetricsPixelPlugin
3232
import com.duckduckgo.feature.toggles.api.RemoteFeatureStoreNamed
3333
import com.duckduckgo.feature.toggles.api.Toggle
34+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
3435
import com.duckduckgo.feature.toggles.api.Toggle.DefaultValue
3536
import com.duckduckgo.feature.toggles.api.Toggle.State
3637
import com.duckduckgo.feature.toggles.api.Toggle.State.CohortName
@@ -54,43 +55,43 @@ import kotlinx.coroutines.withContext
5455
settingsStore = ExceptionListsSettingStore::class,
5556
)
5657
interface AppTpRemoteFeatures {
57-
@Toggle.DefaultValue(true)
58+
@DefaultValue(DefaultFeatureValue.TRUE)
5859
fun self(): Toggle
5960

60-
@Toggle.DefaultValue(true)
61+
@DefaultValue(DefaultFeatureValue.TRUE)
6162
fun restartOnConnectivityLoss(): Toggle
6263

63-
@DefaultValue(true)
64+
@DefaultValue(DefaultFeatureValue.TRUE)
6465
fun setSearchDomains(): Toggle // kill switch
6566

66-
@DefaultValue(false)
67+
@DefaultValue(DefaultFeatureValue.FALSE)
6768
fun atpTdsExperiment001(): Toggle
6869

69-
@DefaultValue(false)
70+
@DefaultValue(DefaultFeatureValue.FALSE)
7071
fun atpTdsExperiment002(): Toggle
7172

72-
@DefaultValue(false)
73+
@DefaultValue(DefaultFeatureValue.FALSE)
7374
fun atpTdsExperiment003(): Toggle
7475

75-
@DefaultValue(false)
76+
@DefaultValue(DefaultFeatureValue.FALSE)
7677
fun atpTdsExperiment004(): Toggle
7778

78-
@DefaultValue(false)
79+
@DefaultValue(DefaultFeatureValue.FALSE)
7980
fun atpTdsExperiment005(): Toggle
8081

81-
@DefaultValue(false)
82+
@DefaultValue(DefaultFeatureValue.FALSE)
8283
fun atpTdsExperiment006(): Toggle
8384

84-
@DefaultValue(false)
85+
@DefaultValue(DefaultFeatureValue.FALSE)
8586
fun atpTdsExperiment007(): Toggle
8687

87-
@DefaultValue(false)
88+
@DefaultValue(DefaultFeatureValue.FALSE)
8889
fun atpTdsExperiment008(): Toggle
8990

90-
@DefaultValue(false)
91+
@DefaultValue(DefaultFeatureValue.FALSE)
9192
fun atpTdsExperiment009(): Toggle
9293

93-
@DefaultValue(false)
94+
@DefaultValue(DefaultFeatureValue.FALSE)
9495
fun atpTdsExperiment010(): Toggle
9596

9697
enum class Cohorts(override val cohortName: String) : CohortName {

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/newtab/AppTrackingProtectionNewTabSettingView.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import com.duckduckgo.di.scopes.ActivityScope
3535
import com.duckduckgo.di.scopes.AppScope
3636
import com.duckduckgo.di.scopes.ViewScope
3737
import com.duckduckgo.feature.toggles.api.Toggle
38+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
3839
import com.duckduckgo.mobile.android.vpn.databinding.ViewApptpSettingsItemBinding
3940
import com.duckduckgo.mobile.android.vpn.feature.removal.VpnFeatureRemover
4041
import com.duckduckgo.mobile.android.vpn.ui.newtab.AppTrackingProtectionNewTabSettingsViewModel.ViewState
@@ -119,6 +120,6 @@ class AppTrackingProtectionNewTabSettingViewPlugin @Inject constructor(
119120
featureName = "newTabAppTPSectionSetting",
120121
)
121122
interface NewTabAppTrackingProtectionSectionSetting {
122-
@Toggle.DefaultValue(true)
123+
@Toggle.DefaultValue(DefaultFeatureValue.TRUE)
123124
fun self(): Toggle
124125
}

app-tracking-protection/vpn-impl/src/test/java/com/duckduckgo/mobile/android/vpn/blocklist/AppTPBlockListInterceptorApiPluginTest.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import com.duckduckgo.feature.toggles.api.FakeToggleStore
2626
import com.duckduckgo.feature.toggles.api.FeatureToggles
2727
import com.duckduckgo.feature.toggles.api.FeatureTogglesInventory
2828
import com.duckduckgo.feature.toggles.api.Toggle
29+
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
2930
import com.duckduckgo.feature.toggles.api.Toggle.DefaultValue
3031
import com.duckduckgo.feature.toggles.api.Toggle.State
3132
import com.duckduckgo.mobile.android.app.tracking.AppTrackingProtection
@@ -272,15 +273,15 @@ abstract class TriggerTestScope private constructor()
272273
featureName = "appTrackerProtection",
273274
)
274275
interface TestBlockListFeature {
275-
@DefaultValue(false)
276+
@DefaultValue(DefaultFeatureValue.FALSE)
276277
fun self(): Toggle
277278

278-
@Toggle.DefaultValue(false)
279+
@DefaultValue(DefaultFeatureValue.FALSE)
279280
fun atpTdsNextExperimentTest(): Toggle
280281

281-
@Toggle.DefaultValue(false)
282+
@DefaultValue(DefaultFeatureValue.FALSE)
282283
fun atpTdsNextExperimentAnotherTest(): Toggle
283284

284-
@Toggle.DefaultValue(false)
285+
@DefaultValue(DefaultFeatureValue.FALSE)
285286
fun nonMatchingFeatureName(): Toggle
286287
}

app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ dependencies {
402402

403403
implementation project(':breakage-reporting-impl')
404404

405+
implementation project(':dax-prompts-api')
406+
implementation project(':dax-prompts-impl')
407+
405408
// Deprecated. TODO: Stop using this artifact.
406409
implementation "androidx.legacy:legacy-support-v4:_"
407410
debugImplementation Square.leakCanary.android

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

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ import com.duckduckgo.common.test.CoroutineTestRule
217217
import com.duckduckgo.common.test.InstantSchedulersRule
218218
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore
219219
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore.FeatureState
220+
import com.duckduckgo.common.ui.tabs.SwipingTabsFeature
221+
import com.duckduckgo.common.ui.tabs.SwipingTabsFeatureProvider
220222
import com.duckduckgo.common.utils.DispatcherProvider
221223
import com.duckduckgo.common.utils.device.DeviceInfo
222224
import com.duckduckgo.common.utils.plugins.PluginPoint
@@ -606,6 +608,7 @@ class BrowserTabViewModelTest {
606608
whenever(mockSitePermissionsManager.hasSitePermanentPermission(any(), any())).thenReturn(false)
607609
whenever(mockToggleReports.shouldPrompt()).thenReturn(false)
608610
whenever(subscriptions.isEligible()).thenReturn(false)
611+
whenever(mockDuckChat.showInBrowserMenu).thenReturn(MutableStateFlow(false))
609612

610613
remoteMessagingModel = givenRemoteMessagingModel(mockRemoteMessagingRepository, mockPixel, coroutineRule.testDispatcherProvider)
611614

@@ -862,15 +865,15 @@ class BrowserTabViewModelTest {
862865

863866
@Test
864867
fun whenViewBecomesVisibleAndDuckChatDisabledThenDuckChatNotVisible() {
865-
whenever(mockDuckChat.showInBrowserMenu()).thenReturn(false)
868+
whenever(mockDuckChat.showInBrowserMenu).thenReturn(MutableStateFlow(false))
866869
setBrowserShowing(true)
867870
testee.onViewVisible()
868871
assertFalse(browserViewState().showDuckChatOption)
869872
}
870873

871874
@Test
872875
fun whenViewBecomesVisibleAndDuckChatEnabledThenDuckChatIsVisible() {
873-
whenever(mockDuckChat.showInBrowserMenu()).thenReturn(true)
876+
whenever(mockDuckChat.showInBrowserMenu).thenReturn(MutableStateFlow(true))
874877
setBrowserShowing(true)
875878
testee.onViewVisible()
876879
assertTrue(browserViewState().showDuckChatOption)
@@ -6252,6 +6255,51 @@ class BrowserTabViewModelTest {
62526255
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
62536256
}
62546257

6258+
@Test
6259+
fun whenOpenDuckChatWithQueryEqualToUrlThenOpenDuckChat() = runTest {
6260+
val url = "https://example.com"
6261+
loadUrl(url)
6262+
6263+
testee.openDuckChat(url)
6264+
6265+
verify(mockDuckChat).openDuckChat()
6266+
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6267+
}
6268+
6269+
@Test
6270+
fun whenOpenDuckChatWithLastSubmittedUserQueryThenOpenDuckChatWithQuery() = runTest {
6271+
val query = "example"
6272+
testee.setLastSubmittedUserQuery(query)
6273+
6274+
testee.openDuckChat(query)
6275+
6276+
verify(mockDuckChat).openDuckChat(query)
6277+
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6278+
}
6279+
6280+
@Test
6281+
fun whenLastSubmittedUserQueryIsNullAndOmnibarHasTextThenOpenDuckChatWithQuery() = runTest {
6282+
val query = "example"
6283+
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "foo")
6284+
6285+
testee.openDuckChat(query)
6286+
6287+
verify(mockDuckChat).openDuckChat(query)
6288+
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6289+
}
6290+
6291+
@Test
6292+
fun whenLastSubmittedUserQueryDiffersFromNewQueryThenOpenWithAutoPrompt() = runTest {
6293+
val query = "example"
6294+
testee.setLastSubmittedUserQuery("foo")
6295+
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "")
6296+
6297+
testee.openDuckChat(query)
6298+
6299+
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6300+
verify(mockDuckChat, never()).openDuckChat()
6301+
}
6302+
62556303
private fun aCredential(): LoginCredentials {
62566304
return LoginCredentials(domain = null, username = null, password = null)
62576305
}

0 commit comments

Comments
 (0)