Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
For #10867 - Dismisses user prompt when GV calls onPromptDismiss
Browse files Browse the repository at this point in the history
  • Loading branch information
codrut.topliceanu authored and mergify[bot] committed Oct 6, 2021
1 parent a992c20 commit fd2ce39
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 6 deletions.
Expand Up @@ -125,7 +125,11 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe
logins = prompt.options.map { it.value.toLogin() },
onConfirm = onConfirmSave,
onDismiss = onDismiss
)
).also {
prompt.delegate = PromptInstanceDismissDelegate(
geckoEngineSession, it
)
}
)
}
return geckoResult
Expand Down
@@ -0,0 +1,21 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.browser.engine.gecko.prompt

import mozilla.components.browser.engine.gecko.GeckoEngineSession
import mozilla.components.concept.engine.prompt.PromptRequest
import org.mozilla.geckoview.GeckoSession

internal class PromptInstanceDismissDelegate(
private val geckoSession: GeckoEngineSession,
private val promptRequest: PromptRequest
) : GeckoSession.PromptDelegate.PromptInstanceDelegate {

override fun onPromptDismiss(prompt: GeckoSession.PromptDelegate.BasePrompt) {
geckoSession.notifyObservers {
onPromptDismissed(promptRequest)
}
}
}
Expand Up @@ -682,6 +682,26 @@ class GeckoPromptDelegateTest {
assertFalse(onLoginSaved)
}

@Test
fun `Calling onLoginSave must set a PromptInstanceDismissDelegate`() {
val mockSession = GeckoEngineSession(runtime)
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())
val saveLoginPrompt = spy(geckoLoginSavePrompt(arrayOf(saveOption)))

promptDelegate.onLoginSave(mock(), saveLoginPrompt)

assertNotNull(loginSaveRequest)
assertNotNull(saveLoginPrompt.delegate)
}

@Test
fun `Calling onLoginSelect must provide an SelectLoginPrompt PromptRequest`() {
val mockSession = GeckoEngineSession(runtime)
Expand Down
@@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package mozilla.components.browser.engine.gecko.prompt

import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.browser.engine.gecko.GeckoEngineSession
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.prompt.PromptRequest
import mozilla.components.support.test.mock
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.geckoview.Autocomplete
import org.mozilla.geckoview.GeckoSession

@RunWith(AndroidJUnit4::class)
class PromptInstanceDismissDelegateTest {

@Test
fun `GIVEN delegate with promptRequest WHEN onPromptDismiss called from geckoview THEN notifyObservers the prompt is dismissed`() {
val mockSession = GeckoEngineSession(mock())
var onDismissWasCalled = false
mockSession.register(object : EngineSession.Observer {
override fun onPromptDismissed(promptRequest: PromptRequest) {
super.onPromptDismissed(promptRequest)
onDismissWasCalled = true
}
})
val basePrompt: GeckoSession.PromptDelegate.AutocompleteRequest<Autocomplete.LoginSaveOption> = mock()
val prompt: PromptRequest = mock()
val delegate = PromptInstanceDismissDelegate(mockSession, prompt)

delegate.onPromptDismiss(basePrompt)

assertTrue(onDismissWasCalled)
}
}
Expand Up @@ -256,6 +256,12 @@ internal class EngineObserver(
)
}

override fun onPromptDismissed(promptRequest: PromptRequest) {
store.dispatch(
ContentAction.ConsumePromptRequestAction(tabId, promptRequest)
)
}

override fun onRepostPromptCancelled() {
store.dispatch(ContentAction.UpdateRefreshCanceledStateAction(tabId, true))
}
Expand Down
Expand Up @@ -74,6 +74,11 @@ abstract class EngineSession(
fun onCancelContentPermissionRequest(permissionRequest: PermissionRequest) = Unit
fun onPromptRequest(promptRequest: PromptRequest) = Unit

/**
* The engine has requested a prompt be dismissed.
*/
fun onPromptDismissed(promptRequest: PromptRequest) = Unit

/**
* User cancelled a repost prompt. Page will not be reloaded.
*/
Expand Down
Expand Up @@ -298,26 +298,28 @@ class PromptFeature private constructor(
arrayOf(it?.content?.promptRequests, it?.content?.loading)
}
.collect { state ->
state?.content?.let {
if (it.promptRequests.lastOrNull() != activePromptRequest) {
state?.content?.let { content ->
if (content.promptRequests.lastOrNull() != activePromptRequest) {
// Dismiss any active select login or credit card prompt if it does
// not match the current prompt request for the session.
if (activePromptRequest is SelectLoginPrompt) {
loginPicker?.dismissCurrentLoginSelect(activePromptRequest as SelectLoginPrompt)
} else if (activePromptRequest is SaveLoginPrompt) {
(activePrompt?.get() as? SaveLoginDialogFragment)?.dismissAllowingStateLoss()
} else if (activePromptRequest is SelectCreditCard) {
creditCardPicker?.dismissSelectCreditCardRequest(
activePromptRequest as SelectCreditCard
)
}

onPromptRequested(state)
} else if (!it.loading) {
} else if (!content.loading) {
promptAbuserDetector.resetJSAlertAbuseState()
} else if (it.loading) {
} else if (content.loading) {
dismissSelectPrompts()
}

activePromptRequest = it.promptRequests.lastOrNull()
activePromptRequest = content.promptRequests.lastOrNull()
}
}
}
Expand Down
Expand Up @@ -300,6 +300,36 @@ class PromptFeatureTest {
assertEquals(true, result)
}

@Test
fun `GIVEN saveLoginPrompt is visible WHEN prompt is removed from state THEN dismiss saveLoginPrompt`() {
// given
val saveLoginPrompt: SaveLoginDialogFragment = mock()
val promptRequest: PromptRequest.SaveLoginPrompt = mock()

store.dispatch(ContentAction.UpdatePromptRequestAction(tabId, promptRequest))
.joinBlocking()
store.waitUntilIdle()

val feature = spy(
PromptFeature(
mock<Activity>(),
store,
fragmentManager = fragmentManager
) { }
)

feature.start()
feature.activePrompt = WeakReference(saveLoginPrompt)
feature.activePromptRequest = promptRequest

// when
store.dispatch(ContentAction.ConsumePromptRequestAction(tabId, promptRequest))
.joinBlocking()

// then
verify(saveLoginPrompt).dismissAllowingStateLoss()
}

@Test
fun `GIVEN loginPickerView is not visible WHEN dismissSelectPrompts THEN dismissCurrentLoginSelect called and false returned`() {
// given
Expand Down

1 comment on commit fd2ce39

@firefoxci-taskcluster
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh! Looks like an error! Details

Failed to fetch task artifact public/github/customCheckRunText.md for GitHub integration.
Make sure the artifact exists on the worker or other location.

Please sign in to comment.