Commits:
-
8e9aca94
by Titouan Thibaud at 2024-05-13T09:31:35+02:00
Bug 1885171 - set private keyboard on _javascript_ prompts in private browsing r=android-reviewers,boek
Differential Revision: https://phabricator.services.mozilla.com/D208135
3 changed files:
Changes:
android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt
... |
... |
@@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.map |
17
|
17
|
import mozilla.components.browser.state.action.ContentAction
|
18
|
18
|
import mozilla.components.browser.state.selector.findTabOrCustomTab
|
19
|
19
|
import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
|
|
20
|
+import mozilla.components.browser.state.selector.selectedTab
|
20
|
21
|
import mozilla.components.browser.state.state.SessionState
|
21
|
22
|
import mozilla.components.browser.state.store.BrowserStore
|
22
|
23
|
import mozilla.components.concept.engine.prompt.Choice
|
... |
... |
@@ -772,6 +773,7 @@ class PromptFeature private constructor( |
772
|
773
|
inputLabel,
|
773
|
774
|
inputValue,
|
774
|
775
|
promptAbuserDetector.areDialogsBeingAbused(),
|
|
776
|
+ store.state.selectedTab?.content?.private == true,
|
775
|
777
|
)
|
776
|
778
|
}
|
777
|
779
|
}
|
android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragment.kt
... |
... |
@@ -11,14 +11,17 @@ import android.os.Bundle |
11
|
11
|
import android.text.Editable
|
12
|
12
|
import android.text.TextWatcher
|
13
|
13
|
import android.view.LayoutInflater
|
|
14
|
+import android.view.inputmethod.EditorInfo.IME_NULL
|
14
|
15
|
import android.widget.EditText
|
15
|
16
|
import android.widget.TextView
|
16
|
17
|
import androidx.appcompat.app.AlertDialog
|
|
18
|
+import androidx.core.view.inputmethod.EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING
|
17
|
19
|
import mozilla.components.feature.prompts.R
|
18
|
20
|
|
19
|
21
|
private const val KEY_USER_EDIT_TEXT = "KEY_USER_EDIT_TEXT"
|
20
|
22
|
private const val KEY_LABEL_INPUT = "KEY_LABEL_INPUT"
|
21
|
23
|
private const val KEY_DEFAULT_INPUT_VALUE = "KEY_DEFAULT_INPUT_VALUE"
|
|
24
|
+private const val KEY_PRIVATE = "KEY_PRIVATE"
|
22
|
25
|
|
23
|
26
|
/**
|
24
|
27
|
* [androidx.fragment.app.DialogFragment] implementation to display a
|
... |
... |
@@ -37,6 +40,11 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te |
37
|
40
|
*/
|
38
|
41
|
internal val labelInput: String? by lazy { safeArguments.getString(KEY_LABEL_INPUT) }
|
39
|
42
|
|
|
43
|
+ /**
|
|
44
|
+ * Tells if the Dialog is shown from private browsing
|
|
45
|
+ */
|
|
46
|
+ internal val private: Boolean? by lazy { safeArguments.getBoolean(KEY_PRIVATE) }
|
|
47
|
+
|
40
|
48
|
private var userSelectionEditText: String
|
41
|
49
|
get() = safeArguments.getString(KEY_USER_EDIT_TEXT, defaultInputValue)
|
42
|
50
|
set(value) {
|
... |
... |
@@ -72,6 +80,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te |
72
|
80
|
label.text = labelInput
|
73
|
81
|
editText.setText(defaultInputValue)
|
74
|
82
|
editText.addTextChangedListener(this)
|
|
83
|
+ editText.imeOptions = if (private == true) IME_FLAG_NO_PERSONALIZED_LEARNING else IME_NULL
|
75
|
84
|
|
76
|
85
|
addCheckBoxIfNeeded(view)
|
77
|
86
|
|
... |
... |
@@ -99,6 +108,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te |
99
|
108
|
* @param hasShownManyDialogs tells if this [sessionId] has shown many dialogs
|
100
|
109
|
* in a short period of time, if is true a checkbox will be part of the dialog, for the user
|
101
|
110
|
* to choose if wants to prevent this [sessionId] continuing showing dialogs.
|
|
111
|
+ * @param private tells if this dialog is triggered from private browsing
|
102
|
112
|
*/
|
103
|
113
|
@Suppress("LongParameterList")
|
104
|
114
|
fun newInstance(
|
... |
... |
@@ -109,6 +119,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te |
109
|
119
|
inputLabel: String,
|
110
|
120
|
defaultInputValue: String,
|
111
|
121
|
hasShownManyDialogs: Boolean,
|
|
122
|
+ private: Boolean,
|
112
|
123
|
): TextPromptDialogFragment {
|
113
|
124
|
val fragment = TextPromptDialogFragment()
|
114
|
125
|
val arguments = fragment.arguments ?: Bundle()
|
... |
... |
@@ -121,6 +132,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te |
121
|
132
|
putString(KEY_LABEL_INPUT, inputLabel)
|
122
|
133
|
putString(KEY_DEFAULT_INPUT_VALUE, defaultInputValue)
|
123
|
134
|
putBoolean(KEY_MANY_ALERTS, hasShownManyDialogs)
|
|
135
|
+ putBoolean(KEY_PRIVATE, private)
|
124
|
136
|
}
|
125
|
137
|
|
126
|
138
|
fragment.arguments = arguments
|
android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragmentTest.kt
... |
... |
@@ -6,9 +6,11 @@ package mozilla.components.feature.prompts.dialog |
6
|
6
|
|
7
|
7
|
import android.content.DialogInterface.BUTTON_POSITIVE
|
8
|
8
|
import android.os.Looper.getMainLooper
|
|
9
|
+import android.view.inputmethod.EditorInfo.IME_NULL
|
9
|
10
|
import android.widget.CheckBox
|
10
|
11
|
import android.widget.TextView
|
11
|
12
|
import androidx.appcompat.app.AlertDialog
|
|
13
|
+import androidx.core.view.inputmethod.EditorInfoCompat
|
12
|
14
|
import androidx.core.view.isVisible
|
13
|
15
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
14
|
16
|
import mozilla.components.feature.prompts.R.id
|
... |
... |
@@ -41,7 +43,7 @@ class TextPromptDialogFragmentTest { |
41
|
43
|
@Test
|
42
|
44
|
fun `build dialog`() {
|
43
|
45
|
val fragment = spy(
|
44
|
|
- TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true),
|
|
46
|
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true, false),
|
45
|
47
|
)
|
46
|
48
|
|
47
|
49
|
doReturn(appCompatContext).`when`(fragment).requireContext()
|
... |
... |
@@ -73,12 +75,14 @@ class TextPromptDialogFragmentTest { |
73
|
75
|
|
74
|
76
|
inputValue.text = "NewValue"
|
75
|
77
|
assertEquals(inputValue.text.toString(), "NewValue")
|
|
78
|
+
|
|
79
|
+ assertEquals(IME_NULL, inputValue.imeOptions)
|
76
|
80
|
}
|
77
|
81
|
|
78
|
82
|
@Test
|
79
|
83
|
fun `TextPrompt with hasShownManyDialogs equals false should not have a checkbox`() {
|
80
|
84
|
val fragment = spy(
|
81
|
|
- TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", false),
|
|
85
|
+ TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", false, false),
|
82
|
86
|
)
|
83
|
87
|
|
84
|
88
|
doReturn(appCompatContext).`when`(fragment).requireContext()
|
... |
... |
@@ -95,7 +99,7 @@ class TextPromptDialogFragmentTest { |
95
|
99
|
@Test
|
96
|
100
|
fun `Clicking on positive button notifies the feature`() {
|
97
|
101
|
val fragment = spy(
|
98
|
|
- TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", false),
|
|
102
|
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", false, false),
|
99
|
103
|
)
|
100
|
104
|
|
101
|
105
|
fragment.feature = mockFeature
|
... |
... |
@@ -115,7 +119,7 @@ class TextPromptDialogFragmentTest { |
115
|
119
|
@Test
|
116
|
120
|
fun `After checking no more dialogs checkbox feature onNoMoreDialogsChecked must be called`() {
|
117
|
121
|
val fragment = spy(
|
118
|
|
- TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", true),
|
|
122
|
+ TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", true, false),
|
119
|
123
|
)
|
120
|
124
|
|
121
|
125
|
fragment.feature = mockFeature
|
... |
... |
@@ -139,7 +143,7 @@ class TextPromptDialogFragmentTest { |
139
|
143
|
@Test
|
140
|
144
|
fun `touching outside of the dialog must notify the feature onCancel`() {
|
141
|
145
|
val fragment = spy(
|
142
|
|
- TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true),
|
|
146
|
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true, false),
|
143
|
147
|
)
|
144
|
148
|
|
145
|
149
|
fragment.feature = mockFeature
|
... |
... |
@@ -150,4 +154,19 @@ class TextPromptDialogFragmentTest { |
150
|
154
|
|
151
|
155
|
verify(mockFeature).onCancel("sessionId", "uid")
|
152
|
156
|
}
|
|
157
|
+
|
|
158
|
+ @Test
|
|
159
|
+ fun `when TextPromptDialogFragment is created in private mode then keyboard is in private mode`() {
|
|
160
|
+ val fragment = spy(
|
|
161
|
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true, true),
|
|
162
|
+ )
|
|
163
|
+
|
|
164
|
+ fragment.feature = mockFeature
|
|
165
|
+ doReturn(appCompatContext).`when`(fragment).requireContext()
|
|
166
|
+
|
|
167
|
+ val dialog = fragment.onCreateDialog(null).also { it.show() }
|
|
168
|
+ val editText = dialog.findViewById<TextView>(id.input_value)
|
|
169
|
+
|
|
170
|
+ assertEquals(EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING, editText.imeOptions)
|
|
171
|
+ }
|
153
|
172
|
} |
|