For #14034: Add debug preference to override AMO collection in Nightly

pull/184/head
Christian Sadilek 4 years ago
parent a92356fe00
commit d4ab728cff

@ -17,8 +17,10 @@ import mozilla.components.feature.addons.update.DefaultAddonUpdater
import mozilla.components.lib.publicsuffixlist.PublicSuffixList import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.migration.state.MigrationStore import mozilla.components.support.migration.state.MigrationStore
import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.components.metrics.AppStartupTelemetry import org.mozilla.fenix.components.metrics.AppStartupTelemetry
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.utils.ClipboardHandler
import org.mozilla.fenix.utils.Mockable import org.mozilla.fenix.utils.Mockable
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
@ -71,14 +73,26 @@ class Components(private val context: Context) {
} }
val addonCollectionProvider by lazy { val addonCollectionProvider by lazy {
if (!BuildConfig.AMO_COLLECTION.isNullOrEmpty()) { // Check if we have a customized (overridden) AMO collection (only supported in Nightly)
if (Config.channel.isNightlyOrDebug && context.settings().amoCollectionOverrideConfigured()) {
AddonCollectionProvider(
context,
core.client,
collectionUser = context.settings().overrideAmoUser,
collectionName = context.settings().overrideAmoCollection
)
}
// Use build config otherwise
else if (!BuildConfig.AMO_COLLECTION.isNullOrEmpty()) {
AddonCollectionProvider( AddonCollectionProvider(
context, context,
core.client, core.client,
collectionName = BuildConfig.AMO_COLLECTION, collectionName = BuildConfig.AMO_COLLECTION,
maxCacheAgeInMinutes = DAY_IN_MINUTES maxCacheAgeInMinutes = DAY_IN_MINUTES
) )
} else { }
// Fall back to defaults
else {
AddonCollectionProvider(context, core.client, maxCacheAgeInMinutes = DAY_IN_MINUTES) AddonCollectionProvider(context, core.client, maxCacheAgeInMinutes = DAY_IN_MINUTES)
} }
} }

@ -6,13 +6,16 @@ package org.mozilla.fenix.settings
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.provider.Settings import android.view.LayoutInflater
import android.widget.Toast import android.widget.Toast
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavDirections import androidx.navigation.NavDirections
import androidx.navigation.findNavController import androidx.navigation.findNavController
@ -20,6 +23,8 @@ import androidx.navigation.fragment.navArgs
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.amo_collection_override_dialog.view.*
import kotlinx.android.synthetic.main.fragment_installed_add_on_details.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -28,6 +33,7 @@ import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile import mozilla.components.concept.sync.Profile
import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.content.getColorFromAttr
import mozilla.components.support.ktx.android.view.showKeyboard
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.Config import org.mozilla.fenix.Config
import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.FeatureFlags
@ -43,6 +49,7 @@ import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.account.AccountUiView import org.mozilla.fenix.settings.account.AccountUiView
import org.mozilla.fenix.utils.Settings
import kotlin.system.exitProcess import kotlin.system.exitProcess
@Suppress("LargeClass", "TooManyFunctions") @Suppress("LargeClass", "TooManyFunctions")
@ -304,6 +311,41 @@ class SettingsFragment : PreferenceFragmentCompat() {
resources.getString(R.string.pref_key_debug_settings) -> { resources.getString(R.string.pref_key_debug_settings) -> {
SettingsFragmentDirections.actionSettingsFragmentToSecretSettingsFragment() SettingsFragmentDirections.actionSettingsFragmentToSecretSettingsFragment()
} }
resources.getString(R.string.pref_key_override_amo_collection) -> {
val context = requireContext()
val dialogView = LayoutInflater.from(context).inflate(R.layout.amo_collection_override_dialog, null)
AlertDialog.Builder(context).apply {
setTitle(context.getString(R.string.preferences_customize_amo_collection))
setView(dialogView)
setNegativeButton(R.string.customize_addon_collection_cancel) { dialog: DialogInterface, _ ->
dialog.cancel()
}
setPositiveButton(R.string.customize_addon_collection_ok) { _, _ ->
context.settings().overrideAmoUser = dialogView.custom_amo_user.text.toString()
context.settings().overrideAmoCollection = dialogView.custom_amo_collection.text.toString()
Toast.makeText(
context,
getString(R.string.toast_customize_addon_collection_done),
Toast.LENGTH_LONG
).show()
Handler().postDelayed({
exitProcess(0)
}, AMO_COLLECTION_OVERRIDE_EXIT_DELAY)
}
dialogView.custom_amo_collection.setText(context.settings().overrideAmoCollection)
dialogView.custom_amo_user.setText(context.settings().overrideAmoUser)
dialogView.custom_amo_user.requestFocus()
dialogView.custom_amo_user.showKeyboard()
create()
}.show()
null
}
else -> null else -> null
} }
directions?.let { navigateFromSettings(directions) } directions?.let { navigateFromSettings(directions) }
@ -374,12 +416,14 @@ class SettingsFragment : PreferenceFragmentCompat() {
findPreference<Preference>( findPreference<Preference>(
getPreferenceKey(R.string.pref_key_debug_settings) getPreferenceKey(R.string.pref_key_debug_settings)
)?.isVisible = requireContext().settings().showSecretDebugMenuThisSession )?.isVisible = requireContext().settings().showSecretDebugMenuThisSession
setupAmoCollectionOverridePreference(requireContext().settings())
} }
private fun getClickListenerForMakeDefaultBrowser(): Preference.OnPreferenceClickListener { private fun getClickListenerForMakeDefaultBrowser(): Preference.OnPreferenceClickListener {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Preference.OnPreferenceClickListener { Preference.OnPreferenceClickListener {
val intent = Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS) val intent = Intent(android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
startActivity(intent) startActivity(intent)
true true
} }
@ -446,8 +490,23 @@ class SettingsFragment : PreferenceFragmentCompat() {
} }
} }
@VisibleForTesting
internal fun setupAmoCollectionOverridePreference(settings: Settings) {
val preferenceAmoCollectionOverride =
findPreference<Preference>(getPreferenceKey(R.string.pref_key_override_amo_collection))
val show = (Config.channel.isNightlyOrDebug && (
settings.amoCollectionOverrideConfigured() || settings.showSecretDebugMenuThisSession)
)
preferenceAmoCollectionOverride?.apply {
isVisible = show
summary = settings.overrideAmoCollection.ifEmpty { null }
}
}
companion object { companion object {
private const val SCROLL_INDICATOR_DELAY = 10L private const val SCROLL_INDICATOR_DELAY = 10L
private const val FXA_SYNC_OVERRIDE_EXIT_DELAY = 2000L private const val FXA_SYNC_OVERRIDE_EXIT_DELAY = 2000L
private const val AMO_COLLECTION_OVERRIDE_EXIT_DELAY = 3000L
} }
} }

