Closes #1167: Added behavior for site permissions custom settings.

This commit is contained in:
Arturo Mejia 2019-03-29 13:57:49 -04:00 committed by Colin Lee
parent 0bf8b83e03
commit 061b6f3cd5
8 changed files with 199 additions and 30 deletions

View File

@ -33,7 +33,6 @@ import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.session.ThumbnailsFeature
import mozilla.components.feature.sitepermissions.SitePermissionsFeature
import mozilla.components.feature.sitepermissions.SitePermissionsRules
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.support.ktx.android.view.enterToImmersiveMode
@ -345,16 +344,10 @@ class BrowserFragment : Fragment(), BackHandler {
private fun assignSitePermissionsRules() {
val settings = Settings.getInstance(requireContext())
val recommendedSettings = SitePermissionsRules(
camera = ASK_TO_ALLOW,
notification = ASK_TO_ALLOW,
location = ASK_TO_ALLOW,
microphone = ASK_TO_ALLOW
)
val rules: SitePermissionsRules? = if (settings.shouldRecommendedSettingsBeActivated) {
recommendedSettings
val rules: SitePermissionsRules = if (settings.shouldRecommendedSettingsBeActivated) {
settings.getSitePermissionsRecommendedSettingsRules()
} else {
null
settings.getSitePermissionsCustomSettingsRules()
}
sitePermissionsFeature.withFeature {
it.sitePermissionsRules = rules

View File

@ -0,0 +1,20 @@
/* 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.content.Context
import mozilla.components.feature.sitepermissions.SitePermissionsRules
import org.mozilla.fenix.R
internal fun SitePermissionsRules.Action.toString(context: Context): String {
return when (this) {
SitePermissionsRules.Action.ASK_TO_ALLOW -> {
context.getString(R.string.preference_option_phone_feature_ask_to_allow)
}
SitePermissionsRules.Action.BLOCKED -> {
context.getString(R.string.preference_option_phone_feature_block)
}
}
}

View File

@ -8,9 +8,11 @@ import android.view.View
import androidx.preference.PreferenceViewHolder
import android.widget.TextView
import android.content.Context
import android.content.res.TypedArray
import android.text.TextUtils
import android.util.AttributeSet
import android.widget.RadioButton
import androidx.core.content.res.TypedArrayUtils
import androidx.core.text.HtmlCompat
import androidx.preference.Preference
import org.mozilla.fenix.R
@ -20,19 +22,22 @@ class RadioButtonPreference : Preference {
private lateinit var summaryView: TextView
private lateinit var radioButton: RadioButton
var shouldSummaryBeParsedAsHtmlContent: Boolean = true
private var defaultValue: Boolean = false
private var clickListener: (() -> Unit)? = null
init {
layoutResource = R.layout.preference_widget_radiobutton
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
val typedArray = context.obtainStyledAttributes(
attrs, androidx.preference.R.styleable.Preference, TypedArrayUtils.getAttr(
context, androidx.preference.R.attr.preferenceStyle,
android.R.attr.preferenceStyle
), 0
)
initDefaultValue(typedArray)
}
fun addToRadioGroup(radioPreference: RadioButtonPreference) {
radioGroups.add(radioPreference)
@ -67,7 +72,15 @@ class RadioButtonPreference : Preference {
private fun bindRadioButton(holder: PreferenceViewHolder) {
radioButton = holder.findViewById(R.id.radio_button) as RadioButton
radioButton.isChecked = getPersistedBoolean(false)
radioButton.isChecked = getPersistedBoolean(defaultValue)
}
private fun initDefaultValue(typedArray: TypedArray) {
if (typedArray.hasValue(androidx.preference.R.styleable.Preference_defaultValue)) {
defaultValue = typedArray.getBoolean(androidx.preference.R.styleable.Preference_defaultValue, false)
} else if (typedArray.hasValue(androidx.preference.R.styleable.Preference_android_defaultValue)) {
defaultValue = typedArray.getBoolean(androidx.preference.R.styleable.Preference_android_defaultValue, false)
}
}
private fun toggleRadioGroups() {

View File

@ -17,6 +17,7 @@ import org.mozilla.fenix.settings.SitePermissionsManagePhoneFeature.PhoneFeature
import org.mozilla.fenix.settings.SitePermissionsManagePhoneFeature.PhoneFeature.LOCATION
import org.mozilla.fenix.settings.SitePermissionsManagePhoneFeature.PhoneFeature.CAMERA
import org.mozilla.fenix.settings.SitePermissionsManagePhoneFeature.PhoneFeature.MICROPHONE
import org.mozilla.fenix.utils.Settings
@SuppressWarnings("TooManyFunctions")
class SitePermissionsFragment : PreferenceFragmentCompat() {
@ -82,15 +83,35 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
if (isCategoryActivate) {
categoryPhoneFeatures.isVisible = true
}
initPhoneFeature(CAMERA)
initPhoneFeature(LOCATION)
initPhoneFeature(MICROPHONE)
initPhoneFeature(NOTIFICATION)
val settings = Settings.getInstance(requireContext())
val cameraAction = settings
.getSitePermissionsPhoneFeatureCameraAction()
.toString(requireContext())
val locationAction = settings
.getSitePermissionsPhoneFeatureLocation()
.toString(requireContext())
val microPhoneAction = settings
.getSitePermissionsPhoneFeatureMicrophoneAction()
.toString(requireContext())
val notificationAction = settings
.getSitePermissionsPhoneFeatureNotificationAction()
.toString(requireContext())
initPhoneFeature(CAMERA, cameraAction)
initPhoneFeature(LOCATION, locationAction)
initPhoneFeature(MICROPHONE, microPhoneAction)
initPhoneFeature(NOTIFICATION, notificationAction)
}
private fun initPhoneFeature(phoneFeature: PhoneFeature) {
private fun initPhoneFeature(phoneFeature: PhoneFeature, summary: String) {
val keyPreference = getPreferenceKeyBy(phoneFeature)
val cameraPhoneFeatures: Preference = requireNotNull(findPreference(keyPreference))
cameraPhoneFeatures.summary = summary
cameraPhoneFeatures.onPreferenceClickListener = OnPreferenceClickListener {
navigateToPhoneFeature(phoneFeature)

View File

@ -12,7 +12,8 @@ import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
import org.mozilla.fenix.utils.Settings
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE
@ -29,12 +30,16 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.HtmlCompat
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT
import androidx.fragment.app.Fragment
import mozilla.components.feature.sitepermissions.SitePermissionsRules
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW
import mozilla.components.support.ktx.android.content.isPermissionGranted
import org.mozilla.fenix.R
class SitePermissionsManagePhoneFeature : Fragment() {
private lateinit var phoneFeature: PhoneFeature
private lateinit var settings: Settings
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -45,6 +50,7 @@ class SitePermissionsManagePhoneFeature : Fragment() {
(activity as AppCompatActivity).title = phoneFeature.label
(activity as AppCompatActivity).supportActionBar?.show()
settings = Settings.getInstance(requireContext())
}
override fun onCreateView(
@ -55,14 +61,14 @@ class SitePermissionsManagePhoneFeature : Fragment() {
val rootView = inflater.inflate(R.layout.fragment_manage_site_permissions_feature_phone, container, false)
initAskToAllowRadio(rootView)
initBlockRadio(rootView)
initBockedByAndroidContainer(rootView)
return rootView
}
private fun initAskToAllowRadio(rootView: View) {
val radio = rootView.findViewById<RadioButton>(R.id.ask_to_allow_switch)
val radio = rootView.findViewById<RadioButton>(R.id.ask_to_allow_radio)
val askToAllowText = getString(R.string.preference_option_phone_feature_ask_to_allow)
val recommendedText = getString(R.string.phone_feature_recommended)
val recommendedTextSize = resources.getDimensionPixelSize(R.dimen.phone_feature_label_recommended_text_size)
@ -87,6 +93,24 @@ class SitePermissionsManagePhoneFeature : Fragment() {
append(recommendedSpannable)
this
}
radio.setOnClickListener {
saveActionInSettings(ASK_TO_ALLOW)
}
radio.restoreState(ASK_TO_ALLOW)
}
private fun RadioButton.restoreState(action: SitePermissionsRules.Action) {
if (phoneFeature.action == action) {
this.isChecked = true
}
}
private fun initBlockRadio(rootView: View) {
val radio = rootView.findViewById<RadioButton>(R.id.block_radio)
radio.setOnClickListener {
saveActionInSettings(BLOCKED)
}
radio.restoreState(BLOCKED)
}
private fun initBockedByAndroidContainer(rootView: View) {
@ -141,6 +165,16 @@ class SitePermissionsManagePhoneFeature : Fragment() {
}
}
private val PhoneFeature.action: SitePermissionsRules.Action
get() {
return when (phoneFeature) {
PhoneFeature.CAMERA -> settings.getSitePermissionsPhoneFeatureCameraAction()
PhoneFeature.LOCATION -> settings.getSitePermissionsPhoneFeatureLocation()
PhoneFeature.MICROPHONE -> settings.getSitePermissionsPhoneFeatureMicrophoneAction()
PhoneFeature.NOTIFICATION -> settings.getSitePermissionsPhoneFeatureNotificationAction()
}
}
private fun initSettingsButton(rootView: View) {
val button = rootView.findViewById<Button>(R.id.settings_button)
button.setOnClickListener {
@ -149,12 +183,21 @@ class SitePermissionsManagePhoneFeature : Fragment() {
}
private fun openSettings() {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val intent = Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", requireContext().packageName, null)
intent.data = uri
startActivity(intent)
}
private fun saveActionInSettings(action: SitePermissionsRules.Action) {
when (phoneFeature) {
PhoneFeature.CAMERA -> settings.setSitePermissionsPhoneFeatureCameraAction(action)
PhoneFeature.LOCATION -> settings.setSitePermissionsPhoneFeatureLocation(action)
PhoneFeature.MICROPHONE -> settings.setSitePermissionsPhoneFeatureMicrophoneAction(action)
PhoneFeature.NOTIFICATION -> settings.setSitePermissionsPhoneFeatureNotificationAction(action)
}
}
companion object {
const val CAMERA_PERMISSION = 0
const val LOCATION_PERMISSION = 1

View File

@ -7,12 +7,15 @@ package org.mozilla.fenix.utils
import android.content.Context
import android.content.SharedPreferences
import android.preference.PreferenceManager
import mozilla.components.feature.sitepermissions.SitePermissionsRules
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.getPreferenceKey
import java.security.InvalidParameterException
/**
* A simple wrapper for SharedPreferences that makes reading preference a little bit easier.
*/
@SuppressWarnings("TooManyFunctions")
class Settings private constructor(context: Context) {
companion object {
@ -71,4 +74,80 @@ class Settings private constructor(context: Context) {
appContext.getPreferenceKey(R.string.pref_key_show_search_suggestions),
true
)
fun setSitePermissionsPhoneFeatureCameraAction(action: SitePermissionsRules.Action) {
preferences.edit()
.putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera), action.id)
.apply()
}
fun getSitePermissionsPhoneFeatureCameraAction(): SitePermissionsRules.Action {
return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera), 1)
.toSitePermissionsRulesAction()
}
fun setSitePermissionsPhoneFeatureMicrophoneAction(action: SitePermissionsRules.Action) {
preferences.edit()
.putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone), action.id)
.apply()
}
fun getSitePermissionsPhoneFeatureMicrophoneAction(): SitePermissionsRules.Action {
return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone), 1)
.toSitePermissionsRulesAction()
}
fun setSitePermissionsPhoneFeatureNotificationAction(action: SitePermissionsRules.Action) {
preferences.edit()
.putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_notification), action.id)
.apply()
}
fun getSitePermissionsPhoneFeatureNotificationAction(): SitePermissionsRules.Action {
return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_notification), 1)
.toSitePermissionsRulesAction()
}
fun setSitePermissionsPhoneFeatureLocation(action: SitePermissionsRules.Action) {
preferences.edit()
.putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_location), action.id)
.apply()
}
fun getSitePermissionsPhoneFeatureLocation(): SitePermissionsRules.Action {
return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_location), 1)
.toSitePermissionsRulesAction()
}
fun getSitePermissionsRecommendedSettingsRules() = SitePermissionsRules(
camera = SitePermissionsRules.Action.ASK_TO_ALLOW,
notification = SitePermissionsRules.Action.ASK_TO_ALLOW,
location = SitePermissionsRules.Action.ASK_TO_ALLOW,
microphone = SitePermissionsRules.Action.ASK_TO_ALLOW
)
fun getSitePermissionsCustomSettingsRules(): SitePermissionsRules {
return SitePermissionsRules(
notification = getSitePermissionsPhoneFeatureNotificationAction(),
microphone = getSitePermissionsPhoneFeatureMicrophoneAction(),
location = getSitePermissionsPhoneFeatureLocation(),
camera = getSitePermissionsPhoneFeatureCameraAction()
)
}
private val SitePermissionsRules.Action.id: Int
get() {
return when (this) {
SitePermissionsRules.Action.BLOCKED -> 0
SitePermissionsRules.Action.ASK_TO_ALLOW -> 1
}
}
private fun Int.toSitePermissionsRulesAction(): SitePermissionsRules.Action {
return when (this) {
0 -> SitePermissionsRules.Action.BLOCKED
1 -> SitePermissionsRules.Action.ASK_TO_ALLOW
else -> throw InvalidParameterException("$this is not a valid SitePermissionsRules.Action")
}
}
}

View File

@ -16,7 +16,7 @@
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/ask_to_allow_switch"
android:id="@+id/ask_to_allow_radio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/preference_option_phone_feature_ask_to_allow"
@ -31,7 +31,7 @@
android:paddingBottom="@dimen/radio_button_preference_vertical"/>
<RadioButton
android:id="@+id/block_switch"
android:id="@+id/block_radio"
android:layout_width="match_parent"
android:layout_height="@dimen/radio_button_preference_height"
android:text="@string/preference_option_phone_feature_block"

View File

@ -22,7 +22,7 @@
android:key="@string/pref_key_recommended_settings"
android:title="@string/preference_recommended_settings"
android:summary="@string/preference_recommended_settings_summary"
android:defaultValue="false"/>
android:defaultValue="true"/>
<org.mozilla.fenix.settings.RadioButtonPreference
android:key="@string/pref_key_custom_settings"