Copione merged onto master
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
1aa2ee31a1
|
@ -4,17 +4,20 @@
|
|||
|
||||
package org.mozilla.fenix
|
||||
|
||||
import android.os.StrictMode
|
||||
import androidx.preference.PreferenceManager
|
||||
import leakcanary.AppWatcher
|
||||
import leakcanary.LeakCanary
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
|
||||
class DebugFenixApplication : FenixApplication() {
|
||||
|
||||
override fun setupLeakCanary() {
|
||||
val isEnabled = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean(getPreferenceKey(R.string.pref_key_leakcanary), true)
|
||||
|
||||
val isEnabled = StrictMode.allowThreadDiskReads().resetAfter {
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean(getPreferenceKey(R.string.pref_key_leakcanary), true)
|
||||
}
|
||||
updateLeakCanaryState(isEnabled)
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ import org.mozilla.fenix.session.PerformanceActivityLifecycleCallbacks
|
|||
import org.mozilla.fenix.session.VisibilityLifecycleCallback
|
||||
import org.mozilla.fenix.utils.BrowsersCache
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
import org.mozilla.fenix.StrictModeManager.enableStrictMode
|
||||
|
||||
/**
|
||||
*The main application class for Fenix. Records data to measure initialization performance.
|
||||
|
@ -124,12 +126,13 @@ open class FenixApplication : LocaleAwareApplication() {
|
|||
val megazordSetup = setupMegazord()
|
||||
|
||||
setDayNightTheme()
|
||||
enableStrictMode()
|
||||
enableStrictMode(true)
|
||||
warmBrowsersCache()
|
||||
|
||||
// Make sure the engine is initialized and ready to use.
|
||||
components.core.engine.warmUp()
|
||||
|
||||
StrictMode.allowThreadDiskReads().resetAfter {
|
||||
components.core.engine.warmUp()
|
||||
}
|
||||
initializeWebExtensionSupport()
|
||||
|
||||
// Just to make sure it is impossible for any application-services pieces
|
||||
|
@ -336,28 +339,6 @@ open class FenixApplication : LocaleAwareApplication() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun enableStrictMode() {
|
||||
if (Config.channel.isDebug) {
|
||||
StrictMode.setThreadPolicy(
|
||||
StrictMode.ThreadPolicy.Builder()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
.build()
|
||||
)
|
||||
var builder = StrictMode.VmPolicy.Builder()
|
||||
.detectLeakedSqlLiteObjects()
|
||||
.detectLeakedClosableObjects()
|
||||
.detectLeakedRegistrationObjects()
|
||||
.detectActivityLeaks()
|
||||
.detectFileUriExposure()
|
||||
.penaltyLog()
|
||||
if (SDK_INT >= Build.VERSION_CODES.O) builder =
|
||||
builder.detectContentUriWithoutPermission()
|
||||
if (SDK_INT >= Build.VERSION_CODES.P) builder = builder.detectNonSdkApiUsage()
|
||||
StrictMode.setVmPolicy(builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeWebExtensionSupport() {
|
||||
try {
|
||||
GlobalAddonDependencyProvider.initialize(
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.fenix
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.StrictMode
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
|
@ -39,6 +40,7 @@ import mozilla.components.service.fxa.sync.SyncReason
|
|||
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
||||
import mozilla.components.support.ktx.android.content.share
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
import mozilla.components.support.ktx.kotlin.isUrl
|
||||
import mozilla.components.support.ktx.kotlin.toNormalizedUrl
|
||||
import mozilla.components.support.locale.LocaleAwareAppCompatActivity
|
||||
|
@ -122,7 +124,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
|||
}
|
||||
|
||||
final override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
StrictModeManager.changeStrictModePolicies(supportFragmentManager)
|
||||
// There is disk read violations on some devices such as samsung and pixel for android 9/10
|
||||
StrictMode.allowThreadDiskReads().resetAfter {
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
components.publicSuffixList.prefetch()
|
||||
|
||||
|
@ -428,6 +434,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
|||
browsingModeManager.mode = sessionMode
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
StrictMode.allowThreadDiskReads().resetAfter {
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun createBrowsingModeManager(initialMode: BrowsingMode): BrowsingModeManager {
|
||||
return DefaultBrowsingModeManager(initialMode) { newMode ->
|
||||
themeManager.currentTheme = newMode
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* 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
|
||||
|
||||
import android.os.Build
|
||||
import android.os.StrictMode
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
||||
/**
|
||||
* Manages strict mode settings for the application.
|
||||
*/
|
||||
object StrictModeManager {
|
||||
|
||||
/***
|
||||
* Enables strict mode for debug purposes. meant to be run only in the main process.
|
||||
* @param setPenaltyDialog boolean value to decide setting the dialog box as a penalty.
|
||||
*/
|
||||
fun enableStrictMode(setPenaltyDialog: Boolean) {
|
||||
if (Config.channel.isDebug) {
|
||||
val threadPolicy = StrictMode.ThreadPolicy.Builder()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
if (setPenaltyDialog) {
|
||||
threadPolicy.penaltyDialog()
|
||||
}
|
||||
StrictMode.setThreadPolicy(threadPolicy.build())
|
||||
var builder = StrictMode.VmPolicy.Builder()
|
||||
.detectLeakedSqlLiteObjects()
|
||||
.detectLeakedClosableObjects()
|
||||
.detectLeakedRegistrationObjects()
|
||||
.detectActivityLeaks()
|
||||
.detectFileUriExposure()
|
||||
.penaltyLog()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) builder =
|
||||
builder.detectContentUriWithoutPermission()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
if (setPenaltyDialog) {
|
||||
builder.permitNonSdkApiUsage()
|
||||
} else {
|
||||
builder.detectNonSdkApiUsage()
|
||||
}
|
||||
}
|
||||
StrictMode.setVmPolicy(builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert strict mode to disable penalty dialog. Tied to fragment lifecycle since strict mode
|
||||
* needs to switch to penalty logs. Using the fragment life cycle allows decoupling from any
|
||||
* specific fragment.
|
||||
*/
|
||||
fun changeStrictModePolicies(fragmentManager: FragmentManager) {
|
||||
fragmentManager.registerFragmentLifecycleCallbacks(object :
|
||||
FragmentManager.FragmentLifecycleCallbacks() {
|
||||
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
|
||||
enableStrictMode(false)
|
||||
fm.unregisterFragmentLifecycleCallbacks(this)
|
||||
}
|
||||
}, false)
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
package org.mozilla.fenix.components
|
||||
|
||||
import android.content.Context
|
||||
import android.os.StrictMode
|
||||
import androidx.annotation.GuardedBy
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -17,6 +18,7 @@ import mozilla.components.concept.sync.OAuthAccount
|
|||
import mozilla.components.lib.crash.CrashReporter
|
||||
import mozilla.components.service.fxa.manager.FxaAccountManager
|
||||
import mozilla.components.support.base.log.logger.Logger
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
|
@ -75,7 +77,9 @@ class AccountAbnormalities(
|
|||
|
||||
private val logger = Logger("AccountAbnormalities")
|
||||
|
||||
private val prefs = context.getSharedPreferences(PREF_FXA_ABNORMALITIES, Context.MODE_PRIVATE)
|
||||
private val prefs = StrictMode.allowThreadDiskReads().resetAfter {
|
||||
context.getSharedPreferences(PREF_FXA_ABNORMALITIES, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
/**
|
||||
* Once [accountManager] is initialized, queries it to detect abnormal account states.
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package org.mozilla.fenix.components
|
||||
|
||||
import android.content.Context
|
||||
import android.os.StrictMode
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.paging.DataSource
|
||||
import mozilla.components.browser.session.Session
|
||||
|
@ -14,6 +15,7 @@ import mozilla.components.feature.tab.collections.TabCollection
|
|||
import mozilla.components.feature.tab.collections.TabCollectionStorage
|
||||
import mozilla.components.support.base.observer.Observable
|
||||
import mozilla.components.support.base.observer.ObserverRegistry
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.toShortUrl
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder
|
||||
|
@ -49,7 +51,9 @@ class TabCollectionStorage(
|
|||
var cachedTabCollections = listOf<TabCollection>()
|
||||
|
||||
private val collectionStorage by lazy {
|
||||
TabCollectionStorage(context, sessionManager)
|
||||
StrictMode.allowThreadDiskReads().resetAfter {
|
||||
TabCollectionStorage(context, sessionManager)
|
||||
}
|
||||
}
|
||||
|
||||
fun createCollection(title: String, sessions: List<Session>) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.content.DialogInterface
|
|||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.os.StrictMode
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -59,6 +60,7 @@ import mozilla.components.concept.sync.OAuthAccount
|
|||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
import mozilla.components.support.ktx.android.util.dpToPx
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
|
@ -146,8 +148,10 @@ class HomeFragment : Fragment() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
postponeEnterTransition()
|
||||
if (!onboarding.userHasBeenOnboarded()) {
|
||||
requireComponents.analytics.metrics.track(Event.OpenedAppFirstRun)
|
||||
StrictMode.allowThreadDiskReads().resetAfter {
|
||||
if (!onboarding.userHasBeenOnboarded()) {
|
||||
requireComponents.analytics.metrics.track(Event.OpenedAppFirstRun)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +176,9 @@ class HomeFragment : Fragment() {
|
|||
collections = requireComponents.core.tabCollectionStorage.cachedTabCollections,
|
||||
expandedCollections = emptySet(),
|
||||
mode = currentMode.getCurrentMode(),
|
||||
topSites = requireComponents.core.topSiteStorage.cachedTopSites,
|
||||
topSites = StrictMode.allowThreadDiskReads().resetAfter {
|
||||
requireComponents.core.topSiteStorage.cachedTopSites
|
||||
},
|
||||
tip = FenixTipManager(listOf(MigrationTipProvider(requireContext()))).getTip()
|
||||
)
|
||||
)
|
||||
|
|
|
@ -4,26 +4,33 @@
|
|||
|
||||
package org.mozilla.fenix.settings
|
||||
|
||||
import android.view.View
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.preference.Preference
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.theme.ThemeManager
|
||||
|
||||
fun SitePermissions.toggle(featurePhone: PhoneFeature): SitePermissions {
|
||||
return when (featurePhone) {
|
||||
PhoneFeature.CAMERA -> copy(camera = camera.toggle())
|
||||
PhoneFeature.LOCATION -> copy(location = location.toggle())
|
||||
PhoneFeature.MICROPHONE -> copy(microphone = microphone.toggle())
|
||||
PhoneFeature.NOTIFICATION -> copy(notification = notification.toggle())
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE -> copy(autoplayAudible = autoplayAudible.toggle())
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE -> copy(autoplayInaudible = autoplayInaudible.toggle())
|
||||
}
|
||||
return update(featurePhone, get(featurePhone).toggle())
|
||||
}
|
||||
|
||||
fun SitePermissions.get(field: PhoneFeature) = when (field) {
|
||||
PhoneFeature.CAMERA -> camera
|
||||
PhoneFeature.LOCATION -> location
|
||||
PhoneFeature.MICROPHONE -> microphone
|
||||
PhoneFeature.NOTIFICATION -> notification
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE -> autoplayAudible
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE -> autoplayInaudible
|
||||
}
|
||||
|
||||
fun SitePermissions.update(field: PhoneFeature, value: SitePermissions.Status) = when (field) {
|
||||
PhoneFeature.CAMERA -> copy(camera = value)
|
||||
PhoneFeature.LOCATION -> copy(location = value)
|
||||
PhoneFeature.MICROPHONE -> copy(microphone = value)
|
||||
PhoneFeature.NOTIFICATION -> copy(notification = value)
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE -> copy(autoplayAudible = value)
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE -> copy(autoplayInaudible = value)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,26 +46,6 @@ fun RadioButton.setStartCheckedIndicator() {
|
|||
putCompoundDrawablesRelative(start = buttonDrawable)
|
||||
}
|
||||
|
||||
fun initBlockedByAndroidView(phoneFeature: PhoneFeature, blockedByAndroidView: View) {
|
||||
val context = blockedByAndroidView.context
|
||||
if (!phoneFeature.isAndroidPermissionGranted(context)) {
|
||||
blockedByAndroidView.visibility = View.VISIBLE
|
||||
|
||||
val descriptionLabel = blockedByAndroidView.findViewById<TextView>(R.id.blocked_by_android_feature_label)
|
||||
val descriptionText = context.getString(
|
||||
R.string.phone_feature_blocked_step_feature,
|
||||
phoneFeature.getLabel(context)
|
||||
)
|
||||
descriptionLabel.text = HtmlCompat.fromHtml(descriptionText, HtmlCompat.FROM_HTML_MODE_COMPACT)
|
||||
|
||||
val permissionsLabel = blockedByAndroidView.findViewById<TextView>(R.id.blocked_by_android_permissions_label)
|
||||
val permissionsText = context.getString(R.string.phone_feature_blocked_step_permissions)
|
||||
permissionsLabel.text = HtmlCompat.fromHtml(permissionsText, HtmlCompat.FROM_HTML_MODE_COMPACT)
|
||||
} else {
|
||||
blockedByAndroidView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callback to be invoked when this preference is changed by the user (but before
|
||||
* the internal state has been updated). Allows the type of the preference to be specified.
|
||||
|
|
|
@ -8,7 +8,9 @@ import android.Manifest.permission.ACCESS_COARSE_LOCATION
|
|||
import android.Manifest.permission.ACCESS_FINE_LOCATION
|
||||
import android.Manifest.permission.RECORD_AUDIO
|
||||
import android.content.Context
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.StringRes
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
import mozilla.components.support.ktx.android.content.isPermissionGranted
|
||||
|
@ -21,26 +23,17 @@ import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_AUDIBLE
|
|||
import org.mozilla.fenix.utils.Settings
|
||||
import android.Manifest.permission.CAMERA as CAMERA_PERMISSION
|
||||
|
||||
const val ID_CAMERA_PERMISSION = 0
|
||||
const val ID_LOCATION_PERMISSION = 1
|
||||
const val ID_MICROPHONE_PERMISSION = 2
|
||||
const val ID_NOTIFICATION_PERMISSION = 3
|
||||
const val ID_AUTOPLAY_AUDIBLE_PERMISSION = 4
|
||||
const val ID_AUTOPLAY_INAUDIBLE_PERMISSION = 5
|
||||
|
||||
enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>) {
|
||||
CAMERA(ID_CAMERA_PERMISSION, arrayOf(CAMERA_PERMISSION)),
|
||||
LOCATION(ID_LOCATION_PERMISSION, arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)),
|
||||
MICROPHONE(ID_MICROPHONE_PERMISSION, arrayOf(RECORD_AUDIO)),
|
||||
NOTIFICATION(ID_NOTIFICATION_PERMISSION, emptyArray()),
|
||||
AUTOPLAY_AUDIBLE(ID_AUTOPLAY_AUDIBLE_PERMISSION, emptyArray()),
|
||||
AUTOPLAY_INAUDIBLE(ID_AUTOPLAY_INAUDIBLE_PERMISSION, emptyArray());
|
||||
@Parcelize
|
||||
enum class PhoneFeature(val androidPermissionsList: Array<String>) : Parcelable {
|
||||
CAMERA(arrayOf(CAMERA_PERMISSION)),
|
||||
LOCATION(arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)),
|
||||
MICROPHONE(arrayOf(RECORD_AUDIO)),
|
||||
NOTIFICATION(emptyArray()),
|
||||
AUTOPLAY_AUDIBLE(emptyArray()),
|
||||
AUTOPLAY_INAUDIBLE(emptyArray());
|
||||
|
||||
fun isAndroidPermissionGranted(context: Context): Boolean {
|
||||
return when (this) {
|
||||
CAMERA, LOCATION, MICROPHONE -> context.isPermissionGranted(androidPermissionsList.asIterable())
|
||||
NOTIFICATION, AUTOPLAY_AUDIBLE, AUTOPLAY_INAUDIBLE -> true
|
||||
}
|
||||
return context.isPermissionGranted(androidPermissionsList.asIterable())
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod")
|
||||
|
@ -78,7 +71,7 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>)
|
|||
sitePermissions: SitePermissions? = null,
|
||||
settings: Settings? = null
|
||||
): SitePermissions.Status {
|
||||
val status = getStatus(sitePermissions) ?: settings?.let(::getAction)?.toStatus()
|
||||
val status = sitePermissions?.get(this) ?: settings?.let(::getAction)?.toStatus()
|
||||
return requireNotNull(status)
|
||||
}
|
||||
|
||||
|
@ -114,18 +107,6 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>)
|
|||
}
|
||||
}
|
||||
|
||||
private fun getStatus(sitePermissions: SitePermissions?): SitePermissions.Status? {
|
||||
sitePermissions ?: return null
|
||||
return when (this) {
|
||||
CAMERA -> sitePermissions.camera
|
||||
LOCATION -> sitePermissions.location
|
||||
MICROPHONE -> sitePermissions.microphone
|
||||
NOTIFICATION -> sitePermissions.notification
|
||||
AUTOPLAY_AUDIBLE -> sitePermissions.autoplayAudible
|
||||
AUTOPLAY_INAUDIBLE -> sitePermissions.autoplayInaudible
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun findFeatureBy(permissions: Array<out String>): PhoneFeature? {
|
||||
return values().find { feature ->
|
||||
|
|
|
@ -52,7 +52,7 @@ interface QuickSettingsController {
|
|||
* Default behavior of [QuickSettingsController]. Other implementations are possible.
|
||||
*
|
||||
* @param context [Context] used for various Android interactions.
|
||||
* @param quickSettingsStore [QuickSettingsFragmentStore] holding the [State] for all Views displayed
|
||||
* @param quickSettingsStore [QuickSettingsFragmentStore] holding the State for all Views displayed
|
||||
* in this Controller's Fragment.
|
||||
* @param coroutineScope [CoroutineScope] used for structed concurrency.
|
||||
* @param navController NavController] used for navigation.
|
||||
|
@ -88,21 +88,20 @@ class DefaultQuickSettingsController(
|
|||
}
|
||||
|
||||
override fun handlePermissionToggled(permission: WebsitePermission) {
|
||||
val featureToggled = permission.getBackingFeature()
|
||||
val featureToggled = permission.phoneFeature
|
||||
|
||||
when (permission.isBlockedByAndroid) {
|
||||
true -> handleAndroidPermissionRequest(featureToggled.androidPermissionsList)
|
||||
false -> {
|
||||
val permissions = sitePermissions
|
||||
if (permissions != null) {
|
||||
val newPermissions = permissions.toggle(featureToggled).also {
|
||||
handlePermissionsChange(it)
|
||||
}
|
||||
val newPermissions = permissions.toggle(featureToggled)
|
||||
handlePermissionsChange(newPermissions)
|
||||
sitePermissions = newPermissions
|
||||
|
||||
quickSettingsStore.dispatch(
|
||||
WebsitePermissionAction.TogglePermission(
|
||||
permission,
|
||||
featureToggled,
|
||||
featureToggled.getActionLabel(context, newPermissions, settings),
|
||||
featureToggled.shouldBeEnabled(context, newPermissions, settings)
|
||||
)
|
||||
|
@ -117,7 +116,7 @@ class DefaultQuickSettingsController(
|
|||
override fun handleAndroidPermissionGranted(feature: PhoneFeature) {
|
||||
quickSettingsStore.dispatch(
|
||||
WebsitePermissionAction.TogglePermission(
|
||||
feature.getCorrespondingPermission(),
|
||||
feature,
|
||||
feature.getActionLabel(context, sitePermissions, settings),
|
||||
feature.shouldBeEnabled(context, sitePermissions, settings)
|
||||
)
|
||||
|
@ -150,56 +149,6 @@ class DefaultQuickSettingsController(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Each [WebsitePermission] is mapped after a [PhoneFeature].
|
||||
*
|
||||
* Get this [WebsitePermission]'s [PhoneFeature].
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
fun WebsitePermission.getBackingFeature(): PhoneFeature = when (this) {
|
||||
is WebsitePermission.Camera -> PhoneFeature.CAMERA
|
||||
is WebsitePermission.Microphone -> PhoneFeature.MICROPHONE
|
||||
is WebsitePermission.Notification -> PhoneFeature.NOTIFICATION
|
||||
is WebsitePermission.Location -> PhoneFeature.LOCATION
|
||||
is WebsitePermission.AutoplayAudible -> PhoneFeature.AUTOPLAY_AUDIBLE
|
||||
is WebsitePermission.AutoplayInaudible -> PhoneFeature.AUTOPLAY_INAUDIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific [WebsitePermission] implementation which this [PhoneFeature] is tied to.
|
||||
*
|
||||
* **The result only informs about the type of [WebsitePermission].
|
||||
* The resulting object's properties are just stubs and not dependable.**
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
fun PhoneFeature.getCorrespondingPermission(): WebsitePermission {
|
||||
val defaultStatus = ""
|
||||
val defaultEnabled = false
|
||||
val defaultVisible = false
|
||||
val defaultBlockedByAndroid = false
|
||||
|
||||
return when (this) {
|
||||
PhoneFeature.CAMERA -> WebsitePermission.Camera(
|
||||
defaultStatus, defaultVisible, defaultEnabled, defaultBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.LOCATION -> WebsitePermission.Location(
|
||||
defaultStatus, defaultVisible, defaultEnabled, defaultBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.MICROPHONE -> WebsitePermission.Microphone(
|
||||
defaultStatus, defaultVisible, defaultEnabled, defaultBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.NOTIFICATION -> WebsitePermission.Notification(
|
||||
defaultStatus, defaultVisible, defaultEnabled, defaultBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE -> WebsitePermission.AutoplayAudible(
|
||||
defaultStatus, defaultVisible, defaultEnabled, defaultBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE -> WebsitePermission.AutoplayInaudible(
|
||||
defaultStatus, defaultVisible, defaultEnabled, defaultBlockedByAndroid
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to toggle [SitePermissions] for the specified [PhoneFeature]
|
||||
*
|
||||
|
@ -207,7 +156,7 @@ class DefaultQuickSettingsController(
|
|||
*/
|
||||
private fun navigateToManagePhoneFeature(phoneFeature: PhoneFeature) {
|
||||
val directions = QuickSettingsSheetDialogFragmentDirections
|
||||
.actionGlobalSitePermissionsManagePhoneFeature(phoneFeature.id)
|
||||
.actionGlobalSitePermissionsManagePhoneFeature(phoneFeature)
|
||||
navController.navigate(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* 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.quicksettings
|
||||
|
||||
import mozilla.components.lib.state.Action
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
|
||||
/**
|
||||
* Parent [Action] for all the [QuickSettingsFragmentState] changes.
|
||||
*/
|
||||
sealed class QuickSettingsFragmentAction : Action
|
||||
|
||||
/**
|
||||
* All possible [WebsiteInfoState] changes as result of user / system interactions.
|
||||
*/
|
||||
sealed class WebsiteInfoAction : QuickSettingsFragmentAction()
|
||||
|
||||
/**
|
||||
* All possible [WebsitePermissionsState] changes as result of user / system interactions.
|
||||
*/
|
||||
sealed class WebsitePermissionAction : QuickSettingsFragmentAction() {
|
||||
/**
|
||||
* Change resulting from toggling a specific [WebsitePermission] for the current website.
|
||||
*
|
||||
* @param updatedFeature [PhoneFeature] backing a certain [WebsitePermission].
|
||||
* Allows to easily identify which permission changed
|
||||
* **Must be the name of one of the properties of [WebsitePermissionsState]**.
|
||||
* @param updatedStatus [String] the new [WebsitePermission#status] which will be shown to the user.
|
||||
* @param updatedEnabledStatus [Boolean] the new [WebsitePermission#enabled] which will be shown to the user.
|
||||
*/
|
||||
class TogglePermission(
|
||||
val updatedFeature: PhoneFeature,
|
||||
val updatedStatus: String,
|
||||
val updatedEnabledStatus: Boolean
|
||||
) : WebsitePermissionAction()
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* 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.quicksettings
|
||||
|
||||
/**
|
||||
* Parent Reducer for all [QuickSettingsFragmentState]s of all Views shown in this Fragment.
|
||||
*/
|
||||
fun quickSettingsFragmentReducer(
|
||||
state: QuickSettingsFragmentState,
|
||||
action: QuickSettingsFragmentAction
|
||||
): QuickSettingsFragmentState {
|
||||
return when (action) {
|
||||
is WebsiteInfoAction -> {
|
||||
// There is no possible action that can change this View's state while it is displayed to the user.
|
||||
// Every time the View is recreated it starts with a fresh state. This is the only way to display
|
||||
// something different.
|
||||
state
|
||||
}
|
||||
is WebsitePermissionAction -> state.copy(
|
||||
websitePermissionsState = WebsitePermissionsStateReducer.reduce(
|
||||
state.websitePermissionsState,
|
||||
action
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object WebsitePermissionsStateReducer {
|
||||
/**
|
||||
* Handles creating a new [WebsitePermissionsState] based on the specific [WebsitePermissionAction]
|
||||
*/
|
||||
fun reduce(
|
||||
state: WebsitePermissionsState,
|
||||
action: WebsitePermissionAction
|
||||
): WebsitePermissionsState {
|
||||
return when (action) {
|
||||
is WebsitePermissionAction.TogglePermission -> {
|
||||
val key = action.updatedFeature
|
||||
val newWebsitePermission = state.getValue(key).copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
|
||||
state + Pair(key, newWebsitePermission)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* 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.quicksettings
|
||||
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import mozilla.components.lib.state.State
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
|
||||
/**
|
||||
* [State] containing all data displayed to the user by this Fragment.
|
||||
*
|
||||
* Partitioned further to contain mutiple states for each standalone View this Fragment holds.
|
||||
*/
|
||||
data class QuickSettingsFragmentState(
|
||||
val webInfoState: WebsiteInfoState,
|
||||
val websitePermissionsState: WebsitePermissionsState
|
||||
) : State
|
||||
|
||||
/**
|
||||
* [State] to be rendered by [WebsiteInfoView] indicating whether the connection is secure or not.
|
||||
*
|
||||
* @param websiteUrl [String] the URL of the current web page.
|
||||
* @param websiteTitle [String] the title of the current web page.
|
||||
* @param websiteSecurityUiValues UI values to represent the security of the website.
|
||||
*/
|
||||
data class WebsiteInfoState(
|
||||
val websiteUrl: String,
|
||||
val websiteTitle: String,
|
||||
val websiteSecurityUiValues: WebsiteSecurityUiValues,
|
||||
val certificateName: String
|
||||
) : State
|
||||
|
||||
enum class WebsiteSecurityUiValues(
|
||||
@StringRes val securityInfoRes: Int,
|
||||
@DrawableRes val iconRes: Int,
|
||||
@ColorRes val iconTintRes: Int
|
||||
) {
|
||||
SECURE(
|
||||
R.string.quick_settings_sheet_secure_connection,
|
||||
R.drawable.mozac_ic_lock,
|
||||
R.color.photonGreen50
|
||||
),
|
||||
INSECURE(
|
||||
R.string.quick_settings_sheet_insecure_connection,
|
||||
R.drawable.mozac_ic_globe,
|
||||
R.color.photonRed50
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* [State] to be rendered by [WebsitePermissionsView] displaying all explicitly allowed or blocked
|
||||
* website permissions.
|
||||
*/
|
||||
typealias WebsitePermissionsState = Map<PhoneFeature, WebsitePermission>
|
||||
|
||||
/**
|
||||
* Wrapper over a website permission encompassing all it's needed state to be rendered on the screen.
|
||||
*
|
||||
* Contains a limited number of implementations because there is a known, finite number of permissions
|
||||
* we need to display to the user.
|
||||
*
|
||||
* @property status The *allowed* / *blocked* permission status to be shown to the user.
|
||||
* @property isVisible Whether this permission should be shown to the user.
|
||||
* @property isEnabled Visual indication about whether this permission is *enabled* / *disabled*
|
||||
* @property isBlockedByAndroid Whether the corresponding *dangerous* Android permission is granted
|
||||
* for the app by the user or not.
|
||||
*/
|
||||
data class WebsitePermission(
|
||||
val phoneFeature: PhoneFeature,
|
||||
val status: String,
|
||||
val isVisible: Boolean,
|
||||
val isEnabled: Boolean,
|
||||
val isBlockedByAndroid: Boolean
|
||||
)
|
|
@ -5,21 +5,18 @@
|
|||
package org.mozilla.fenix.settings.quicksettings
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.lib.state.Action
|
||||
import mozilla.components.lib.state.Reducer
|
||||
import mozilla.components.lib.state.State
|
||||
import mozilla.components.lib.state.Store
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.createStore
|
||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeVisible
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import java.util.EnumMap
|
||||
|
||||
/**
|
||||
* [QuickSettingsSheetDialogFragment]'s unique [Store].
|
||||
|
@ -40,27 +37,6 @@ class QuickSettingsFragmentStore(
|
|||
::quickSettingsFragmentReducer
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
* String, Drawable & Drawable Tint color used to display that the current website connection is secured.
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
val getSecuredWebsiteUiValues = Triple(
|
||||
R.string.quick_settings_sheet_secure_connection,
|
||||
R.drawable.mozac_ic_lock,
|
||||
R.color.photonGreen50
|
||||
)
|
||||
|
||||
/**
|
||||
* String, Drawable & Drawable Tint color used to display that the current website connection is
|
||||
* **not** secured.
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
val getInsecureWebsiteUiValues = Triple(
|
||||
R.string.quick_settings_sheet_insecure_connection,
|
||||
R.drawable.mozac_ic_globe,
|
||||
R.color.photonRed50
|
||||
)
|
||||
|
||||
/**
|
||||
* Construct an initial [QuickSettingsFragmentState] for all Views displayed by the
|
||||
* [QuickSettingsSheetDialogFragment].
|
||||
|
@ -109,11 +85,8 @@ class QuickSettingsFragmentStore(
|
|||
isSecured: Boolean,
|
||||
certificateName: String
|
||||
): WebsiteInfoState {
|
||||
val (stringRes, iconRes, colorRes) = when (isSecured) {
|
||||
true -> getSecuredWebsiteUiValues
|
||||
false -> getInsecureWebsiteUiValues
|
||||
}
|
||||
return WebsiteInfoState(websiteUrl, websiteTitle, stringRes, iconRes, colorRes, certificateName)
|
||||
val uiValues = if (isSecured) WebsiteSecurityUiValues.SECURE else WebsiteSecurityUiValues.INSECURE
|
||||
return WebsiteInfoState(websiteUrl, websiteTitle, uiValues, certificateName)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,26 +105,11 @@ class QuickSettingsFragmentStore(
|
|||
permissions: SitePermissions?,
|
||||
settings: Settings
|
||||
): WebsitePermissionsState {
|
||||
val cameraPermission =
|
||||
PhoneFeature.CAMERA.toWebsitePermission(context, permissions, settings)
|
||||
val microphonePermission =
|
||||
PhoneFeature.MICROPHONE.toWebsitePermission(context, permissions, settings)
|
||||
val notificationPermission =
|
||||
PhoneFeature.NOTIFICATION.toWebsitePermission(context, permissions, settings)
|
||||
val locationPermission =
|
||||
PhoneFeature.LOCATION.toWebsitePermission(context, permissions, settings)
|
||||
val autoplayAudiblePermission =
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE.toWebsitePermission(context, permissions, settings)
|
||||
val autoplayInaudiblePermission =
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE.toWebsitePermission(context, permissions, settings)
|
||||
val shouldBeVisible = cameraPermission.isVisible || microphonePermission.isVisible ||
|
||||
notificationPermission.isVisible || locationPermission.isVisible
|
||||
|
||||
return WebsitePermissionsState(
|
||||
shouldBeVisible, cameraPermission, microphonePermission,
|
||||
notificationPermission, locationPermission, autoplayAudiblePermission,
|
||||
autoplayInaudiblePermission
|
||||
)
|
||||
val state = EnumMap<PhoneFeature, WebsitePermission>(PhoneFeature::class.java)
|
||||
for (feature in PhoneFeature.values()) {
|
||||
state[feature] = feature.toWebsitePermission(context, permissions, settings)
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,425 +121,13 @@ class QuickSettingsFragmentStore(
|
|||
permissions: SitePermissions?,
|
||||
settings: Settings
|
||||
): WebsitePermission {
|
||||
val status = getPermissionStatus(context, permissions, settings)
|
||||
return when (this) {
|
||||
PhoneFeature.CAMERA -> WebsitePermission.Camera(
|
||||
status.status, status.isVisible, status.isEnabled, status.isBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.LOCATION -> WebsitePermission.Location(
|
||||
status.status, status.isVisible, status.isEnabled, status.isBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.MICROPHONE -> WebsitePermission.Microphone(
|
||||
status.status, status.isVisible, status.isEnabled, status.isBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.NOTIFICATION -> WebsitePermission.Notification(
|
||||
status.status, status.isVisible, status.isEnabled, status.isBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE -> WebsitePermission.AutoplayAudible(
|
||||
status.status, status.isVisible, status.isEnabled, status.isBlockedByAndroid
|
||||
)
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE -> WebsitePermission.AutoplayInaudible(
|
||||
status.status, status.isVisible, status.isEnabled, status.isBlockedByAndroid
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for getting the [WebsitePermission] properties based on a specific [PhoneFeature].
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
fun PhoneFeature.getPermissionStatus(
|
||||
context: Context,
|
||||
permissions: SitePermissions?,
|
||||
settings: Settings
|
||||
) = PermissionStatus(
|
||||
status = getActionLabel(context, permissions, settings),
|
||||
isVisible = shouldBeVisible(permissions, settings),
|
||||
isEnabled = shouldBeEnabled(context, permissions, settings),
|
||||
isBlockedByAndroid = !isAndroidPermissionGranted(context)
|
||||
)
|
||||
|
||||
/**
|
||||
* Helper class acting as a temporary container of [WebsitePermission] properties.
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
data class PermissionStatus(
|
||||
val status: String,
|
||||
val isVisible: Boolean,
|
||||
val isEnabled: Boolean,
|
||||
val isBlockedByAndroid: Boolean
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// States
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* [State] containing all data displayed to the user by this Fragment.
|
||||
*
|
||||
* Partitioned further to contain mutiple states for each standalone View this Fragment holds.
|
||||
*/
|
||||
data class QuickSettingsFragmentState(
|
||||
val webInfoState: WebsiteInfoState,
|
||||
val websitePermissionsState: WebsitePermissionsState
|
||||
) : State
|
||||
|
||||
/**
|
||||
* [State] to be rendered by [WebsiteInfoView] indicating whether the connection is secure or not.
|
||||
*
|
||||
* @param websiteUrl [String] the URL of the current web page.
|
||||
* @param websiteTitle [String] the title of the current web page.
|
||||
* @param securityInfoRes [StringRes] for the connection description.
|
||||
* @param iconRes [DrawableRes] image indicating the connection status.
|
||||
* @param iconTintRes [ColorRes] icon color.
|
||||
*/
|
||||
data class WebsiteInfoState(
|
||||
val websiteUrl: String,
|
||||
val websiteTitle: String,
|
||||
@StringRes val securityInfoRes: Int,
|
||||
@DrawableRes val iconRes: Int,
|
||||
@ColorRes val iconTintRes: Int,
|
||||
val certificateName: String
|
||||
) : State
|
||||
|
||||
/**
|
||||
* /**
|
||||
* [State] to be rendered by [WebsitePermissionsView] displaying all explicitly allowed or blocked
|
||||
* website permissions.
|
||||
*
|
||||
* @param isVisible [Boolean] whether this contains data that needs to be displayed to the user.
|
||||
* @param camera [WebsitePermission] containing all information about the *camera* permission.
|
||||
* @param microphone [WebsitePermission] containing all information about the *microphone* permission.
|
||||
* @param notification [notification] containing all information about the *notification* permission.
|
||||
* @param location [WebsitePermission] containing all information about the *location* permission.
|
||||
*/
|
||||
*/
|
||||
data class WebsitePermissionsState(
|
||||
val isVisible: Boolean,
|
||||
val camera: WebsitePermission,
|
||||
val microphone: WebsitePermission,
|
||||
val notification: WebsitePermission,
|
||||
val location: WebsitePermission,
|
||||
val autoplayAudible: WebsitePermission,
|
||||
val autoplayInaudible: WebsitePermission
|
||||
) : State
|
||||
|
||||
/**
|
||||
* Wrapper over a website permission encompassing all it's needed state to be rendered on the screen.
|
||||
*
|
||||
* Contains a limited number of implementations because there is a known, finite number of permissions
|
||||
* we need to display to the user.
|
||||
*/
|
||||
sealed class WebsitePermission {
|
||||
/**
|
||||
* The *allowed* / *blocked* permission status to be shown to the user.
|
||||
*/
|
||||
abstract val status: String
|
||||
|
||||
/**
|
||||
* Whether this permission should be shown to the user.
|
||||
*/
|
||||
abstract val isVisible: Boolean
|
||||
|
||||
/**
|
||||
* Visual indication about whether this permission is *enabled* / *disabled*
|
||||
*/
|
||||
abstract val isEnabled: Boolean
|
||||
|
||||
/**
|
||||
* Whether the corresponding *dangerous* Android permission is granted for the app by the user or not.
|
||||
*/
|
||||
abstract val isBlockedByAndroid: Boolean
|
||||
|
||||
/**
|
||||
* Helper method mimicking the default generated *copy()* method for a data class.
|
||||
* Allows us using a familiar API in the reducer.
|
||||
*/
|
||||
abstract fun copy(
|
||||
status: String = this.status,
|
||||
isVisible: Boolean = this.isVisible,
|
||||
isEnabled: Boolean = this.isEnabled,
|
||||
isBlockedByAndroid: Boolean = this.isBlockedByAndroid
|
||||
): WebsitePermission
|
||||
|
||||
/**
|
||||
* Contains all information about the *camera* permission.
|
||||
*/
|
||||
data class Camera(
|
||||
override val status: String,
|
||||
override val isVisible: Boolean,
|
||||
override val isEnabled: Boolean,
|
||||
override val isBlockedByAndroid: Boolean,
|
||||
val name: String = "Camera" // helps to resolve the overload resolution ambiguity for the copy() method
|
||||
) : WebsitePermission() {
|
||||
override fun copy(
|
||||
status: String,
|
||||
isVisible: Boolean,
|
||||
isEnabled: Boolean,
|
||||
isBlockedByAndroid: Boolean
|
||||
) = copy(
|
||||
status = status,
|
||||
isVisible = isVisible,
|
||||
isEnabled = isEnabled,
|
||||
isBlockedByAndroid = isBlockedByAndroid,
|
||||
name = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all information about the *microphone* permission.
|
||||
*/
|
||||
data class Microphone(
|
||||
override val status: String,
|
||||
override val isVisible: Boolean,
|
||||
override val isEnabled: Boolean,
|
||||
override val isBlockedByAndroid: Boolean,
|
||||
val name: String = "Microphone" // helps to resolve the overload resolution ambiguity for the copy() method
|
||||
) : WebsitePermission() {
|
||||
override fun copy(
|
||||
status: String,
|
||||
isVisible: Boolean,
|
||||
isEnabled: Boolean,
|
||||
isBlockedByAndroid: Boolean
|
||||
) = copy(
|
||||
status = status,
|
||||
isVisible = isVisible,
|
||||
isEnabled = isEnabled,
|
||||
isBlockedByAndroid = isBlockedByAndroid,
|
||||
name = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all information about the *notification* permission.
|
||||
*/
|
||||
data class Notification(
|
||||
override val status: String,
|
||||
override val isVisible: Boolean,
|
||||
override val isEnabled: Boolean,
|
||||
override val isBlockedByAndroid: Boolean,
|
||||
val name: String = "Notification" // helps to resolve the overload resolution ambiguity for the copy() method
|
||||
) : WebsitePermission() {
|
||||
override fun copy(
|
||||
status: String,
|
||||
isVisible: Boolean,
|
||||
isEnabled: Boolean,
|
||||
isBlockedByAndroid: Boolean
|
||||
) = copy(
|
||||
status = status,
|
||||
isVisible = isVisible,
|
||||
isEnabled = isEnabled,
|
||||
isBlockedByAndroid = isBlockedByAndroid,
|
||||
name = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all information about the *location* permission.
|
||||
*/
|
||||
data class Location(
|
||||
override val status: String,
|
||||
override val isVisible: Boolean,
|
||||
override val isEnabled: Boolean,
|
||||
override val isBlockedByAndroid: Boolean,
|
||||
val name: String = "Location" // helps to resolve the overload resolution ambiguity for the copy() method
|
||||
) : WebsitePermission() {
|
||||
override fun copy(
|
||||
status: String,
|
||||
isVisible: Boolean,
|
||||
isEnabled: Boolean,
|
||||
isBlockedByAndroid: Boolean
|
||||
) = copy(
|
||||
status = status,
|
||||
isVisible = isVisible,
|
||||
isEnabled = isEnabled,
|
||||
isBlockedByAndroid = isBlockedByAndroid,
|
||||
name = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all information about the *autoplay audible* permission.
|
||||
*/
|
||||
data class AutoplayAudible(
|
||||
override val status: String,
|
||||
override val isVisible: Boolean,
|
||||
override val isEnabled: Boolean,
|
||||
override val isBlockedByAndroid: Boolean,
|
||||
val name: String = "AutoplayAudible" // helps to resolve the overload resolution ambiguity for the copy() method
|
||||
) : WebsitePermission() {
|
||||
override fun copy(
|
||||
status: String,
|
||||
isVisible: Boolean,
|
||||
isEnabled: Boolean,
|
||||
isBlockedByAndroid: Boolean
|
||||
) = copy(
|
||||
status = status,
|
||||
isVisible = isVisible,
|
||||
isEnabled = isEnabled,
|
||||
isBlockedByAndroid = isBlockedByAndroid,
|
||||
name = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all information about the *autoplay inaudible* permission.
|
||||
*/
|
||||
data class AutoplayInaudible(
|
||||
override val status: String,
|
||||
override val isVisible: Boolean,
|
||||
override val isEnabled: Boolean,
|
||||
override val isBlockedByAndroid: Boolean,
|
||||
// helps to resolve the overload resolution ambiguity for the copy() method
|
||||
val name: String = "AutoplayInaudible"
|
||||
) : WebsitePermission() {
|
||||
override fun copy(
|
||||
status: String,
|
||||
isVisible: Boolean,
|
||||
isEnabled: Boolean,
|
||||
isBlockedByAndroid: Boolean
|
||||
) = copy(
|
||||
status = status,
|
||||
isVisible = isVisible,
|
||||
isEnabled = isEnabled,
|
||||
isBlockedByAndroid = isBlockedByAndroid,
|
||||
name = name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// Actions
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parent [Action] for all the [QuickSettingsFragmentState] changes.
|
||||
*/
|
||||
sealed class QuickSettingsFragmentAction : Action
|
||||
|
||||
/**
|
||||
* All possible [WebsiteInfoState] changes as result of user / system interactions.
|
||||
*/
|
||||
sealed class WebsiteInfoAction : QuickSettingsFragmentAction()
|
||||
|
||||
/**
|
||||
* All possible [WebsitePermissionsState] changes as result of user / system interactions.
|
||||
*/
|
||||
sealed class WebsitePermissionAction : QuickSettingsFragmentAction() {
|
||||
/**
|
||||
* Change resulting from toggling a specific [WebsitePermission] for the current website.
|
||||
*
|
||||
* @param updatedFeature [PhoneFeature] backing a certain [WebsitePermission].
|
||||
* Allows to easily identify which permission changed
|
||||
* **Must be the name of one of the properties of [WebsitePermissionsState]**.
|
||||
* @param updatedStatus [String] the new [WebsitePermission#status] which will be shown to the user.
|
||||
* @param updatedEnabledStatus [Boolean] the new [WebsitePermission#enabled] which will be shown to the user.
|
||||
*/
|
||||
class TogglePermission(
|
||||
val websitePermission: WebsitePermission,
|
||||
val updatedStatus: String,
|
||||
val updatedEnabledStatus: Boolean
|
||||
) : WebsitePermissionAction()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// Reducers
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parent [Reducer] for all [QuickSettingsFragmentState]s of all Views shown in this Fragment.
|
||||
*/
|
||||
fun quickSettingsFragmentReducer(
|
||||
state: QuickSettingsFragmentState,
|
||||
action: QuickSettingsFragmentAction
|
||||
): QuickSettingsFragmentState {
|
||||
return when (action) {
|
||||
is WebsiteInfoAction -> state.copy(
|
||||
webInfoState = WebsiteInfoStateReducer.reduce(
|
||||
state.webInfoState,
|
||||
action
|
||||
return WebsitePermission(
|
||||
phoneFeature = this,
|
||||
status = getActionLabel(context, permissions, settings),
|
||||
isVisible = shouldBeVisible(permissions, settings),
|
||||
isEnabled = shouldBeEnabled(context, permissions, settings),
|
||||
isBlockedByAndroid = !isAndroidPermissionGranted(context)
|
||||
)
|
||||
)
|
||||
is WebsitePermissionAction -> state.copy(
|
||||
websitePermissionsState = WebsitePermissionsStateReducer.reduce(
|
||||
state.websitePermissionsState,
|
||||
action
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER") // the action paramater is unused
|
||||
object WebsiteInfoStateReducer {
|
||||
/**
|
||||
* Handles creating a new [WebsiteInfoState] based on the specific [WebsiteInfoAction]
|
||||
*/
|
||||
fun reduce(
|
||||
state: WebsiteInfoState,
|
||||
action: WebsiteInfoAction
|
||||
): WebsiteInfoState {
|
||||
// There is no possible action that can change this View's state while it is displayed to the user.
|
||||
// Everytime the View is recreated it starts with a fresh state. This is the only way to display
|
||||
// something different.
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
object WebsitePermissionsStateReducer {
|
||||
/**
|
||||
* Handles creating a new [WebsitePermissionsState] based on the specific [WebsitePermissionAction]
|
||||
*/
|
||||
fun reduce(
|
||||
state: WebsitePermissionsState,
|
||||
action: WebsitePermissionAction
|
||||
): WebsitePermissionsState {
|
||||
return when (action) {
|
||||
is WebsitePermissionAction.TogglePermission -> {
|
||||
when (action.websitePermission) {
|
||||
is WebsitePermission.Camera -> state.copy(
|
||||
camera = state.camera.copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
)
|
||||
is WebsitePermission.Microphone -> state.copy(
|
||||
microphone = state.microphone.copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
)
|
||||
is WebsitePermission.Notification -> state.copy(
|
||||
notification = state.notification.copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
)
|
||||
is WebsitePermission.Location -> state.copy(
|
||||
location = state.location.copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
)
|
||||
is WebsitePermission.AutoplayAudible -> {
|
||||
return state.copy(
|
||||
autoplayAudible = state.autoplayAudible.copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
)
|
||||
}
|
||||
is WebsitePermission.AutoplayInaudible -> {
|
||||
return state.copy(
|
||||
autoplayInaudible = state.autoplayInaudible.copy(
|
||||
status = action.updatedStatus,
|
||||
isEnabled = action.updatedEnabledStatus
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,11 @@ package org.mozilla.fenix.settings.quicksettings
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.getColor
|
||||
import androidx.core.view.isVisible
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.quicksettings_website_info.view.*
|
||||
import mozilla.components.support.ktx.android.content.getDrawableWithTint
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
/**
|
||||
|
@ -38,7 +35,7 @@ class WebsiteInfoView(
|
|||
fun update(state: WebsiteInfoState) {
|
||||
bindUrl(state.websiteUrl)
|
||||
bindTitle(state.websiteTitle)
|
||||
bindSecurityInfo(state.securityInfoRes, state.iconRes, state.iconTintRes)
|
||||
bindSecurityInfo(state.websiteSecurityUiValues)
|
||||
bindCertificateName(state.certificateName)
|
||||
}
|
||||
|
||||
|
@ -56,14 +53,11 @@ class WebsiteInfoView(
|
|||
view.certificateInfo.isVisible = cert.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun bindSecurityInfo(
|
||||
@StringRes securityInfoRes: Int,
|
||||
@DrawableRes iconRes: Int,
|
||||
@ColorRes iconTintRes: Int
|
||||
) {
|
||||
val icon = AppCompatResources.getDrawable(view.context, iconRes)
|
||||
icon?.setTint(ContextCompat.getColor(view.context, iconTintRes))
|
||||
view.securityInfo.setText(securityInfoRes)
|
||||
view.securityInfoIcon.setImageResource(iconRes)
|
||||
private fun bindSecurityInfo(uiValues: WebsiteSecurityUiValues) {
|
||||
val tint = getColor(view.context, uiValues.iconTintRes)
|
||||
view.securityInfo.setText(uiValues.securityInfoRes)
|
||||
view.securityInfoIcon.setImageDrawable(
|
||||
view.context.getDrawableWithTint(uiValues.iconRes, tint)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@ import android.view.ViewGroup
|
|||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.quicksettings_permissions.view.*
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import java.util.EnumMap
|
||||
|
||||
/**
|
||||
* Contract declaring all possible user interactions with [WebsitePermissionsView]
|
||||
|
@ -49,26 +52,31 @@ class WebsitePermissionsView(
|
|||
val view: View = LayoutInflater.from(context)
|
||||
.inflate(R.layout.quicksettings_permissions, containerView, true)
|
||||
|
||||
private val permissionViews: Map<PhoneFeature, PermissionViewHolder> = EnumMap(mapOf(
|
||||
PhoneFeature.CAMERA to PermissionViewHolder(view.cameraLabel, view.cameraStatus),
|
||||
PhoneFeature.LOCATION to PermissionViewHolder(view.locationLabel, view.locationStatus),
|
||||
PhoneFeature.MICROPHONE to PermissionViewHolder(view.microphoneLabel, view.microphoneStatus),
|
||||
PhoneFeature.NOTIFICATION to PermissionViewHolder(view.notificationLabel, view.notificationStatus)
|
||||
))
|
||||
|
||||
/**
|
||||
* Allows changing what this View displays.
|
||||
*
|
||||
* @param state [WebsitePermissionsState] to be rendered.
|
||||
*/
|
||||
fun update(state: WebsitePermissionsState) {
|
||||
if (state.isVisible) {
|
||||
val isVisible = permissionViews.keys
|
||||
.map { feature -> state.getValue(feature) }
|
||||
.any { it.isVisible }
|
||||
if (isVisible) {
|
||||
interactor.onPermissionsShown()
|
||||
}
|
||||
|
||||
// If more permissions are added into this View we can display them into a list
|
||||
// and also use DiffUtil to only update one item in case of a permission change
|
||||
bindPermission(state.camera,
|
||||
Pair(view.findViewById(R.id.cameraLabel), view.findViewById(R.id.cameraStatus)))
|
||||
bindPermission(state.location,
|
||||
Pair(view.findViewById(R.id.locationLabel), view.findViewById(R.id.locationStatus)))
|
||||
bindPermission(state.microphone,
|
||||
Pair(view.findViewById(R.id.microphoneLabel), view.findViewById(R.id.microphoneStatus)))
|
||||
bindPermission(state.notification,
|
||||
Pair(view.findViewById(R.id.notificationLabel), view.findViewById(R.id.notificationStatus)))
|
||||
for ((feature, views) in permissionViews) {
|
||||
bindPermission(state.getValue(feature), views)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,15 +84,15 @@ class WebsitePermissionsView(
|
|||
* which will display permission's [icon, label, status] and register user inputs.
|
||||
*
|
||||
* @param permissionState [WebsitePermission] specific permission that can be shown to the user.
|
||||
* @param permissionViews Views that will render [WebsitePermission]'s state.
|
||||
* @param viewHolder Views that will render [WebsitePermission]'s state.
|
||||
*/
|
||||
private fun bindPermission(permissionState: WebsitePermission, permissionViews: Pair<TextView, TextView>) {
|
||||
val (label, status) = permissionViews
|
||||
|
||||
status.text = permissionState.status
|
||||
label.isEnabled = permissionState.isEnabled
|
||||
label.isVisible = permissionState.isVisible
|
||||
status.isVisible = permissionState.isVisible
|
||||
status.setOnClickListener { interactor.onPermissionToggled(permissionState) }
|
||||
private fun bindPermission(permissionState: WebsitePermission, viewHolder: PermissionViewHolder) {
|
||||
viewHolder.label.isEnabled = permissionState.isEnabled
|
||||
viewHolder.label.isVisible = permissionState.isVisible
|
||||
viewHolder.status.text = permissionState.status
|
||||
viewHolder.status.isVisible = permissionState.isVisible
|
||||
viewHolder.status.setOnClickListener { interactor.onPermissionToggled(permissionState) }
|
||||
}
|
||||
|
||||
data class PermissionViewHolder(val label: TextView, val status: TextView)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
|
||||
package org.mozilla.fenix.settings.sitepermissions
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.text.HtmlCompat
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.Components
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
|
||||
/**
|
||||
* Try to reload a session if a session with the given [origin] it is found.
|
||||
|
@ -15,3 +20,23 @@ internal fun Components.tryReloadTabBy(origin: String) {
|
|||
val session = core.sessionManager.all.find { it.url.toUri().host == origin }
|
||||
useCases.sessionUseCases.reload(session)
|
||||
}
|
||||
|
||||
internal fun initBlockedByAndroidView(phoneFeature: PhoneFeature, blockedByAndroidView: View) {
|
||||
val context = blockedByAndroidView.context
|
||||
if (!phoneFeature.isAndroidPermissionGranted(context)) {
|
||||
blockedByAndroidView.visibility = View.VISIBLE
|
||||
|
||||
val descriptionLabel = blockedByAndroidView.findViewById<TextView>(R.id.blocked_by_android_feature_label)
|
||||
val descriptionText = context.getString(
|
||||
R.string.phone_feature_blocked_step_feature,
|
||||
phoneFeature.getLabel(context)
|
||||
)
|
||||
descriptionLabel.text = HtmlCompat.fromHtml(descriptionText, HtmlCompat.FROM_HTML_MODE_COMPACT)
|
||||
|
||||
val permissionsLabel = blockedByAndroidView.findViewById<TextView>(R.id.blocked_by_android_permissions_label)
|
||||
val permissionsText = context.getString(R.string.phone_feature_blocked_step_permissions)
|
||||
permissionsLabel.text = HtmlCompat.fromHtml(permissionsText, HtmlCompat.FROM_HTML_MODE_COMPACT)
|
||||
} else {
|
||||
blockedByAndroidView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() {
|
|||
private fun navigateToPhoneFeature(phoneFeature: PhoneFeature) {
|
||||
val directions =
|
||||
SitePermissionsDetailsExceptionsFragmentDirections.actionSitePermissionsToExceptionsToManagePhoneFeature(
|
||||
phoneFeatureId = phoneFeature.id,
|
||||
phoneFeature = phoneFeature,
|
||||
sitePermissions = sitePermissions
|
||||
)
|
||||
requireView().findNavController().navigate(directions)
|
||||
|
|
|
@ -77,7 +77,7 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun navigateToPhoneFeature(phoneFeature: PhoneFeature) {
|
||||
val directions = SitePermissionsFragmentDirections
|
||||
.actionSitePermissionsToManagePhoneFeatures(phoneFeature.id)
|
||||
.actionSitePermissionsToManagePhoneFeatures(phoneFeature)
|
||||
Navigation.findNavController(requireView()).navigate(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,29 +28,22 @@ import org.mozilla.fenix.R
|
|||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.initBlockedByAndroidView
|
||||
import org.mozilla.fenix.settings.setStartCheckedIndicator
|
||||
import org.mozilla.fenix.settings.update
|
||||
|
||||
@SuppressWarnings("TooManyFunctions")
|
||||
class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
|
||||
|
||||
private lateinit var phoneFeature: PhoneFeature
|
||||
private lateinit var sitePermissions: SitePermissions
|
||||
private lateinit var radioAllow: RadioButton
|
||||
private lateinit var radioBlock: RadioButton
|
||||
private lateinit var blockedByAndroidView: View
|
||||
private val args by navArgs<SitePermissionsManageExceptionsPhoneFeatureFragmentArgs>()
|
||||
val settings by lazy { requireContext().settings() }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val args by navArgs<SitePermissionsManageExceptionsPhoneFeatureFragmentArgs>()
|
||||
|
||||
phoneFeature = args.phoneFeatureId.toPhoneFeature()
|
||||
sitePermissions = args.sitePermissions
|
||||
|
||||
showToolbar(phoneFeature.getLabel(requireContext()))
|
||||
showToolbar(args.phoneFeature.getLabel(requireContext()))
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -71,7 +64,7 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
initBlockedByAndroidView(phoneFeature, blockedByAndroidView)
|
||||
initBlockedByAndroidView(args.phoneFeature, blockedByAndroidView)
|
||||
}
|
||||
|
||||
private fun initAskToAllowRadio(rootView: View) {
|
||||
|
@ -87,7 +80,7 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun RadioButton.restoreState(status: SitePermissions.Status) {
|
||||
if (phoneFeature.getStatus(sitePermissions) == status) {
|
||||
if (args.phoneFeature.getStatus(args.sitePermissions) == status) {
|
||||
this.isChecked = true
|
||||
this.setStartCheckedIndicator()
|
||||
}
|
||||
|
@ -109,7 +102,7 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
|
|||
setMessage(R.string.confirm_clear_permission_site)
|
||||
setTitle(R.string.clear_permission)
|
||||
setPositiveButton(android.R.string.yes) { dialog: DialogInterface, _ ->
|
||||
val defaultStatus = phoneFeature.getStatus(settings = settings)
|
||||
val defaultStatus = args.phoneFeature.getStatus(settings = settings)
|
||||
updatedSitePermissions(defaultStatus)
|
||||
resetRadioButtonsStatus(defaultStatus)
|
||||
dialog.dismiss()
|
||||
|
@ -147,23 +140,8 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
|
|||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun Int.toPhoneFeature(): PhoneFeature {
|
||||
return requireNotNull(PhoneFeature.values().find { feature ->
|
||||
this == feature.id
|
||||
}) {
|
||||
"$this is a invalid PhoneFeature"
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatedSitePermissions(status: SitePermissions.Status) {
|
||||
val updatedSitePermissions = when (phoneFeature) {
|
||||
PhoneFeature.CAMERA -> sitePermissions.copy(camera = status)
|
||||
PhoneFeature.LOCATION -> sitePermissions.copy(location = status)
|
||||
PhoneFeature.MICROPHONE -> sitePermissions.copy(microphone = status)
|
||||
PhoneFeature.NOTIFICATION -> sitePermissions.copy(notification = status)
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE -> sitePermissions.copy(autoplayAudible = status)
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE -> sitePermissions.copy(autoplayInaudible = status)
|
||||
}
|
||||
val updatedSitePermissions = args.sitePermissions.update(args.phoneFeature, status)
|
||||
viewLifecycleOwner.lifecycleScope.launch(IO) {
|
||||
requireComponents.core.permissionStorage.updateSitePermissions(updatedSitePermissions)
|
||||
launch(Main) {
|
||||
|
|
|
@ -20,10 +20,8 @@ import android.view.ViewGroup
|
|||
import android.widget.Button
|
||||
import android.widget.RadioButton
|
||||
import androidx.fragment.app.Fragment
|
||||
import kotlinx.android.synthetic.main.fragment_manage_site_permissions_feature_phone.view.ask_to_allow_radio
|
||||
import kotlinx.android.synthetic.main.fragment_manage_site_permissions_feature_phone.view.block_radio
|
||||
import kotlinx.android.synthetic.main.fragment_manage_site_permissions_feature_phone.view.fourth_radio
|
||||
import kotlinx.android.synthetic.main.fragment_manage_site_permissions_feature_phone.view.third_radio
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import kotlinx.android.synthetic.main.fragment_manage_site_permissions_feature_phone.view.*
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ALLOWED
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW
|
||||
|
@ -31,10 +29,8 @@ import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BL
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.PhoneFeature.AUTOPLAY_AUDIBLE
|
||||
import org.mozilla.fenix.settings.PhoneFeature.AUTOPLAY_INAUDIBLE
|
||||
import org.mozilla.fenix.settings.initBlockedByAndroidView
|
||||
import org.mozilla.fenix.settings.setStartCheckedIndicator
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
|
@ -45,19 +41,11 @@ const val AUTOPLAY_ALLOW_ALL = 3
|
|||
|
||||
@SuppressWarnings("TooManyFunctions")
|
||||
class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
||||
private lateinit var phoneFeature: PhoneFeature
|
||||
private lateinit var settings: Settings
|
||||
|
||||
private val args by navArgs<SitePermissionsManagePhoneFeatureFragmentArgs>()
|
||||
private val settings by lazy { requireContext().settings() }
|
||||
private lateinit var blockedByAndroidView: View
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
phoneFeature = SitePermissionsManagePhoneFeatureFragmentArgs
|
||||
.fromBundle(requireArguments())
|
||||
.permission.toPhoneFeature()
|
||||
settings = requireContext().settings()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
@ -80,13 +68,13 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
showToolbar(phoneFeature.getLabel(requireContext()))
|
||||
initBlockedByAndroidView(phoneFeature, blockedByAndroidView)
|
||||
showToolbar(args.phoneFeature.getLabel(requireContext()))
|
||||
initBlockedByAndroidView(args.phoneFeature, blockedByAndroidView)
|
||||
}
|
||||
|
||||
private fun initFirstRadio(rootView: View) {
|
||||
with(rootView.ask_to_allow_radio) {
|
||||
if (phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
if (args.phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
// Disabled because GV does not allow this setting. TODO Reenable after
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed
|
||||
// text = getString(R.string.preference_option_autoplay_allowed2)
|
||||
|
@ -111,7 +99,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
|
||||
private fun initSecondRadio(rootView: View) {
|
||||
with(rootView.block_radio) {
|
||||
if (phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
if (args.phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
text = getCombinedLabel(
|
||||
getString(R.string.preference_option_autoplay_allowed_wifi_only2),
|
||||
getString(R.string.preference_option_autoplay_allowed_wifi_subtext)
|
||||
|
@ -135,7 +123,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
|
||||
private fun initThirdRadio(rootView: View) {
|
||||
with(rootView.third_radio) {
|
||||
if (phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
if (args.phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
visibility = View.VISIBLE
|
||||
text = getString(R.string.preference_option_autoplay_block_audio2)
|
||||
setOnClickListener {
|
||||
|
@ -150,7 +138,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
|
||||
private fun initFourthRadio(rootView: View) {
|
||||
with(rootView.fourth_radio) {
|
||||
if (phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
if (args.phoneFeature == AUTOPLAY_AUDIBLE) {
|
||||
visibility = View.VISIBLE
|
||||
text = getCombinedLabel(
|
||||
getString(R.string.preference_option_autoplay_blocked3),
|
||||
|
@ -167,7 +155,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun RadioButton.restoreState(buttonAction: SitePermissionsRules.Action) {
|
||||
if (phoneFeature.getAction(settings) == buttonAction) {
|
||||
if (args.phoneFeature.getAction(settings) == buttonAction) {
|
||||
this.isChecked = true
|
||||
this.setStartCheckedIndicator()
|
||||
}
|
||||
|
@ -181,7 +169,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun saveActionInSettings(action: SitePermissionsRules.Action) {
|
||||
settings.setSitePermissionsPhoneFeatureAction(phoneFeature, action)
|
||||
settings.setSitePermissionsPhoneFeatureAction(args.phoneFeature, action)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,14 +199,6 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||
initSettingsButton(blockedByAndroidView)
|
||||
}
|
||||
|
||||
private fun Int.toPhoneFeature(): PhoneFeature {
|
||||
return requireNotNull(PhoneFeature.values().find { feature ->
|
||||
this == feature.id
|
||||
}) {
|
||||
"$this is a invalid PhoneFeature"
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSettingsButton(rootView: View) {
|
||||
val button = rootView.findViewById<Button>(R.id.settings_button)
|
||||
button.setOnClickListener {
|
||||
|
|
|
@ -5,6 +5,8 @@ package org.mozilla.fenix.whatsnew
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import android.content.Context
|
||||
import android.os.StrictMode
|
||||
import mozilla.components.support.ktx.android.os.resetAfter
|
||||
|
||||
// This file is a modified port from Focus Android
|
||||
|
||||
|
@ -68,7 +70,9 @@ class WhatsNew private constructor(private val storage: WhatsNewStorage) {
|
|||
fun shouldHighlightWhatsNew(context: Context): Boolean {
|
||||
return shouldHighlightWhatsNew(
|
||||
ContextWhatsNewVersion(context),
|
||||
SharedPreferenceWhatsNewStorage(context)
|
||||
StrictMode.allowThreadDiskReads().resetAfter {
|
||||
SharedPreferenceWhatsNewStorage(context)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -92,8 +92,8 @@
|
|||
android:name="org.mozilla.fenix.settings.sitepermissions.SitePermissionsManagePhoneFeatureFragment"
|
||||
tools:layout="@layout/fragment_manage_site_permissions_feature_phone">
|
||||
<argument
|
||||
android:name="permission"
|
||||
app:argType="integer" />
|
||||
android:name="phoneFeature"
|
||||
app:argType="org.mozilla.fenix.settings.PhoneFeature" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
|
@ -125,8 +125,8 @@
|
|||
android:name="org.mozilla.fenix.settings.sitepermissions.SitePermissionsManageExceptionsPhoneFeatureFragment"
|
||||
tools:layout="@layout/fragment_manage_site_permissions_feature_phone">
|
||||
<argument
|
||||
android:name="phoneFeatureId"
|
||||
app:argType="integer" />
|
||||
android:name="phoneFeature"
|
||||
app:argType="org.mozilla.fenix.settings.PhoneFeature" />
|
||||
<argument
|
||||
android:name="sitePermissions"
|
||||
app:argType="mozilla.components.feature.sitepermissions.SitePermissions" />
|
||||
|
|
|
@ -89,6 +89,8 @@
|
|||
<string name="browser_menu_add_to_homescreen">Amestar a la pantalla d\'aniciu</string>
|
||||
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
|
||||
<string name="browser_menu_install_on_homescreen">Instalar</string>
|
||||
<!-- Menu option on the toolbar that takes you to synced tabs page-->
|
||||
<string name="synced_tabs">Llingüetes sincronizaes</string>
|
||||
<!-- Browser menu button that opens the find in page menu -->
|
||||
<string name="browser_menu_find_in_page">Alcontrar na páxina</string>
|
||||
<!-- Browser menu button that creates a private tab -->
|
||||
|
@ -377,6 +379,8 @@
|
|||
<string name="library_desktop_bookmarks_unfiled">Otros marcadores</string>
|
||||
<!-- Option in Library to open History page -->
|
||||
<string name="library_history">Historial</string>
|
||||
<!-- Option in Library to open Synced Tabs page -->
|
||||
<string name="library_synced_tabs">Llingüetes sincronizaes</string>
|
||||
<!-- Option in Library to open Reading List -->
|
||||
<string name="library_reading_list">Llista de llectura</string>
|
||||
<!-- Settings Page Title -->
|
||||
|
@ -1139,6 +1143,9 @@
|
|||
<!-- Summary for Accessibility Force Enable Zoom Preference -->
|
||||
<string name="preference_accessibility_force_enable_zoom_summary">Activa l\'averamientu y alloñamientu, tamién en sitios web qu\'eviten estos xestos.</string>
|
||||
|
||||
<!-- Saved logins sorting strategy menu item -by name- (if selected, it will sort saved logins alphabetically) -->
|
||||
<string name="saved_logins_sort_strategy_alphabetically">Nome (A-Z)</string>
|
||||
|
||||
<!-- Title of the Add search engine screen -->
|
||||
<string name="search_engine_add_custom_search_engine_title">Amestar un motor de gueta</string>
|
||||
<!-- Title of the Edit search engine screen -->
|
||||
|
@ -1226,6 +1233,8 @@
|
|||
<!-- Message in delete confirmation dialog for logins -->
|
||||
<string name="login_deletion_confirmation">¿De xuru que quies desaniciar esti aniciu de sesión?</string>
|
||||
|
||||
<!-- Voice search button content description -->
|
||||
<string name="voice_search_content_description">Gueta pela voz</string>
|
||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Fala agora</string>
|
||||
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Text for the negative button -->
|
||||
<string name="search_widget_cfr_neg_button_text">Не зараз</string>
|
||||
|
||||
<!-- Home screen icons - Long press shortcuts -->
|
||||
<!-- Shortcut action to open new tab -->
|
||||
<string name="home_screen_shortcut_open_new_tab_2">Новая картка</string>
|
||||
<!-- Shortcut action to open new private tab -->
|
||||
<string name="home_screen_shortcut_open_new_private_tab_2">Прыватная картка</string>
|
||||
<!-- Heading for the Top Sites block -->
|
||||
<string name="home_screen_top_sites_heading">Папулярныя сайты</string>
|
||||
|
||||
<!-- Browser Fragment -->
|
||||
<!-- Content description (not visible, for screen readers etc.): Navigate to open tabs -->
|
||||
<string name="browser_tabs_button">Адкрытыя карткі</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Navigate backward (browsing history) -->
|
||||
<string name="browser_menu_back">Назад</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Navigate forward (browsing history) -->
|
||||
<string name="browser_menu_forward">Наперад</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Refresh current website -->
|
||||
<string name="browser_menu_refresh">Абнавіць</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Stop loading current website -->
|
||||
<string name="browser_menu_stop">Спыніць</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Bookmark the current page -->
|
||||
<string name="browser_menu_bookmark">Дадаць у закладкі</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Un-bookmark the current page -->
|
||||
<string name="browser_menu_edit_bookmark">Рэдагаваць закладку</string>
|
||||
<!-- Browser menu button that opens the addon manager -->
|
||||
<string name="browser_menu_add_ons">Дадаткі</string>
|
||||
<!-- Browser menu button that sends a user to help articles -->
|
||||
<string name="browser_menu_help">Даведка</string>
|
||||
<!-- Browser menu button that sends a to a the what's new article -->
|
||||
<string name="browser_menu_whats_new">Што новага</string>
|
||||
<!-- Browser menu button that opens the settings menu -->
|
||||
<string name="browser_menu_settings">Налады</string>
|
||||
<!-- Browser menu button that opens a user's library -->
|
||||
<string name="browser_menu_library">Бібліятэка</string>
|
||||
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
|
||||
<string name="browser_menu_install_on_homescreen">Усталяваць</string>
|
||||
<!-- Menu option on the toolbar that takes you to synced tabs page-->
|
||||
<string name="synced_tabs">Сінхранізаваныя карткі</string>
|
||||
<!-- Browser menu button that opens the find in page menu -->
|
||||
<string name="browser_menu_find_in_page">Знайсці на старонцы</string>
|
||||
<!-- Browser menu button that creates a private tab -->
|
||||
<string name="browser_menu_private_tab">Прыватная картка</string>
|
||||
<!-- Browser menu button that creates a new tab -->
|
||||
<string name="browser_menu_new_tab">Новая картка</string>
|
||||
<!-- Browser menu button that saves the current tab to a collection -->
|
||||
<string name="browser_menu_save_to_collection_2">Захаваць у калекцыі</string>
|
||||
|
||||
<!-- Browser menu button that opens a dialog to report issues with the current site -->
|
||||
<string name="browser_menu_report_issue">Паведаміць аб праблеме з сайтам</string>
|
||||
<!-- Browser menu button that open a share menu to share the current site -->
|
||||
<string name="browser_menu_share">Падзяліцца</string>
|
||||
|
||||
<!-- Search suggestion onboarding hint Learn more link text -->
|
||||
<string name="search_suggestions_onboarding_learn_more_link">Даведацца больш</string>
|
||||
|
||||
<!-- Search Widget -->
|
||||
<!-- Text preview for smaller sized widgets -->
|
||||
<string name="search_widget_text_short">Пошук</string>
|
||||
<!-- Text preview for larger sized widgets -->
|
||||
<string name="search_widget_text_long">Пошук у інтэрнэце</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Voice search -->
|
||||
<string name="search_widget_voice">Галасавы пошук</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<!-- Title for the settings page-->
|
||||
<string name="settings">Налады</string>
|
||||
<!-- Preference category for basic settings -->
|
||||
<string name="preferences_category_basics">Асноўнае</string>
|
||||
<!-- Preference category for general settings -->
|
||||
<string name="preferences_category_general">Агульныя</string>
|
||||
<!-- Preference category for all links about Fenix -->
|
||||
<string name="preferences_category_about">Аб праграме</string>
|
||||
<!-- Preference for settings related to changing the default search engine -->
|
||||
<string name="preferences_default_search_engine">Прадвызначаны пашукавік</string>
|
||||
<!-- Preference for settings related to Search -->
|
||||
<string name="preferences_search">Пошук</string>
|
||||
<!-- Preference for settings related to Search address bar -->
|
||||
<string name="preferences_search_address_bar">Адрасны радок</string>
|
||||
<!-- Preference linking to help about Fenix -->
|
||||
<string name="preferences_help">Даведка</string>
|
||||
<!-- Preference linking to about page for Fenix
|
||||
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
|
||||
<string name="preferences_about">Пра %1$s</string>
|
||||
<!-- Preference linking to the your rights SUMO page -->
|
||||
<string name="preferences_your_rights">Вашы правы</string>
|
||||
<!-- Preference for settings related to saved passwords -->
|
||||
<string name="preferences_passwords">Паролі</string>
|
||||
<!-- Preference for settings related to saved credit cards and addresses -->
|
||||
<string name="preferences_credit_cards_addresses">Крэдытныя карткі і адрасы</string>
|
||||
<!-- Preference for settings related to changing the default browser -->
|
||||
<string name="preferences_set_as_default_browser">Зрабіць прадвызначаным браўзерам</string>
|
||||
<!-- Preference category for advanced settings -->
|
||||
<string name="preferences_category_advanced">Дадаткова</string>
|
||||
<!-- Preference category for privacy settings -->
|
||||
<string name="preferences_category_privacy">Прыватнасць</string>
|
||||
<!-- Preference category for privacy and security settings -->
|
||||
<string name="preferences_category_privacy_security">Прыватнасць і бяспека</string>
|
||||
<!-- Preference for advanced site permissions -->
|
||||
<string name="preferences_site_permissions">Дазволы для сайтаў</string>
|
||||
<!-- Preference for private browsing options -->
|
||||
<string name="preferences_private_browsing_options">Прыватнае агляданне</string>
|
||||
<!-- Preference for opening links in a private tab-->
|
||||
<string name="preferences_open_links_in_a_private_tab">Адкрываць спасылкі ў прыватнай картцы</string>
|
||||
<!-- Preference shown on banner to sign into account -->
|
||||
<string name="preferences_sign_in">Увайсці</string>
|
||||
<!-- Preference for changing where the toolbar is positioned -->
|
||||
<string name="preferences_toolbar">Паліца прылад</string>
|
||||
<!-- Preference for changing default theme to dark or light mode -->
|
||||
<string name="preferences_theme">Тэма</string>
|
||||
<!-- Preference for settings related to visual options -->
|
||||
<string name="preferences_customize">Уладкаванне</string>
|
||||
|
||||
<!-- Preference description for banner about signing in -->
|
||||
<string name="preferences_sign_in_description">Сінхранізуйце закладкі, гісторыю і шмат іншага з уліковым запісам Firefox</string>
|
||||
<!-- Preference shown instead of account display name while account profile information isn't available yet. -->
|
||||
<string name="preferences_account_default_name">Уліковы запіс Firefox</string>
|
||||
<!-- Preference text for account title when there was an error syncing FxA -->
|
||||
<string name="preferences_account_sync_error">Падключыцеся, каб аднавіць сінхранізацыю</string>
|
||||
<!-- Preference for language -->
|
||||
<string name="preferences_language">Мова</string>
|
||||
<!-- Preference for data choices -->
|
||||
<string name="preferences_data_choices">Выбар дадзеных</string>
|
||||
<!-- Preference for data collection -->
|
||||
<string name="preferences_data_collection">Збор дадзеных</string>
|
||||
<!-- Preference linking to the privacy notice -->
|
||||
<string name="preferences_privacy_link">Паведамленне аб прыватнасці</string>
|
||||
<!-- Preference category for developer tools -->
|
||||
<string name="developer_tools_category">Прылады распрацоўшчыка</string>
|
||||
<!-- Preference for add_ons -->
|
||||
<string name="preferences_addons">Дадаткі</string>
|
||||
|
||||
<!-- Account Preferences -->
|
||||
<!-- Preference for triggering sync -->
|
||||
<string name="preferences_sync_now">Сінхранізаваць</string>
|
||||
<!-- Preference category for sync -->
|
||||
<string name="preferences_sync_category">Выберыце, што сінхранізаваць</string>
|
||||
<!-- Preference for syncing history -->
|
||||
<string name="preferences_sync_history">Гісторыю</string>
|
||||
<!-- Preference for syncing bookmarks -->
|
||||
<string name="preferences_sync_bookmarks">Закладкі</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">Лагіны</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">Карткі</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">Выйсці</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
<string name="preferences_sync_device_name">Назва прылады</string>
|
||||
|
||||
<!-- Option in library to open Bookmarks page -->
|
||||
<string name="library_bookmarks">Закладкі</string>
|
||||
<!-- Option in library to open Desktop Bookmarks "menu" page -->
|
||||
<string name="library_desktop_bookmarks_menu">Меню закладак</string>
|
||||
<!-- Option in library to open Desktop Bookmarks "toolbar" page -->
|
||||
<string name="library_desktop_bookmarks_toolbar">Паліца закладак</string>
|
||||
<!-- Option in library to open Desktop Bookmarks "unfiled" page -->
|
||||
<string name="library_desktop_bookmarks_unfiled">Іншыя закладкі</string>
|
||||
<!-- Option in Library to open History page -->
|
||||
<string name="library_history">Гісторыя</string>
|
||||
<!-- Option in Library to open Synced Tabs page -->
|
||||
<string name="library_synced_tabs">Сінхранізаваныя карткі</string>
|
||||
<!-- Option in Library to open Reading List -->
|
||||
<string name="library_reading_list">Спіс для чытання</string>
|
||||
<!-- Menu Item Label for Search in Library -->
|
||||
<string name="library_search">Пошук</string>
|
||||
<!-- Settings Page Title -->
|
||||
<string name="settings_title">Налады</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): "Menu icon for items on a history item" -->
|
||||
<string name="content_description_history_menu">Меню элемента гісторыі</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): "Close button for library settings" -->
|
||||
<string name="content_description_close_button">Закрыць</string>
|
||||
|
||||
<!-- Sessions -->
|
||||
<!-- Title for the list of tabs -->
|
||||
<string name="tab_header_label">Адкрытыя карткі</string>
|
||||
<!-- Title for the list of tabs in the current private session -->
|
||||
<string name="tabs_header_private_title">Прыватны сеанс</string>
|
||||
<!-- Title for the list of tabs in the current private session -->
|
||||
<string name="tabs_header_private_tabs_title">Прыватныя карткі</string>
|
||||
|
||||
<!-- Content description (not visible, for screen readers etc.): Add tab button. Adds a news tab when pressed -->
|
||||
<string name="add_tab">Дадаць картку</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Removes tab from collection button. Removes the selected tab from collection when pressed -->
|
||||
<string name="remove_tab_from_collection">Выдаліць картку з калекцыі</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Close tab button. Closes the current session when pressed -->
|
||||
<string name="close_tab">Закрыць картку</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Close tab <title> button. First parameter is tab title -->
|
||||
<string name="close_tab_title">Закрыць картку %s</string>
|
||||
<!-- Open tabs menu item to close all tabs -->
|
||||
<string name="tabs_menu_close_all_tabs">Закрыць усе карткі</string>
|
||||
<!-- Open tabs menu item to share all tabs -->
|
||||
<string name="tabs_menu_share_tabs">Падзяліцца карткамі</string>
|
||||
<!-- Open tabs menu item to save tabs to collection -->
|
||||
<string name="tabs_menu_save_to_collection">Захаваць у калекцыі</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Opens the tab menu when pressed -->
|
||||
<string name="tab_menu">Меню картак</string>
|
||||
<!-- Tab menu item to share the tab -->
|
||||
<string name="tab_share">Падзяліцца карткай</string>
|
||||
<!-- Button in the current session menu. Deletes the session when pressed -->
|
||||
<string name="current_session_delete">Выдаліць</string>
|
||||
<!-- Button in the current session menu. Saves the session when pressed -->
|
||||
<string name="current_session_save">Захаваць</string>
|
||||
<!-- Button in the current session menu. Opens the share menu when pressed -->
|
||||
<string name="current_session_share">Падзяліцца</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Title icon for current session menu -->
|
||||
<string name="current_session_image">Выява бягучага сеансу</string>
|
||||
<!-- Button to save the current set of tabs into a collection -->
|
||||
<string name="save_to_collection">Захаваць у калекцыі</string>
|
||||
<!-- Text for the menu button to delete a collection -->
|
||||
<string name="collection_delete">Выдаліць калекцыю</string>
|
||||
<!-- Text for the menu button to rename a collection -->
|
||||
<string name="collection_rename">Перайменаваць калекцыю</string>
|
||||
<!-- Text for the button to open tabs of the selected collection -->
|
||||
<string name="collection_open_tabs">Адкрыць карткі</string>
|
||||
<!-- Text for the menu button to remove a top site -->
|
||||
<string name="remove_top_site">Выдаліць</string>
|
||||
|
||||
</resources>
|
|
@ -1416,4 +1416,14 @@
|
|||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Parlate avà</string>
|
||||
|
||||
</resources>
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Cunnettatevi cù un contu Firefox.</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Cunnettate un altru apparechju.</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">Ci vole à autenticassi torna.</string>
|
||||
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
|
||||
<string name="synced_tabs_enable_tab_syncing">Ci vole à attivà a sincrunizazione di l’unghjette.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -96,6 +96,8 @@
|
|||
<string name="browser_menu_add_to_homescreen">Agregar a pantalla de inicio</string>
|
||||
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
|
||||
<string name="browser_menu_install_on_homescreen">Instalar</string>
|
||||
<!-- Menu option on the toolbar that takes you to synced tabs page-->
|
||||
<string name="synced_tabs">Pestañas sincronizadas</string>
|
||||
<!-- Browser menu button that opens the find in page menu -->
|
||||
<string name="browser_menu_find_in_page">Buscar en la página</string>
|
||||
<!-- Browser menu button that creates a private tab -->
|
||||
|
@ -296,6 +298,8 @@
|
|||
<string name="preferences_sync_bookmarks">Marcadores</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">Inicios de sesión</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">Pestañas</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">Cerrar sesión</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
|
@ -436,6 +440,8 @@
|
|||
<string name="library_desktop_bookmarks_unfiled">Otros marcadores</string>
|
||||
<!-- Option in Library to open History page -->
|
||||
<string name="library_history">Historial</string>
|
||||
<!-- Option in Library to open Synced Tabs page -->
|
||||
<string name="library_synced_tabs">Pestañas sincronizadas</string>
|
||||
<!-- Option in Library to open Reading List -->
|
||||
<string name="library_reading_list">Lista de lectura</string>
|
||||
<!-- Menu Item Label for Search in Library -->
|
||||
|
@ -970,6 +976,8 @@
|
|||
<string name="onboarding_tracking_protection_standard_button_description">Bloquea menos rastreadores pero permite que las páginas se carguen correctamente</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_button">Estricta (recomendada)</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_option">Estricto</string>
|
||||
<!-- text for strict blocking option button description -->
|
||||
<string name="onboarding_tracking_protection_strict_button_description">Bloquea más rastreadores para una mejor protección y rendimiento, pero es posible que algunos sitios no se carguen correctamente</string>
|
||||
<!-- text for the toolbar position card header
|
||||
|
@ -1418,4 +1426,15 @@
|
|||
<string name="voice_search_content_description">Búsqueda por voz</string>
|
||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Hablar ahora</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Conectate con una cuenta de Firefox.</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Conectar otro dispositivo.</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">Volver a autenticar.</string>
|
||||
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
|
||||
<string name="synced_tabs_enable_tab_syncing">Habilitar sincronización de pestañas.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -96,6 +96,8 @@
|
|||
<string name="browser_menu_add_to_homescreen">Agregar a la pantalla de Inicio</string>
|
||||
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
|
||||
<string name="browser_menu_install_on_homescreen">Instalar</string>
|
||||
<!-- Menu option on the toolbar that takes you to synced tabs page-->
|
||||
<string name="synced_tabs">Pestañas sincronizadas</string>
|
||||
<!-- Browser menu button that opens the find in page menu -->
|
||||
<string name="browser_menu_find_in_page">Buscar en la página</string>
|
||||
<!-- Browser menu button that creates a private tab -->
|
||||
|
@ -296,6 +298,8 @@
|
|||
<string name="preferences_sync_bookmarks">Marcadores</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">Inicios de sesión</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">Pestañas</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">Cerrar sesión</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
|
@ -433,6 +437,8 @@
|
|||
<string name="library_desktop_bookmarks_unfiled">Otros marcadores</string>
|
||||
<!-- Option in Library to open History page -->
|
||||
<string name="library_history">Historial</string>
|
||||
<!-- Option in Library to open Synced Tabs page -->
|
||||
<string name="library_synced_tabs">Pestañas sincronizadas</string>
|
||||
<!-- Option in Library to open Reading List -->
|
||||
<string name="library_reading_list">Lista de lectura</string>
|
||||
<!-- Menu Item Label for Search in Library -->
|
||||
|
@ -982,6 +988,8 @@
|
|||
<string name="onboarding_tracking_protection_standard_button_description">Bloquea menos rastreadores pero permite que las páginas carguen con normalidad</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_button">Estricta (recomendada)</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_option">Estricto</string>
|
||||
<!-- text for strict blocking option button description -->
|
||||
<string name="onboarding_tracking_protection_strict_button_description">Bloquea más rastreadores para una mejor protección y rendimiento, pero puede hacer que algunos sitios no funcionen correctamente</string>
|
||||
<!-- text for the toolbar position card header
|
||||
|
@ -1432,4 +1440,15 @@
|
|||
<string name="voice_search_content_description">Búsqueda por voz</string>
|
||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Habla ahora</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Conectarse con una cuenta de Firefox.</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Conectar otro dispositivo.</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">Por favor, vuelve a autentificarte.</string>
|
||||
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
|
||||
<string name="synced_tabs_enable_tab_syncing">Por favor, activa la sincronización de pestañas.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<string name="no_private_tabs_description">Yksityiset välilehdet näkyvät tässä.</string>
|
||||
|
||||
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
||||
<string name="about_content">%1$s on Mozillan tekemä.</string>
|
||||
<string name="about_content">%1$s on Mozillan tuote.</string>
|
||||
|
||||
<!-- Private Browsing -->
|
||||
<!-- Title for private session option -->
|
||||
|
@ -1192,7 +1192,7 @@
|
|||
<string name="add_to_homescreen_text_placeholder">Pikakuvakkeen nimi</string>
|
||||
|
||||
<!-- Describes the add to homescreen functionality -->
|
||||
<string name="add_to_homescreen_description">Voit lisätä tämän sivuston puhelimesi kotinäytölle, jolloin sivuston käyttö onnistuu nopeasti ja tarjoaa sovelluksen kaltaisen kokemuksen.</string>
|
||||
<string name="add_to_homescreen_description">Voit lisätä tämän sivuston puhelimesi aloitusnäytölle, jolloin sivuston käyttö onnistuu nopeasti ja tarjoaa sovelluksen kaltaisen kokemuksen.</string>
|
||||
|
||||
<!-- Preference for managing the settings for logins and passwords in Fenix -->
|
||||
<string name="preferences_passwords_logins_and_passwords">Käyttäjätunnukset ja salasanat</string>
|
||||
|
@ -1411,4 +1411,5 @@
|
|||
<string name="voice_search_content_description">Äänihaku</string>
|
||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Puhu nyt</string>
|
||||
</resources>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -96,6 +96,8 @@
|
|||
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
|
||||
<string name="browser_menu_install_on_homescreen">Տեղադրել</string>
|
||||
|
||||
<!-- Menu option on the toolbar that takes you to synced tabs page-->
|
||||
<string name="synced_tabs">Համաժամեցված ներդիրներ</string>
|
||||
<!-- Browser menu button that opens the find in page menu -->
|
||||
<string name="browser_menu_find_in_page">Գտնել էջում</string>
|
||||
<!-- Browser menu button that creates a private tab -->
|
||||
|
@ -291,6 +293,8 @@
|
|||
<string name="preferences_sync_bookmarks">Էջանիշեր</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">Մուտքանուններ</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">Ներդիրներ</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">Դուրս գրվել</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
|
@ -423,6 +427,8 @@
|
|||
<string name="library_desktop_bookmarks_unfiled">Այլ էջանիշեր</string>
|
||||
<!-- Option in Library to open History page -->
|
||||
<string name="library_history">Պատմություն</string>
|
||||
<!-- Option in Library to open Synced Tabs page -->
|
||||
<string name="library_synced_tabs">Համաժամեցված ներդիրներ</string>
|
||||
<!-- Option in Library to open Reading List -->
|
||||
<string name="library_reading_list">Ընթերցացուցակ</string>
|
||||
<!-- Menu Item Label for Search in Library -->
|
||||
|
@ -949,6 +955,8 @@
|
|||
<string name="onboarding_tracking_protection_standard_button_description">Արգելափակում է ավելի քիչ հետագծիչներ, բայց թույլ է տալիս էջերը նորմալ բեռնել</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_button">Խիստ (հանձնարարելի)</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_option">Խիստ</string>
|
||||
<!-- text for strict blocking option button description -->
|
||||
<string name="onboarding_tracking_protection_strict_button_description">Ավելի լավ պաշտպանության և արտադրողականության համար արգելափակում է ավելի շատ հետագծիչներ, բայց կարող է պատճառ դառնալ, որ որոշ կայքեր պատշաճ չաշխատեն</string>
|
||||
<!-- text for the toolbar position card header
|
||||
|
@ -1397,4 +1405,15 @@
|
|||
<string name="voice_search_content_description">Ձայնային որոնում</string>
|
||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Խոսել</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Կապակցել Firefox-ի հաշվով:</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Կապակցել այլ սարքի:</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">Խնդրում ենք վերահաստատել:</string>
|
||||
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
|
||||
<string name="synced_tabs_enable_tab_syncing">Խնդրում ենք միացնել ներդիրի համաժամացումը:</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1440,6 +1440,14 @@
|
|||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Parla ora</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Connetti un account Firefox.</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Connetti un altro dispositivo.</string>
|
||||
</resources>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">Esegui nuovamente l’accesso.</string>
|
||||
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
|
||||
<string name="synced_tabs_enable_tab_syncing">Attiva la sincronizzazione delle schede.</string>
|
||||
|
||||
</resources>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -156,6 +156,9 @@
|
|||
<!-- Text preview for larger sized widgets -->
|
||||
<string name="search_widget_text_long">ຄົ້ນຫາເວັບໄຊທ</string>
|
||||
|
||||
<!-- Content description (not visible, for screen readers etc.): Voice search -->
|
||||
<string name="search_widget_voice">ຄົ້ນຫາດ້ວຍສຽງ</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<!-- Title for the settings page-->
|
||||
<string name="settings">ການຕັ້ງຄ່າ</string>
|
||||
|
@ -165,6 +168,8 @@
|
|||
<string name="preferences_category_general">ທົ່ວໄປ</string>
|
||||
<!-- Preference category for all links about Fenix -->
|
||||
<string name="preferences_category_about">ກ່ຽວກັບ</string>
|
||||
<!-- Preference for settings related to changing the default search engine -->
|
||||
<string name="preferences_default_search_engine">ເຄື່ອງມືການຄົ້ນຫາພື້ນຖານ</string>
|
||||
<!-- Preference for settings related to Search -->
|
||||
<string name="preferences_search">ຄົ້ນຫາ</string>
|
||||
<!-- Preference for settings related to Search address bar -->
|
||||
|
@ -184,6 +189,8 @@
|
|||
<string name="preferences_passwords">ລະຫັດຜ່ານ</string>
|
||||
<!-- Preference for settings related to saved credit cards and addresses -->
|
||||
<string name="preferences_credit_cards_addresses">ບັດເຄດິດ ແລະ ທີ່ຢູ່</string>
|
||||
<!-- Preference for settings related to changing the default browser -->
|
||||
<string name="preferences_set_as_default_browser">ຕັ້ງໃຫ້ເປັນບຣາວເຊີພື້ນຖານ</string>
|
||||
<!-- Preference category for advanced settings -->
|
||||
<string name="preferences_category_advanced">ຂັ້ນສູງ</string>
|
||||
<!-- Preference category for privacy settings -->
|
||||
|
@ -194,6 +201,8 @@
|
|||
<string name="preferences_private_browsing_options">ການທ່ອງເວັບແບບສ່ວນຕົວ</string>
|
||||
<!-- Preference for opening links in a private tab-->
|
||||
<string name="preferences_open_links_in_a_private_tab">ເປີດລີ້ງໃນແທັບສ່ວນຕົວ</string>
|
||||
<!-- Preference for allowing screenshots to be taken while in a private tab-->
|
||||
<string name="preferences_allow_screenshots_in_private_mode">ອະນຸຍາດໃຫ້ຖ່າຍຫນ້າຈໍໃນໂຫມດການທ່ອງເວັບແບບສ່ວນຕົວ</string>
|
||||
<!-- Preference for adding private browsing shortcut -->
|
||||
<string name="preferences_add_private_browsing_shortcut">ເພີ່ມທາງລັດການທ່ອງເວັບແບບສ່ວນຕົວ</string>
|
||||
<!-- Preference for accessibility -->
|
||||
|
@ -208,8 +217,12 @@
|
|||
<string name="preferences_theme">ຊຸດປັບແຕ່ງ</string>
|
||||
<!-- Preference for settings related to visual options -->
|
||||
<string name="preferences_customize">ການປັບແຕ່ງ</string>
|
||||
<!-- Preference description for banner about signing in -->
|
||||
<string name="preferences_sign_in_description">Sync ບຸກມາກ, ປະຫວັດ, ແລະ ອື່ນໆດ້ວຍບັນຊີ Firefox ຂອງທ່ານ</string>
|
||||
<!-- Preference shown instead of account display name while account profile information isn't available yet. -->
|
||||
<string name="preferences_account_default_name">ບັນຊີ Firefox</string>
|
||||
<!-- Preference text for account title when there was an error syncing FxA -->
|
||||
<string name="preferences_account_sync_error">ເຊື່ອມຕໍຄືນເພື່ອເລີ່ມ sync ຄືນໃຫມ່</string>
|
||||
<!-- Preference for language -->
|
||||
<string name="preferences_language">ພາສາ</string>
|
||||
|
||||
|
@ -224,6 +237,10 @@
|
|||
<!-- Preference for developers -->
|
||||
<string name="preferences_remote_debugging">ການດີບັກທາງໄກຜ່ານທາງ USB</string>
|
||||
|
||||
<!-- Preference for account settings -->
|
||||
<string name="preferences_account_settings">ການຕັ້ງຄ່າບັນຊີ</string>
|
||||
<!-- Preference for open links in third party apps -->
|
||||
<string name="preferences_open_links_in_apps">ເປີດລີ້ງໃນແອັບ</string>
|
||||
<!-- Preference for add_ons -->
|
||||
<string name="preferences_addons">Add-ons</string>
|
||||
|
||||
|
@ -238,6 +255,8 @@
|
|||
<string name="preferences_sync_bookmarks">ບຸກມາກ</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">ລັອກອິນ</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">ແທັບ</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">ອອກຈາກລະບົບ</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
<!-- No Open Tabs Message Description -->
|
||||
<string name="no_open_tabs_description">แท็บที่คุณเปิดจะถูกแสดงที่นี่</string>
|
||||
|
||||
<!-- No Private Tabs Message Description -->
|
||||
<string name="no_private_tabs_description">แท็บส่วนตัวของคุณจะถูกแสดงที่นี่</string>
|
||||
|
||||
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
||||
<string name="about_content">%1$s ผลิตขึ้นโดย Mozilla</string>
|
||||
|
||||
|
@ -40,6 +43,14 @@
|
|||
<!-- Text for the negative button -->
|
||||
<string name="cfr_neg_button_text">ไม่ ขอบคุณ</string>
|
||||
|
||||
<!-- Search widget "contextual feature recommendation" (CFR) -->
|
||||
<!-- Text for the main message. 'Firefox' intentionally hardcoded here.-->
|
||||
<string name="search_widget_cfr_message">เข้า Firefox ได้เร็วขึ้นโดยเพิ่มวิดเจ็ตไปยังหน้าจอหลักของคุณ</string>
|
||||
<!-- Text for the positive button -->
|
||||
<string name="search_widget_cfr_pos_button_text">เพิ่มวิดเจ็ต</string>
|
||||
<!-- Text for the negative button -->
|
||||
<string name="search_widget_cfr_neg_button_text">ไม่ใช่ตอนนี้</string>
|
||||
|
||||
<!-- Home screen icons - Long press shortcuts -->
|
||||
<!-- Shortcut action to open new tab -->
|
||||
<string name="home_screen_shortcut_open_new_tab_2">แท็บใหม่</string>
|
||||
|
@ -83,6 +94,8 @@
|
|||
<string name="browser_menu_add_to_homescreen">เพิ่มไปยังหน้าจอหลัก</string>
|
||||
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
|
||||
<string name="browser_menu_install_on_homescreen">ติดตั้ง</string>
|
||||
<!-- Menu option on the toolbar that takes you to synced tabs page-->
|
||||
<string name="synced_tabs">แท็บที่ซิงค์</string>
|
||||
<!-- Browser menu button that opens the find in page menu -->
|
||||
<string name="browser_menu_find_in_page">ค้นหาในหน้า</string>
|
||||
<!-- Browser menu button that creates a private tab -->
|
||||
|
@ -250,6 +263,8 @@
|
|||
<string name="preferences_show_search_shortcuts">แสดงทางลัดการค้นหา</string>
|
||||
<!-- Preference title for switch preference to show search suggestions -->
|
||||
<string name="preferences_show_search_suggestions">แสดงข้อเสนอแนะการค้นหา</string>
|
||||
<!-- Preference title for switch preference to show voice search button -->
|
||||
<string name="preferences_show_voice_search">แสดงการค้นหาด้วยเสียง</string>
|
||||
<!-- Preference title for switch preference to show search suggestions also in private mode -->
|
||||
<string name="preferences_show_search_suggestions_in_private">แสดงในวาระส่วนตัว</string>
|
||||
<!-- Preference title for switch preference to show a clipboard suggestion when searching -->
|
||||
|
@ -277,6 +292,8 @@
|
|||
<string name="preferences_sync_bookmarks">ที่คั่นหน้า</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">การเข้าสู่ระบบ</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">แท็บ</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">ลงชื่อออก</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
|
@ -366,6 +383,9 @@
|
|||
<!-- Preference for removing FxA account -->
|
||||
<string name="preferences_sync_remove_account">เอาบัญชีออก</string>
|
||||
|
||||
<!-- Pairing Feature strings -->
|
||||
<!-- Instructions on how to access pairing -->
|
||||
<string name="pair_instructions_2"><![CDATA[สแกนรหัส QR ที่แสดงใน <b>firefox.com/pair</b>]]></string>
|
||||
<!-- Button to open camera for pairing -->
|
||||
<string name="pair_open_camera">เปิดกล้อง</string>
|
||||
<!-- Button to cancel pairing -->
|
||||
|
@ -406,6 +426,8 @@
|
|||
<string name="library_desktop_bookmarks_unfiled">ที่คั่นหน้าอื่น ๆ</string>
|
||||
<!-- Option in Library to open History page -->
|
||||
<string name="library_history">ประวัติ</string>
|
||||
<!-- Option in Library to open Synced Tabs page -->
|
||||
<string name="library_synced_tabs">แท็บที่ซิงค์</string>
|
||||
<!-- Option in Library to open Reading List -->
|
||||
<string name="library_reading_list">รายการอ่าน</string>
|
||||
<!-- Menu Item Label for Search in Library -->
|
||||
|
@ -426,6 +448,8 @@
|
|||
<string name="tabs_header_private_tabs_title">แท็บส่วนตัว</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Add tab button. Adds a news tab when pressed -->
|
||||
<string name="add_tab">เพิ่มแท็บ</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Removes tab from collection button. Removes the selected tab from collection when pressed -->
|
||||
<string name="remove_tab_from_collection">เอาแท็บออกจากชุดสะสม</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Close tab button. Closes the current session when pressed -->
|
||||
<string name="close_tab">ปิดแท็บ</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Close tab <title> button. First parameter is tab title -->
|
||||
|
@ -798,6 +822,8 @@
|
|||
<!-- Title for Accessibility Text Size Scaling Preference -->
|
||||
<string name="preference_accessibility_font_size_title">ขนาดแบบอักษร</string>
|
||||
|
||||
<!-- Title for Accessibility Text Automatic Size Scaling Preference -->
|
||||
<string name="preference_accessibility_auto_size_2">การปรับขนาดแบบอักษรโดยอัตโนมัติ</string>
|
||||
<!-- Summary for Accessibility Text Automatic Size Scaling Preference -->
|
||||
<string name="preference_accessibility_auto_size_summary">ขนาดแบบอักษรจะตรงกับการตั้งค่า Android ของคุณ ปิดใช้งานเพื่อจัดการขนาดแบบอักษรที่นี่</string>
|
||||
|
||||
|
@ -855,6 +881,9 @@
|
|||
<!-- Text for the snackbar to show the user that the deletion of browsing data is in progress -->
|
||||
<string name="deleting_browsing_data_in_progress">กำลังลบข้อมูลการเรียกดู…</string>
|
||||
|
||||
<!-- Tips -->
|
||||
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
|
||||
<string name="tip_firefox_preview_moved_header">ตอนนี้ Firefox Preview เป็น Firefox Nightly แล้ว</string>
|
||||
<!-- text for firefox preview moving tip description -->
|
||||
<string name="tip_firefox_preview_moved_description">Firefox Nightly อัปเดตทุกคืนและมีลูกเล่นใหม่ ๆ ทุกคืน
|
||||
อย่างไรก็ตามความเสถียรอาจลดลง ดาวน์โหลดเบราว์เซอร์เบต้าของเราเพื่อประสบการณ์ที่เสถียรยิ่งขึ้น</string>
|
||||
|
@ -923,6 +952,8 @@
|
|||
<string name="onboarding_tracking_protection_standard_button_description">ปิดกันตัวติดตามน้อยลง แต่อนุญาตให้โหลดหน้าได้ตามปกติ</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_button">เข้มงวด (แนะนำ)</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_option">เข้มงวด</string>
|
||||
<!-- text for strict blocking option button description -->
|
||||
<string name="onboarding_tracking_protection_strict_button_description">ปิดกันตัวติดตามมากขึ้นเพื่อการปกป้องและประสิทธิภาพที่ดีกว่า แต่ก็อาจทำให้บางไซต์ทำงานไม่สมบูรณ์</string>
|
||||
<!-- text for the toolbar position card header
|
||||
|
@ -1108,6 +1139,8 @@
|
|||
|
||||
<!-- About page link text to open support link -->
|
||||
<string name="about_support">การสนับสนุน</string>
|
||||
<!-- About page link text to list of past crashes (like about:crashes on desktop) -->
|
||||
<string name="about_crashes">ข้อขัดข้อง</string>
|
||||
<!-- About page link text to open privacy notice link -->
|
||||
<string name="about_privacy_notice">ประกาศความเป็นส่วนตัว</string>
|
||||
<!-- About page link text to open know your rights link -->
|
||||
|
@ -1361,4 +1394,9 @@
|
|||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">พูดเลย</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">เชื่อมต่อกับบัญชี Firefox</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">เชื่อมต่ออุปกรณ์อื่น</string>
|
||||
</resources>
|
||||
|
|
|
@ -184,4 +184,88 @@
|
|||
<!-- Title for the settings page-->
|
||||
<string name="settings">Nāgi\'iô\'</string>
|
||||
|
||||
<!-- Preference category for basic settings -->
|
||||
<string name="preferences_category_basics">Dòj sā huāa</string>
|
||||
<!-- Preference category for general settings -->
|
||||
<string name="preferences_category_general">Da\' huā ngej</string>
|
||||
<!-- Preference category for all links about Fenix -->
|
||||
<string name="preferences_category_about">Rayi\'î</string>
|
||||
<!-- Preference for settings related to changing the default search engine -->
|
||||
<string name="preferences_default_search_engine">Sa nana\'ui\' nīka \'na\'</string>
|
||||
<!-- Preference for settings related to Search -->
|
||||
<string name="preferences_search">Nānà\'uì\'</string>
|
||||
|
||||
<!-- Preference for settings related to Search address bar -->
|
||||
<string name="preferences_search_address_bar">Dukuán direksion</string>
|
||||
|
||||
<!-- Preference linking to help about Fenix -->
|
||||
<string name="preferences_help">Sa rugûñu\'ūnj</string>
|
||||
<!-- Preference link to rating Fenix on the Play Store -->
|
||||
<string name="preferences_rate">Nāga\'uì\' du\'uej riña Google Play</string>
|
||||
<!-- Preference for giving feedback about Fenix -->
|
||||
<string name="preferences_feedback">Ga\'uì\' si nūguàn\'t</string>
|
||||
<!-- Preference linking to about page for Fenix
|
||||
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
|
||||
<string name="preferences_about">Rayi\'î %1$s</string>
|
||||
<!-- Preference linking to the your rights SUMO page -->
|
||||
<string name="preferences_your_rights">Sa tna\'uēj Rayi\'ît</string>
|
||||
<!-- Preference for settings related to saved passwords -->
|
||||
<string name="preferences_passwords">Nej da\'nga\' huìi</string>
|
||||
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">Nej rakïj ñaj</string>
|
||||
|
||||
<!-- Text displayed when there are no exceptions, with learn more link that brings users to a tracking protection SUMO page -->
|
||||
<string name="exceptions_empty_message_learn_more_link">Gāhuin chrūn doj</string>
|
||||
|
||||
<!-- Option in Library to open Downloads page -->
|
||||
<string name="library_downloads">Sa nadunïnjt</string>
|
||||
<!-- Menu Item Label for Search in Library -->
|
||||
<string name="library_search">Nānà\'uì\'</string>
|
||||
|
||||
<!-- Content description (not visible, for screen readers etc.): "Close button for library settings" -->
|
||||
<string name="content_description_close_button">Nārán</string>
|
||||
|
||||
<!-- Sessions -->
|
||||
<!-- Title for the list of tabs -->
|
||||
<string name="tab_header_label">Nej Rakïj ñanj huā nî\'nïnj ïn</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Close tab button. Closes the current session when pressed -->
|
||||
<string name="close_tab">Nārán rakïj ñanj</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Close tab <title> button. First parameter is tab title -->
|
||||
<string name="close_tab_title">Nārán rakij ñanj %s</string>
|
||||
|
||||
<!-- Bookmark overflow menu share button -->
|
||||
<string name="bookmark_menu_share_button">Dūyingô\'</string>
|
||||
<!-- Bookmark URL editing field label -->
|
||||
<string name="bookmark_url_label">URL</string>
|
||||
|
||||
<!-- Summary of tracking protection preference if tracking protection is set to on -->
|
||||
<string name="tracking_protection_on">Nāchrūn</string>
|
||||
<!-- Summary of tracking protection preference if tracking protection is set to off -->
|
||||
<string name="tracking_protection_off">Dūnâ\’àj</string>
|
||||
<!-- Summary of delete browsing data on quit preference if it is set to on -->
|
||||
<string name="delete_browsing_data_quit_on">Nāchrūn</string>
|
||||
<!-- Summary of delete browsing data on quit preference if it is set to off -->
|
||||
<string name="delete_browsing_data_quit_off">Dūnâ\’àj</string>
|
||||
|
||||
<!-- Content description (not visible, for screen readers etc.): button to close the collection creator -->
|
||||
<string name="create_collection_close">Nārán</string>
|
||||
|
||||
<!-- Content description (not visible, for screen readers etc.): Close onboarding screen -->
|
||||
<string name="onboarding_close">Nārán</string>
|
||||
|
||||
<!-- Text displayed that links to website about enhanced tracking protection -->
|
||||
<string name="preference_enhanced_tracking_protection_explanation_learn_more">Gāhuin chrūn doj</string>
|
||||
|
||||
<!-- Syncing saved logins in Fenix is on -->
|
||||
<string name="preferences_passwords_sync_logins_on">Nāchrūn</string>
|
||||
<!-- Syncing saved logins in Fenix is off -->
|
||||
<string name="preferences_passwords_sync_logins_off">Dūnâ\’àj</string>
|
||||
|
||||
<!-- Learn more link that will link to a page with more information displayed when a connection is insecure and we detect the user is entering a password -->
|
||||
<string name="logins_insecure_connection_warning_learn_more">Gāhuin chrūn doj</string>
|
||||
|
||||
<!-- Placeholder text shown in the Search Engine Name TextField before a user enters text -->
|
||||
<string name="search_add_custom_engine_name_hint">Si yugui</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
<!-- Text for the negative button -->
|
||||
<string name="cfr_neg_button_text">نہیں شکریہ</string>
|
||||
|
||||
<!-- Text for the negative button -->
|
||||
<string name="search_widget_cfr_neg_button_text">ابھی نہیں</string>
|
||||
|
||||
<!-- Home screen icons - Long press shortcuts -->
|
||||
<!-- Shortcut action to open new tab -->
|
||||
<string name="home_screen_shortcut_open_new_tab_2">نیا ٹیب</string>
|
||||
|
@ -263,6 +266,8 @@
|
|||
<string name="preferences_sync_bookmarks">بک مارکس</string>
|
||||
<!-- Preference for syncing logins -->
|
||||
<string name="preferences_sync_logins">لاگانز</string>
|
||||
<!-- Preference for syncing tabs -->
|
||||
<string name="preferences_sync_tabs">ٹیبس</string>
|
||||
<!-- Preference for signing out -->
|
||||
<string name="preferences_sign_out">سائن آؤٹ</string>
|
||||
<!-- Preference displays and allows changing current FxA device name -->
|
||||
|
@ -788,6 +793,8 @@
|
|||
|
||||
<!-- Title for the Delete browsing data preference -->
|
||||
<string name="preferences_delete_browsing_data">براؤزنگ کا ڈیٹا مٹائیں</string>
|
||||
<!-- Title for the tabs item in Delete browsing data -->
|
||||
<string name="preferences_delete_browsing_data_tabs_title_2">ٹیبز کھولیں</string>
|
||||
<!-- Subtitle for the tabs item in Delete browsing data, parameter will be replaced with the number of open tabs -->
|
||||
<string name="preferences_delete_browsing_data_tabs_subtitle">%d ٹیب</string>
|
||||
<!-- Title for the data and history items in Delete browsing data -->
|
||||
|
@ -882,6 +889,8 @@
|
|||
<string name="onboarding_tracking_protection_standard_button">معیاری</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_button">سخت (سفارش شدا)</string>
|
||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||
<string name="onboarding_tracking_protection_strict_option">سخت</string>
|
||||
<!-- text for the toolbar position card header
|
||||
In English this is an idiom for "choose a side as in an argument or fight"
|
||||
but it is ok to make this more literally about "choosing a position in a physical space -->
|
||||
|
@ -1039,6 +1048,8 @@
|
|||
<!-- About page link text to open support link -->
|
||||
<string name="about_support">معاونت</string>
|
||||
|
||||
<!-- About page link text to list of past crashes (like about:crashes on desktop) -->
|
||||
<string name="about_crashes">کریش</string>
|
||||
<!-- About page link text to open privacy notice link -->
|
||||
<string name="about_privacy_notice">رازداری کا نوٹس</string>
|
||||
<!-- About page link text to open know your rights link -->
|
||||
|
@ -1265,10 +1276,27 @@
|
|||
<string name="login_deletion_confirmation">کیا آپ واقعی اس لاگ ان کو حذف کرنا چاہتے ہیں؟</string>
|
||||
<!-- Positive action of a dialog asking to delete -->
|
||||
<string name="dialog_delete_positive">حذف کریں</string>
|
||||
<!-- The saved login options menu description. -->
|
||||
<string name="login_options_menu">لاگ ان اختیارات</string>
|
||||
<!-- The button description to save changes to an edited login. -->
|
||||
<string name="save_changes_to_login">لاگ ان میں تبدیلیاں محفوظ کریں۔</string>
|
||||
<!-- The button description to discard changes to an edited login. -->
|
||||
<string name="discard_changes">تبدیلیاں ترک کریں</string>
|
||||
<!-- The page title for editing a saved login. -->
|
||||
<string name="edit">تدوین</string>
|
||||
|
||||
<!-- The error message in edit login view when password field is blank. -->
|
||||
<string name="saved_login_password_required">پاس ورڈ کی درکار</string>
|
||||
<!-- Voice search button content description -->
|
||||
<string name="voice_search_content_description">آواز سے تلاش</string>
|
||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">اب بولیں</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Firefox اکاؤنٹس کے ساتھ جوڑیں۔</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">ایک اور آلہ جوڑیں۔</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">برائے مہربانی دوبارہ توثیق کریں۔</string>
|
||||
</resources>
|
||||
|
|
|
@ -6,36 +6,33 @@ package org.mozilla.fenix.settings.quicksettings
|
|||
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDirections
|
||||
import io.mockk.MockKMatcherScope
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.slot
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyOrder
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.TestCoroutineScope
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions.Status.NO_DECISION
|
||||
import mozilla.components.feature.tabs.TabsUseCases
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertSame
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.components.PermissionStorage
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||
import org.mozilla.fenix.settings.toggle
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
|
@ -53,7 +50,7 @@ class DefaultQuickSettingsControllerTest {
|
|||
private val requestPermissions = mockk<(Array<String>) -> Unit>(relaxed = true)
|
||||
private val displayPermissions = mockk<() -> Unit>(relaxed = true)
|
||||
private val dismiss = mockk<() -> Unit>(relaxed = true)
|
||||
private val controller = DefaultQuickSettingsController(
|
||||
private val controller = spyk(DefaultQuickSettingsController(
|
||||
context = context,
|
||||
quickSettingsStore = store,
|
||||
coroutineScope = coroutinesScope,
|
||||
|
@ -67,7 +64,7 @@ class DefaultQuickSettingsControllerTest {
|
|||
requestRuntimePermissions = requestPermissions,
|
||||
displayPermissions = displayPermissions,
|
||||
dismiss = dismiss
|
||||
)
|
||||
))
|
||||
|
||||
@Test
|
||||
fun `handlePermissionsShown should delegate to an injected parameter`() {
|
||||
|
@ -81,58 +78,42 @@ class DefaultQuickSettingsControllerTest {
|
|||
@Test
|
||||
fun `handlePermissionToggled blocked by Android should handleAndroidPermissionRequest`() {
|
||||
val cameraFeature = PhoneFeature.CAMERA
|
||||
val websitePermission = mockk<WebsitePermission.Camera>()
|
||||
val androidPermissions = slot<Array<String>>()
|
||||
val websitePermission = mockk<WebsitePermission>()
|
||||
every { websitePermission.phoneFeature } returns cameraFeature
|
||||
every { websitePermission.isBlockedByAndroid } returns true
|
||||
|
||||
controller.handlePermissionToggled(websitePermission)
|
||||
|
||||
verify {
|
||||
controller.handleAndroidPermissionRequest(capture(androidPermissions))
|
||||
controller.handleAndroidPermissionRequest(eqArray(cameraFeature.androidPermissionsList))
|
||||
}
|
||||
|
||||
assertTrue(androidPermissions.isCaptured)
|
||||
assertArrayEquals(cameraFeature.androidPermissionsList, androidPermissions.captured)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Disabling because of intermittent failures https://github.com/mozilla-mobile/fenix/issues/8621")
|
||||
fun `handlePermissionToggled allowed by Android should toggle the permissions and modify View's state`() {
|
||||
val permissionName = "CAMERA"
|
||||
val websitePermission = mockk<WebsitePermission.Camera>()
|
||||
val toggledFeature = slot<PhoneFeature>()
|
||||
val action = slot<WebsitePermissionAction>()
|
||||
val websitePermission = mockk<WebsitePermission>()
|
||||
every { websitePermission.phoneFeature } returns PhoneFeature.CAMERA
|
||||
every { websitePermission.isBlockedByAndroid } returns false
|
||||
every { websitePermission.name } returns permissionName
|
||||
every { store.dispatch(any()) } returns mockk()
|
||||
// For using the SitePermissions.toggle(..) extension method we need a static mock of SitePermissions.
|
||||
mockkStatic("org.mozilla.fenix.settings.ExtensionsKt")
|
||||
|
||||
controller.handlePermissionToggled(websitePermission)
|
||||
|
||||
// We want to verify that the Status is toggled and this event is passed to Controller also.
|
||||
assertSame(NO_DECISION, sitePermissions.camera)
|
||||
verifyOrder {
|
||||
val permission = sitePermissions.toggle(capture(toggledFeature))
|
||||
controller.handlePermissionsChange(permission)
|
||||
verify {
|
||||
controller.handlePermissionsChange(sitePermissions.toggle(PhoneFeature.CAMERA))
|
||||
}
|
||||
// We should also modify View's state. Not necessarily as the last operation.
|
||||
verify {
|
||||
store.dispatch(capture(action))
|
||||
store.dispatch(match { action ->
|
||||
PhoneFeature.CAMERA == (action as WebsitePermissionAction.TogglePermission).updatedFeature
|
||||
})
|
||||
}
|
||||
|
||||
assertTrue(toggledFeature.isCaptured)
|
||||
assertSame(PhoneFeature.CAMERA, toggledFeature.captured)
|
||||
|
||||
assertTrue(action.isCaptured)
|
||||
assertEquals(WebsitePermissionAction.TogglePermission::class, action.captured::class)
|
||||
assertEquals(websitePermission::class,
|
||||
(action.captured as WebsitePermissionAction.TogglePermission).websitePermission::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handlePermissionToggled blocked by user should navigate to site permission manager`() {
|
||||
val websitePermission = mockk<WebsitePermission.Camera>()
|
||||
val websitePermission = mockk<WebsitePermission>()
|
||||
val invalidSitePermissionsController = DefaultQuickSettingsController(
|
||||
context = context,
|
||||
quickSettingsStore = store,
|
||||
|
@ -149,6 +130,7 @@ class DefaultQuickSettingsControllerTest {
|
|||
dismiss = dismiss
|
||||
)
|
||||
|
||||
every { websitePermission.phoneFeature } returns PhoneFeature.CAMERA
|
||||
every { websitePermission.isBlockedByAndroid } returns false
|
||||
every { navController.navigate(any<NavDirections>()) } just Runs
|
||||
|
||||
|
@ -162,88 +144,44 @@ class DefaultQuickSettingsControllerTest {
|
|||
@Test
|
||||
fun `handleAndroidPermissionGranted should update the View's state`() {
|
||||
val featureGranted = PhoneFeature.CAMERA
|
||||
val permission = with(controller) {
|
||||
featureGranted.getCorrespondingPermission()
|
||||
}
|
||||
val permissionStatus = featureGranted.getActionLabel(context, sitePermissions, appSettings)
|
||||
val permissionEnabled =
|
||||
featureGranted.shouldBeEnabled(context, sitePermissions, appSettings)
|
||||
val action = slot<QuickSettingsFragmentAction>()
|
||||
val permissionEnabled = featureGranted.shouldBeEnabled(context, sitePermissions, appSettings)
|
||||
every { store.dispatch(any()) } returns mockk()
|
||||
|
||||
controller.handleAndroidPermissionGranted(featureGranted)
|
||||
|
||||
verify {
|
||||
store.dispatch(capture(action))
|
||||
store.dispatch(withArg { action ->
|
||||
action as WebsitePermissionAction.TogglePermission
|
||||
assertEquals(featureGranted, action.updatedFeature)
|
||||
assertEquals(permissionStatus, action.updatedStatus)
|
||||
assertEquals(permissionEnabled, action.updatedEnabledStatus)
|
||||
})
|
||||
}
|
||||
|
||||
assertTrue(action.isCaptured)
|
||||
assertEquals(WebsitePermissionAction.TogglePermission::class, action.captured::class)
|
||||
assertEquals(permission, (action.captured as WebsitePermissionAction.TogglePermission).websitePermission)
|
||||
assertEquals(permissionStatus, (action.captured as WebsitePermissionAction.TogglePermission).updatedStatus)
|
||||
assertEquals(permissionEnabled, (action.captured as WebsitePermissionAction.TogglePermission).updatedEnabledStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handleAndroidPermissionRequest should request from the injected callback`() {
|
||||
val testPermissions = arrayOf("TestPermission")
|
||||
val requiredPermissions = slot<Array<String>>()
|
||||
// every { requestPermissions(capture(requiredPermissions)) } just Runs
|
||||
|
||||
controller.handleAndroidPermissionRequest(testPermissions)
|
||||
|
||||
verify { requestPermissions(capture(requiredPermissions)) }
|
||||
|
||||
assertTrue(requiredPermissions.isCaptured)
|
||||
assertArrayEquals(testPermissions, requiredPermissions.captured)
|
||||
verify { requestPermissions(eqArray(testPermissions)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExperimentalCoroutinesApi
|
||||
@Ignore("Intermittently failing; https://github.com/mozilla-mobile/fenix/issues/8621")
|
||||
fun `handlePermissionsChange should store the updated permission and reload webpage`() =
|
||||
runBlocking {
|
||||
val testPermissions = mockk<SitePermissions>()
|
||||
val permissions = slot<SitePermissions>()
|
||||
val session = slot<Session>()
|
||||
fun `handlePermissionsChange should store the updated permission and reload webpage`() = coroutinesScope.runBlockingTest {
|
||||
val testPermissions = mockk<SitePermissions>()
|
||||
|
||||
controller.handlePermissionsChange(testPermissions)
|
||||
controller.handlePermissionsChange(testPermissions)
|
||||
|
||||
verifyOrder {
|
||||
permissionStorage.updateSitePermissions(capture(permissions))
|
||||
reload(capture(session))
|
||||
}
|
||||
|
||||
assertTrue(permissions.isCaptured)
|
||||
assertEquals(testPermissions, permissions.captured)
|
||||
assertTrue(session.isCaptured)
|
||||
assertEquals(browserSession, session.captured)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WebsitePermission#getBackingFeature should return the PhoneFeature this permission is mapped from`() {
|
||||
val cameraPermission = mockk<WebsitePermission.Camera>()
|
||||
val microphonePermission = mockk<WebsitePermission.Microphone>()
|
||||
val notificationPermission = mockk<WebsitePermission.Notification>()
|
||||
val locationPermission = mockk<WebsitePermission.Location>()
|
||||
|
||||
with(controller) {
|
||||
assertSame(PhoneFeature.CAMERA, cameraPermission.getBackingFeature())
|
||||
assertSame(PhoneFeature.MICROPHONE, microphonePermission.getBackingFeature())
|
||||
assertSame(PhoneFeature.NOTIFICATION, notificationPermission.getBackingFeature())
|
||||
assertSame(PhoneFeature.LOCATION, locationPermission.getBackingFeature())
|
||||
verifyOrder {
|
||||
permissionStorage.updateSitePermissions(testPermissions)
|
||||
reload(browserSession)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `PhoneFeature#getCorrespondingPermission should return the WebsitePermission which it maps to`() {
|
||||
with(controller) {
|
||||
assertEquals(WebsitePermission.Camera::class, PhoneFeature.CAMERA.getCorrespondingPermission()::class)
|
||||
assertEquals(WebsitePermission.Microphone::class, PhoneFeature.MICROPHONE.getCorrespondingPermission()::class)
|
||||
assertEquals(WebsitePermission.Notification::class, PhoneFeature.NOTIFICATION.getCorrespondingPermission()::class)
|
||||
assertEquals(WebsitePermission.Location::class, PhoneFeature.LOCATION.getCorrespondingPermission()::class)
|
||||
assertEquals(WebsitePermission.AutoplayAudible::class, PhoneFeature.AUTOPLAY_AUDIBLE.getCorrespondingPermission()::class)
|
||||
assertEquals(WebsitePermission.AutoplayInaudible::class, PhoneFeature.AUTOPLAY_INAUDIBLE.getCorrespondingPermission()::class)
|
||||
}
|
||||
}
|
||||
private inline fun <reified T> MockKMatcherScope.eqArray(value: Array<T>): Array<T> =
|
||||
match { it contentEquals value }
|
||||
}
|
||||
|
|
|
@ -24,9 +24,6 @@ import org.junit.runner.RunWith
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.getInsecureWebsiteUiValues
|
||||
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.getPermissionStatus
|
||||
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.getSecuredWebsiteUiValues
|
||||
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.toWebsitePermission
|
||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeVisible
|
||||
|
@ -38,12 +35,6 @@ class QuickSettingsFragmentStoreTest {
|
|||
private val context = spyk(testContext)
|
||||
private val permissions = mockk<SitePermissions>()
|
||||
private val appSettings = mockk<Settings>()
|
||||
private val secureStringRes = R.string.quick_settings_sheet_secure_connection
|
||||
private val secureDrawableRes = R.drawable.mozac_ic_lock
|
||||
private val secureColorRes = R.color.photonGreen50
|
||||
private val insecureStringRes = R.string.quick_settings_sheet_insecure_connection
|
||||
private val insecureDrawableRes = R.drawable.mozac_ic_globe
|
||||
private val insecureColorRes = R.color.photonRed50
|
||||
|
||||
@Test
|
||||
fun `createStore constructs a QuickSettingsFragmentState`() {
|
||||
|
@ -72,9 +63,7 @@ class QuickSettingsFragmentStoreTest {
|
|||
assertNotNull(state)
|
||||
assertSame(websiteUrl, state.websiteUrl)
|
||||
assertSame(websiteTitle, state.websiteTitle)
|
||||
assertEquals(secureStringRes, state.securityInfoRes)
|
||||
assertEquals(secureDrawableRes, state.iconRes)
|
||||
assertEquals(secureColorRes, state.iconTintRes)
|
||||
assertEquals(WebsiteSecurityUiValues.SECURE, state.websiteSecurityUiValues)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -89,9 +78,7 @@ class QuickSettingsFragmentStoreTest {
|
|||
assertNotNull(state)
|
||||
assertSame(websiteUrl, state.websiteUrl)
|
||||
assertSame(websiteTitle, state.websiteTitle)
|
||||
assertEquals(insecureStringRes, state.securityInfoRes)
|
||||
assertEquals(insecureDrawableRes, state.iconRes)
|
||||
assertEquals(insecureColorRes, state.iconTintRes)
|
||||
assertEquals(WebsiteSecurityUiValues.INSECURE, state.websiteSecurityUiValues)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -118,12 +105,12 @@ class QuickSettingsFragmentStoreTest {
|
|||
// Just need to know that the WebsitePermissionsState properties are initialized.
|
||||
// Making sure they are correctly initialized is tested in the `initWebsitePermission` test.
|
||||
assertNotNull(state)
|
||||
assertNotNull(state.camera)
|
||||
assertNotNull(state.microphone)
|
||||
assertNotNull(state.notification)
|
||||
assertNotNull(state.location)
|
||||
assertNotNull(state.autoplayAudible)
|
||||
assertNotNull(state.autoplayInaudible)
|
||||
assertNotNull(state[PhoneFeature.CAMERA])
|
||||
assertNotNull(state[PhoneFeature.MICROPHONE])
|
||||
assertNotNull(state[PhoneFeature.NOTIFICATION])
|
||||
assertNotNull(state[PhoneFeature.LOCATION])
|
||||
assertNotNull(state[PhoneFeature.AUTOPLAY_AUDIBLE])
|
||||
assertNotNull(state[PhoneFeature.AUTOPLAY_INAUDIBLE])
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,7 +129,7 @@ class QuickSettingsFragmentStoreTest {
|
|||
val websitePermission = cameraFeature.toWebsitePermission(context, permissions, appSettings)
|
||||
|
||||
assertNotNull(websitePermission)
|
||||
assertEquals(WebsitePermission.Camera::class, websitePermission::class)
|
||||
assertEquals(cameraFeature, websitePermission.phoneFeature)
|
||||
assertEquals(allowedStatus, websitePermission.status)
|
||||
assertTrue(websitePermission.isVisible)
|
||||
assertTrue(websitePermission.isEnabled)
|
||||
|
@ -154,7 +141,7 @@ class QuickSettingsFragmentStoreTest {
|
|||
val phoneFeature = PhoneFeature.CAMERA
|
||||
every { permissions.camera } returns SitePermissions.Status.NO_DECISION
|
||||
|
||||
val permissionsStatus = phoneFeature.getPermissionStatus(context, permissions, appSettings)
|
||||
val permissionsStatus = phoneFeature.toWebsitePermission(context, permissions, appSettings)
|
||||
|
||||
verify {
|
||||
// Verifying phoneFeature.getActionLabel gets "Status(child of #2#4).ordinal()) was not called"
|
||||
|
@ -174,12 +161,6 @@ class QuickSettingsFragmentStoreTest {
|
|||
@ExperimentalCoroutinesApi
|
||||
fun `TogglePermission should only modify status and visibility of a specific WebsitePermissionsState`() =
|
||||
runBlocking {
|
||||
val cameraPermissionName = "Camera"
|
||||
val microphonePermissionName = "Microphone"
|
||||
val notificationPermissionName = "Notification"
|
||||
val locationPermissionName = "Location"
|
||||
val autoplayAudiblePermissionName = "AutoplayAudible"
|
||||
val autoplayInaudiblePermissionName = "AutoplayInaudible"
|
||||
val initialCameraStatus = "initialCameraStatus"
|
||||
val initialMicStatus = "initialMicStatus"
|
||||
val initialNotificationStatus = "initialNotificationStatus"
|
||||
|
@ -192,31 +173,37 @@ class QuickSettingsFragmentStoreTest {
|
|||
val defaultEnabledStatus = true
|
||||
val defaultBlockedByAndroidStatus = true
|
||||
val websiteInfoState = mockk<WebsiteInfoState>()
|
||||
val initialWebsitePermissionsState = WebsitePermissionsState(
|
||||
val baseWebsitePermission = WebsitePermission(
|
||||
phoneFeature = PhoneFeature.CAMERA,
|
||||
status = "",
|
||||
isVisible = true,
|
||||
camera = WebsitePermission.Camera(
|
||||
initialCameraStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, cameraPermissionName
|
||||
isEnabled = true,
|
||||
isBlockedByAndroid = true
|
||||
)
|
||||
val initialWebsitePermissionsState = mapOf(
|
||||
PhoneFeature.CAMERA to baseWebsitePermission.copy(
|
||||
phoneFeature = PhoneFeature.CAMERA,
|
||||
status = initialCameraStatus
|
||||
),
|
||||
microphone = WebsitePermission.Microphone(
|
||||
initialMicStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, microphonePermissionName
|
||||
PhoneFeature.MICROPHONE to baseWebsitePermission.copy(
|
||||
phoneFeature = PhoneFeature.MICROPHONE,
|
||||
status = initialMicStatus
|
||||
),
|
||||
notification = WebsitePermission.Notification(
|
||||
initialNotificationStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, notificationPermissionName
|
||||
PhoneFeature.NOTIFICATION to baseWebsitePermission.copy(
|
||||
phoneFeature = PhoneFeature.NOTIFICATION,
|
||||
status = initialNotificationStatus
|
||||
),
|
||||
location = WebsitePermission.Location(
|
||||
initialLocationStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, locationPermissionName
|
||||
PhoneFeature.LOCATION to baseWebsitePermission.copy(
|
||||
phoneFeature = PhoneFeature.LOCATION,
|
||||
status = initialLocationStatus
|
||||
),
|
||||
autoplayAudible = WebsitePermission.AutoplayAudible(
|
||||
initialAutoplayAudibleStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, autoplayAudiblePermissionName
|
||||
PhoneFeature.AUTOPLAY_AUDIBLE to baseWebsitePermission.copy(
|
||||
phoneFeature = PhoneFeature.AUTOPLAY_AUDIBLE,
|
||||
status = initialAutoplayAudibleStatus
|
||||
),
|
||||
autoplayInaudible = WebsitePermission.AutoplayInaudible(
|
||||
initialAutoplayInaudibleStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, autoplayInaudiblePermissionName
|
||||
PhoneFeature.AUTOPLAY_INAUDIBLE to baseWebsitePermission.copy(
|
||||
phoneFeature = PhoneFeature.AUTOPLAY_INAUDIBLE,
|
||||
status = initialAutoplayInaudibleStatus
|
||||
)
|
||||
)
|
||||
val initialState = QuickSettingsFragmentState(
|
||||
|
@ -226,7 +213,7 @@ class QuickSettingsFragmentStoreTest {
|
|||
|
||||
store.dispatch(
|
||||
WebsitePermissionAction.TogglePermission(
|
||||
mockk<WebsitePermission.Microphone>(),
|
||||
PhoneFeature.MICROPHONE,
|
||||
updatedMicrophoneStatus,
|
||||
updatedMicrophoneEnabledStatus
|
||||
)
|
||||
|
@ -237,53 +224,35 @@ class QuickSettingsFragmentStoreTest {
|
|||
assertNotSame(initialWebsitePermissionsState, store.state.websitePermissionsState)
|
||||
assertSame(websiteInfoState, store.state.webInfoState)
|
||||
|
||||
assertNotNull(store.state.websitePermissionsState.camera)
|
||||
assertEquals(cameraPermissionName, (store.state.websitePermissionsState.camera as WebsitePermission.Camera).name)
|
||||
assertEquals(initialCameraStatus, store.state.websitePermissionsState.camera.status)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.camera.isVisible)
|
||||
assertEquals(defaultEnabledStatus, store.state.websitePermissionsState.camera.isEnabled)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.camera.isBlockedByAndroid)
|
||||
assertNotNull(store.state.websitePermissionsState[PhoneFeature.CAMERA])
|
||||
assertEquals(PhoneFeature.CAMERA, store.state.websitePermissionsState.getValue(PhoneFeature.CAMERA).phoneFeature)
|
||||
assertEquals(initialCameraStatus, store.state.websitePermissionsState.getValue(PhoneFeature.CAMERA).status)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.getValue(PhoneFeature.CAMERA).isVisible)
|
||||
assertEquals(defaultEnabledStatus, store.state.websitePermissionsState.getValue(PhoneFeature.CAMERA).isEnabled)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.getValue(PhoneFeature.CAMERA).isBlockedByAndroid)
|
||||
|
||||
assertNotNull(store.state.websitePermissionsState.microphone)
|
||||
assertEquals(microphonePermissionName, (store.state.websitePermissionsState.microphone as WebsitePermission.Microphone).name)
|
||||
assertNotNull(store.state.websitePermissionsState[PhoneFeature.MICROPHONE])
|
||||
assertEquals(PhoneFeature.MICROPHONE, store.state.websitePermissionsState.getValue(PhoneFeature.MICROPHONE).phoneFeature)
|
||||
|
||||
// Only the following two properties must have been changed!
|
||||
assertEquals(updatedMicrophoneStatus, store.state.websitePermissionsState.microphone.status)
|
||||
assertEquals(updatedMicrophoneEnabledStatus, store.state.websitePermissionsState.microphone.isEnabled)
|
||||
assertEquals(updatedMicrophoneStatus, store.state.websitePermissionsState.getValue(PhoneFeature.MICROPHONE).status)
|
||||
assertEquals(updatedMicrophoneEnabledStatus, store.state.websitePermissionsState.getValue(PhoneFeature.MICROPHONE).isEnabled)
|
||||
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.microphone.isVisible)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.microphone.isBlockedByAndroid)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.getValue(PhoneFeature.MICROPHONE).isVisible)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.getValue(PhoneFeature.MICROPHONE).isBlockedByAndroid)
|
||||
|
||||
assertNotNull(store.state.websitePermissionsState.notification)
|
||||
assertEquals(notificationPermissionName, (store.state.websitePermissionsState.notification as WebsitePermission.Notification).name)
|
||||
assertEquals(initialNotificationStatus, store.state.websitePermissionsState.notification.status)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.notification.isVisible)
|
||||
assertEquals(defaultEnabledStatus, store.state.websitePermissionsState.notification.isEnabled)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.notification.isBlockedByAndroid)
|
||||
assertNotNull(store.state.websitePermissionsState[PhoneFeature.NOTIFICATION])
|
||||
assertEquals(PhoneFeature.NOTIFICATION, store.state.websitePermissionsState.getValue(PhoneFeature.NOTIFICATION).phoneFeature)
|
||||
assertEquals(initialNotificationStatus, store.state.websitePermissionsState.getValue(PhoneFeature.NOTIFICATION).status)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.getValue(PhoneFeature.NOTIFICATION).isVisible)
|
||||
assertEquals(defaultEnabledStatus, store.state.websitePermissionsState.getValue(PhoneFeature.NOTIFICATION).isEnabled)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.getValue(PhoneFeature.NOTIFICATION).isBlockedByAndroid)
|
||||
|
||||
assertNotNull(store.state.websitePermissionsState.location)
|
||||
assertEquals(locationPermissionName, (store.state.websitePermissionsState.location as WebsitePermission.Location).name)
|
||||
assertEquals(initialLocationStatus, store.state.websitePermissionsState.location.status)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.location.isVisible)
|
||||
assertEquals(defaultEnabledStatus, store.state.websitePermissionsState.location.isEnabled)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.location.isBlockedByAndroid)
|
||||
assertNotNull(store.state.websitePermissionsState[PhoneFeature.LOCATION])
|
||||
assertEquals(PhoneFeature.LOCATION, store.state.websitePermissionsState.getValue(PhoneFeature.LOCATION).phoneFeature)
|
||||
assertEquals(initialLocationStatus, store.state.websitePermissionsState.getValue(PhoneFeature.LOCATION).status)
|
||||
assertEquals(defaultVisibilityStatus, store.state.websitePermissionsState.getValue(PhoneFeature.LOCATION).isVisible)
|
||||
assertEquals(defaultEnabledStatus, store.state.websitePermissionsState.getValue(PhoneFeature.LOCATION).isEnabled)
|
||||
assertEquals(defaultBlockedByAndroidStatus, store.state.websitePermissionsState.getValue(PhoneFeature.LOCATION).isBlockedByAndroid)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getSecuredWebsiteUiValues() should return the right values`() {
|
||||
val uiValues = getSecuredWebsiteUiValues
|
||||
|
||||
assertEquals(secureStringRes, uiValues.first)
|
||||
assertEquals(secureDrawableRes, uiValues.second)
|
||||
assertEquals(secureColorRes, uiValues.third)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getInsecureWebsiteUiValues() should return the right values`() {
|
||||
val uiValues = getInsecureWebsiteUiValues
|
||||
|
||||
assertEquals(insecureStringRes, uiValues.first)
|
||||
assertEquals(insecureDrawableRes, uiValues.second)
|
||||
assertEquals(insecureColorRes, uiValues.third)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
object AndroidComponents {
|
||||
const val VERSION = "45.0.20200605130045"
|
||||
const val VERSION = "45.0.20200607130045"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue