зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1659073 - Implement confirmRepost on Mobile. r=owlish,snorp
Differential Revision: https://phabricator.services.mozilla.com/D89658
This commit is contained in:
Родитель
c978775400
Коммит
68bde3475c
|
@ -20,6 +20,15 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
const { debug, warn } = GeckoViewUtils.initLogging("PromptCollection");
|
||||
|
||||
class PromptCollection {
|
||||
confirmRepost(browsingContext) {
|
||||
const msg = {
|
||||
type: "repost",
|
||||
};
|
||||
const prompter = new GeckoViewPrompter(browsingContext);
|
||||
const result = prompter.showPrompt(msg);
|
||||
return !!result?.allow;
|
||||
}
|
||||
|
||||
beforeUnloadCheck(browsingContext) {
|
||||
const msg = {
|
||||
type: "beforeUnload",
|
||||
|
|
|
@ -927,6 +927,7 @@ package org.mozilla.geckoview {
|
|||
method @UiThread @Nullable default public GeckoResult<GeckoSession.PromptDelegate.PromptResponse> onLoginSave(@NonNull GeckoSession, @NonNull GeckoSession.PromptDelegate.AutocompleteRequest<Autocomplete.LoginSaveOption>);
|
||||
method @UiThread @Nullable default public GeckoResult<GeckoSession.PromptDelegate.PromptResponse> onLoginSelect(@NonNull GeckoSession, @NonNull GeckoSession.PromptDelegate.AutocompleteRequest<Autocomplete.LoginSelectOption>);
|
||||
method @UiThread @Nullable default public GeckoResult<GeckoSession.PromptDelegate.PromptResponse> onPopupPrompt(@NonNull GeckoSession, @NonNull GeckoSession.PromptDelegate.PopupPrompt);
|
||||
method @UiThread @Nullable default public GeckoResult<GeckoSession.PromptDelegate.PromptResponse> onRepostConfirmPrompt(@NonNull GeckoSession, @NonNull GeckoSession.PromptDelegate.RepostConfirmPrompt);
|
||||
method @UiThread @Nullable default public GeckoResult<GeckoSession.PromptDelegate.PromptResponse> onSharePrompt(@NonNull GeckoSession, @NonNull GeckoSession.PromptDelegate.SharePrompt);
|
||||
method @UiThread @Nullable default public GeckoResult<GeckoSession.PromptDelegate.PromptResponse> onTextPrompt(@NonNull GeckoSession, @NonNull GeckoSession.PromptDelegate.TextPrompt);
|
||||
}
|
||||
|
@ -1084,6 +1085,11 @@ package org.mozilla.geckoview {
|
|||
public static class GeckoSession.PromptDelegate.PromptResponse {
|
||||
}
|
||||
|
||||
public static class GeckoSession.PromptDelegate.RepostConfirmPrompt extends GeckoSession.PromptDelegate.BasePrompt {
|
||||
ctor protected RepostConfirmPrompt();
|
||||
method @UiThread @NonNull public GeckoSession.PromptDelegate.PromptResponse confirm(@Nullable AllowOrDeny);
|
||||
}
|
||||
|
||||
public static class GeckoSession.PromptDelegate.SharePrompt extends GeckoSession.PromptDelegate.BasePrompt {
|
||||
ctor protected SharePrompt(@Nullable String, @Nullable String, @Nullable String);
|
||||
method @UiThread @NonNull public GeckoSession.PromptDelegate.PromptResponse confirm(int);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<form action="hello.html" method="post">
|
||||
<input id=text>
|
||||
<button id=submit>Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -26,6 +26,7 @@ import kotlin.reflect.KClass
|
|||
*/
|
||||
open class BaseSessionTest(noErrorCollector: Boolean = false) {
|
||||
companion object {
|
||||
const val RESUBMIT_CONFIRM = "/assets/www/resubmit.html"
|
||||
const val BEFORE_UNLOAD = "/assets/www/beforeunload.html"
|
||||
const val CLICK_TO_RELOAD_HTML_PATH = "/assets/www/clickToReload.html"
|
||||
const val CONTENT_CRASH_URL = "about:crashcontent"
|
||||
|
|
|
@ -147,6 +147,66 @@ class PromptDelegateTest : BaseSessionTest() {
|
|||
equalTo(false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onFormResubmissionPrompt() {
|
||||
sessionRule.session.loadTestPath(RESUBMIT_CONFIRM)
|
||||
sessionRule.waitForPageStop()
|
||||
|
||||
sessionRule.session.evaluateJS(
|
||||
"document.querySelector('#text').value = 'Some text';" +
|
||||
"document.querySelector('#submit').click();"
|
||||
)
|
||||
|
||||
// Submitting the form causes a navigation
|
||||
sessionRule.waitForPageStop()
|
||||
|
||||
val result = GeckoResult<Void>()
|
||||
sessionRule.delegateUntilTestEnd(object: Callbacks.ProgressDelegate {
|
||||
override fun onPageStart(session: GeckoSession, url: String) {
|
||||
assertThat("Only HELLO_HTML_PATH should load", url, endsWith(HELLO_HTML_PATH))
|
||||
result.complete(null)
|
||||
}
|
||||
})
|
||||
|
||||
val promptResult = GeckoResult<PromptDelegate.PromptResponse>()
|
||||
val promptResult2 = GeckoResult<PromptDelegate.PromptResponse>()
|
||||
|
||||
sessionRule.delegateUntilTestEnd(object : Callbacks.PromptDelegate {
|
||||
@AssertCalled(count = 2)
|
||||
override fun onRepostConfirmPrompt(session: GeckoSession, prompt: PromptDelegate.RepostConfirmPrompt): GeckoResult<PromptDelegate.PromptResponse>? {
|
||||
// We have to return something here because otherwise the delegate will be invoked
|
||||
// before we have a chance to override it in the waitUntilCalled call below
|
||||
return forEachCall(promptResult, promptResult2)
|
||||
}
|
||||
})
|
||||
|
||||
// This should trigger a confirm resubmit prompt
|
||||
sessionRule.session.reload();
|
||||
|
||||
sessionRule.waitUntilCalled(object : Callbacks.PromptDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onRepostConfirmPrompt(session: GeckoSession, prompt: PromptDelegate.RepostConfirmPrompt): GeckoResult<PromptDelegate.PromptResponse>? {
|
||||
promptResult.complete(prompt.confirm(AllowOrDeny.DENY))
|
||||
return promptResult
|
||||
}
|
||||
})
|
||||
|
||||
sessionRule.waitForResult(promptResult)
|
||||
|
||||
// Trigger it again, this time the load should go through
|
||||
sessionRule.session.reload();
|
||||
sessionRule.waitUntilCalled(object : Callbacks.PromptDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onRepostConfirmPrompt(session: GeckoSession, prompt: PromptDelegate.RepostConfirmPrompt): GeckoResult<PromptDelegate.PromptResponse>? {
|
||||
promptResult2.complete(prompt.confirm(AllowOrDeny.ALLOW))
|
||||
return promptResult2
|
||||
}
|
||||
})
|
||||
|
||||
sessionRule.waitForResult(promptResult2)
|
||||
sessionRule.waitForResult(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onBeforeUnloadTest() {
|
||||
sessionRule.setPrefsUntilTestEnd(mapOf(
|
||||
|
|
|
@ -2775,6 +2775,12 @@ public class GeckoSession implements Parcelable {
|
|||
res = delegate.onBeforeUnloadPrompt(session, prompt);
|
||||
break;
|
||||
}
|
||||
case "repost": {
|
||||
final PromptDelegate.RepostConfirmPrompt prompt =
|
||||
new PromptDelegate.RepostConfirmPrompt();
|
||||
res = delegate.onRepostConfirmPrompt(session, prompt);
|
||||
break;
|
||||
}
|
||||
case "button": {
|
||||
final PromptDelegate.ButtonPrompt prompt =
|
||||
new PromptDelegate.ButtonPrompt(title, msg);
|
||||
|
@ -4087,6 +4093,31 @@ public class GeckoSession implements Parcelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RepostConfirmPrompt represents a prompt shown whenever the browser
|
||||
* needs to resubmit POST data (e.g. due to page refresh).
|
||||
*/
|
||||
class RepostConfirmPrompt extends BasePrompt {
|
||||
protected RepostConfirmPrompt() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms the prompt.
|
||||
*
|
||||
* @param allowOrDeny whether the browser should allow resubmitting
|
||||
* data.
|
||||
*
|
||||
* @return A {@link PromptResponse} which can be used to complete
|
||||
* the {@link GeckoResult} associated with this prompt.
|
||||
*/
|
||||
@UiThread
|
||||
public @NonNull PromptResponse confirm(final @Nullable AllowOrDeny allowOrDeny) {
|
||||
ensureResult().putBoolean("allow", allowOrDeny != AllowOrDeny.DENY);
|
||||
return super.confirm();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AlertPrompt contains the information necessary to represent a JavaScript
|
||||
* alert() call from content; it can only be dismissed, not confirmed.
|
||||
|
@ -5020,6 +5051,27 @@ public class GeckoSession implements Parcelable {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a POST resubmission confirmation prompt.
|
||||
*
|
||||
* This prompt will trigger whenever refreshing or navigating to a page needs resubmitting
|
||||
* POST data that has been submitted already.
|
||||
*
|
||||
* @param session GeckoSession that triggered the prompt
|
||||
* @param prompt the {@link RepostConfirmPrompt} that describes the
|
||||
* prompt.
|
||||
* @return A {@link GeckoResult} resolving to {@link AllowOrDeny#ALLOW}
|
||||
* if the page is allowed to continue with the navigation and resubmit the POST
|
||||
* data or {@link AllowOrDeny#DENY} otherwise.
|
||||
*/
|
||||
@UiThread
|
||||
default @Nullable GeckoResult<PromptResponse> onRepostConfirmPrompt(
|
||||
@NonNull final GeckoSession session,
|
||||
@NonNull final RepostConfirmPrompt prompt
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a button prompt.
|
||||
*
|
||||
|
|
|
@ -27,10 +27,14 @@ exclude: true
|
|||
([bug 1658456]({{bugzilla}}1658456))
|
||||
- ⚠️ Use [`Image`][82.3] for [`MediaSession`][81.6] artwork and [`WebExtension`][69.5] icon support.
|
||||
([bug 1662508]({{bugzilla}}1662508))
|
||||
- Added [`RepostConfirmPrompt`][82.4] to prompt the user for cofirmation before
|
||||
resending POST requests.
|
||||
([bug 1659073]({{bugzilla}}1659073))
|
||||
|
||||
[82.1]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onExternalResponse-org.mozilla.geckoview.GeckoSession-org.mozilla.geckoview.GeckoSession.WebResponseInfo-
|
||||
[82.2]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onExternalResponse-org.mozilla.geckoview.GeckoSession-org.mozilla.geckoview.GeckoResult-
|
||||
[82.3]: {{javadoc_uri}}/Image.html
|
||||
[82.4]: {{javadoc_uri}}/GeckoSession.PromptDelegate.RepostConfirmPrompt.html
|
||||
|
||||
## v81
|
||||
- Added `cookiePurging` to [`ContentBlocking.Settings.Builder`][81.1] and `getCookiePurging` and `setCookiePurging`
|
||||
|
@ -789,4 +793,4 @@ to allow adding gecko profiler markers.
|
|||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||
|
||||
[api-version]: 802b991116bf1a90050c412c32bc8ac3e7343fed
|
||||
[api-version]: b2f304bfc18a9b3ce4bbe4cc12bc31be42f6fde8
|
||||
|
|
|
@ -122,6 +122,37 @@ final class BasicGeckoViewPrompt implements GeckoSession.PromptDelegate {
|
|||
return GeckoResult.fromValue(prompt.dismiss());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GeckoResult<PromptResponse> onRepostConfirmPrompt(final GeckoSession session,
|
||||
final RepostConfirmPrompt prompt) {
|
||||
final Activity activity = mActivity;
|
||||
if (activity == null) {
|
||||
return GeckoResult.fromValue(prompt.dismiss());
|
||||
}
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.repost_confirm_title)
|
||||
.setMessage(R.string.repost_confirm_message);
|
||||
|
||||
GeckoResult<PromptResponse> res = new GeckoResult<>();
|
||||
|
||||
final DialogInterface.OnClickListener listener = (dialog, which) -> {
|
||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||
res.complete(prompt.confirm(AllowOrDeny.ALLOW));
|
||||
} else if (which == DialogInterface.BUTTON_NEGATIVE) {
|
||||
res.complete(prompt.confirm(AllowOrDeny.DENY));
|
||||
} else {
|
||||
res.complete(prompt.dismiss());
|
||||
}
|
||||
};
|
||||
|
||||
builder.setPositiveButton(R.string.repost_confirm_resend, listener);
|
||||
builder.setNegativeButton(R.string.repost_confirm_cancel, listener);
|
||||
|
||||
createStandardDialog(builder, prompt, res).show();
|
||||
return res;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GeckoResult<PromptResponse> onBeforeUnloadPrompt(final GeckoSession session,
|
||||
|
|
|
@ -58,11 +58,17 @@
|
|||
<string name="key_allow_extensions_in_private_browsing">allow_extensions_in_private_browsing</string>
|
||||
<string name="key_preferred_color_scheme">preferred_color_scheme</string>
|
||||
<string name="key_user_agent_override">user_agent_override</string>
|
||||
|
||||
<string name="before_unload_message">This page is asking you to confirm that you want to leave - data you have entered may not be saved</string>
|
||||
<string name="before_unload_title">Are you sure?</string>
|
||||
<string name="before_unload_leave_page">Leave Page</string>
|
||||
<string name="before_unload_stay">Stay on Page</string>
|
||||
|
||||
<string name="repost_confirm_message">To display this page, GeckoViewExample must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.</string>
|
||||
<string name="repost_confirm_title">Are you sure?</string>
|
||||
<string name="repost_confirm_resend">Resend</string>
|
||||
<string name="repost_confirm_cancel">Cancel</string>
|
||||
|
||||
<string-array name="pref_preferred_color_scheme_display_names">
|
||||
<item>Follow System Preference</item>
|
||||
<item>Light</item>
|
||||
|
|
Загрузка…
Ссылка в новой задаче