1
0
Fork 0

For #1084 - Add tracking protection toggle to quick settings dialog

master
Emily Kager 2019-04-15 17:14:50 -07:00 committed by Colin Lee
parent 3f906dc58a
commit 01a181975d
9 changed files with 177 additions and 14 deletions

View File

@ -517,10 +517,14 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope {
val quickSettingsSheet = QuickSettingsSheetDialogFragment.newInstance(
url = session.url,
isSecured = session.securityInfo.secure,
isTrackingProtectionOn = Settings.getInstance(context!!).shouldUseTrackingProtection,
sitePermissions = sitePermissions
)
quickSettingsSheet.sitePermissions = sitePermissions
quickSettingsSheet.show(requireFragmentManager(), QuickSettingsSheetDialogFragment.FRAGMENT_TAG)
quickSettingsSheet.show(
requireFragmentManager(),
QuickSettingsSheetDialogFragment.FRAGMENT_TAG
)
}
}
}
@ -572,6 +576,6 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope {
private const val REQUEST_CODE_PROMPT_PERMISSIONS = 2
private const val REQUEST_CODE_APP_PERMISSIONS = 3
private const val TOOLBAR_HEIGHT = 56f
private const val REPORT_SITE_ISSUE_URL = "https://webcompat.com/issues/new?url=%s&label=browser-fenix"
const val REPORT_SITE_ISSUE_URL = "https://webcompat.com/issues/new?url=%s&label=browser-fenix"
}
}

View File

@ -80,6 +80,16 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
requireComponents.search.searchEngineManager.getDefaultSearchEngine(it).name
}
val trackingProtectionPreference =
findPreference<Preference>(getString(R.string.pref_key_tracking_protection_settings))
trackingProtectionPreference?.summary = context?.let {
if (org.mozilla.fenix.utils.Settings.getInstance(it).shouldUseTrackingProtection) {
getString(R.string.tracking_protection_on)
} else {
getString(R.string.tracking_protection_off)
}
}
val themesPreference =
findPreference<Preference>(getString(R.string.pref_key_theme))
themesPreference?.summary = context?.let {

View File

@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.requireComponents
@ -40,6 +41,7 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
sessions.forEach { getEngineSession(it)?.enableTrackingProtection(policy) }
}
}
requireContext().components.useCases.sessionUseCases.reload.invoke()
true
}

View File

