Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
The Tor Project
Applications
android-components
Commits
a861537a
Commit
a861537a
authored
Aug 19, 2020
by
ekager
Browse files
For #7134 - Adds login selection to prompt feature
parent
3d471434
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt
View file @
a861537a
...
...
@@ -8,17 +8,18 @@ import android.content.Context
import
android.net.Uri
import
androidx.annotation.VisibleForTesting
import
mozilla.components.browser.engine.gecko.GeckoEngineSession
import
mozilla.components.concept.storage.Login
import
mozilla.components.concept.engine.prompt.Choice
import
mozilla.components.concept.engine.prompt.PromptRequest
import
mozilla.components.concept.engine.prompt.PromptRequest.MenuChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice
import
mozilla.components.concept.engine.prompt.ShareData
import
mozilla.components.concept.storage.Login
import
mozilla.components.support.base.log.logger.Logger
import
mozilla.components.support.ktx.android.net.getFileName
import
mozilla.components.support.ktx.kotlin.toDate
import
org.mozilla.geckoview.AllowOrDeny
import
org.mozilla.geckoview.Autocomplete
import
org.mozilla.geckoview.GeckoResult
import
org.mozilla.geckoview.GeckoSession
import
org.mozilla.geckoview.GeckoSession.PromptDelegate
...
...
@@ -29,7 +30,6 @@ import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.MON
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.TIME
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.WEEK
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.PromptResponse
import
org.mozilla.geckoview.Autocomplete
import
java.io.File
import
java.io.FileOutputStream
import
java.io.IOException
...
...
@@ -106,19 +106,25 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe
prompt
:
PromptDelegate
.
AutocompleteRequest
<
Autocomplete
.
LoginSelectOption
>
):
GeckoResult
<
PromptResponse
>?
{
val
geckoResult
=
GeckoResult
<
PromptResponse
>()
val
onConfirmS
ave
:
(
Login
)
->
Unit
=
{
login
->
val
onConfirmS
elect
:
(
Login
)
->
Unit
=
{
login
->
geckoResult
.
complete
(
prompt
.
confirm
(
Autocomplete
.
LoginSelectOption
(
login
.
toLoginEntry
())))
}
val
onDismiss
:
()
->
Unit
=
{
geckoResult
.
complete
(
prompt
.
dismiss
())
}
// Currently no-op will be addressed in https://github.com/mozilla-mobile/android-components/issues/7134
// Exactly one of `httpRealm` and `formSubmitURL` must be present to be a valid login entry.
val
loginList
=
prompt
.
options
.
filter
{
option
->
option
.
value
.
formActionOrigin
!=
null
||
option
.
value
.
httpRealm
!=
null
}.
map
{
option
->
option
.
value
.
toLogin
()
}
geckoEngineSession
.
notifyObservers
{
onPromptRequest
(
PromptRequest
.
SelectLoginPrompt
(
logins
=
l
istOf
()
,
onConfirm
=
onConfirmS
ave
,
logins
=
l
oginList
,
onConfirm
=
onConfirmS
elect
,
onDismiss
=
onDismiss
)
)
...
...
components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt
View file @
a861537a
...
...
@@ -8,17 +8,18 @@ import android.content.Context
import
android.net.Uri
import
androidx.annotation.VisibleForTesting
import
mozilla.components.browser.engine.gecko.GeckoEngineSession
import
mozilla.components.concept.storage.Login
import
mozilla.components.concept.engine.prompt.Choice
import
mozilla.components.concept.engine.prompt.PromptRequest
import
mozilla.components.concept.engine.prompt.PromptRequest.MenuChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice
import
mozilla.components.concept.engine.prompt.ShareData
import
mozilla.components.concept.storage.Login
import
mozilla.components.support.base.log.logger.Logger
import
mozilla.components.support.ktx.android.net.getFileName
import
mozilla.components.support.ktx.kotlin.toDate
import
org.mozilla.geckoview.AllowOrDeny
import
org.mozilla.geckoview.Autocomplete
import
org.mozilla.geckoview.GeckoResult
import
org.mozilla.geckoview.GeckoSession
import
org.mozilla.geckoview.GeckoSession.PromptDelegate
...
...
@@ -29,7 +30,6 @@ import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.MON
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.TIME
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.WEEK
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.PromptResponse
import
org.mozilla.geckoview.Autocomplete
import
java.io.File
import
java.io.FileOutputStream
import
java.io.IOException
...
...
@@ -106,19 +106,25 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe
prompt
:
PromptDelegate
.
AutocompleteRequest
<
Autocomplete
.
LoginSelectOption
>
):
GeckoResult
<
PromptResponse
>?
{
val
geckoResult
=
GeckoResult
<
PromptResponse
>()
val
onConfirmS
ave
:
(
Login
)
->
Unit
=
{
login
->
val
onConfirmS
elect
:
(
Login
)
->
Unit
=
{
login
->
geckoResult
.
complete
(
prompt
.
confirm
(
Autocomplete
.
LoginSelectOption
(
login
.
toLoginEntry
())))
}
val
onDismiss
:
()
->
Unit
=
{
geckoResult
.
complete
(
prompt
.
dismiss
())
}
// Currently no-op will be addressed in https://github.com/mozilla-mobile/android-components/issues/7134
// Exactly one of `httpRealm` and `formSubmitURL` must be present to be a valid login entry.
val
loginList
=
prompt
.
options
.
filter
{
option
->
option
.
value
.
formActionOrigin
!=
null
||
option
.
value
.
httpRealm
!=
null
}.
map
{
option
->
option
.
value
.
toLogin
()
}
geckoEngineSession
.
notifyObservers
{
onPromptRequest
(
PromptRequest
.
SelectLoginPrompt
(
logins
=
l
istOf
()
,
onConfirm
=
onConfirmS
ave
,
logins
=
l
oginList
,
onConfirm
=
onConfirmS
elect
,
onDismiss
=
onDismiss
)
)
...
...
components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegateTest.kt
View file @
a861537a
...
...
@@ -12,6 +12,7 @@ import mozilla.components.concept.engine.prompt.Choice
import
mozilla.components.concept.engine.prompt.PromptRequest
import
mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice
import
mozilla.components.concept.storage.Login
import
mozilla.components.support.ktx.kotlin.toDate
import
mozilla.components.support.test.any
import
mozilla.components.support.test.mock
...
...
@@ -25,9 +26,10 @@ import org.junit.Assert.assertTrue
import
org.junit.Before
import
org.junit.Test
import
org.junit.runner.RunWith
import
org.mockito.Mockito.spy
import
org.mockito.Mockito.doReturn
import
org.mockito.Mockito.spy
import
org.mozilla.gecko.util.GeckoBundle
import
org.mozilla.geckoview.Autocomplete
import
org.mozilla.geckoview.GeckoRuntime
import
org.mozilla.geckoview.GeckoSession
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.DATE
...
...
@@ -43,6 +45,7 @@ import java.security.InvalidParameterException
import
java.util.Calendar
import
java.util.Calendar.YEAR
import
java.util.Date
typealias
GeckoChoice
=
GeckoSession
.
PromptDelegate
.
ChoicePrompt
.
Choice
typealias
GECKO_AUTH_LEVEL
=
GeckoSession
.
PromptDelegate
.
AuthPrompt
.
AuthOptions
.
Level
typealias
GECKO_PROMPT_CHOICE_TYPE
=
GeckoSession
.
PromptDelegate
.
ChoicePrompt
.
Type
...
...
@@ -142,11 +145,11 @@ class GeckoPromptDelegateTest {
)
mockSession
.
register
(
object
:
EngineSession
.
Observer
{
override
fun
onPromptRequest
(
promptRequest
:
PromptRequest
)
{
promptRequestSingleChoice
=
promptRequest
}
})
object
:
EngineSession
.
Observer
{
override
fun
onPromptRequest
(
promptRequest
:
PromptRequest
)
{
promptRequestSingleChoice
=
promptRequest
}
})
val
geckoResult
=
gecko
.
onChoicePrompt
(
mock
(),
geckoPrompt
)
geckoResult
!!
.
accept
{
...
...
@@ -475,7 +478,8 @@ class GeckoPromptDelegateTest {
dateRequest
=
promptRequest
}
})
val
geckoResult
=
promptDelegate
.
onDateTimePrompt
(
mock
(),
GeckoDateTimePrompt
(
type
=
DATETIME_LOCAL
))
val
geckoResult
=
promptDelegate
.
onDateTimePrompt
(
mock
(),
GeckoDateTimePrompt
(
type
=
DATETIME_LOCAL
))
geckoResult
!!
.
accept
{
confirmCalled
=
true
}
...
...
@@ -618,6 +622,125 @@ class GeckoPromptDelegateTest {
)
}
@Test
fun
`Calling
onLoginSave
must
provide
an
SaveLoginPrompt
PromptRequest`
()
{
val
mockSession
=
GeckoEngineSession
(
runtime
)
var
onLoginSaved
=
false
var
onDismissWasCalled
=
false
var
loginSaveRequest
:
PromptRequest
.
SaveLoginPrompt
=
mock
()
val
promptDelegate
=
spy
(
GeckoPromptDelegate
(
mockSession
))
mockSession
.
register
(
object
:
EngineSession
.
Observer
{
override
fun
onPromptRequest
(
promptRequest
:
PromptRequest
)
{
loginSaveRequest
=
promptRequest
as
PromptRequest
.
SaveLoginPrompt
}
})
val
login
=
createLogin
()
val
saveOption
=
Autocomplete
.
LoginSaveOption
(
login
.
toLoginEntry
())
var
geckoResult
=
promptDelegate
.
onLoginSave
(
mock
(),
GeckoLoginSavePrompt
(
arrayOf
(
saveOption
)))
geckoResult
!!
.
accept
{
onDismissWasCalled
=
true
}
loginSaveRequest
.
onDismiss
()
assertTrue
(
onDismissWasCalled
)
geckoResult
=
promptDelegate
.
onLoginSave
(
mock
(),
GeckoLoginSavePrompt
(
arrayOf
(
saveOption
)))
geckoResult
!!
.
accept
{
onLoginSaved
=
true
}
loginSaveRequest
.
onConfirm
(
login
)
assertTrue
(
onLoginSaved
)
}
@Test
fun
`Calling
onLoginSelect
must
provide
an
SelectLoginPrompt
PromptRequest`
()
{
val
mockSession
=
GeckoEngineSession
(
runtime
)
var
onLoginSelected
=
false
var
onDismissWasCalled
=
false
var
loginSelectRequest
:
PromptRequest
.
SelectLoginPrompt
=
mock
()
val
promptDelegate
=
spy
(
GeckoPromptDelegate
(
mockSession
))
mockSession
.
register
(
object
:
EngineSession
.
Observer
{
override
fun
onPromptRequest
(
promptRequest
:
PromptRequest
)
{
loginSelectRequest
=
promptRequest
as
PromptRequest
.
SelectLoginPrompt
}
})
val
login
=
createLogin
()
val
loginSelectOption
=
Autocomplete
.
LoginSelectOption
(
login
.
toLoginEntry
())
val
secondLogin
=
createLogin
(
username
=
"username2"
)
val
secondLoginSelectOption
=
Autocomplete
.
LoginSelectOption
(
secondLogin
.
toLoginEntry
())
var
geckoResult
=
promptDelegate
.
onLoginSelect
(
mock
(),
GeckoLoginSelectPrompt
(
arrayOf
(
loginSelectOption
,
secondLoginSelectOption
))
)
geckoResult
!!
.
accept
{
onDismissWasCalled
=
true
}
loginSelectRequest
.
onDismiss
()
assertTrue
(
onDismissWasCalled
)
geckoResult
=
promptDelegate
.
onLoginSelect
(
mock
(),
GeckoLoginSelectPrompt
(
arrayOf
(
loginSelectOption
,
secondLoginSelectOption
))
)
geckoResult
!!
.
accept
{
onLoginSelected
=
true
}
loginSelectRequest
.
onConfirm
(
login
)
assertTrue
(
onLoginSelected
)
}
fun
createLogin
(
guid
:
String
=
"id"
,
password
:
String
=
"password"
,
username
:
String
=
"username"
,
origin
:
String
=
"https://www.origin.com"
,
httpRealm
:
String
=
"httpRealm"
,
formActionOrigin
:
String
=
"https://www.origin.com"
,
usernameField
:
String
=
"usernameField"
,
passwordField
:
String
=
"passwordField"
)
=
Login
(
guid
=
guid
,
origin
=
origin
,
password
=
password
,
username
=
username
,
httpRealm
=
httpRealm
,
formActionOrigin
=
formActionOrigin
,
usernameField
=
usernameField
,
passwordField
=
passwordField
)
/**
* Converts an Android Components [Login] to a GeckoView [LoginStorage.LoginEntry]
*/
private
fun
Login
.
toLoginEntry
()
=
Autocomplete
.
LoginEntry
.
Builder
()
.
guid
(
guid
)
.
origin
(
origin
)
.
formActionOrigin
(
formActionOrigin
)
.
httpRealm
(
httpRealm
)
.
username
(
username
)
.
password
(
password
)
.
build
()
@Test
fun
`Calling
onAuthPrompt
must
provide
an
Authentication
PromptRequest`
()
{
val
mockSession
=
GeckoEngineSession
(
runtime
)
...
...
@@ -979,7 +1102,7 @@ class GeckoPromptDelegateTest {
title
:
String
=
"title"
,
type
:
Int
,
capture
:
Int
=
0
,
mimeTypes
:
Array
<
out
String
>
=
emptyArray
()
mimeTypes
:
Array
<
out
String
>
=
emptyArray
()
)
:
GeckoSession
.
PromptDelegate
.
FilePrompt
(
title
,
type
,
capture
,
mimeTypes
)
class
GeckoAuthPrompt
(
...
...
@@ -1016,6 +1139,14 @@ class GeckoPromptDelegateTest {
message
:
String
=
"message"
)
:
GeckoSession
.
PromptDelegate
.
ButtonPrompt
(
title
,
message
)
class
GeckoLoginSelectPrompt
(
loginArray
:
Array
<
Autocomplete
.
LoginSelectOption
>
)
:
GeckoSession
.
PromptDelegate
.
AutocompleteRequest
<
Autocomplete
.
LoginSelectOption
>(
loginArray
)
class
GeckoLoginSavePrompt
(
login
:
Array
<
Autocomplete
.
LoginSaveOption
>
)
:
GeckoSession
.
PromptDelegate
.
AutocompleteRequest
<
Autocomplete
.
LoginSaveOption
>(
login
)
class
GeckoAuthOptions
:
GeckoSession
.
PromptDelegate
.
AuthPrompt
.
AuthOptions
()
private
fun
GeckoSession
.
PromptDelegate
.
BasePrompt
.
getGeckoResult
():
GeckoBundle
{
...
...
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt
View file @
a861537a
...
...
@@ -8,17 +8,18 @@ import android.content.Context
import
android.net.Uri
import
androidx.annotation.VisibleForTesting
import
mozilla.components.browser.engine.gecko.GeckoEngineSession
import
mozilla.components.concept.storage.Login
import
mozilla.components.concept.engine.prompt.Choice
import
mozilla.components.concept.engine.prompt.PromptRequest
import
mozilla.components.concept.engine.prompt.PromptRequest.MenuChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice
import
mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice
import
mozilla.components.concept.engine.prompt.ShareData
import
mozilla.components.concept.storage.Login
import
mozilla.components.support.base.log.logger.Logger
import
mozilla.components.support.ktx.android.net.getFileName
import
mozilla.components.support.ktx.kotlin.toDate
import
org.mozilla.geckoview.AllowOrDeny
import
org.mozilla.geckoview.Autocomplete
import
org.mozilla.geckoview.GeckoResult
import
org.mozilla.geckoview.GeckoSession
import
org.mozilla.geckoview.GeckoSession.PromptDelegate
...
...
@@ -29,7 +30,6 @@ import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.MON
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.TIME
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.WEEK
import
org.mozilla.geckoview.GeckoSession.PromptDelegate.PromptResponse
import
org.mozilla.geckoview.Autocomplete
import
java.io.File
import
java.io.FileOutputStream
import
java.io.IOException
...
...
@@ -106,19 +106,25 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe
prompt
:
PromptDelegate
.
AutocompleteRequest
<
Autocomplete
.
LoginSelectOption
>
):
GeckoResult
<
PromptResponse
>?
{
val
geckoResult
=
GeckoResult
<
PromptResponse
>()
val
onConfirmS
ave
:
(
Login
)
->
Unit
=
{
login
->
val
onConfirmS
elect
:
(
Login
)
->
Unit
=
{
login
->
geckoResult
.
complete
(
prompt
.
confirm
(
Autocomplete
.
LoginSelectOption
(
login
.
toLoginEntry
())))
}
val
onDismiss
:
()
->
Unit
=
{
geckoResult
.
complete
(
prompt
.
dismiss
())
}
// Currently no-op will be addressed in https://github.com/mozilla-mobile/android-components/issues/7134
// Exactly one of `httpRealm` and `formSubmitURL` must be present to be a valid login entry.
val
loginList
=
prompt
.
options
.
filter
{
option
->
option
.
value
.
formActionOrigin
!=
null
||
option
.
value
.
httpRealm
!=
null
}.
map
{
option
->
option
.
value
.
toLogin
()
}
geckoEngineSession
.
notifyObservers
{
onPromptRequest
(
PromptRequest
.
SelectLoginPrompt
(
logins
=
l
istOf
()
,
onConfirm
=
onConfirmS
ave
,
logins
=
l
oginList
,
onConfirm
=
onConfirmS
elect
,
onDismiss
=
onDismiss
)
)
...
...
components/feature/logins/src/main/java/mozilla/components/feature/logins/exceptions/LoginExceptionStorage.kt
View file @
a861537a
...
...
@@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.map
import
mozilla.components.feature.logins.exceptions.adapter.LoginExceptionAdapter
import
mozilla.components.feature.logins.exceptions.db.LoginExceptionDatabase
import
mozilla.components.feature.logins.exceptions.db.LoginExceptionEntity
import
mozilla.components.feature.prompts.LoginExceptions
import
mozilla.components.feature.prompts.
login.
LoginExceptions
/**
* A storage implementation for organizing login exceptions.
...
...
components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt
View file @
a861537a
...
...
@@ -50,14 +50,17 @@ import mozilla.components.feature.prompts.dialog.ChoiceDialogFragment.Companion.
import
mozilla.components.feature.prompts.dialog.ChoiceDialogFragment.Companion.SINGLE_CHOICE_DIALOG_TYPE
import
mozilla.components.feature.prompts.dialog.ColorPickerDialogFragment
import
mozilla.components.feature.prompts.dialog.ConfirmDialogFragment
import
mozilla.components.feature.prompts.dialog.LoginDialogFragment
import
mozilla.components.feature.prompts.dialog.MultiButtonDialogFragment
import
mozilla.components.feature.prompts.dialog.PromptAbuserDetector
import
mozilla.components.feature.prompts.dialog.PromptDialogFragment
import
mozilla.components.feature.prompts.dialog.Prompter
import
mozilla.components.feature.prompts.dialog.SaveLoginDialogFragment
import
mozilla.components.feature.prompts.dialog.TextPromptDialogFragment
import
mozilla.components.feature.prompts.dialog.TimePickerDialogFragment
import
mozilla.components.feature.prompts.file.FilePicker
import
mozilla.components.feature.prompts.login.LoginExceptions
import
mozilla.components.feature.prompts.login.LoginPicker
import
mozilla.components.feature.prompts.login.LoginPickerView
import
mozilla.components.feature.prompts.share.DefaultShareDelegate
import
mozilla.components.feature.prompts.share.ShareDelegate
import
mozilla.components.lib.state.ext.flowScoped
...
...
@@ -105,6 +108,9 @@ private const val PROGRESS_ALMOST_COMPLETE = 90
* 'save login'prompts will not be shown.
* @property loginExceptionStorage An implementation of [LoginExceptions] that saves and checks origins
* the user does not want to see a save login dialog for.
* @property loginPickerView The [LoginPickerView] used for [LoginPicker] to display select login options.
* @property onManageLogins A callback invoked when a user selects "manage logins" from the
* select login prompt.
* @property onNeedToRequestPermissions A callback invoked when permissions
* need to be requested before a prompt (e.g. a file picker) can be displayed.
* Once the request is completed, [onPermissionsResult] needs to be invoked.
...
...
@@ -119,11 +125,14 @@ class PromptFeature private constructor(
override
val
loginValidationDelegate
:
LoginValidationDelegate
?
=
null
,
private
val
isSaveLoginEnabled
:
()
->
Boolean
=
{
false
},
override
val
loginExceptionStorage
:
LoginExceptions
?
=
null
,
private
val
loginPickerView
:
LoginPickerView
?
=
null
,
private
val
onManageLogins
:
()
->
Unit
=
{},
onNeedToRequestPermissions
:
OnNeedToRequestPermissions
)
:
LifecycleAwareFeature
,
PermissionsFeature
,
Prompter
{
// These t
wo
scopes have identical lifetimes. We do not yet have a way of combining scopes
// These t
hree
scopes have identical lifetimes. We do not yet have a way of combining scopes
private
var
handlePromptScope
:
CoroutineScope
?
=
null
private
var
dismissPromptScope
:
CoroutineScope
?
=
null
private
var
sessionPromptScope
:
CoroutineScope
?
=
null
private
var
activePromptRequest
:
PromptRequest
?
=
null
internal
val
promptAbuserDetector
=
PromptAbuserDetector
()
...
...
@@ -141,6 +150,8 @@ class PromptFeature private constructor(
loginValidationDelegate
:
LoginValidationDelegate
?
=
null
,
isSaveLoginEnabled
:
()
->
Boolean
=
{
false
},
loginExceptionStorage
:
LoginExceptions
?
=
null
,
loginPickerView
:
LoginPickerView
?
=
null
,
onManageLogins
:
()
->
Unit
=
{},
onNeedToRequestPermissions
:
OnNeedToRequestPermissions
)
:
this
(
container
=
PromptContainer
.
Activity
(
activity
),
...
...
@@ -151,7 +162,9 @@ class PromptFeature private constructor(
loginValidationDelegate
=
loginValidationDelegate
,
isSaveLoginEnabled
=
isSaveLoginEnabled
,
loginExceptionStorage
=
loginExceptionStorage
,
onNeedToRequestPermissions
=
onNeedToRequestPermissions
onNeedToRequestPermissions
=
onNeedToRequestPermissions
,
loginPickerView
=
loginPickerView
,
onManageLogins
=
onManageLogins
)
constructor
(
...
...
@@ -163,6 +176,8 @@ class PromptFeature private constructor(
loginValidationDelegate
:
LoginValidationDelegate
?
=
null
,
isSaveLoginEnabled
:
()
->
Boolean
=
{
false
},
loginExceptionStorage
:
LoginExceptions
?
=
null
,
loginPickerView
:
LoginPickerView
?
=
null
,
onManageLogins
:
()
->
Unit
=
{},
onNeedToRequestPermissions
:
OnNeedToRequestPermissions
)
:
this
(
container
=
PromptContainer
.
Fragment
(
fragment
),
...
...
@@ -173,7 +188,9 @@ class PromptFeature private constructor(
loginValidationDelegate
=
loginValidationDelegate
,
isSaveLoginEnabled
=
isSaveLoginEnabled
,
loginExceptionStorage
=
loginExceptionStorage
,
onNeedToRequestPermissions
=
onNeedToRequestPermissions
onNeedToRequestPermissions
=
onNeedToRequestPermissions
,
loginPickerView
=
loginPickerView
,
onManageLogins
=
onManageLogins
)
@Deprecated
(
"Pass only activity or fragment instead"
)
...
...
@@ -183,6 +200,8 @@ class PromptFeature private constructor(
store
:
BrowserStore
,
customTabId
:
String
?
=
null
,
fragmentManager
:
FragmentManager
,
loginPickerView
:
LoginPickerView
?
=
null
,
onManageLogins
:
()
->
Unit
=
{},
onNeedToRequestPermissions
:
OnNeedToRequestPermissions
)
:
this
(
container
=
activity
?.
let
{
PromptContainer
.
Activity
(
it
)
}
...
...
@@ -196,11 +215,16 @@ class PromptFeature private constructor(
fragmentManager
=
fragmentManager
,
shareDelegate
=
DefaultShareDelegate
(),
loginValidationDelegate
=
null
,
onNeedToRequestPermissions
=
onNeedToRequestPermissions
onNeedToRequestPermissions
=
onNeedToRequestPermissions
,
loginPickerView
=
loginPickerView
,
onManageLogins
=
onManageLogins
)
private
val
filePicker
=
FilePicker
(
container
,
store
,
customTabId
,
onNeedToRequestPermissions
)
private
val
loginPicker
=
loginPickerView
?.
let
{
LoginPicker
(
store
,
it
,
onManageLogins
,
customTabId
)
}
override
val
onNeedToRequestPermissions
get
()
=
filePicker
.
onNeedToRequestPermissions
...
...
@@ -240,6 +264,20 @@ class PromptFeature private constructor(
prompt
.
dismiss
()
}
activePrompt
?.
clear
()
loginPicker
?.
dismissCurrentLoginSelect
()
}
}
// Dismiss prompts when a new tab is selected.
sessionPromptScope
=
store
.
flowScoped
{
flow
->
flow
.
ifChanged
{
browserState
->
browserState
.
selectedTabId
}
.
collect
{
val
prompt
=
activePrompt
?.
get
()
if
(
prompt
?.
shouldDismissOnLoad
()
==
true
)
{
prompt
.
dismiss
()
}
activePrompt
?.
clear
()
loginPicker
?.
dismissCurrentLoginSelect
()
}
}
...
...
@@ -257,6 +295,7 @@ class PromptFeature private constructor(
override
fun
stop
()
{
handlePromptScope
?.
cancel
()
dismissPromptScope
?.
cancel
()
sessionPromptScope
?.
cancel
()
}
/**
...
...
@@ -294,6 +333,13 @@ class PromptFeature private constructor(
when
(
promptRequest
)
{
is
File
->
filePicker
.
handleFileRequest
(
promptRequest
)
is
Share
->
handleShareRequest
(
promptRequest
,
session
)
is
SelectLoginPrompt
->
{
if
(
promptRequest
.
logins
.
isNotEmpty
())
{
loginPicker
?.
handleSelectLoginRequest
(
promptRequest
)
}
}
else
->
handleDialogsRequest
(
promptRequest
,
session
)
}
}
...
...
@@ -439,7 +485,7 @@ class PromptFeature private constructor(
return
}
LoginDialogFragment
.
newInstance
(
Save
LoginDialogFragment
.
newInstance
(
sessionId
=
session
.
id
,
hint
=
promptRequest
.
hint
,
// For v1, we only handle a single login and drop all others on the floor
...
...
@@ -447,12 +493,6 @@ class PromptFeature private constructor(
)
}
/**
* This feature isn't implemented yet
* see https://github.com/mozilla-mobile/android-components/issues/7134
*/
is
SelectLoginPrompt
->
return
is
SingleChoice
->
ChoiceDialogFragment
.
newInstance
(
promptRequest
.
choices
,