Commit a02358d3 authored by wittman@chromium.org's avatar wittman@chromium.org

Provide configurable closing of web contents modal dialogs on interstitial webui

Allow individual web contents modal dialog users to specify that dialogs
should be closed when encountering interstitial webui (e.g. due to
SSL warnings).

Future CLs will enable use of this functionality for most dialogs. 

BUG=240575

Review URL: https://chromiumcodereview.appspot.com/23981002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221575 0039d316-1c4b-4281-b951-d872f2087c98
parent 5e3484fc
......@@ -34,7 +34,7 @@ void WebContentsModalDialogManager::SetDelegate(
void WebContentsModalDialogManager::ShowDialog(
NativeWebContentsModalDialog dialog) {
child_dialogs_.push_back(dialog);
child_dialogs_.push_back(DialogState(dialog));
native_manager_->ManageDialog(dialog);
......@@ -51,7 +51,15 @@ bool WebContentsModalDialogManager::IsShowingDialog() const {
void WebContentsModalDialogManager::FocusTopmostDialog() {
DCHECK(!child_dialogs_.empty());
native_manager_->FocusDialog(child_dialogs_.front());
native_manager_->FocusDialog(child_dialogs_.front().dialog);
}
void WebContentsModalDialogManager::SetCloseOnInterstitialWebUI(
NativeWebContentsModalDialog dialog,
bool close) {
WebContentsModalDialogList::iterator loc = FindDialogState(dialog);
DCHECK(loc != child_dialogs_.end());
loc->close_on_interstitial_webui = close;
}
content::WebContents* WebContentsModalDialogManager::GetWebContents() const {
......@@ -60,8 +68,7 @@ content::WebContents* WebContentsModalDialogManager::GetWebContents() const {
void WebContentsModalDialogManager::WillClose(
NativeWebContentsModalDialog dialog) {
WebContentsModalDialogList::iterator i(
std::find(child_dialogs_.begin(), child_dialogs_.end(), dialog));
WebContentsModalDialogList::iterator i = FindDialogState(dialog);
// The Views tab contents modal dialog calls WillClose twice. Ignore the
// second invocation.
......@@ -72,7 +79,7 @@ void WebContentsModalDialogManager::WillClose(
child_dialogs_.erase(i);
if (!child_dialogs_.empty() && removed_topmost_dialog &&
!closing_all_dialogs_)
native_manager_->ShowDialog(child_dialogs_.front());
native_manager_->ShowDialog(child_dialogs_.front().dialog);
BlockWebContentsInteraction(!child_dialogs_.empty());
}
......@@ -82,15 +89,14 @@ void WebContentsModalDialogManager::Observe(
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED);
if (child_dialogs_.empty())
return;
bool visible = *content::Details<bool>(details).ptr();
if (visible)
native_manager_->ShowDialog(child_dialogs_.front());
native_manager_->ShowDialog(child_dialogs_.front().dialog);
else
native_manager_->HideDialog(child_dialogs_.front());
native_manager_->HideDialog(child_dialogs_.front().dialog);
}
WebContentsModalDialogManager::WebContentsModalDialogManager(
......@@ -105,6 +111,24 @@ WebContentsModalDialogManager::WebContentsModalDialogManager(
content::Source<content::WebContents>(web_contents));
}
WebContentsModalDialogManager::DialogState::DialogState(
NativeWebContentsModalDialog dialog)
: dialog(dialog),
close_on_interstitial_webui(false) {
}
WebContentsModalDialogManager::WebContentsModalDialogList::iterator
WebContentsModalDialogManager::FindDialogState(
NativeWebContentsModalDialog dialog) {
WebContentsModalDialogList::iterator i;
for (i = child_dialogs_.begin(); i != child_dialogs_.end(); ++i) {
if (i->dialog == dialog)
break;
}
return i;
}
void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked) {
WebContents* contents = web_contents();
if (!contents) {
......@@ -125,7 +149,7 @@ void WebContentsModalDialogManager::CloseAllDialogs() {
// Clear out any dialogs since we are leaving this page entirely.
while (!child_dialogs_.empty())
native_manager_->CloseDialog(child_dialogs_.front());
native_manager_->CloseDialog(child_dialogs_.front().dialog);
closing_all_dialogs_ = false;
}
......@@ -142,7 +166,7 @@ void WebContentsModalDialogManager::DidNavigateMainFrame(
void WebContentsModalDialogManager::DidGetIgnoredUIEvent() {
if (!child_dialogs_.empty())
native_manager_->FocusDialog(child_dialogs_.front());
native_manager_->FocusDialog(child_dialogs_.front().dialog);
}
void WebContentsModalDialogManager::WebContentsDestroyed(WebContents* tab) {
......@@ -153,4 +177,15 @@ void WebContentsModalDialogManager::WebContentsDestroyed(WebContents* tab) {
CloseAllDialogs();
}
void WebContentsModalDialogManager::DidAttachInterstitialPage() {
// Copy the dialogs so we can close and remove them while iterating over the
// list.
WebContentsModalDialogList dialogs(child_dialogs_);
for (WebContentsModalDialogList::iterator it = dialogs.begin();
it != dialogs.end(); ++it) {
if (it->close_on_interstitial_webui)
native_manager_->CloseDialog(it->dialog);
}
}
} // namespace web_modal
......@@ -47,6 +47,10 @@ class WebContentsModalDialogManager
// calling this function.
void FocusTopmostDialog();
// Set to true to close the window when a page load starts on the WebContents.
void SetCloseOnInterstitialWebUI(NativeWebContentsModalDialog dialog,
bool close);
// Overriden from NativeWebContentsModalDialogManagerDelegate:
virtual content::WebContents* GetWebContents() const OVERRIDE;
// Called when a WebContentsModalDialogs we own is about to be closed.
......@@ -64,6 +68,7 @@ class WebContentsModalDialogManager
: manager_(manager) {}
void CloseAllDialogs() { manager_->CloseAllDialogs(); }
void DidAttachInterstitialPage() { manager_->DidAttachInterstitialPage(); }
void ResetNativeManager(NativeWebContentsModalDialogManager* delegate) {
manager_->native_manager_.reset(delegate);
}
......@@ -78,7 +83,18 @@ class WebContentsModalDialogManager
explicit WebContentsModalDialogManager(content::WebContents* web_contents);
friend class content::WebContentsUserData<WebContentsModalDialogManager>;
typedef std::deque<NativeWebContentsModalDialog> WebContentsModalDialogList;
struct DialogState {
explicit DialogState(NativeWebContentsModalDialog dialog);
NativeWebContentsModalDialog dialog;
bool close_on_interstitial_webui;
};
typedef std::deque<DialogState> WebContentsModalDialogList;
// Utility function to get the dialog state for a dialog.
WebContentsModalDialogList::iterator FindDialogState(
NativeWebContentsModalDialog dialog);
// Blocks/unblocks interaction with renderer process.
void BlockWebContentsInteraction(bool blocked);
......@@ -94,6 +110,7 @@ class WebContentsModalDialogManager
const content::FrameNavigateParams& params) OVERRIDE;
virtual void DidGetIgnoredUIEvent() OVERRIDE;
virtual void WebContentsDestroyed(content::WebContents* tab) OVERRIDE;
virtual void DidAttachInterstitialPage() OVERRIDE;
// Delegate for notifying our owner about stuff. Not owned by us.
WebContentsModalDialogManagerDelegate* delegate_;
......
......@@ -245,6 +245,30 @@ TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
native_manager->GetDialogState(dialog1));
}
// Test that attaching an interstitial WebUI page closes dialogs configured to
// close on interstitial WebUI.
TEST_F(WebContentsModalDialogManagerTest, InterstitialWebUI) {
const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
manager->ShowDialog(dialog1);
manager->ShowDialog(dialog2);
manager->ShowDialog(dialog3);
manager->SetCloseOnInterstitialWebUI(dialog1, true);
manager->SetCloseOnInterstitialWebUI(dialog3, true);
test_api->DidAttachInterstitialPage();
EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
native_manager->GetDialogState(dialog1));
EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
native_manager->GetDialogState(dialog2));
EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
native_manager->GetDialogState(dialog3));
}
// Test that the first dialog is always shown, regardless of the order in which
// dialogs are closed.
TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment