1
0
Fork 0

For #255: Toggle Media Autoplay

master
Colin Lee 2019-09-12 14:58:25 -05:00 committed by Emily Kager
parent a470b1c74c
commit 1aa4f5a519
11 changed files with 184 additions and 71 deletions

View File

@ -55,7 +55,8 @@ class Core(private val context: Context) {
preferredColorScheme = getPreferredColorScheme(), preferredColorScheme = getPreferredColorScheme(),
automaticFontSizeAdjustment = context.settings.shouldUseAutoSize, automaticFontSizeAdjustment = context.settings.shouldUseAutoSize,
fontInflationEnabled = context.settings.shouldUseAutoSize, fontInflationEnabled = context.settings.shouldUseAutoSize,
suspendMediaWhenInactive = !FeatureFlags.mediaIntegration suspendMediaWhenInactive = !FeatureFlags.mediaIntegration,
allowAutoplayMedia = context.settings.isAutoPlayEnabled
) )
GeckoEngine(context, defaultSettings, GeckoProvider.getOrCreateRuntime(context)) GeckoEngine(context, defaultSettings, GeckoProvider.getOrCreateRuntime(context))

View File

@ -20,6 +20,7 @@ fun SitePermissions.toggle(featurePhone: PhoneFeature): SitePermissions {
PhoneFeature.LOCATION -> copy(location = location.toggle()) PhoneFeature.LOCATION -> copy(location = location.toggle())
PhoneFeature.MICROPHONE -> copy(microphone = microphone.toggle()) PhoneFeature.MICROPHONE -> copy(microphone = microphone.toggle())
PhoneFeature.NOTIFICATION -> copy(notification = notification.toggle()) PhoneFeature.NOTIFICATION -> copy(notification = notification.toggle())
PhoneFeature.AUTOPLAY -> copy() // not supported by GV or A-C yet
} }
} }

View File