@ -35,6 +35,7 @@ class QuickSettingsComponent(
mode = QuickSettingsState.Mode.Normal(
change.url,
change.isSecured,
change.isTrackingProtectionOn,
change.sitePermissions
)
)
@ -97,15 +98,27 @@ class QuickSettingsComponent(
data class QuickSettingsState(val mode: Mode) : ViewState {
sealed class Mode {
data class Normal(val url: String, val isSecured: Boolean, val sitePermissions: SitePermissions?) : Mode()
data class ActionLabelUpdated(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) :
data class Normal(
val url: String,
val isSecured: Boolean,
val isTrackingProtectionOn: Boolean,
val sitePermissions: SitePermissions?
) : Mode()
data class ActionLabelUpdated(
val phoneFeature: PhoneFeature,
val sitePermissions: SitePermissions?
) :
Mode()
data class CheckPendingFeatureBlockedByAndroid(val sitePermissions: SitePermissions?) : Mode()
data class CheckPendingFeatureBlockedByAndroid(val sitePermissions: SitePermissions?) :
Mode()
}
}
sealed class QuickSettingsAction : Action {
data class SelectReportProblem(val url: String) : QuickSettingsAction()
data class ToggleTrackingProtection(val trackingProtection: Boolean) : QuickSettingsAction()
data class SelectBlockedByAndroid(val permissions: Array<String>) : QuickSettingsAction()
data class TogglePermission(val featurePhone: PhoneFeature) : QuickSettingsAction()
}
@ -114,6 +127,7 @@ sealed class QuickSettingsChange : Change {
data class Change(
val url: String,
val isSecured: Boolean,
val isTrackingProtectionOn: Boolean,
val sitePermissions: SitePermissions?
) : QuickSettingsChange()

View File

@ -10,6 +10,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.PreferenceManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -17,7 +18,9 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import mozilla.components.feature.sitepermissions.SitePermissions
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter
@ -27,6 +30,7 @@ import kotlin.coroutines.CoroutineContext
private const val KEY_URL = "KEY_URL"
private const val KEY_IS_SECURED = "KEY_IS_SECURED"
private const val KEY_SITE_PERMISSIONS = "KEY_SITE_PERMISSIONS"
private const val KEY_IS_TP_ON = "KEY_IS_TP_ON"
private const val REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS = 4
@SuppressWarnings("TooManyFunctions")
@ -34,6 +38,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
private val safeArguments get() = requireNotNull(arguments)
private val url: String by lazy { safeArguments.getString(KEY_URL) }
private val isSecured: Boolean by lazy { safeArguments.getBoolean(KEY_IS_SECURED) }
private val isTrackingProtectionOn: Boolean by lazy { safeArguments.getBoolean(KEY_IS_TP_ON) }
private lateinit var quickSettingsComponent: QuickSettingsComponent
private lateinit var job: Job
@ -59,7 +64,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
quickSettingsComponent = QuickSettingsComponent(
rootView as ConstraintLayout, ActionBusFactory.get(this),
QuickSettingsState(
QuickSettingsState.Mode.Normal(url, isSecured, sitePermissions)
QuickSettingsState.Mode.Normal(url, isSecured, isTrackingProtectionOn, sitePermissions)
)
)
}
@ -70,6 +75,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
fun newInstance(
url: String,
isSecured: Boolean,
isTrackingProtectionOn: Boolean,
sitePermissions: SitePermissions?
): QuickSettingsSheetDialogFragment {
@ -79,6 +85,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
with(arguments) {
putString(KEY_URL, url)
putBoolean(KEY_IS_SECURED, isSecured)
putBoolean(KEY_IS_TP_ON, isTrackingProtectionOn)
putParcelable(KEY_SITE_PERMISSIONS, sitePermissions)
}
fragment.arguments = arguments
@ -110,6 +117,37 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
is QuickSettingsAction.SelectBlockedByAndroid -> {
requestPermissions(it.permissions, REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS)
}
is QuickSettingsAction.SelectReportProblem -> {
launch(Dispatchers.Main) {
val reportUrl =
String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, it.url)
requireComponents.useCases.sessionUseCases.loadUrl.invoke(reportUrl)
}
}
is QuickSettingsAction.ToggleTrackingProtection -> {
val trackingEnabled = it.trackingProtection
with(requireComponents.core) {
val policy =
createTrackingProtectionPolicy(trackingEnabled)
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putBoolean(
context!!.getString(R.string.pref_key_tracking_protection),
trackingEnabled
).apply()
engine.settings.trackingProtectionPolicy = policy
with(sessionManager) {
sessions.forEach {
getEngineSession(it)?.enableTrackingProtection(
policy
)
}
}
}
launch(Dispatchers.Main) {
requireContext().components.useCases.sessionUseCases.reload.invoke()
}
}
is QuickSettingsAction.TogglePermission -> {
launch {

View File

@ -8,6 +8,7 @@ import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import android.widget.Switch
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.AppCompatTextView
@ -19,6 +20,7 @@ import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.feature.sitepermissions.SitePermissions.Status.NO_DECISION
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
import mozilla.components.support.ktx.kotlin.toUri
import org.mozilla.fenix.DefaultThemeManager
import org.mozilla.fenix.R
import org.mozilla.fenix.mvi.UIView
import org.mozilla.fenix.settings.PhoneFeature
@ -28,6 +30,7 @@ import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE
import org.mozilla.fenix.settings.PhoneFeature.NOTIFICATION
import org.mozilla.fenix.utils.Settings
@Suppress("TooManyFunctions")
class QuickSettingsUIView(
container: ViewGroup,
actionEmitter: Observer<QuickSettingsAction>,
@ -38,6 +41,8 @@ class QuickSettingsUIView(
) {
private val securityInfoLabel: TextView
private val urlLabel: TextView
private val trackingProtectionSwitch: Switch
private val reportProblemAction: TextView
private val cameraActionLabel: TextView
private val cameraLabel: TextView
private val microphoneActionLabel: TextView
@ -53,6 +58,8 @@ class QuickSettingsUIView(
init {
urlLabel = view.findViewById<AppCompatTextView>(R.id.url)
securityInfoLabel = view.findViewById<AppCompatTextView>(R.id.security_info)
trackingProtectionSwitch = view.findViewById(R.id.tracking_protection)
reportProblemAction = view.findViewById(R.id.report_problem)
cameraActionLabel = view.findViewById<AppCompatTextView>(R.id.camera_action_label)
cameraLabel = view.findViewById<AppCompatTextView>(R.id.camera_icon)
microphoneActionLabel = view.findViewById<AppCompatTextView>(R.id.microphone_action_label)
@ -68,6 +75,8 @@ class QuickSettingsUIView(
is QuickSettingsState.Mode.Normal -> {
bindUrl(state.mode.url)
bindSecurityInfo(state.mode.isSecured)
bindReportProblemAction(state.mode.url)
bindTrackingProtectionInfo(state.mode.isTrackingProtectionOn)
bindPhoneFeatureItem(cameraActionLabel, CAMERA, state.mode.sitePermissions)
bindPhoneFeatureItem(microphoneActionLabel, MICROPHONE, state.mode.sitePermissions)
bindPhoneFeatureItem(notificationActionLabel, NOTIFICATION, state.mode.sitePermissions)
@ -90,6 +99,38 @@ class QuickSettingsUIView(
urlLabel.text = url.toUri().hostWithoutCommonPrefixes
}
private fun bindTrackingProtectionInfo(isTrackingProtectionOn: Boolean) {
val drawableId =
if (isTrackingProtectionOn) R.drawable.ic_tracking_protection else
R.drawable.ic_tracking_protection_disabled
val drawableTint = if (isTrackingProtectionOn) DefaultThemeManager.resolveAttribute(
R.attr.primaryText,
context
) else DefaultThemeManager.resolveAttribute(R.attr.neutral, context)
val icon = AppCompatResources.getDrawable(context, drawableId)
val resolvedColor = ContextCompat.getColor(context, drawableTint)
icon?.setTint(resolvedColor)
trackingProtectionSwitch.setTextColor(resolvedColor)
trackingProtectionSwitch.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null)
trackingProtectionSwitch.isChecked = isTrackingProtectionOn
trackingProtectionSwitch.setOnCheckedChangeListener { _, isChecked ->
actionEmitter.onNext(
QuickSettingsAction.ToggleTrackingProtection(
isChecked
)
)
}
}
private fun bindReportProblemAction(url: String) {
reportProblemAction.setOnClickListener {
actionEmitter.onNext(
QuickSettingsAction.SelectReportProblem(url)
)
}
}
private fun bindSecurityInfo(isSecured: Boolean) {
val stringId: Int
val drawableId: Int

File diff suppressed because one or more lines are too long

View File

@ -35,14 +35,48 @@
app:layout_constraintTop_toBottomOf="@id/url"/>
<View
android:id="@+id/line_divider"
android:layout_width="match_parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_height="1dp"
android:background="?neutral"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/security_info"/>
android:id="@+id/line_divider_security"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?neutral"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/security_info" />
<Switch
android:id="@+id/tracking_protection"
style="@style/QuickSettingsText.Icon"
android:layout_width="match_parent"
android:layout_height="@dimen/quicksettings_item_height"
android:drawableStart="@drawable/ic_tracking_protection"
android:paddingEnd="24dp"
android:text="@string/preferences_tracking_protection"
app:layout_constraintBottom_toTopOf="@id/report_problem"
app:layout_constraintTop_toBottomOf="@id/line_divider_security" />
<TextView
android:id="@+id/report_problem"
style="@style/QuickSettingsText.Icon"
android:layout_width="match_parent"
android:layout_height="@dimen/quicksettings_item_height"
android:gravity="top"
android:paddingStart="48dp"
android:text="@string/tracking_protection_report_problem"
android:textColor="?accentBright"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@id/line_divider"
app:layout_constraintTop_toBottomOf="@id/tracking_protection" />
<View
android:id="@+id/line_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?neutral"
app:layout_constraintBottom_toTopOf="@id/camera_icon"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/camera_icon"

View File

@ -386,4 +386,10 @@
<string name="phone_feature_blocked_by_android">Blocked by Android</string>
<!-- Preference for showing a list of websites that the default configurations won't apply to them -->
<string name="preference_exceptions">Exceptions</string>
<!-- Action in Quick Settings dialog to report a site problem related to tracking protection -->
<string name="tracking_protection_report_problem">Report a problem</string>
<!-- Summary of tracking protection preference if tracking protection is set to on -->
<string name="tracking_protection_on">On</string>
<!-- Summary of tracking protection preference if tracking protection is set to off -->
<string name="tracking_protection_off">Off</string>
</resources>