Skip to content
This repository has been archived by the owner on Feb 20, 2023. It is now read-only.

For #3700 - Add Setting to Delete Data on "Quit" menu action #5098

Merged
merged 1 commit into from Sep 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/metrics.yaml
Expand Up @@ -78,11 +78,12 @@ events:
description: >
A string containing the name of the item the user tapped. These items include:
Settings, Library, Help, Desktop Site toggle on/off, Find in Page, New Tab,
Private Tab, Share, Report Site Issue, Back/Forward button, Reload Button
Private Tab, Share, Report Site Issue, Back/Forward button, Reload Button, Quit
bugs:
- 1024
data_reviews:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a link to this PR for this data review?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just did!

- https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708
- https://github.com/mozilla-mobile/fenix/pull/5098#issuecomment-529658996
notification_emails:
- fenix-core@mozilla.com
expires: "2020-03-01"
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/org/mozilla/fenix/FeatureFlags.kt
Expand Up @@ -47,4 +47,9 @@ object FeatureFlags {
* setting screen for cookies, cached images and files, and site permissions.
*/
val granularDataDeletion = nightly or debug

/**
* Gives option in Settings to Delete Browsing Data on new menu option Quit
*/
val deleteDataOnQuit = nightly or debug
}
Expand Up @@ -171,7 +171,8 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs
action = Intent.ACTION_VIEW
flags = Intent.FLAG_ACTIVITY_NEW_TASK
},
bottomSheetBehavior = QuickActionSheetBehavior.from(nestedScrollQuickAction)
bottomSheetBehavior = QuickActionSheetBehavior.from(nestedScrollQuickAction),
scope = lifecycleScope
)

