1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.chrome.browser;
6
7import android.app.AlertDialog;
8import android.test.suitebuilder.annotation.MediumTest;
9import android.test.suitebuilder.annotation.SmallTest;
10
11import org.chromium.base.test.util.Feature;
12import org.chromium.chrome.shell.ChromeShellTab;
13import org.chromium.chrome.shell.ChromeShellTestBase;
14import org.chromium.chrome.test.util.TestHttpServerClient;
15import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
16
17import java.util.concurrent.TimeoutException;
18
19/**
20 * Integration tests verifying that form resubmission dialogs are correctly displayed and handled.
21 */
22public class RepostFormWarningTest extends ChromeShellTestBase {
23    // Active tab.
24    private ChromeShellTab mTab;
25    // Callback helper that manages waiting for pageloads to finish.
26    private TestCallbackHelperContainer mCallbackHelper;
27
28    @Override
29    public void setUp() throws Exception {
30        super.setUp();
31
32        mTab = launchChromeShellWithBlankPage().getActiveTab();
33        mCallbackHelper = new TestCallbackHelperContainer(mTab.getContentViewCore());
34
35        // Wait for the initial load of about://blank to finish.
36        mCallbackHelper.getOnPageFinishedHelper().waitForCallback(0);
37    }
38
39    /** Verifies that the form resubmission warning is not displayed upon first POST navigation. */
40    @MediumTest
41    @Feature({"Navigation"})
42    public void testFormFirstNavigation() throws Throwable {
43        // Load the url posting data for the first time.
44        postNavigation();
45        mCallbackHelper.getOnPageFinishedHelper().waitForCallback(1);
46        getInstrumentation().waitForIdleSync();
47
48        // Verify that the form resubmission warning was not shown.
49        assertNull("Form resubmission warning shown upon first load.",
50                RepostFormWarningDialog.getCurrentDialog());
51    }
52
53    /** Verifies that confirming the form reload performs the reload. */
54    @MediumTest
55    @Feature({"Navigation"})
56    public void testFormResubmissionContinue() throws Throwable {
57        // Load the url posting data for the first time.
58        postNavigation();
59        mCallbackHelper.getOnPageFinishedHelper().waitForCallback(1);
60
61        // Trigger a reload and wait for the warning to be displayed.
62        reload();
63        getInstrumentation().waitForIdleSync();
64        AlertDialog dialog = (AlertDialog) RepostFormWarningDialog.getCurrentDialog();
65        assertNotNull("Form resubmission warning not shown upon reload.", dialog);
66
67        // Click "Continue" and verify that the page is reloaded.
68        clickButton(dialog, AlertDialog.BUTTON_POSITIVE);
69        mCallbackHelper.getOnPageFinishedHelper().waitForCallback(2);
70
71        // Verify that the reference to the dialog in RepostFormWarningDialog was cleared.
72        assertNull("Form resubmission warning dialog was not dismissed correctly.",
73                RepostFormWarningDialog.getCurrentDialog());
74    }
75
76    /**
77     * Verifies that cancelling the form reload prevents it from happening. Currently the test waits
78     * after the "Cancel" button is clicked to verify that the load was not triggered, which blocks
79     * for CallbackHelper's default timeout upon each execution.
80     */
81    @SmallTest
82    @Feature({"Navigation"})
83    public void testFormResubmissionCancel() throws Throwable {
84        // Load the url posting data for the first time.
85        postNavigation();
86        mCallbackHelper.getOnPageFinishedHelper().waitForCallback(1);
87
88        // Trigger a reload and wait for the warning to be displayed.
89        reload();
90        getInstrumentation().waitForIdleSync();
91        AlertDialog dialog = (AlertDialog) RepostFormWarningDialog.getCurrentDialog();
92        assertNotNull("Form resubmission warning not shown upon reload.", dialog);
93
94        // Click "Cancel" and verify that the page is not reloaded.
95        clickButton(dialog, AlertDialog.BUTTON_NEGATIVE);
96        boolean timedOut = false;
97        try {
98            mCallbackHelper.getOnPageFinishedHelper().waitForCallback(2);
99        } catch (TimeoutException ex) {
100            timedOut = true;
101        }
102        assertTrue("Page was reloaded despite selecting Cancel.", timedOut);
103
104        // Verify that the reference to the dialog in RepostFormWarningDialog was cleared.
105        assertNull("Form resubmission warning dialog was not dismissed correctly.",
106                RepostFormWarningDialog.getCurrentDialog());
107    }
108
109    /** Performs a POST navigation in mTab. */
110    private void postNavigation() throws Throwable {
111        final String url = "chrome/test/data/empty.html";
112        final byte[] postData = new byte[] { 42 };
113
114        runTestOnUiThread(new Runnable() {
115            @Override
116            public void run() {
117                mTab.loadUrlWithSanitization(TestHttpServerClient.getUrl(url), postData);
118            }
119        });
120    }
121
122    /** Reloads mTab. */
123    private void reload() throws Throwable {
124        runTestOnUiThread(new Runnable() {
125            @Override
126            public void run() {
127                mTab.reload();
128            }
129        });
130    }
131
132    /** Clicks the given button in the given dialog. */
133    private void clickButton(final AlertDialog dialog, final int buttonId) throws Throwable {
134        runTestOnUiThread(new Runnable() {
135            @Override
136            public void run() {
137                dialog.getButton(buttonId).performClick();
138            }
139        });
140    }
141}
142