diff options
author | creis <creis@chromium.org> | 2015-05-27 09:13:17 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-27 16:13:54 +0000 |
commit | 89a0f782193755ad7a0b93c58dbcc1b96528405f (patch) | |
tree | 427065bf2bf7eabae88fc659cdf6ae3255138666 | |
parent | 0a5834c562d3455f3e70c50506453d19170e0b51 (diff) | |
download | chromium_src-89a0f782193755ad7a0b93c58dbcc1b96528405f.zip chromium_src-89a0f782193755ad7a0b93c58dbcc1b96528405f.tar.gz chromium_src-89a0f782193755ad7a0b93c58dbcc1b96528405f.tar.bz2 |
Dismiss browser plugin modal dialogs when the embedder needs to.
Test from wjmaclean@. PDF simply shows an alert dialog using script.
BUG=482380
TEST=See bug for repro steps.
Review URL: https://codereview.chromium.org/1150843002
Cr-Commit-Position: refs/heads/master@{#331584}
-rw-r--r-- | chrome/browser/ui/browser_browsertest.cc | 26 | ||||
-rw-r--r-- | chrome/test/data/alert_dialog.pdf | bin | 0 -> 1083 bytes | |||
-rw-r--r-- | content/browser/browser_plugin/browser_plugin_embedder.cc | 14 | ||||
-rw-r--r-- | content/browser/browser_plugin/browser_plugin_embedder.h | 6 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.cc | 21 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.h | 4 |
6 files changed, 65 insertions, 6 deletions
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 68eb19f..99cdde0 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc @@ -586,6 +586,32 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsSubframeDialogs) { ui_test_utils::NavigateToURL(browser(), url2); } +// Make sure modal dialogs within a guestview are closed when an interstitial +// page is showing. See crbug.com/482380. +IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCancelsGuestViewDialogs) { + // Navigate to a PDF, which is loaded within a guestview. + ASSERT_TRUE(test_server()->Start()); + GURL pdf_with_dialog(test_server()->GetURL("files/alert_dialog.pdf")); + ui_test_utils::NavigateToURL(browser(), pdf_with_dialog); + + AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); + EXPECT_TRUE(alert->IsValid()); + AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); + EXPECT_TRUE(dialog_queue->HasActiveDialog()); + + WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); + + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, false, GURL()); + content::WaitForInterstitialAttach(contents); + + // The interstitial should have closed the dialog. + EXPECT_TRUE(contents->ShowingInterstitialPage()); + EXPECT_FALSE(dialog_queue->HasActiveDialog()); + + interstitial->DontProceed(); +} + // Test for crbug.com/22004. Reloading a page with a before unload handler and // then canceling the dialog should not leave the throbber spinning. IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) { diff --git a/chrome/test/data/alert_dialog.pdf b/chrome/test/data/alert_dialog.pdf Binary files differnew file mode 100644 index 0000000..5c20ec5 --- /dev/null +++ b/chrome/test/data/alert_dialog.pdf diff --git a/content/browser/browser_plugin/browser_plugin_embedder.cc b/content/browser/browser_plugin/browser_plugin_embedder.cc index cee9b43..e563df0 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder.cc +++ b/content/browser/browser_plugin/browser_plugin_embedder.cc @@ -64,6 +64,20 @@ void BrowserPluginEmbedder::ScreenInfoChanged() { &BrowserPluginEmbedder::NotifyScreenInfoChanged)); } +// static +bool BrowserPluginEmbedder::CancelDialogs(WebContents* guest_web_contents) { + static_cast<WebContentsImpl*>(guest_web_contents) + ->CancelActiveAndPendingDialogs(); + + // Returns false to iterate over all guests. + return false; +} + +void BrowserPluginEmbedder::CancelGuestDialogs() { + GetBrowserPluginGuestManager()->ForEachGuest( + web_contents(), base::Bind(&BrowserPluginEmbedder::CancelDialogs)); +} + void BrowserPluginEmbedder::StartDrag(BrowserPluginGuest* guest) { guest_started_drag_ = guest->AsWeakPtr(); guest_drag_ending_ = false; diff --git a/content/browser/browser_plugin/browser_plugin_embedder.h b/content/browser/browser_plugin/browser_plugin_embedder.h index 721814f..842d3ee 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder.h +++ b/content/browser/browser_plugin/browser_plugin_embedder.h @@ -56,6 +56,9 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { // Called when the screen info has changed. void ScreenInfoChanged(); + // Closes modal dialogs in all of the guests. + void CancelGuestDialogs(); + // Called by WebContentsViewGuest when a drag operation is started within // |guest|. This |guest| will be signaled at the end of the drag operation. void StartDrag(BrowserPluginGuest* guest); @@ -84,6 +87,9 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { // Notifies a guest that the embedder's screen info has changed. static bool NotifyScreenInfoChanged(WebContents* guest_web_contents); + // Closes modal dialogs in |guest_web_contents|. + static bool CancelDialogs(WebContents* guest_web_contents); + static bool UnlockMouseIfNecessaryCallback(bool* mouse_unlocked, WebContents* guest); diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index e5c61bb..407c25e 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -678,6 +678,13 @@ int WebContentsImpl::GetRoutingID() const { return GetRenderViewHost()->GetRoutingID(); } +void WebContentsImpl::CancelActiveAndPendingDialogs() { + if (dialog_manager_) + dialog_manager_->CancelActiveAndPendingDialogs(this); + if (browser_plugin_embedder_) + browser_plugin_embedder_->CancelGuestDialogs(); +} + int WebContentsImpl::GetFullscreenWidgetRoutingID() const { return fullscreen_widget_routing_id_; } @@ -1995,8 +2002,7 @@ void WebContentsImpl::AttachInterstitialPage( // Cancel any visible dialogs so that they don't interfere with the // interstitial. - if (dialog_manager_) - dialog_manager_->CancelActiveAndPendingDialogs(this); + CancelActiveAndPendingDialogs(); FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidAttachInterstitialPage()); @@ -2752,8 +2758,8 @@ void WebContentsImpl::DidNavigateAnyFramePostCommit( has_accessed_initial_document_ = false; // If we navigate off the page, close all JavaScript dialogs. - if (dialog_manager_ && !details.is_in_page) - dialog_manager_->CancelActiveAndPendingDialogs(this); + if (!details.is_in_page) + CancelActiveAndPendingDialogs(); // Notify observers about navigation. FOR_EACH_OBSERVER(WebContentsObserver, observers_, @@ -3604,8 +3610,7 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh, ExitFullscreenMode(); // Cancel any visible dialogs so they are not left dangling over the sad tab. - if (dialog_manager_) - dialog_manager_->CancelActiveAndPendingDialogs(this); + CancelActiveAndPendingDialogs(); if (delegate_) delegate_->HideValidationMessage(this); @@ -4054,6 +4059,10 @@ void WebContentsImpl::CancelModalDialogsForRenderManager() { // deferrer would prevent us from swapping out. We also clear the state // because this is a cross-process navigation, which means that it's a new // site that should not have to pay for the sins of its predecessor. + // + // Note that we don't bother telling browser_plugin_embedder_ because the + // cross-process navigation will either destroy the browser plugins or not + // require their dialogs to close. if (dialog_manager_) dialog_manager_->ResetDialogState(this); } diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 91a395f..709071f 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -158,6 +158,10 @@ class CONTENT_EXPORT WebContentsImpl // already exist. void CreateBrowserPluginEmbedderIfNecessary(); + // Cancels modal dialogs in this WebContents, as well as in any browser + // plugins it is hosting. + void CancelActiveAndPendingDialogs(); + // Gets the current fullscreen render widget's routing ID. Returns // MSG_ROUTING_NONE when there is no fullscreen render widget. int GetFullscreenWidgetRoutingID() const; |