browserInteractor =
Expand Down
Expand Up @@ -260,7 +260,7 @@ sealed class Event {
enum class Item {
SETTINGS, LIBRARY, HELP, DESKTOP_VIEW_ON, DESKTOP_VIEW_OFF, FIND_IN_PAGE, NEW_TAB,
NEW_PRIVATE_TAB, SHARE, REPORT_SITE_ISSUE, BACK, FORWARD, RELOAD, STOP, OPEN_IN_FENIX,
SAVE_TO_COLLECTION, ADD_TO_HOMESCREEN
SAVE_TO_COLLECTION, ADD_TO_HOMESCREEN, QUIT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@boek how do new events get into the metrics.md file? Do you have to change more files, or does the documentation automatically get added when you just add an event?

Should these be updated in the metrics.md file as part of the PR? At a quick glance I also didn't see save_to_collection or add_to_homescreen, so I'm wondering if I'm looking in the wrong place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to manually add this to metrics.md for now. At least until the Glean auto-generate documentation PR is merged

@ekager

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to metrics.md and metrics.yaml!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated, @boek does this mean open_in_fenix, save_to_collection, and add_to_homescreen did not get data review, or need to be updated?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liuche that is correct
https://github.com/mozilla-mobile/fenix/pull/2131/files
and #4925 didn't get data reviews. In the short term I could put myself as a codeowner of metrics.kt until we get a better process

}

override val extras: Map<Events.browserMenuActionKeys, String>?
Expand Down
Expand Up @@ -8,6 +8,7 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.core.widget.NestedScrollView
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.navigation.NavController
import com.google.android.material.bottomsheet.BottomSheetBehavior
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand All @@ -29,6 +30,7 @@ import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.toTab
import org.mozilla.fenix.lib.Do
import org.mozilla.fenix.quickactionsheet.QuickActionSheetBehavior
import org.mozilla.fenix.utils.deleteAndQuit

/**
* An interface that handles the view manipulation of the BrowserToolbar, triggered by the Interactor
Expand All @@ -50,7 +52,8 @@ class DefaultBrowserToolbarController(
private val viewModel: CreateCollectionViewModel,
private val getSupportUrl: () -> String,
private val openInFenixIntent: Intent,
private val bottomSheetBehavior: QuickActionSheetBehavior<NestedScrollView>
private val bottomSheetBehavior: QuickActionSheetBehavior<NestedScrollView>,
private val scope: LifecycleCoroutineScope
) : BrowserToolbarController {

override fun handleToolbarPaste(text: String) {
Expand Down Expand Up @@ -176,6 +179,7 @@ class DefaultBrowserToolbarController(
// Close this activity since it is no longer displaying any session
(context as Activity).finish()
}
ToolbarMenu.Item.Quit -> context.deleteAndQuit(scope)
}
}

Expand Down Expand Up @@ -204,6 +208,7 @@ class DefaultBrowserToolbarController(
ToolbarMenu.Item.Share -> Event.BrowserMenuItemTapped.Item.SHARE
ToolbarMenu.Item.SaveToCollection -> Event.BrowserMenuItemTapped.Item.SAVE_TO_COLLECTION
ToolbarMenu.Item.AddToHomeScreen -> Event.BrowserMenuItemTapped.Item.ADD_TO_HOMESCREEN
ToolbarMenu.Item.Quit -> Event.BrowserMenuItemTapped.Item.QUIT
}

context.components.analytics.metrics.track(Event.BrowserMenuItemTapped(eventItem))
Expand Down
Expand Up @@ -17,6 +17,7 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.Settings

class DefaultToolbarMenu(
private val context: Context,
Expand Down Expand Up @@ -203,6 +204,18 @@ class DefaultToolbarMenu(
)
}

if (Settings.getInstance(context).shouldDeleteBrowsingDataOnQuit) {
items.add(
BrowserMenuImageText(
context.getString(R.string.delete_browsing_data_on_quit_action),
R.drawable.ic_exit,
ThemeManager.resolveAttribute(R.attr.primaryText, context)
) {
onItemTapped.invoke(ToolbarMenu.Item.Quit)
}
)
}

items.add(
BrowserMenuDivider()
)
Expand Down
Expand Up @@ -25,6 +25,7 @@ interface ToolbarMenu {
object OpenInFenix : Item()
object SaveToCollection : Item()
object AddToHomeScreen : Item()
object Quit : Item()
}

val menuBuilder: BrowserMenuBuilder
Expand Down
Expand Up @@ -34,12 +34,19 @@ class DefaultDeleteBrowsingDataController(
}

override suspend fun deleteBrowsingData() {
withContext(coroutineContext) {
if (FeatureFlags.granularDataDeletion) {
context.components.core.engine.clearData(Engine.BrowsingData.select(Engine.BrowsingData.DOM_STORAGES))
} else {
if (FeatureFlags.granularDataDeletion) {
deleteHistoryAndDOMStorages()
} else {
withContext(coroutineContext) {
context.components.core.engine.clearData(Engine.BrowsingData.all())
}
context.components.core.historyStorage.deleteEverything()
}
}

suspend fun deleteHistoryAndDOMStorages() {
withContext(coroutineContext) {
context.components.core.engine.clearData(Engine.BrowsingData.select(Engine.BrowsingData.DOM_STORAGES))
}
context.components.core.historyStorage.deleteEverything()
}
Expand Down
@@ -0,0 +1,105 @@
/* 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 android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.CheckBoxPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.utils.Settings

class DeleteBrowsingDataOnQuitFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.delete_browsing_data_quit_preferences, rootKey)
}

@Suppress("ComplexMethod")
override fun onResume() {
super.onResume()
activity?.title = getString(R.string.preferences_delete_browsing_data_on_quit)
(activity as AppCompatActivity).supportActionBar?.show()

val checkboxUpdater = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
super.onPreferenceChange(preference, newValue)
if (!Settings.getInstance(preference.context).shouldDeleteAnyDataOnQuit()) {
findPreference<SwitchPreference>(
getPreferenceKey(R.string.pref_key_delete_browsing_data_on_quit)
)?.apply {
isChecked = false
}
Settings.getInstance(preference.context).preferences.edit().putBoolean(
getString(R.string.pref_key_delete_browsing_data_on_quit),
false
).apply()
}
return true
}
}

val switchUpdater = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
setAllCheckboxes(newValue as Boolean)
return super.onPreferenceChange(preference, newValue)
}
}

findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_open_tabs_on_quit))?.apply {
onPreferenceChangeListener = checkboxUpdater
}
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_browsing_history_on_quit))?.apply {
onPreferenceChangeListener = checkboxUpdater
}
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_caches_on_quit))?.apply {
onPreferenceChangeListener = checkboxUpdater
}
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_permissions_on_quit))?.apply {
onPreferenceChangeListener = checkboxUpdater
}
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_cookies_on_quit))?.apply {
onPreferenceChangeListener = checkboxUpdater
}

// Delete Browsing Data on Quit Switch
val deleteOnQuitKey = getPreferenceKey(R.string.pref_key_delete_browsing_data_on_quit)
findPreference<SwitchPreference>(deleteOnQuitKey)?.apply {
onPreferenceChangeListener = switchUpdater
isChecked = Settings.getInstance(context!!).shouldDeleteBrowsingDataOnQuit
}
}

private fun setAllCheckboxes(newValue: Boolean) {
val openTabs =
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_open_tabs_on_quit))
val history =
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_browsing_history_on_quit))
val cache =
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_caches_on_quit))
val permissions =
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_permissions_on_quit))
val cookies =
findPreference<CheckBoxPreference>(getPreferenceKey(R.string.pref_key_delete_cookies_on_quit))

openTabs?.isChecked = newValue
history?.isChecked = newValue
cache?.isChecked = newValue
permissions?.isChecked = newValue
cookies?.isChecked = newValue

Settings.getInstance(context!!).preferences.edit().putBoolean(openTabs?.key, newValue)
.apply()
Settings.getInstance(context!!).preferences.edit().putBoolean(history?.key, newValue)
.apply()
Settings.getInstance(context!!).preferences.edit().putBoolean(cache?.key, newValue).apply()
Settings.getInstance(context!!).preferences.edit().putBoolean(permissions?.key, newValue)
.apply()
Settings.getInstance(context!!).preferences.edit().putBoolean(cookies?.key, newValue)
.apply()
}
}
19 changes: 19 additions & 0 deletions app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt
Expand Up @@ -29,6 +29,7 @@ import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.Config
import org.mozilla.fenix.FeatureFlags
import org.mozilla.fenix.FenixApplication
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
Expand All @@ -40,6 +41,7 @@ import org.mozilla.fenix.R.string.pref_key_account_category
import org.mozilla.fenix.R.string.pref_key_add_private_browsing_shortcut
import org.mozilla.fenix.R.string.pref_key_data_choices
import org.mozilla.fenix.R.string.pref_key_delete_browsing_data
import org.mozilla.fenix.R.string.pref_key_delete_browsing_data_on_quit_preference
import org.mozilla.fenix.R.string.pref_key_help
import org.mozilla.fenix.R.string.pref_key_language
import org.mozilla.fenix.R.string.pref_key_leakcanary
Expand Down Expand Up @@ -98,6 +100,14 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
isVisible = false
}
}

if (FeatureFlags.deleteDataOnQuit) {
findPreference<Preference>(
getPreferenceKey(R.string.pref_key_delete_browsing_data_on_quit_preference)
)?.apply {
isVisible = true
}
}
}

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
Expand Down Expand Up @@ -201,6 +211,9 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
resources.getString(pref_key_delete_browsing_data) -> {
navigateToDeleteBrowsingData()
}
resources.getString(pref_key_delete_browsing_data_on_quit_preference) -> {
navigateToDeleteBrowsingDataOnQuit()
}
resources.getString(pref_key_theme) -> {
navigateToThemeSettings()
}
Expand Down Expand Up @@ -333,6 +346,12 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
Navigation.findNavController(view!!).navigate(directions)
}

private fun navigateToDeleteBrowsingDataOnQuit() {
val directions =
SettingsFragmentDirections.actionSettingsFragmentToDeleteBrowsingDataOnQuitFragment()
Navigation.findNavController(view!!).navigate(directions)
}

override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
lifecycleScope.launch {
context?.let {
Expand Down
Expand Up @@ -8,7 +8,7 @@ import org.mozilla.fenix.ext.settings
* Updates the corresponding [android.content.SharedPreferences] when the boolean [Preference] is changed.
* The preference key is used as the shared preference key.
*/
class SharedPreferenceUpdater : Preference.OnPreferenceChangeListener {
open class SharedPreferenceUpdater : Preference.OnPreferenceChangeListener {

override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
val newBooleanValue = newValue as? Boolean ?: return false
Expand Down
43 changes: 43 additions & 0 deletions app/src/main/java/org/mozilla/fenix/utils/DeleteAndQuit.kt
@@ -0,0 +1,43 @@
/* 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.utils

import android.content.Context
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.settings.DefaultDeleteBrowsingDataController

/**
* Deletes selected browsing data and finishes the activity
*/
fun Context.deleteAndQuit(coroutineScope: CoroutineScope) {
coroutineScope.launch {
runBlocking {
val controller =
DefaultDeleteBrowsingDataController(this@deleteAndQuit, coroutineContext)
if (Settings.getInstance(this@deleteAndQuit).deleteCacheOnQuit) {
controller.deleteCachedFiles()
}
if (Settings.getInstance(this@deleteAndQuit).deleteTabsOnQuit) {
controller.deleteTabs()
}
if (Settings.getInstance(this@deleteAndQuit).deletePermissionsOnQuit) {
launch(Dispatchers.IO) {
controller.deleteSitePermissions()
}
}
if (Settings.getInstance(this@deleteAndQuit).deleteCookiesOnQuit) {
controller.deleteCookies()
}
if (Settings.getInstance(this@deleteAndQuit).deleteHistoryOnQuit) {
controller.deleteHistoryAndDOMStorages()
}
}
this@deleteAndQuit.asActivity()?.finish()
}
}