@ -886,6 +886,20 @@ class Settings(private val appContext: Context) : PreferencesHolder {
default = "" default = ""
) )
var overrideAmoUser by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_override_amo_user),
default = ""
)
var overrideAmoCollection by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_override_amo_collection),
default = ""
)
fun amoCollectionOverrideConfigured(): Boolean {
return overrideAmoUser.isNotEmpty() || overrideAmoCollection.isNotEmpty()
}
val topSitesSize by intPreference( val topSitesSize by intPreference(
appContext.getPreferenceKey(R.string.pref_key_top_sites_size), appContext.getPreferenceKey(R.string.pref_key_top_sites_size),
default = 0 default = 0

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/custom_amo_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/customize_addon_collection_user_hint"
android:singleLine="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="8dp"
android:textColor="?primaryText"/>
<EditText
android:id="@+id/custom_amo_collection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/customize_addon_collection_hint"
android:singleLine="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textColor="?primaryText"/>
</LinearLayout>

@ -35,6 +35,8 @@
<string name="pref_key_delete_browsing_data_on_quit_categories" translatable="false">pref_key_delete_browsing_data_on_quit_categories</string> <string name="pref_key_delete_browsing_data_on_quit_categories" translatable="false">pref_key_delete_browsing_data_on_quit_categories</string>
<string name="pref_key_last_known_mode_private" translatable="false">pref_key_last_known_mode_private</string> <string name="pref_key_last_known_mode_private" translatable="false">pref_key_last_known_mode_private</string>
<string name="pref_key_addons" translatable="false">pref_key_addons</string> <string name="pref_key_addons" translatable="false">pref_key_addons</string>
<string name="pref_key_override_amo_user" translatable="false">pref_key_override_amo_user</string>
<string name="pref_key_override_amo_collection" translatable="false">pref_key_override_amo_collection</string>
<string name="pref_key_last_maintenance" translatable="false">pref_key_last_maintenance</string> <string name="pref_key_last_maintenance" translatable="false">pref_key_last_maintenance</string>
<string name="pref_key_help" translatable="false">pref_key_help</string> <string name="pref_key_help" translatable="false">pref_key_help</string>
<string name="pref_key_rate" translatable="false">pref_key_rate</string> <string name="pref_key_rate" translatable="false">pref_key_rate</string>

@ -337,6 +337,20 @@
<!-- Preference for notifications --> <!-- Preference for notifications -->
<string name="preferences_notifications">Notifications</string> <string name="preferences_notifications">Notifications</string>
<!-- Add-on Preferences -->
<!-- Preference to customize the configured AMO (addons.mozilla.org) collection -->
<string name="preferences_customize_amo_collection">Custom Add-on collection</string>
<!-- Button caption to confirm the add-on collection configuration -->
<string name="customize_addon_collection_ok">OK</string>
<!-- Button caption to abort the add-on collection configuration -->
<string name="customize_addon_collection_cancel">Cancel</string>
<!-- Hint displayed on input field for custom collection name -->
<string name="customize_addon_collection_hint">Collection name</string>
<!-- Hint displayed on input field for custom collection user ID-->
<string name="customize_addon_collection_user_hint">Collection owner (User ID)</string>
<!-- Toast shown after confirming the custom add-on collection configuration -->
<string name="toast_customize_addon_collection_done">Add-on collection modified. Quitting the application to apply changes…</string>
<!-- Account Preferences --> <!-- Account Preferences -->
<!-- Preference for triggering sync --> <!-- Preference for triggering sync -->
<string name="preferences_sync_now">Sync now</string> <string name="preferences_sync_now">Sync now</string>

@ -136,6 +136,11 @@
android:key="@string/pref_key_addons" android:key="@string/pref_key_addons"
android:title="@string/preferences_addons" /> android:title="@string/preferences_addons" />
<androidx.preference.Preference
android:icon="@drawable/ic_addons_extensions"
android:key="@string/pref_key_override_amo_collection"
android:title="@string/preferences_customize_amo_collection"/>
<androidx.preference.SwitchPreference <androidx.preference.SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:icon="@drawable/ic_open_in_app" android:icon="@drawable/ic_open_in_app"

@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.settings
import androidx.fragment.app.FragmentActivity
import androidx.preference.Preference
import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.utils.Settings
import org.robolectric.Robolectric
@RunWith(FenixRobolectricTestRunner::class)
class SettingsFragmentTest {
@Test
fun `Add-on collection override pref is visible if debug menu active`() {
val settingsFragment = SettingsFragment()
val activity = Robolectric.buildActivity(FragmentActivity::class.java).create().get()
activity.supportFragmentManager.beginTransaction()
.add(settingsFragment, "test")
.commitNow()
val preferenceAmoCollectionOverride = settingsFragment.findPreference<Preference>(
settingsFragment.getPreferenceKey(R.string.pref_key_override_amo_collection)
)
settingsFragment.setupAmoCollectionOverridePreference(mockk(relaxed = true))
assertNotNull(preferenceAmoCollectionOverride)
assertFalse(preferenceAmoCollectionOverride!!.isVisible)
val settings: Settings = mockk(relaxed = true)
every { settings.showSecretDebugMenuThisSession } returns true
settingsFragment.setupAmoCollectionOverridePreference(settings)
assertTrue(preferenceAmoCollectionOverride.isVisible)
}
@Test
fun `Add-on collection override pref is visible if already configured`() {
val settingsFragment = SettingsFragment()
val activity = Robolectric.buildActivity(FragmentActivity::class.java).create().get()
activity.supportFragmentManager.beginTransaction()
.add(settingsFragment, "test")
.commitNow()
val preferenceAmoCollectionOverride = settingsFragment.findPreference<Preference>(
settingsFragment.getPreferenceKey(R.string.pref_key_override_amo_collection)
)
settingsFragment.setupAmoCollectionOverridePreference(mockk(relaxed = true))
assertNotNull(preferenceAmoCollectionOverride)
assertFalse(preferenceAmoCollectionOverride!!.isVisible)
val settings: Settings = mockk(relaxed = true)
every { settings.showSecretDebugMenuThisSession } returns false
every { settings.amoCollectionOverrideConfigured() } returns false
settingsFragment.setupAmoCollectionOverridePreference(settings)
assertFalse(preferenceAmoCollectionOverride.isVisible)
every { settings.amoCollectionOverrideConfigured() } returns true
settingsFragment.setupAmoCollectionOverridePreference(settings)
assertTrue(preferenceAmoCollectionOverride.isVisible)
}
}

@ -576,4 +576,34 @@ class SettingsTest {
settings.getSitePermissionsCustomSettingsRules() settings.getSitePermissionsCustomSettingsRules()
) )
} }
@Test
fun overrideAmoCollection() {
// When just created
// Then
assertEquals("", settings.overrideAmoCollection)
assertFalse(settings.amoCollectionOverrideConfigured())
// When
settings.overrideAmoCollection = "testCollection"
// Then
assertEquals("testCollection", settings.overrideAmoCollection)
assertTrue(settings.amoCollectionOverrideConfigured())
}
@Test
fun overrideAmoUser() {
// When just created
// Then
assertEquals("", settings.overrideAmoUser)
assertFalse(settings.amoCollectionOverrideConfigured())
// When
settings.overrideAmoUser = "testAmoUser"
// Then
assertEquals("testAmoUser", settings.overrideAmoUser)
assertTrue(settings.amoCollectionOverrideConfigured())
}
} }

Loading…
Cancel
Save