Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(743)

Unified Diff: content/browser/web_contents/web_contents_impl_browsertest.cc

Issue 2919593007: Always update the omnibox URL when cancelling via onbeforeunload (Closed)
Patch Set: Merge remote-tracking branch 'origin/master' into spoof Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/web_contents/web_contents_impl.cc ('k') | content/public/browser/navigation_controller.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/web_contents/web_contents_impl_browsertest.cc
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 2f161b0134423a18edfa73ad2a9d3d710586340e..736114380ee338844ca378f9bd22c230348bafb4 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -939,6 +939,145 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
namespace {
+// Test implementation of WebContentsDelegate that handles and automatically
+// cancels beforeunload dialogs. This class also listens for
+// NavigationStateChanged(INVALIDATE_TYPE_URL) and records the state of
+// GetVisibleURL().
+class DialogDismissingWebContentsDelegate : public JavaScriptDialogManager,
+ public WebContentsDelegate {
+ public:
+ DialogDismissingWebContentsDelegate()
+ : message_loop_runner_(new MessageLoopRunner) {}
+ ~DialogDismissingWebContentsDelegate() override {}
+
+ void WaitForDialogDismissed() {
+ message_loop_runner_->Run();
+ message_loop_runner_ = new MessageLoopRunner;
+ }
+
+ // The recent of values of web_contents()->GetVisibleURL(), recorded each time
+ // this WebContentsDelegate gets an INVALIDATE_TYPE_URL event.
+ std::vector<GURL> GetAndClearVisibleUrlInvalidations() {
+ return std::move(visible_url_invalidations_);
+ }
+
+ // WebContentsDelegate
+
+ JavaScriptDialogManager* GetJavaScriptDialogManager(
+ WebContents* source) override {
+ return this;
+ }
+ void NavigationStateChanged(WebContents* web_contents,
+ InvalidateTypes invalidate_types) override {
+ if (invalidate_types & INVALIDATE_TYPE_URL) {
+ visible_url_invalidations_.push_back(web_contents->GetVisibleURL());
+ }
+ }
+
+ // JavaScriptDialogManager
+
+ void RunJavaScriptDialog(WebContents* web_contents,
+ const GURL& origin_url,
+ JavaScriptDialogType dialog_type,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
+ const DialogClosedCallback& callback,
+ bool* did_suppress_message) override {}
+
+ void RunBeforeUnloadDialog(WebContents* web_contents,
+ bool is_reload,
+ const DialogClosedCallback& callback) override {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, false, base::string16()));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ message_loop_runner_->QuitClosure());
+ }
+
+ bool HandleJavaScriptDialog(WebContents* web_contents,
+ bool accept,
+ const base::string16* prompt_override) override {
+ return true;
+ }
+
+ void CancelDialogs(WebContents* web_contents, bool reset_state) override {}
+
+ private:
+ std::vector<GURL> visible_url_invalidations_;
+
+ // The MessageLoopRunner used to spin the message loop.
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(DialogDismissingWebContentsDelegate);
+};
+
+} // namespace
+
+// Test that if a BeforeUnload dialog is destroyed due to the commit of a
+// same-site or cross-site navigation, it will not reset the loading state.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ DismissingBeforeUnloadDialogInvalidatesUrl) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const GURL kStartURL(embedded_test_server()->GetURL(
+ "foo.com", "/render_frame_host/beforeunload.html"));
+ const GURL kSameSiteURL(
+ embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ const GURL kCrossSiteURL(
+ embedded_test_server()->GetURL("bar.com", "/title1.html"));
+
+ // Navigate to a first web page with a BeforeUnload event listener.
+ EXPECT_TRUE(NavigateToURL(shell(), kStartURL));
+
+ DialogDismissingWebContentsDelegate web_contents_delegate;
+ shell()->web_contents()->SetDelegate(&web_contents_delegate);
+ PrepContentsForBeforeUnloadTest(shell()->web_contents());
+
+ // Start a same-site navigation that is cancelled because of the beforeunload
+ // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the
+ // cancellation, so that the location bar resets to the original URL.
+ shell()->LoadURL(kSameSiteURL);
+ EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL());
+ web_contents_delegate.WaitForDialogDismissed();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(std::vector<GURL>{kStartURL},
+ web_contents_delegate.GetAndClearVisibleUrlInvalidations());
+
+ // Start a cross-site navigation that is cancelled because of the beforeunload
+ // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the
+ // cancellation, so that the location bar resets to the original URL.
+ shell()->LoadURL(kCrossSiteURL);
+ EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL());
+ web_contents_delegate.WaitForDialogDismissed();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(std::vector<GURL>{kStartURL},
+ web_contents_delegate.GetAndClearVisibleUrlInvalidations());
+
+ // Now clear the unload handler and re-try the navigations, which should now
+ // succeed. INVALIDATE_TYPE_URL should happen on commit, with the value of the
+ // new URL.
+ EXPECT_TRUE(ExecuteScript(shell(),
+ "window.onbeforeunload=function(e){return null;}"));
+ shell()->LoadURL(kSameSiteURL);
+ EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL());
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL());
+ EXPECT_EQ(std::vector<GURL>{kSameSiteURL},
+ web_contents_delegate.GetAndClearVisibleUrlInvalidations());
+
+ shell()->LoadURL(kCrossSiteURL);
+ EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL());
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL());
+ EXPECT_EQ(std::vector<GURL>{kCrossSiteURL},
+ web_contents_delegate.GetAndClearVisibleUrlInvalidations());
+
+ // Clear the test delegates.
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->SetJavaScriptDialogManagerForTesting(nullptr);
+ shell()->web_contents()->SetDelegate(shell());
+}
+
+namespace {
+
class TestJavaScriptDialogManager : public JavaScriptDialogManager,
public WebContentsDelegate {
public:
« no previous file with comments | « content/browser/web_contents/web_contents_impl.cc ('k') | content/public/browser/navigation_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698