TunnelEditorFragment: add hooks for biometric auth
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									2337fe37be
								
							
						
					
					
						commit
						d44a83faaa
					
				| @ -6,6 +6,8 @@ package com.wireguard.android.databinding | ||||
| 
 | ||||
| import android.text.InputFilter | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.widget.EditText | ||||
| import android.widget.LinearLayout | ||||
| import android.widget.TextView | ||||
| import androidx.databinding.BindingAdapter | ||||
| @ -13,6 +15,7 @@ import androidx.databinding.DataBindingUtil | ||||
| import androidx.databinding.ObservableList | ||||
| import androidx.databinding.ViewDataBinding | ||||
| import androidx.databinding.adapters.ListenerUtil | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.wireguard.android.BR | ||||
| @ -41,10 +44,10 @@ object BindingAdapters { | ||||
|     } | ||||
| 
 | ||||
|     @JvmStatic | ||||
|     @BindingAdapter("items", "layout") | ||||
|     @BindingAdapter("items", "layout", "fragment") | ||||
|     fun <E> setItems(view: LinearLayout, | ||||
|                      oldList: ObservableList<E>?, oldLayoutId: Int, | ||||
|                      newList: ObservableList<E>?, newLayoutId: Int) { | ||||
|                      oldList: ObservableList<E>?, oldLayoutId: Int, @Suppress("UNUSED_PARAMETER") oldFragment: Fragment?, | ||||
|                      newList: ObservableList<E>?, newLayoutId: Int, newFragment: Fragment?) { | ||||
|         if (oldList === newList && oldLayoutId == newLayoutId) | ||||
|             return | ||||
|         var listener: ItemChangeListener<E>? = ListenerUtil.getListener(view, R.id.item_change_listener) | ||||
| @ -59,7 +62,7 @@ object BindingAdapters { | ||||
|         if (newList == null || newLayoutId == 0) | ||||
|             return | ||||
|         if (listener == null) { | ||||
|             listener = ItemChangeListener(view, newLayoutId) | ||||
|             listener = ItemChangeListener(view, newLayoutId, newFragment) | ||||
|             ListenerUtil.trackListener(view, listener, R.id.item_change_listener) | ||||
|         } | ||||
|         // Either the list changed, or this is an entirely new listener because the layout changed. | ||||
| @ -123,6 +126,13 @@ object BindingAdapters { | ||||
|         view.setOnBeforeCheckedChangeListener(listener) | ||||
|     } | ||||
| 
 | ||||
|     @JvmStatic | ||||
|     @BindingAdapter("onFocusChange") | ||||
|     fun setOnFocusChange(view: EditText, | ||||
|                          listener: View.OnFocusChangeListener?) { | ||||
|         view.setOnFocusChangeListener(listener) | ||||
|     } | ||||
| 
 | ||||
|     @JvmStatic | ||||
|     @BindingAdapter("android:text") | ||||
|     fun setText(view: TextView, text: Optional<*>) { | ||||
|  | ||||
| @ -10,13 +10,14 @@ import android.view.ViewGroup | ||||
| import androidx.databinding.DataBindingUtil | ||||
| import androidx.databinding.ObservableList | ||||
| import androidx.databinding.ViewDataBinding | ||||
| import androidx.fragment.app.Fragment | ||||
| import com.wireguard.android.BR | ||||
| import java.lang.ref.WeakReference | ||||
| 
 | ||||
| /** | ||||
|  * Helper class for binding an ObservableList to the children of a ViewGroup. | ||||
|  */ | ||||
| internal class ItemChangeListener<T>(private val container: ViewGroup, private val layoutId: Int) { | ||||
| internal class ItemChangeListener<T>(private val container: ViewGroup, private val layoutId: Int, private val fragment: Fragment?) { | ||||
|     private val callback = OnListChangedCallback(this) | ||||
|     private val layoutInflater: LayoutInflater = LayoutInflater.from(container.context) | ||||
|     private var list: ObservableList<T>? = null | ||||
| @ -29,6 +30,7 @@ internal class ItemChangeListener<T>(private val container: ViewGroup, private v | ||||
|         require(list != null) { "Trying to get a view while list is still null" } | ||||
|         binding!!.setVariable(BR.collection, list) | ||||
|         binding.setVariable(BR.item, list!![position]) | ||||
|         binding.setVariable(BR.fragment, fragment) | ||||
|         binding.executePendingBindings() | ||||
|         return binding.root | ||||
|     } | ||||
|  | ||||
| @ -6,6 +6,7 @@ package com.wireguard.android.fragment | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.os.Bundle | ||||
| import android.text.InputType | ||||
| import android.util.Log | ||||
| import android.view.LayoutInflater | ||||
| import android.view.Menu | ||||
| @ -15,9 +16,9 @@ import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.view.WindowManager | ||||
| import android.view.inputmethod.InputMethodManager | ||||
| import android.widget.EditText | ||||
| import android.widget.Toast | ||||
| import com.google.android.material.snackbar.Snackbar | ||||
| import com.google.android.material.textfield.TextInputLayout | ||||
| import com.wireguard.android.Application | ||||
| import com.wireguard.android.R | ||||
| import com.wireguard.android.backend.Tunnel | ||||
| @ -34,6 +35,7 @@ import com.wireguard.config.Config | ||||
|  * Fragment for editing a WireGuard configuration. | ||||
|  */ | ||||
| class TunnelEditorFragment : BaseFragment(), AppExclusionListener { | ||||
|     private var haveShownKeys = false | ||||
|     private var binding: TunnelEditorFragmentBinding? = null | ||||
|     private var tunnel: ObservableTunnel? = null | ||||
|     private fun onConfigLoaded(config: Config) { | ||||
| @ -76,7 +78,6 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { | ||||
|             setUpScrollingContent(mainContainer, null) | ||||
|             privateKeyTextLayout.setEndIconOnClickListener { config?.`interface`?.generateKeyPair() } | ||||
|         } | ||||
|         requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) | ||||
|         return binding?.root | ||||
|     } | ||||
| 
 | ||||
| @ -226,6 +227,23 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { | ||||
|         super.onViewStateRestored(savedInstanceState) | ||||
|     } | ||||
| 
 | ||||
|     fun onKeyClick(view: View) = onKeyFocusChange(view, true) | ||||
| 
 | ||||
|     fun onKeyFocusChange(view: View, isFocused: Boolean) { | ||||
|         if (!isFocused) return | ||||
|         val edit = view as? EditText ?: return | ||||
|         if (!haveShownKeys && edit.text.isNotEmpty()) { | ||||
|             if (true /* TODO: do biometric auth prompt */) { | ||||
|                 haveShownKeys = true | ||||
|             } else { | ||||
|                 /* Unauthorized, so return and don't change visibility. */ | ||||
|                 return | ||||
|             } | ||||
|         } | ||||
|         requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) | ||||
|         edit.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val KEY_LOCAL_CONFIG = "local_config" | ||||
|         private const val KEY_ORIGINAL_NAME = "original_name" | ||||
|  | ||||
| @ -102,9 +102,11 @@ | ||||
|                                 android:id="@+id/private_key_text" | ||||
|                                 android:layout_width="match_parent" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:inputType="textNoSuggestions|textVisiblePassword" | ||||
|                                 android:inputType="textNoSuggestions|textPassword" | ||||
|                                 android:onClick="@{fragment::onKeyClick}" | ||||
|                                 android:text="@={config.interface.privateKey}" | ||||
|                                 app:filter="@{KeyInputFilter.newInstance()}" /> | ||||
|                                 app:filter="@{KeyInputFilter.newInstance()}" | ||||
|                                 app:onFocusChange="@{fragment::onKeyFocusChange}" /> | ||||
|                         </com.google.android.material.textfield.TextInputLayout> | ||||
| 
 | ||||
|                         <com.google.android.material.textfield.TextInputLayout | ||||
| @ -234,6 +236,7 @@ | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:divider="@null" | ||||
|                     android:orientation="vertical" | ||||
|                     app:fragment="@{fragment}" | ||||
|                     app:items="@{config.peers}" | ||||
|                     app:layout="@{@layout/tunnel_editor_peer}" | ||||
|                     tools:ignore="UselessLeaf" /> | ||||
|  | ||||
| @ -15,6 +15,10 @@ | ||||
|         <variable | ||||
|             name="item" | ||||
|             type="com.wireguard.android.viewmodel.PeerProxy" /> | ||||
| 
 | ||||
|         <variable | ||||
|             name="fragment" | ||||
|             type="com.wireguard.android.fragment.TunnelEditorFragment" /> | ||||
|     </data> | ||||
| 
 | ||||
|     <com.google.android.material.card.MaterialCardView | ||||
| @ -91,8 +95,11 @@ | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:hint="@string/hint_optional" | ||||
|                     android:inputType="textNoSuggestions|textVisiblePassword" | ||||
|                     android:text="@={item.preSharedKey}" /> | ||||
|                     android:inputType="textNoSuggestions|textPassword" | ||||
|                     android:onClick="@{fragment::onKeyClick}" | ||||
|                     android:text="@={item.preSharedKey}" | ||||
|                     app:filter="@{KeyInputFilter.newInstance()}" | ||||
|                     app:onFocusChange="@{fragment::onKeyFocusChange}" /> | ||||
|             </com.google.android.material.textfield.TextInputLayout> | ||||
| 
 | ||||
|             <com.google.android.material.textfield.TextInputLayout | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user