[fenix] 8017 advanced autoplay controls. (https://github.com/mozilla-mobile/fenix/pull/8978)
* For https://github.com/mozilla-mobile/fenix/issues/8017: add advanced autoplay controlspull/600/head
parent
1be0825abe
commit
a0193296bf
@ -0,0 +1,14 @@
|
||||
package org.mozilla.fenix.utils;
|
||||
|
||||
/**
|
||||
* Functional interface for listening to when wifi is/is not connected.
|
||||
*
|
||||
* This is not a () -> Boolean so that method parameters can be more clearly typed.
|
||||
*
|
||||
* This file is in Java because of the SAM conversion problem in Kotlin.
|
||||
* See https://youtrack.jetbrains.com/issue/KT-7770.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface OnWifiChanged {
|
||||
void invoke(boolean Connected);
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/* 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.wifi
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkRequest
|
||||
|
||||
/**
|
||||
* Attaches itself to the [Application] and listens for WIFI available/not available events. This
|
||||
* allows calling code to set simpler listeners.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* app.components.wifiConnectionListener.addOnWifiConnectedChangedListener { isConnected ->
|
||||
* if (isConnected) {
|
||||
* downloadThing()
|
||||
* }
|
||||
* }
|
||||
* app.components.wifiConnectionListener.start()
|
||||
* ```
|
||||
*/
|
||||
class WifiConnectionMonitor(app: Application) {
|
||||
private val callbacks = mutableSetOf<(Boolean) -> Unit>()
|
||||
private val connectivityManager = app.getSystemService(Context.CONNECTIVITY_SERVICE) as
|
||||
ConnectivityManager
|
||||
|
||||
private var lastKnownStateWasAvailable: Boolean? = null
|
||||
private var isRegistered = false
|
||||
|
||||
private val frameworkListener = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onLost(network: Network?) {
|
||||
callbacks.forEach { it(false) }
|
||||
lastKnownStateWasAvailable = false
|
||||
}
|
||||
|
||||
override fun onAvailable(network: Network?) {
|
||||
callbacks.forEach { it(true) }
|
||||
lastKnownStateWasAvailable = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the [WifiConnectionMonitor] to the application. After this has been called, callbacks
|
||||
* added via [addOnWifiConnectedChangedListener] will be called until either the app exits, or
|
||||
* [stop] is called.
|
||||
*
|
||||
* Any existing callbacks will be called with the current state when this is called.
|
||||
*/
|
||||
fun start() {
|
||||
// Framework code throws if a listener is registered twice without unregistering.
|
||||
if (isRegistered) return
|
||||
val request = NetworkRequest.Builder()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
.build()
|
||||
|
||||
// AFAICT, the framework does not send an event when a new NetworkCallback is registered
|
||||
// while the WIFI is not connected, so we push this manually. If the WIFI is on, it will send
|
||||
// a follow up event shortly
|
||||
val noCallbacksReceivedYet = lastKnownStateWasAvailable == null
|
||||
if (noCallbacksReceivedYet) {
|
||||
lastKnownStateWasAvailable = false
|
||||
callbacks.forEach { it(false) }
|
||||
}
|
||||
|
||||
connectivityManager.registerNetworkCallback(request, frameworkListener)
|
||||
isRegistered = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Detatches the [WifiConnectionMonitor] from the app. No callbacks added via
|
||||
* [addOnWifiConnectedChangedListener] will be called after this has been called.
|
||||
*/
|
||||
fun stop() {
|
||||
// Framework code will throw if an unregistered listener attempts to unregister.
|
||||
if (!isRegistered) return
|
||||
connectivityManager.unregisterNetworkCallback(frameworkListener)
|
||||
isRegistered = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds [onWifiChanged] to a list of listeners that will be called whenever WIFI connects or
|
||||
* disconnects.
|
||||
*
|
||||
* If [onWifiChanged] is successfully added (i.e., it is a new listener), it will be immediately
|
||||
* called with the last known state.
|
||||
*/
|
||||
fun addOnWifiConnectedChangedListener(onWifiChanged: (Boolean) -> Unit) {
|
||||
val lastKnownState = lastKnownStateWasAvailable
|
||||
if (callbacks.add(onWifiChanged) && lastKnownState != null) {
|
||||
onWifiChanged(lastKnownState)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes [onWifiChanged] from the list of listeners to be called whenever WIFI connects or
|
||||
* disconnects.
|
||||
*/
|
||||
fun removeOnWifiConnectedChangedListener(onWifiChanged: (Boolean) -> Unit) {
|
||||
callbacks.remove(onWifiChanged)
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/* 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.wifi
|
||||
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_ALLOW_ON_WIFI
|
||||
import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
/**
|
||||
* Handles implementation details of only setting up a WIFI connectivity listener if the current
|
||||
* user settings require it.
|
||||
*/
|
||||
class WifiIntegration(private val settings: Settings, private val wifiConnectionMonitor: WifiConnectionMonitor) {
|
||||
|
||||
/**
|
||||
* Adds listener for autplay setting [AUTOPLAY_ALLOW_ON_WIFI]. Sets all autoplay to allowed when
|
||||
* WIFI is connected, blocked otherwise.
|
||||
*/
|
||||
private val wifiConnectedListener: ((Boolean) -> Unit) by lazy {
|
||||
{ connected: Boolean ->
|
||||
val setting =
|
||||
if (connected) SitePermissionsRules.Action.ALLOWED else SitePermissionsRules.Action.BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.AUTOPLAY_AUDIBLE, setting)
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.AUTOPLAY_INAUDIBLE, setting)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If autoplay is only enabled on WIFI, sets a WIFI listener to set them accordingly. Otherwise
|
||||
* noop.
|
||||
*/
|
||||
fun maybeAddWifiConnectedListener() {
|
||||
if (settings.getAutoplayUserSetting(default = AUTOPLAY_BLOCK_ALL) == AUTOPLAY_ALLOW_ON_WIFI) {
|
||||
addWifiConnectedListener()
|
||||
}
|
||||
}
|
||||
|
||||
fun addWifiConnectedListener() {
|
||||
wifiConnectionMonitor.addOnWifiConnectedChangedListener(wifiConnectedListener)
|
||||
}
|
||||
|
||||
fun removeWifiConnectedListener() {
|
||||
wifiConnectionMonitor.removeOnWifiConnectedChangedListener(wifiConnectedListener)
|
||||
}
|
||||
|
||||
// Until https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed, AUTOPLAY_ALLOW_ALL
|
||||
// only works while WIFI is active, so we are not using AUTOPLAY_ALLOW_ON_WIFI (or this class).
|
||||
// Once that is fixed, [start] and [maybeAddWifiConnectedListener] will need to be called on
|
||||
// activity startup.
|
||||
fun start() { wifiConnectionMonitor.start() }
|
||||
|
||||
fun stop() { wifiConnectionMonitor.stop() }
|
||||
}
|
Loading…
Reference in New Issue