@ -21,30 +21,51 @@ const val ID_CAMERA_PERMISSION = 0
const val ID_LOCATION_PERMISSION = 1 const val ID_LOCATION_PERMISSION = 1
const val ID_MICROPHONE_PERMISSION = 2 const val ID_MICROPHONE_PERMISSION = 2
const val ID_NOTIFICATION_PERMISSION = 3 const val ID_NOTIFICATION_PERMISSION = 3
const val ID_AUTOPLAY_PERMISSION = 4
enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>) { enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>) {
CAMERA(ID_CAMERA_PERMISSION, arrayOf(CAMERA_PERMISSION)), CAMERA(ID_CAMERA_PERMISSION, arrayOf(CAMERA_PERMISSION)),
LOCATION(ID_LOCATION_PERMISSION, arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)), LOCATION(ID_LOCATION_PERMISSION, arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)),
MICROPHONE(ID_MICROPHONE_PERMISSION, arrayOf(RECORD_AUDIO)), MICROPHONE(ID_MICROPHONE_PERMISSION, arrayOf(RECORD_AUDIO)),
NOTIFICATION(ID_NOTIFICATION_PERMISSION, emptyArray()); NOTIFICATION(ID_NOTIFICATION_PERMISSION, emptyArray()),
AUTOPLAY(ID_AUTOPLAY_PERMISSION, emptyArray());
fun isAndroidPermissionGranted(context: Context): Boolean { fun isAndroidPermissionGranted(context: Context): Boolean {
return when (this) { return when (this) {
CAMERA, LOCATION, MICROPHONE -> context.isPermissionGranted(androidPermissionsList.asIterable()) CAMERA, LOCATION, MICROPHONE -> context.isPermissionGranted(androidPermissionsList.asIterable())
NOTIFICATION -> true NOTIFICATION, AUTOPLAY -> true
} }
} }
fun getActionLabel(context: Context, sitePermissions: SitePermissions? = null, settings: Settings? = null): String { fun getActionLabel(
@StringRes val stringRes = when (getStatus(sitePermissions, settings)) { context: Context,
SitePermissions.Status.BLOCKED -> R.string.preference_option_phone_feature_blocked sitePermissions: SitePermissions? = null,
SitePermissions.Status.NO_DECISION -> R.string.preference_option_phone_feature_ask_to_allow settings: Settings? = null
SitePermissions.Status.ALLOWED -> R.string.preference_option_phone_feature_allowed ): String {
} @StringRes val stringRes =
when (this) {
AUTOPLAY -> {
when (getStatus(sitePermissions, settings)) {
SitePermissions.Status.BLOCKED -> R.string.preference_option_autoplay_blocked
SitePermissions.Status.ALLOWED -> R.string.preference_option_autoplay_allowed
else -> R.string.preference_option_autoplay_allowed
}
}
else -> {
when (getStatus(sitePermissions, settings)) {
SitePermissions.Status.BLOCKED -> R.string.preference_option_phone_feature_blocked
SitePermissions.Status.NO_DECISION -> R.string.preference_option_phone_feature_ask_to_allow
SitePermissions.Status.ALLOWED -> R.string.preference_option_phone_feature_allowed
}
}
}
return context.getString(stringRes) return context.getString(stringRes)
} }
fun getStatus(sitePermissions: SitePermissions? = null, settings: Settings? = null): SitePermissions.Status { fun getStatus(
sitePermissions: SitePermissions? = null,
settings: Settings? = null
): SitePermissions.Status {
val status = getStatus(sitePermissions) ?: settings?.let(::getAction)?.toStatus() val status = getStatus(sitePermissions) ?: settings?.let(::getAction)?.toStatus()
return requireNotNull(status) return requireNotNull(status)
} }
@ -55,6 +76,7 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>)
LOCATION -> context.getString(R.string.preference_phone_feature_location) LOCATION -> context.getString(R.string.preference_phone_feature_location)
MICROPHONE -> context.getString(R.string.preference_phone_feature_microphone) MICROPHONE -> context.getString(R.string.preference_phone_feature_microphone)
NOTIFICATION -> context.getString(R.string.preference_phone_feature_notification) NOTIFICATION -> context.getString(R.string.preference_phone_feature_notification)
AUTOPLAY -> context.getString(R.string.preference_browser_feature_autoplay)
} }
} }
@ -64,11 +86,19 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>)
LOCATION -> context.getPreferenceKey(R.string.pref_key_phone_feature_location) LOCATION -> context.getPreferenceKey(R.string.pref_key_phone_feature_location)
MICROPHONE -> context.getPreferenceKey(R.string.pref_key_phone_feature_microphone) MICROPHONE -> context.getPreferenceKey(R.string.pref_key_phone_feature_microphone)
NOTIFICATION -> context.getPreferenceKey(R.string.pref_key_phone_feature_notification) NOTIFICATION -> context.getPreferenceKey(R.string.pref_key_phone_feature_notification)
AUTOPLAY -> context.getPreferenceKey(R.string.pref_key_browser_feature_autoplay)
} }
} }
fun getAction(settings: Settings): SitePermissionsRules.Action = fun getAction(settings: Settings): SitePermissionsRules.Action =
settings.getSitePermissionsPhoneFeatureAction(this) settings.getSitePermissionsPhoneFeatureAction(this, getDefault())
fun getDefault(): SitePermissionsRules.Action {
return when (this) {
AUTOPLAY -> SitePermissionsRules.Action.BLOCKED
else -> SitePermissionsRules.Action.ASK_TO_ALLOW
}
}
private fun getStatus(sitePermissions: SitePermissions?): SitePermissions.Status? { private fun getStatus(sitePermissions: SitePermissions?): SitePermissions.Status? {
sitePermissions ?: return null sitePermissions ?: return null
@ -77,12 +107,13 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>)
LOCATION -> sitePermissions.location LOCATION -> sitePermissions.location
MICROPHONE -> sitePermissions.microphone MICROPHONE -> sitePermissions.microphone
NOTIFICATION -> sitePermissions.notification NOTIFICATION -> sitePermissions.notification
AUTOPLAY -> SitePermissions.Status.NO_DECISION // No support from GV or A-C yet
} }
} }
companion object { companion object {
fun findFeatureBy(permissions: Array<out String>): PhoneFeature? { fun findFeatureBy(permissions: Array<out String>): PhoneFeature? {
return PhoneFeature.values().find { feature -> return values().find { feature ->
feature.androidPermissionsList.any { permission -> feature.androidPermissionsList.any { permission ->
permission == permissions.first() permission == permissions.first()
} }

View File

@ -159,6 +159,7 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
PhoneFeature.LOCATION -> sitePermissions.copy(location = status) PhoneFeature.LOCATION -> sitePermissions.copy(location = status)
PhoneFeature.MICROPHONE -> sitePermissions.copy(microphone = status) PhoneFeature.MICROPHONE -> sitePermissions.copy(microphone = status)
PhoneFeature.NOTIFICATION -> sitePermissions.copy(notification = status) PhoneFeature.NOTIFICATION -> sitePermissions.copy(notification = status)
PhoneFeature.AUTOPLAY -> sitePermissions.copy() // not supported by GV or A-C yet
} }
lifecycleScope.launch(IO) { lifecycleScope.launch(IO) {
requireComponents.core.permissionStorage.updateSitePermissions(updatedSitePermissions) requireComponents.core.permissionStorage.updateSitePermissions(updatedSitePermissions)

View File

@ -25,6 +25,7 @@ import mozilla.components.feature.sitepermissions.SitePermissionsRules
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
@ -46,25 +47,38 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
settings = requireContext().settings settings = requireContext().settings
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(
val rootView = inflater.inflate(R.layout.fragment_manage_site_permissions_feature_phone, container, false) inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView = inflater.inflate(
R.layout.fragment_manage_site_permissions_feature_phone,
container,
false
)
initAskToAllowRadio(rootView) initFirstRadio(rootView)
initBlockRadio(rootView) initSecondRadio(rootView)
bindBlockedByAndroidContainer(rootView) bindBlockedByAndroidContainer(rootView)
return rootView return rootView
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
initBlockedByAndroidView(phoneFeature, blockedByAndroidView) initBlockedByAndroidView(phoneFeature, blockedByAndroidView)
} }
private fun initAskToAllowRadio(rootView: View) { private fun initFirstRadio(rootView: View) {
val radio = rootView.findViewById<RadioButton>(R.id.ask_to_allow_radio) val radio = rootView.findViewById<RadioButton>(R.id.ask_to_allow_radio)
val askToAllowText = getString(R.string.preference_option_phone_feature_ask_to_allow) val askToAllowText = when (phoneFeature) {
PhoneFeature.AUTOPLAY -> getString(R.string.preference_option_autoplay_blocked)
else -> getString(R.string.preference_option_phone_feature_ask_to_allow)
}
val recommendedText = getString(R.string.phone_feature_recommended) val recommendedText = getString(R.string.phone_feature_recommended)
val recommendedTextSize = resources.getDimensionPixelSize(R.dimen.phone_feature_label_recommended_text_size) val recommendedTextSize =
resources.getDimensionPixelSize(R.dimen.phone_feature_label_recommended_text_size)
val recommendedSpannable = SpannableString(recommendedText) val recommendedSpannable = SpannableString(recommendedText)
recommendedSpannable.setSpan( recommendedSpannable.setSpan(
@ -86,10 +100,16 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
append(recommendedSpannable) append(recommendedSpannable)
this this
} }
val expectedAction = if (phoneFeature == PhoneFeature.AUTOPLAY) BLOCKED else ASK_TO_ALLOW
radio.setOnClickListener { radio.setOnClickListener {
saveActionInSettings(ASK_TO_ALLOW) if (phoneFeature == PhoneFeature.AUTOPLAY) {
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.AUTOPLAY, expectedAction)
requireComponents.core.engine.settings.allowAutoplayMedia = false
} else {
saveActionInSettings(expectedAction)
}
} }
radio.restoreState(ASK_TO_ALLOW) radio.restoreState(expectedAction)
} }
private fun RadioButton.restoreState(action: SitePermissionsRules.Action) { private fun RadioButton.restoreState(action: SitePermissionsRules.Action) {
@ -99,12 +119,22 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
} }
} }
private fun initBlockRadio(rootView: View) { private fun initSecondRadio(rootView: View) {
val radio = rootView.findViewById<RadioButton>(R.id.block_radio) val radio = rootView.findViewById<RadioButton>(R.id.block_radio)
radio.setOnClickListener { radio.text = when (phoneFeature) {
saveActionInSettings(BLOCKED) PhoneFeature.AUTOPLAY -> getString(R.string.preference_option_autoplay_allowed)
else -> getString(R.string.preference_option_phone_feature_blocked)
} }
radio.restoreState(BLOCKED) val expectedAction = if (phoneFeature == PhoneFeature.AUTOPLAY) ASK_TO_ALLOW else BLOCKED
radio.setOnClickListener {
if (phoneFeature == PhoneFeature.AUTOPLAY) {
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.AUTOPLAY, expectedAction)
requireComponents.core.engine.settings.allowAutoplayMedia = true
} else {
saveActionInSettings(expectedAction)
}
}
radio.restoreState(expectedAction)
} }
private fun bindBlockedByAndroidContainer(rootView: View) { private fun bindBlockedByAndroidContainer(rootView: View) {

View File

@ -48,16 +48,22 @@ class QuickSettingsComponent(
return if (sitePermissions == null) { return if (sitePermissions == null) {
val settings = context.settings val settings = context.settings
val origin = requireNotNull(url.toUri().host) val origin = requireNotNull(url.toUri().host)
var location = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION).toStatus() var location =
var camera = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA).toStatus() settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION).toStatus()
var microphone = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE).toStatus() var camera =
var notification = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION).toStatus() settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA).toStatus()
var microphone =
settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE).toStatus()
var notification =
settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION).toStatus()
when (featurePhone) { when (featurePhone) {
PhoneFeature.CAMERA -> camera = camera.toggle() PhoneFeature.CAMERA -> camera = camera.toggle()
PhoneFeature.LOCATION -> location = location.toggle() PhoneFeature.LOCATION -> location = location.toggle()
PhoneFeature.MICROPHONE -> microphone = microphone.toggle() PhoneFeature.MICROPHONE -> microphone = microphone.toggle()
PhoneFeature.NOTIFICATION -> notification = notification.toggle() PhoneFeature.NOTIFICATION -> notification = notification.toggle()
PhoneFeature.AUTOPLAY -> { // not supported by GV or A-C yet
}
} }
context.components.core.permissionStorage context.components.core.permissionStorage
.addSitePermissionException(origin, location, notification, microphone, camera) .addSitePermissionException(origin, location, notification, microphone, camera)
@ -105,45 +111,58 @@ sealed class QuickSettingsChange : Change {
val sitePermissions: SitePermissions? val sitePermissions: SitePermissions?
) : QuickSettingsChange() ) : QuickSettingsChange()
data class PermissionGranted(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) : data class PermissionGranted(
val phoneFeature: PhoneFeature,
val sitePermissions: SitePermissions?
) :
QuickSettingsChange() QuickSettingsChange()
data class PromptRestarted(val sitePermissions: SitePermissions?) : QuickSettingsChange() data class PromptRestarted(val sitePermissions: SitePermissions?) : QuickSettingsChange()
data class Stored(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) : QuickSettingsChange() data class Stored(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) :
QuickSettingsChange()
} }
class QuickSettingsViewModel( class QuickSettingsViewModel(
initialState: QuickSettingsState initialState: QuickSettingsState
) : UIComponentViewModelBase<QuickSettingsState, QuickSettingsChange>(initialState, reducer) { ) : UIComponentViewModelBase<QuickSettingsState, QuickSettingsChange>(initialState, reducer) {
companion object { companion object {
val reducer: (QuickSettingsState, QuickSettingsChange) -> QuickSettingsState = { state, change -> val reducer: (QuickSettingsState, QuickSettingsChange) -> QuickSettingsState =
when (change) { { state, change ->
is QuickSettingsChange.Change -> { when (change) {
state.copy( is QuickSettingsChange.Change -> {
mode = QuickSettingsState.Mode.Normal( state.copy(
change.url, mode = QuickSettingsState.Mode.Normal(
change.isSecured, change.url,
change.isTrackingProtectionOn, change.isSecured,
change.sitePermissions change.isTrackingProtectionOn,
change.sitePermissions
)
) )
) }
} is QuickSettingsChange.PermissionGranted -> {
is QuickSettingsChange.PermissionGranted -> { state.copy(
state.copy( mode = QuickSettingsState.Mode.ActionLabelUpdated(
mode = QuickSettingsState.Mode.ActionLabelUpdated(change.phoneFeature, change.sitePermissions) change.phoneFeature,
) change.sitePermissions
} )
is QuickSettingsChange.PromptRestarted -> { )
state.copy( }
mode = QuickSettingsState.Mode.CheckPendingFeatureBlockedByAndroid(change.sitePermissions) is QuickSettingsChange.PromptRestarted -> {
) state.copy(
} mode = QuickSettingsState.Mode.CheckPendingFeatureBlockedByAndroid(
is QuickSettingsChange.Stored -> { change.sitePermissions
state.copy( )
mode = QuickSettingsState.Mode.ActionLabelUpdated(change.phoneFeature, change.sitePermissions) )
) }
is QuickSettingsChange.Stored -> {
state.copy(
mode = QuickSettingsState.Mode.ActionLabelUpdated(
change.phoneFeature,
change.sitePermissions
)
)
}
} }
} }
}
} }
} }

