1
0
Fork 0

Add secret debug menu to override FxA servers

master
Edouard Oger 2020-03-02 18:23:00 -05:00 committed by Emily Kager
parent a4740e0828
commit 394f386ac3
7 changed files with 136 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import android.content.Context
import mozilla.components.service.fxa.ServerConfig
import mozilla.components.service.fxa.ServerConfig.Server
import org.mozilla.fenix.FeatureFlags
import org.mozilla.fenix.ext.settings
/**
* Utility to configure Firefox Account servers.
@ -24,6 +25,11 @@ object FxaServer {
}
fun config(context: Context): ServerConfig {
return ServerConfig(Server.RELEASE, CLIENT_ID, redirectUrl(context))
val serverOverride = context.settings().overrideFxAServer
val tokenServerOverride = context.settings().overrideSyncTokenServer.ifEmpty { null }
if (serverOverride.isEmpty()) {
return ServerConfig(Server.RELEASE, CLIENT_ID, redirectUrl(context), tokenServerOverride)
}
return ServerConfig(serverOverride, CLIENT_ID, redirectUrl(context), tokenServerOverride)
}
}

View File

@ -10,6 +10,8 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.content.res.AppCompatResources
import android.os.Handler
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavDirections
import androidx.navigation.findNavController
@ -45,6 +47,7 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.account.AccountAuthErrorPreference
import org.mozilla.fenix.settings.account.AccountPreference
import kotlin.system.exitProcess
@Suppress("LargeClass", "TooManyFunctions")
class SettingsFragment : PreferenceFragmentCompat() {
@ -300,6 +303,29 @@ class SettingsFragment : PreferenceFragmentCompat() {
requireComponents.core.engine.settings.remoteDebuggingEnabled = newValue
true
}
val preferenceFxAOverride =
findPreference<Preference>(getPreferenceKey(R.string.pref_key_override_fxa_server))
val preferenceSyncOverride =
findPreference<Preference>(getPreferenceKey(R.string.pref_key_override_sync_tokenserver))
val syncFxAOverrideUpdater = object : StringSharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
return super.onPreferenceChange(preference, newValue).also {
updateFxASyncOverrideMenu()
Toast.makeText(
context,
getString(R.string.toast_override_fxa_sync_server_done),
Toast.LENGTH_LONG
).show()
Handler().postDelayed({
exitProcess(0)
}, FXA_SYNC_OVERRIDE_EXIT_DELAY)
}
}
}
preferenceFxAOverride?.onPreferenceChangeListener = syncFxAOverrideUpdater
preferenceSyncOverride?.onPreferenceChangeListener = syncFxAOverrideUpdater
}
private fun navigateFromSettings(directions: NavDirections) {
@ -343,6 +369,8 @@ class SettingsFragment : PreferenceFragmentCompat() {
val accountManager = requireComponents.backgroundServices.accountManager
val account = accountManager.authenticatedAccount()
updateFxASyncOverrideMenu()
// Signed-in, no problems.
if (account != null && !accountManager.accountNeedsReauth()) {
preferenceSignIn?.isVisible = false
@ -388,7 +416,31 @@ class SettingsFragment : PreferenceFragmentCompat() {
}
}
private fun updateFxASyncOverrideMenu() {
val preferenceFxAOverride =
findPreference<Preference>(getPreferenceKey(R.string.pref_key_override_fxa_server))
val preferenceSyncOverride =
findPreference<Preference>(getPreferenceKey(R.string.pref_key_override_sync_tokenserver))
val settings = requireContext().settings()
val show = settings.overrideFxAServer.isNotEmpty() ||
settings.overrideSyncTokenServer.isNotEmpty() ||
settings.showSecretDebugMenuThisSession
// Only enable changes to these prefs when the user isn't connected to an account.
val enabled = requireComponents.backgroundServices.accountManager.authenticatedAccount() == null
preferenceFxAOverride?.apply {
isVisible = show
isEnabled = enabled
summary = settings.overrideFxAServer.ifEmpty { null }
}
preferenceSyncOverride?.apply {
isVisible = show
isEnabled = enabled
summary = settings.overrideSyncTokenServer.ifEmpty { null }
}
}
companion object {
private const val SCROLL_INDICATOR_DELAY = 10L
private const val FXA_SYNC_OVERRIDE_EXIT_DELAY = 2000L
}
}

View File

@ -10,6 +10,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.pm.PackageInfoCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
@ -20,6 +21,7 @@ import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.lib.Do
import org.mozilla.fenix.settings.SupportUtils
import org.mozilla.fenix.settings.about.AboutItemType.LICENSING_INFO
@ -36,6 +38,8 @@ import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
class AboutFragment : Fragment(), AboutPageListener {
private lateinit var appName: String
private val aboutPageAdapter: AboutPageAdapter = AboutPageAdapter(this)
private var secretDebugMenuClicks = 0
private var lastDebugMenuToast: Toast? = null
override fun onCreateView(
inflater: LayoutInflater,
@ -49,6 +53,11 @@ class AboutFragment : Fragment(), AboutPageListener {
return rootView
}
override fun onResume() {
super.onResume()
secretDebugMenuClicks = 0
}
@ExperimentalCoroutinesApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -63,6 +72,34 @@ class AboutFragment : Fragment(), AboutPageListener {
)
}
// 5 taps on the logo activate the "secret" debug menu.
wordmark.setOnClickListener {
// Because the user will mostly likely tap the logo in rapid succession,
// we ensure only 1 toast is shown at any given time.
lastDebugMenuToast?.let { toast -> toast.cancel() }
secretDebugMenuClicks += 1
when (secretDebugMenuClicks) {
in 2 until SECRET_DEBUG_MENU_CLICKS -> {
val clicksLeft = SECRET_DEBUG_MENU_CLICKS - secretDebugMenuClicks
val toast = Toast.makeText(
context,
getString(R.string.about_debug_menu_toast_progress, clicksLeft),
Toast.LENGTH_SHORT
)
toast.show()
lastDebugMenuToast = toast
}
SECRET_DEBUG_MENU_CLICKS -> {
Toast.makeText(
context,
getString(R.string.about_debug_menu_toast_done),
Toast.LENGTH_LONG
).show()
requireContext().settings().showSecretDebugMenuThisSession = true
}
}
}
populateAboutHeader()
aboutPageAdapter.submitList(populateAboutList())
}
@ -183,5 +220,7 @@ class AboutFragment : Fragment(), AboutPageListener {
companion object {
private const val ABOUT_LICENSE_URL = "about:license"
// Number of clicks on the app logo to enable the "secret" debug menu.
private const val SECRET_DEBUG_MENU_CLICKS = 5
}
}

View File

@ -187,6 +187,8 @@ class Settings private constructor(
(trackingProtectionOnboardingCount < trackingProtectionOnboardingMaximumCount &&
!trackingProtectionOnboardingShownThisSession)
var showSecretDebugMenuThisSession = false
val shouldShowSecurityPinWarningSync: Boolean
get() = loginsSecureWarningSyncCount < showLoginsSecureWarningSyncMaxCount
@ -597,4 +599,14 @@ class Settings private constructor(
appContext.getPreferenceKey(R.string.pref_key_open_links_in_external_app),
default = false
)
var overrideFxAServer by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_override_fxa_server),
default = ""
)
var overrideSyncTokenServer by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_override_sync_tokenserver),
default = ""
)
}

View File

@ -38,6 +38,8 @@
<string name="pref_key_account" translatable="false">pref_key_account</string>
<string name="pref_key_sign_in" translatable="false">pref_key_sign_in</string>
<string name="pref_key_account_auth_error" translatable="false">pref_key_account_auth_error</string>
<string name="pref_key_override_fxa_server" translatable="false">pref_key_override_fxa_server</string>
<string name="pref_key_override_sync_tokenserver" translatable="false">pref_key_override_sync_tokenserver</string>
<string name="pref_key_private_mode" translatable="false">pref_key_private_mode</string>
<string name="pref_key_customize" translatable="false">pref_key_customize</string>
<string name="pref_key_toolbar" translatable="false">pref_key_toolbar</string>

View File

@ -202,6 +202,12 @@
<string name="preferences_add_private_browsing_shortcut">Add private browsing shortcut</string>
<!-- Preference for accessibility -->
<string name="preferences_accessibility">Accessibility</string>
<!-- Preference to override the Firefox Account server -->
<string name="preferences_override_fxa_server">Custom Firefox Account server</string>
<!-- Preference to override the Sync token server -->
<string name="preferences_override_sync_tokenserver">Custom Sync server</string>
<!-- Toast shown after updating the FxA/Sync server override preferences -->
<string name="toast_override_fxa_sync_server_done">Firefox Account/Sync server modified. Quitting the application to apply changes…</string>
<!-- Preference category for account information -->
<string name="preferences_category_account">Account</string>
<!-- Preference shown on banner to sign into account -->
@ -1062,6 +1068,10 @@
<string name="about_licensing_information">Licensing information</string>
<!-- About page link text to open a screen with libraries that are used -->
<string name="about_other_open_source_libraries">Libraries that we use</string>
<!-- Toast shown to the user when they are activating the secret dev menu
The first parameter is number of long clicks left to enable the menu -->
<string name="about_debug_menu_toast_progress">Debug menu: %1$d click(s) left to enable</string>
<string name="about_debug_menu_toast_done">Debug menu enabled</string>
<!-- Content description of the tab counter toolbar button when one tab is open -->
<string name="tab_counter_content_description_one_tab">1 tab</string>

View File

@ -29,6 +29,20 @@
android:key="@string/pref_key_account_auth_error"/>
</androidx.preference.PreferenceCategory>
<androidx.preference.EditTextPreference
android:key="@string/pref_key_override_fxa_server"
android:title="@string/preferences_override_fxa_server"
android:inputType="textUri"
app:iconSpaceReserved="false"
app:isPreferenceVisible="false"/>
<androidx.preference.EditTextPreference
android:key="@string/pref_key_override_sync_tokenserver"
android:title="@string/preferences_override_sync_tokenserver"
android:inputType="textUri"
app:iconSpaceReserved="false"
app:isPreferenceVisible="false"/>
<androidx.preference.PreferenceCategory
android:title="@string/preferences_category_general"
app:iconSpaceReserved="false">