Use FLAG_SECURE for sensitive screens such as encrypted chat rooms
This commit is contained in:
parent
c86b548fa9
commit
31bbc9a4d5
13 changed files with 118 additions and 20 deletions
|
@ -25,12 +25,12 @@ import android.os.Bundle
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.databinding.AboutFragmentBinding
|
||||
import org.linphone.utils.AppUtils
|
||||
|
||||
class AboutFragment : GenericFragment<AboutFragmentBinding>() {
|
||||
class AboutFragment : SecureFragment<AboutFragmentBinding>() {
|
||||
private lateinit var viewModel: AboutViewModel
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.about_fragment
|
||||
|
|
|
@ -26,15 +26,15 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.main.chat.adapters.ChatRoomCreationContactsAdapter
|
||||
import org.linphone.activities.main.chat.viewmodels.ChatRoomCreationViewModel
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.core.Address
|
||||
import org.linphone.databinding.ChatRoomCreationFragmentBinding
|
||||
|
||||
class ChatRoomCreationFragment : GenericFragment<ChatRoomCreationFragmentBinding>() {
|
||||
class ChatRoomCreationFragment : SecureFragment<ChatRoomCreationFragmentBinding>() {
|
||||
private lateinit var viewModel: ChatRoomCreationViewModel
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
private lateinit var adapter: ChatRoomCreationContactsAdapter
|
||||
|
|
|
@ -95,6 +95,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
val chatRoom = sharedViewModel.selectedChatRoom.value
|
||||
chatRoom ?: return
|
||||
chatRoomAddress = chatRoom.peerAddress.asStringUriOnly()
|
||||
isSecure = chatRoom.currentParams.encryptionEnabled()
|
||||
|
||||
viewModel = ViewModelProvider(
|
||||
this,
|
||||
|
|
|
@ -23,13 +23,13 @@ import android.os.Bundle
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.chat.viewmodels.DevicesListViewModel
|
||||
import org.linphone.activities.main.chat.viewmodels.DevicesListViewModelFactory
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.databinding.ChatRoomDevicesFragmentBinding
|
||||
|
||||
class DevicesFragment : GenericFragment<ChatRoomDevicesFragmentBinding>() {
|
||||
class DevicesFragment : SecureFragment<ChatRoomDevicesFragmentBinding>() {
|
||||
private lateinit var listViewModel: DevicesListViewModel
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
|
@ -47,6 +47,8 @@ class DevicesFragment : GenericFragment<ChatRoomDevicesFragmentBinding>() {
|
|||
val chatRoom = sharedViewModel.selectedChatRoom.value
|
||||
chatRoom ?: return
|
||||
|
||||
isSecure = chatRoom.currentParams.encryptionEnabled()
|
||||
|
||||
listViewModel = ViewModelProvider(
|
||||
this,
|
||||
DevicesListViewModelFactory(chatRoom)
|
||||
|
|
|
@ -23,13 +23,13 @@ import android.os.Bundle
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.chat.viewmodels.EphemeralViewModel
|
||||
import org.linphone.activities.main.chat.viewmodels.EphemeralViewModelFactory
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.databinding.ChatRoomEphemeralFragmentBinding
|
||||
|
||||
class EphemeralFragment : GenericFragment<ChatRoomEphemeralFragmentBinding>() {
|
||||
class EphemeralFragment : SecureFragment<ChatRoomEphemeralFragmentBinding>() {
|
||||
private lateinit var viewModel: EphemeralViewModel
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
|
@ -40,6 +40,7 @@ class EphemeralFragment : GenericFragment<ChatRoomEphemeralFragmentBinding>() {
|
|||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
isSecure = true
|
||||
binding.lifecycleOwner = this
|
||||
|
||||
sharedViewModel = activity?.run {
|
||||
|
|
|
@ -26,12 +26,12 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.main.chat.GroupChatRoomMember
|
||||
import org.linphone.activities.main.chat.adapters.GroupInfoParticipantsAdapter
|
||||
import org.linphone.activities.main.chat.viewmodels.GroupInfoViewModel
|
||||
import org.linphone.activities.main.chat.viewmodels.GroupInfoViewModelFactory
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.core.Address
|
||||
|
@ -40,7 +40,7 @@ import org.linphone.core.ChatRoomCapabilities
|
|||
import org.linphone.databinding.ChatRoomGroupInfoFragmentBinding
|
||||
import org.linphone.utils.DialogUtils
|
||||
|
||||
class GroupInfoFragment : GenericFragment<ChatRoomGroupInfoFragmentBinding>() {
|
||||
class GroupInfoFragment : SecureFragment<ChatRoomGroupInfoFragmentBinding>() {
|
||||
private lateinit var viewModel: GroupInfoViewModel
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
private lateinit var adapter: GroupInfoParticipantsAdapter
|
||||
|
@ -58,6 +58,7 @@ class GroupInfoFragment : GenericFragment<ChatRoomGroupInfoFragmentBinding>() {
|
|||
} ?: throw Exception("Invalid Activity")
|
||||
|
||||
val chatRoom: ChatRoom? = sharedViewModel.selectedGroupChatRoom.value
|
||||
isSecure = chatRoom?.currentParams?.encryptionEnabled() ?: false
|
||||
|
||||
viewModel = ViewModelProvider(
|
||||
this,
|
||||
|
|
|
@ -25,16 +25,16 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.chat.adapters.ImdnAdapter
|
||||
import org.linphone.activities.main.chat.viewmodels.ImdnViewModel
|
||||
import org.linphone.activities.main.chat.viewmodels.ImdnViewModelFactory
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.ChatRoomImdnFragmentBinding
|
||||
import org.linphone.utils.RecyclerViewHeaderDecoration
|
||||
|
||||
class ImdnFragment : GenericFragment<ChatRoomImdnFragmentBinding>() {
|
||||
class ImdnFragment : SecureFragment<ChatRoomImdnFragmentBinding>() {
|
||||
private lateinit var viewModel: ImdnViewModel
|
||||
private lateinit var adapter: ImdnAdapter
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
@ -55,6 +55,8 @@ class ImdnFragment : GenericFragment<ChatRoomImdnFragmentBinding>() {
|
|||
val chatRoom = sharedViewModel.selectedChatRoom.value
|
||||
chatRoom ?: return
|
||||
|
||||
isSecure = chatRoom.currentParams.encryptionEnabled()
|
||||
|
||||
if (arguments != null) {
|
||||
val messageId = arguments?.getString("MessageId")
|
||||
val message = if (messageId != null) chatRoom.findMessage(messageId) else null
|
||||
|
|
|
@ -71,6 +71,7 @@ class MasterChatRoomsFragment : MasterFragment<ChatRoomMasterFragmentBinding, Ch
|
|||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
isSecure = true
|
||||
binding.lifecycleOwner = this
|
||||
|
||||
listViewModel = ViewModelProvider(this).get(ChatRoomsListViewModel::class.java)
|
||||
|
|
|
@ -33,9 +33,9 @@ import org.linphone.BuildConfig
|
|||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.main.dialer.viewmodels.DialerViewModel
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.core.tools.Log
|
||||
|
@ -43,7 +43,7 @@ import org.linphone.databinding.DialerFragmentBinding
|
|||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
|
||||
class DialerFragment : GenericFragment<DialerFragmentBinding>() {
|
||||
class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
||||
private lateinit var viewModel: DialerViewModel
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import android.os.Bundle
|
|||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.main.viewmodels.ListTopBarViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
|
@ -35,7 +34,7 @@ import org.linphone.utils.SelectionListAdapter
|
|||
* This fragment can be inherited by all fragments that will display a list
|
||||
* where items can be selected for removal through the ListTopBarFragment
|
||||
*/
|
||||
abstract class MasterFragment<T : ViewDataBinding, U : SelectionListAdapter<*, *>> : GenericFragment<T>() {
|
||||
abstract class MasterFragment<T : ViewDataBinding, U : SelectionListAdapter<*, *>> : SecureFragment<T>() {
|
||||
protected var _adapter: U? = null
|
||||
protected val adapter get() = _adapter!!
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.activities.main.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
abstract class SecureFragment<T : ViewDataBinding> : GenericFragment<T>() {
|
||||
protected var isSecure: Boolean = false
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
// Assume we might want to be secure to prevent quick visible blink while screen recording.
|
||||
enableSecureMode(true)
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
if (isSecure) {
|
||||
enableSecureMode(isSecure)
|
||||
} else {
|
||||
// This is a workaround to prevent a small blink showing the previous secured screen
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
delay(200)
|
||||
enableSecureMode(isSecure)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
private fun enableSecureMode(enable: Boolean) {
|
||||
Log.d("[Secure Fragment] ${if (enable) "Enabling" else "Disabling"} secure flag on window")
|
||||
val window = requireActivity().window
|
||||
val windowManager = requireActivity().windowManager
|
||||
|
||||
val flags: Int = window.attributes.flags
|
||||
if ((enable && flags and WindowManager.LayoutParams.FLAG_SECURE != 0) ||
|
||||
(!enable && flags and WindowManager.LayoutParams.FLAG_SECURE == 0)) {
|
||||
Log.d("[Secure Fragment] Secure flag is already ${if (enable) "enabled" else "disabled"}, skipping...")
|
||||
return
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
}
|
||||
|
||||
if (ViewCompat.isAttachedToWindow(window.decorView)) {
|
||||
Log.d("[Secure Fragment] Redrawing window decorView to apply flag")
|
||||
windowManager.updateViewLayout(window.decorView, window.attributes)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,8 +23,8 @@ import android.os.Bundle
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.*
|
||||
import org.linphone.activities.main.fragments.SecureFragment
|
||||
import org.linphone.activities.main.navigateToAccountSettings
|
||||
import org.linphone.activities.main.navigateToAudioSettings
|
||||
import org.linphone.activities.main.navigateToTunnelSettings
|
||||
|
@ -34,7 +34,7 @@ import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
|||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.SettingsFragmentBinding
|
||||
|
||||
class SettingsFragment : GenericFragment<SettingsFragmentBinding>() {
|
||||
class SettingsFragment : SecureFragment<SettingsFragmentBinding>() {
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
private lateinit var viewModel: SettingsViewModel
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/backgroundColor">
|
||||
|
||||
</LinearLayout>
|
Loading…
Reference in a new issue