View File

@ -11,6 +11,7 @@ import android.content.SharedPreferences
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting.PRIVATE import androidx.annotation.VisibleForTesting.PRIVATE
import mozilla.components.feature.sitepermissions.SitePermissionsRules import mozilla.components.feature.sitepermissions.SitePermissionsRules
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action
import mozilla.components.support.ktx.android.content.PreferencesHolder import mozilla.components.support.ktx.android.content.PreferencesHolder
import mozilla.components.support.ktx.android.content.booleanPreference import mozilla.components.support.ktx.android.content.booleanPreference
import mozilla.components.support.ktx.android.content.floatPreference import mozilla.components.support.ktx.android.content.floatPreference
@ -42,14 +43,14 @@ class Settings private constructor(
private const val CFR_COUNT_CONDITION_FOCUS_INSTALLED = 1 private const val CFR_COUNT_CONDITION_FOCUS_INSTALLED = 1
private const val CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED = 3 private const val CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED = 3
private fun actionToInt(action: SitePermissionsRules.Action) = when (action) { private fun actionToInt(action: Action) = when (action) {
SitePermissionsRules.Action.BLOCKED -> BLOCKED_INT Action.BLOCKED -> BLOCKED_INT
SitePermissionsRules.Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT
} }
private fun intToAction(action: Int) = when (action) { private fun intToAction(action: Int) = when (action) {
BLOCKED_INT -> SitePermissionsRules.Action.BLOCKED BLOCKED_INT -> Action.BLOCKED
ASK_TO_ALLOW_INT -> SitePermissionsRules.Action.ASK_TO_ALLOW ASK_TO_ALLOW_INT -> Action.ASK_TO_ALLOW
else -> throw InvalidParameterException("$action is not a valid SitePermissionsRules.Action") else -> throw InvalidParameterException("$action is not a valid SitePermissionsRules.Action")
} }
@ -86,10 +87,10 @@ class Settings private constructor(
val isCrashReportingEnabled: Boolean val isCrashReportingEnabled: Boolean
get() = isCrashReportEnabledInBuild && get() = isCrashReportEnabledInBuild &&
preferences.getBoolean( preferences.getBoolean(
appContext.getPreferenceKey(R.string.pref_key_crash_reporter), appContext.getPreferenceKey(R.string.pref_key_crash_reporter),
true true
) )
val isRemoteDebuggingEnabled by booleanPreference( val isRemoteDebuggingEnabled by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_remote_debugging), appContext.getPreferenceKey(R.string.pref_key_remote_debugging),
@ -106,11 +107,15 @@ class Settings private constructor(
default = true default = true
) )
val isAutoPlayEnabled = getSitePermissionsPhoneFeatureAction(
PhoneFeature.AUTOPLAY, Action.BLOCKED
) != Action.BLOCKED
private var trackingProtectionOnboardingShownThisSession = false private var trackingProtectionOnboardingShownThisSession = false
val shouldShowTrackingProtectionOnboarding: Boolean val shouldShowTrackingProtectionOnboarding: Boolean
get() = trackingProtectionOnboardingCount < trackingProtectionOnboardingMaximumCount && get() = trackingProtectionOnboardingCount < trackingProtectionOnboardingMaximumCount &&
!trackingProtectionOnboardingShownThisSession !trackingProtectionOnboardingShownThisSession
val shouldAutoBounceQuickActionSheet: Boolean val shouldAutoBounceQuickActionSheet: Boolean
get() = autoBounceQuickActionSheetCount < autoBounceMaximumCount get() = autoBounceQuickActionSheetCount < autoBounceMaximumCount
@ -226,12 +231,15 @@ class Settings private constructor(
).apply() ).apply()
} }
fun getSitePermissionsPhoneFeatureAction(feature: PhoneFeature) = fun getSitePermissionsPhoneFeatureAction(
intToAction(preferences.getInt(feature.getPreferenceKey(appContext), ASK_TO_ALLOW_INT)) feature: PhoneFeature,
default: Action = Action.ASK_TO_ALLOW
) =
intToAction(preferences.getInt(feature.getPreferenceKey(appContext), actionToInt(default)))
fun setSitePermissionsPhoneFeatureAction( fun setSitePermissionsPhoneFeatureAction(
feature: PhoneFeature, feature: PhoneFeature,
value: SitePermissionsRules.Action value: Action
) { ) {
preferences.edit().putInt(feature.getPreferenceKey(appContext), actionToInt(value)).apply() preferences.edit().putInt(feature.getPreferenceKey(appContext), actionToInt(value)).apply()
} }
@ -295,7 +303,7 @@ class Settings private constructor(
val showCondition = val showCondition =
(numTimesPrivateModeOpened == CFR_COUNT_CONDITION_FOCUS_INSTALLED && focusInstalled) || (numTimesPrivateModeOpened == CFR_COUNT_CONDITION_FOCUS_INSTALLED && focusInstalled) ||
(numTimesPrivateModeOpened == CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED && !focusInstalled) (numTimesPrivateModeOpened == CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED && !focusInstalled)
if (showCondition && !showedPrivateModeContextualFeatureRecommender) { if (showCondition && !showedPrivateModeContextualFeatureRecommender) {
showedPrivateModeContextualFeatureRecommender = true showedPrivateModeContextualFeatureRecommender = true

View File

@ -0,0 +1,9 @@
<?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/. -->
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10.5,16.357l6.01,-3.492a1,1 0,0 0,0 -1.73L10.5,7.643A1,1 0,0 0,9 8.508v6.984a1,1 0,0 0,1.5 0.865zM15.33,2.569a1,1 0,1 0,-0.666 1.885A8.023,8.023 0,1 1,7 5.773L7,9.5a0.5,0.5 0,0 0,1 0v-6A0.5,0.5 0,0 0,7.5 3h-5a0.5,0.5 0,0 0,0 1h3.524a9.984,9.984 0,1 0,9.308 -1.431z"/>
</vector>

View File

@ -74,6 +74,7 @@
<string name="pref_key_show_site_exceptions" translatable="false">pref_key_show_site_exceptions</string> <string name="pref_key_show_site_exceptions" translatable="false">pref_key_show_site_exceptions</string>
<string name="pref_key_recommended_settings" translatable="false">pref_key_recommended_settings</string> <string name="pref_key_recommended_settings" translatable="false">pref_key_recommended_settings</string>
<string name="pref_key_custom_settings" translatable="false">pref_key_custom_settings</string> <string name="pref_key_custom_settings" translatable="false">pref_key_custom_settings</string>
<string name="pref_key_browser_feature_autoplay" translatable="false">pref_key_browser_feature_autoplay</string>
<string name="pref_key_phone_feature_camera" translatable="false">pref_key_phone_feature_camera</string> <string name="pref_key_phone_feature_camera" translatable="false">pref_key_phone_feature_camera</string>
<string name="pref_key_phone_feature_location" translatable="false">pref_key_phone_feature_location</string> <string name="pref_key_phone_feature_location" translatable="false">pref_key_phone_feature_location</string>
<string name="pref_key_phone_feature_microphone" translatable="false">pref_key_phone_feature_microphone</string> <string name="pref_key_phone_feature_microphone" translatable="false">pref_key_phone_feature_microphone</string>

View File

@ -504,6 +504,8 @@
<string name="clear_permission">Clear permission</string> <string name="clear_permission">Clear permission</string>
<!-- Button label for clearing all the information on all sites--> <!-- Button label for clearing all the information on all sites-->
<string name="clear_permissions_on_all_sites">Clear permissions on all sites</string> <string name="clear_permissions_on_all_sites">Clear permissions on all sites</string>
<!-- Preference for altering video and audio autoplay for all websites -->
<string name="preference_browser_feature_autoplay">Autoplay</string>
<!-- Preference for altering the camera access for all websites --> <!-- Preference for altering the camera access for all websites -->
<string name="preference_phone_feature_camera">Camera</string> <string name="preference_phone_feature_camera">Camera</string>
<!-- Preference for altering the microphone access for all websites --> <!-- Preference for altering the microphone access for all websites -->
@ -526,6 +528,10 @@
<string name="tracking_protection_on">On</string> <string name="tracking_protection_on">On</string>
<!-- Summary of tracking protection preference if tracking protection is set to off --> <!-- Summary of tracking protection preference if tracking protection is set to off -->
<string name="tracking_protection_off">Off</string> <string name="tracking_protection_off">Off</string>
<!-- Label that indicates video and audio autoplay is blocked -->
<string name="preference_option_autoplay_blocked">Video and audio blocked</string>
<!-- Label that indicates video and audio autoplay is allowed -->
<string name="preference_option_autoplay_allowed">Video and audio allowed</string>
<!-- Collections --> <!-- Collections -->
<!-- Label to describe what collections are to a new user without any collections --> <!-- Label to describe what collections are to a new user without any collections -->

View File

@ -5,6 +5,12 @@
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.preference.Preference
android:icon="@drawable/ic_autoplay_enabled"
android:key="@string/pref_key_browser_feature_autoplay"
android:title="@string/preference_browser_feature_autoplay"
android:summary="@string/preference_option_autoplay_blocked"/>
<androidx.preference.Preference <androidx.preference.Preference
android:icon="@drawable/ic_camera_enabled" android:icon="@drawable/ic_camera_enabled"
android:key="@string/pref_key_phone_feature_camera" android:key="@string/pref_key_phone_feature_camera"