@ -7,7 +7,6 @@ import android.app.Application
import android.app.Notification
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationChannel
import android.app.PendingIntent
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.content.IntentFilter
import android.content.IntentFilter
@ -37,11 +36,6 @@ import com.tailscale.ipn.ui.viewModel.VpnViewModel
import com.tailscale.ipn.ui.viewModel.VpnViewModelFactory
import com.tailscale.ipn.ui.viewModel.VpnViewModelFactory
import com.tailscale.ipn.util.FeatureFlags
import com.tailscale.ipn.util.FeatureFlags
import com.tailscale.ipn.util.TSLog
import com.tailscale.ipn.util.TSLog
import java.io.File
import java.io.IOException
import java.net.NetworkInterface
import java.security.GeneralSecurityException
import java.util.Locale
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.SupervisorJob
@ -53,6 +47,11 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.Json
import libtailscale.Libtailscale
import libtailscale.Libtailscale
import java.io.File
import java.io.IOException
import java.net.NetworkInterface
import java.security.GeneralSecurityException
import java.util.Locale
class App : UninitializedApp ( ) , libtailscale . AppContext , ViewModelStoreOwner {
class App : UninitializedApp ( ) , libtailscale . AppContext , ViewModelStoreOwner {
val applicationScope = CoroutineScope ( SupervisorJob ( ) + Dispatchers . Default )
val applicationScope = CoroutineScope ( SupervisorJob ( ) + Dispatchers . Default )
@ -470,25 +469,15 @@ open class UninitializedApp : Application() {
}
}
fun restartVPN ( ) {
fun restartVPN ( ) {
// Register a receiver to listen for the completion of stopVPN
val intent =
val stopReceiver =
Intent ( this , IPNService :: class . java ) . apply { action = IPNService . ACTION _RESTART _VPN }
object : BroadcastReceiver ( ) {
try {
override fun onReceive ( context : Context ? , intent : Intent ? ) {
startService ( intent )
// Ensure stop intent is complete
} catch ( illegalStateException : IllegalStateException ) {
if ( intent ?. action == IPNService . ACTION _STOP _VPN ) {
TSLog . e ( TAG , " restartVPN hit IllegalStateException in startService(): $illegalStateException " )
// Unregister receiver after receiving the broadcast
} catch ( e : Exception ) {
context ?. unregisterReceiver ( this )
TSLog . e ( TAG , " restartVPN hit exception in startService(): $e " )
// Now start the VPN
}
startVPN ( )
}
}
}
// Register the receiver before stopping VPN
val intentFilter = IntentFilter ( IPNService . ACTION _STOP _VPN )
this . registerReceiver ( stopReceiver , intentFilter , Context . RECEIVER _NOT _EXPORTED )
stopVPN ( )
}
}
fun createNotificationChannel ( id : String , name : String , description : String , importance : Int ) {
fun createNotificationChannel ( id : String , name : String , description : String , importance : Int ) {
@ -569,33 +558,13 @@ open class UninitializedApp : Application() {
return builder . build ( )
return builder . build ( )
}
}
fun addUserDisallowedPackageName ( packageName : String ) {
fun updateUserDisallowedPackageNames ( packageNames : List < String > ) {
if ( packageName . isEmpty ( ) ) {
if ( packageNames . any { it . isEmpty ( ) } ) {
TSLog . e ( TAG , " addUserDisallowedPackageName called with empty packageName " )
TSLog . e ( TAG , " updateUserDisallowedPackageNames called with empty packageName(s) " )
return
}
getUnencryptedPrefs ( )
. edit ( )
. putStringSet (
DISALLOWED _APPS _KEY , disallowedPackageNames ( ) . toMutableSet ( ) . union ( setOf ( packageName ) ) )
. apply ( )
this . restartVPN ( )
}
fun removeUserDisallowedPackageName ( packageName : String ) {
if ( packageName . isEmpty ( ) ) {
TSLog . e ( TAG , " removeUserDisallowedPackageName called with empty packageName " )
return
return
}
}
getUnencryptedPrefs ( )
getUnencryptedPrefs ( ) . edit ( ) . putStringSet ( DISALLOWED _APPS _KEY , packageNames . toSet ( ) ) . apply ( )
. edit ( )
. putStringSet (
DISALLOWED _APPS _KEY ,
disallowedPackageNames ( ) . toMutableSet ( ) . subtract ( setOf ( packageName ) ) )
. apply ( )
this . restartVPN ( )
this . restartVPN ( )
}
}