diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 04:37:54 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 04:37:54 +0000 |
commit | e41d0086cc673a9055bbf2bb071c51a141687c22 (patch) | |
tree | f9a45bfe8d6f582c556fb14205c25be8eb949e85 /components/web_modal | |
parent | ed223af80f326118beb39227876684ce3ceb6257 (diff) | |
download | chromium_src-e41d0086cc673a9055bbf2bb071c51a141687c22.zip chromium_src-e41d0086cc673a9055bbf2bb071c51a141687c22.tar.gz chromium_src-e41d0086cc673a9055bbf2bb071c51a141687c22.tar.bz2 |
components: Create web_modal component.
Notable changes:
* Move WebContentsModalDialog related classes into components/web_modal/
* Use namespace web_modal
* Move the logic for sending the Chrome IPC message out of
WebContentsModalDialogManager, and into ChromeModalDialogManager.
Have Browser and ShellWindow subclass ChromeModalDialogManager,
instead of directly from WebContentsModalDialogManager, to be able
to send the IPC.
* Introduce WebContentsModalDialogManagerDelegate::IsWebContentsVisibile.
This is necessary to remove the dependency on platform_util.
BUG=241278
R=ben@chromium.org, wittman@chromium.org
Review URL: https://codereview.chromium.org/14969012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200448 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/web_modal')
10 files changed, 592 insertions, 0 deletions
diff --git a/components/web_modal/DEPS b/components/web_modal/DEPS new file mode 100644 index 0000000..3539cc4 --- /dev/null +++ b/components/web_modal/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + "+content/public/browser", + "+content/public/test", + "+net/base", + "+ui/gfx", +] diff --git a/components/web_modal/native_web_contents_modal_dialog.h b/components/web_modal/native_web_contents_modal_dialog.h new file mode 100644 index 0000000..266e073 --- /dev/null +++ b/components/web_modal/native_web_contents_modal_dialog.h @@ -0,0 +1,22 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEB_MODAL_NATIVE_WEB_CONTENTS_MODAL_DIALOG_H_ +#define COMPONENTS_WEB_MODAL_NATIVE_WEB_CONTENTS_MODAL_DIALOG_H_ + +#include "ui/gfx/native_widget_types.h" + +namespace web_modal { + +#if defined(OS_MACOSX) +// Use a void* since none of the gfx::Native* types are suitable for +// representing the web contents modal dialog under Cocoa. +typedef void* NativeWebContentsModalDialog; +#else +typedef gfx::NativeView NativeWebContentsModalDialog; +#endif + +} // namespace web_modal + +#endif // COMPONENTS_WEB_MODAL_NATIVE_WEB_CONTENTS_MODAL_DIALOG_H_ diff --git a/components/web_modal/native_web_contents_modal_dialog_manager.h b/components/web_modal/native_web_contents_modal_dialog_manager.h new file mode 100644 index 0000000..7145a08 --- /dev/null +++ b/components/web_modal/native_web_contents_modal_dialog_manager.h @@ -0,0 +1,66 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEB_MODAL_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_ +#define COMPONENTS_WEB_MODAL_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_ + +#include "components/web_modal/native_web_contents_modal_dialog.h" + +namespace content { +class WebContents; +} // namespace content + +namespace web_modal { + +// Interface from NativeWebContentsModalDialogManager to +// WebContentsModalDialogManager. +class NativeWebContentsModalDialogManagerDelegate { + public: + NativeWebContentsModalDialogManagerDelegate() {} + virtual ~NativeWebContentsModalDialogManagerDelegate() {} + + virtual content::WebContents* GetWebContents() const = 0; + virtual void WillClose(NativeWebContentsModalDialog dialog) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerDelegate); +}; + +// Provides an interface for platform-specific UI implementation for the web +// contents modal dialog. +class NativeWebContentsModalDialogManager { + public: + virtual ~NativeWebContentsModalDialogManager() {} + + // Starts management of the modal aspects of the dialog. This function should + // also register to be notified when the dialog is closing, so that it can + // notify the manager. + virtual void ManageDialog(NativeWebContentsModalDialog dialog) = 0; + + // Makes the web contents modal dialog visible. Only one web contents modal + // dialog is shown at a time per tab. + virtual void ShowDialog(NativeWebContentsModalDialog dialog) = 0; + + // Hides the web contents modal dialog without closing it. + virtual void HideDialog(NativeWebContentsModalDialog dialog) = 0; + + // Closes the web contents modal dialog. + virtual void CloseDialog(NativeWebContentsModalDialog dialog) = 0; + + // Sets focus on the web contents modal dialog. + virtual void FocusDialog(NativeWebContentsModalDialog dialog) = 0; + + // Runs a pulse animation for the web contents modal dialog. + virtual void PulseDialog(NativeWebContentsModalDialog dialog) = 0; + + protected: + NativeWebContentsModalDialogManager() {} + + private: + DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManager); +}; + +} // namespace web_modal + +#endif // COMPONENTS_WEB_MODAL_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_ diff --git a/components/web_modal/web_contents_modal_dialog_host.cc b/components/web_modal/web_contents_modal_dialog_host.cc new file mode 100644 index 0000000..1dcaa00 --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_host.cc @@ -0,0 +1,21 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/web_modal/web_contents_modal_dialog_host.h" + +namespace web_modal { + +WebContentsModalDialogHostObserver::~WebContentsModalDialogHostObserver() { +} + +WebContentsModalDialogHostObserver::WebContentsModalDialogHostObserver() { +} + +WebContentsModalDialogHost::~WebContentsModalDialogHost() { +} + +WebContentsModalDialogHost::WebContentsModalDialogHost() { +} + +} // namespace web_modal diff --git a/components/web_modal/web_contents_modal_dialog_host.h b/components/web_modal/web_contents_modal_dialog_host.h new file mode 100644 index 0000000..499925c --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_host.h @@ -0,0 +1,54 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_HOST_H_ +#define COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_HOST_H_ + +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/point.h" +#include "ui/gfx/size.h" + +namespace web_modal { + +// Observer to be implemented to update web contents modal dialogs when the host +// indicates their position needs to be changed. +class WebContentsModalDialogHostObserver { + public: + virtual ~WebContentsModalDialogHostObserver(); + + virtual void OnPositionRequiresUpdate() = 0; + + protected: + WebContentsModalDialogHostObserver(); + + private: + DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogHostObserver); +}; + +// Interface for supporting positioning of web contents modal dialogs over a +// window/widget. +class WebContentsModalDialogHost { + public: + virtual ~WebContentsModalDialogHost(); + + // Returns the view against which the dialog is positioned and parented. + virtual gfx::NativeView GetHostView() const = 0; + // Gets the position for the dialog in coordinates relative to the host + // view. + virtual gfx::Point GetDialogPosition(const gfx::Size& size) = 0; + + // Add/remove observer. + virtual void AddObserver(WebContentsModalDialogHostObserver* observer) = 0; + virtual void RemoveObserver(WebContentsModalDialogHostObserver* observer) = 0; + + protected: + WebContentsModalDialogHost(); + + private: + DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogHost); +}; + +} // namespace web_modal + +#endif // COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_HOST_H_ diff --git a/components/web_modal/web_contents_modal_dialog_manager.cc b/components/web_modal/web_contents_modal_dialog_manager.cc new file mode 100644 index 0000000..0e07f8d --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_manager.cc @@ -0,0 +1,149 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/web_modal/web_contents_modal_dialog_manager.h" + +#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_view.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" + +using content::WebContents; + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(web_modal::WebContentsModalDialogManager); + +namespace web_modal { + +WebContentsModalDialogManager::~WebContentsModalDialogManager() { + DCHECK(child_dialogs_.empty()); +} + +void WebContentsModalDialogManager::ShowDialog( + NativeWebContentsModalDialog dialog) { + child_dialogs_.push_back(dialog); + + native_manager_->ManageDialog(dialog); + + if (child_dialogs_.size() == 1) { + if (delegate_ && delegate_->IsWebContentsVisible(web_contents())) + native_manager_->ShowDialog(dialog); + BlockWebContentsInteraction(true); + } +} + +bool WebContentsModalDialogManager::IsShowingDialog() const { + return !child_dialogs_.empty(); +} + +void WebContentsModalDialogManager::FocusTopmostDialog() { + DCHECK(!child_dialogs_.empty()); + native_manager_->FocusDialog(child_dialogs_.front()); +} + +content::WebContents* WebContentsModalDialogManager::GetWebContents() const { + return web_contents(); +} + +void WebContentsModalDialogManager::WillClose( + NativeWebContentsModalDialog dialog) { + WebContentsModalDialogList::iterator i( + std::find(child_dialogs_.begin(), child_dialogs_.end(), dialog)); + + // The Views tab contents modal dialog calls WillClose twice. Ignore the + // second invocation. + if (i == child_dialogs_.end()) + return; + + bool removed_topmost_dialog = i == child_dialogs_.begin(); + child_dialogs_.erase(i); + if (!child_dialogs_.empty() && removed_topmost_dialog && + !closing_all_dialogs_) + native_manager_->ShowDialog(child_dialogs_.front()); + + BlockWebContentsInteraction(!child_dialogs_.empty()); +} + +void WebContentsModalDialogManager::Observe( + int type, + 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()); + else + native_manager_->HideDialog(child_dialogs_.front()); +} + +WebContentsModalDialogManager::WebContentsModalDialogManager( + content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + delegate_(NULL), + native_manager_(CreateNativeManager(this)), + closing_all_dialogs_(false) { + DCHECK(native_manager_); + registrar_.Add(this, + content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, + content::Source<content::WebContents>(web_contents)); +} + +void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked) { + WebContents* contents = web_contents(); + if (!contents) { + // The WebContents has already disconnected. + return; + } + + // RenderViewHost may be NULL during shutdown. + content::RenderViewHost* host = contents->GetRenderViewHost(); + if (host) + host->SetIgnoreInputEvents(blocked); + if (delegate_) + delegate_->SetWebContentsBlocked(contents, blocked); +} + +void WebContentsModalDialogManager::CloseAllDialogs() { + closing_all_dialogs_ = true; + + // Clear out any dialogs since we are leaving this page entirely. + while (!child_dialogs_.empty()) + native_manager_->CloseDialog(child_dialogs_.front()); + + closing_all_dialogs_ = false; +} + +void WebContentsModalDialogManager::DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + // Close constrained windows if necessary. + if (!net::registry_controlled_domains::SameDomainOrHost( + details.previous_url, details.entry->GetURL(), + net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) + CloseAllDialogs(); +} + +void WebContentsModalDialogManager::DidGetIgnoredUIEvent() { + if (!child_dialogs_.empty()) + native_manager_->FocusDialog(child_dialogs_.front()); +} + +void WebContentsModalDialogManager::WebContentsDestroyed(WebContents* tab) { + // First cleanly close all child dialogs. + // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked + // some of these to close. CloseAllDialogs is async, so it might get called + // twice before it runs. + CloseAllDialogs(); +} + +} // namespace web_modal diff --git a/components/web_modal/web_contents_modal_dialog_manager.h b/components/web_modal/web_contents_modal_dialog_manager.h new file mode 100644 index 0000000..e2548c0 --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_manager.h @@ -0,0 +1,116 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_ +#define COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_ + +#include <deque> + +#include "base/memory/scoped_ptr.h" +#include "components/web_modal/native_web_contents_modal_dialog_manager.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" +#include "ui/gfx/native_widget_types.h" + +namespace web_modal { + +class WebContentsModalDialogManagerDelegate; + +// Per-WebContents class to manage WebContents-modal dialogs. +class WebContentsModalDialogManager + : public NativeWebContentsModalDialogManagerDelegate, + public content::WebContentsObserver, + public content::WebContentsUserData<WebContentsModalDialogManager>, + public content::NotificationObserver { + public: + virtual ~WebContentsModalDialogManager(); + + WebContentsModalDialogManagerDelegate* delegate() const { return delegate_; } + void set_delegate(WebContentsModalDialogManagerDelegate* d) { delegate_ = d; } + + static NativeWebContentsModalDialogManager* CreateNativeManager( + NativeWebContentsModalDialogManagerDelegate* native_delegate); + + // Shows the dialog as a web contents modal dialog. The dialog will notify via + // WillClose() when it is being destroyed. + void ShowDialog(NativeWebContentsModalDialog dialog); + + // Returns true if a dialog is currently being shown. + bool IsShowingDialog() const; + + // Focus the topmost modal dialog. IsShowingDialog() must be true when + // calling this function. + void FocusTopmostDialog(); + + // Overriden from NativeWebContentsModalDialogManagerDelegate: + virtual content::WebContents* GetWebContents() const OVERRIDE; + // Called when a WebContentsModalDialogs we own is about to be closed. + virtual void WillClose(NativeWebContentsModalDialog dialog) OVERRIDE; + + // content::NotificationObserver overrides + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // For testing. + class TestApi { + public: + explicit TestApi(WebContentsModalDialogManager* manager) + : manager_(manager) {} + + void CloseAllDialogs() { manager_->CloseAllDialogs(); } + void ResetNativeManager(NativeWebContentsModalDialogManager* delegate) { + manager_->native_manager_.reset(delegate); + } + + private: + WebContentsModalDialogManager* manager_; + + DISALLOW_COPY_AND_ASSIGN(TestApi); + }; + + private: + explicit WebContentsModalDialogManager(content::WebContents* web_contents); + friend class content::WebContentsUserData<WebContentsModalDialogManager>; + + typedef std::deque<NativeWebContentsModalDialog> WebContentsModalDialogList; + + // Blocks/unblocks interaction with renderer process. + void BlockWebContentsInteraction(bool blocked); + + bool IsWebContentsVisible() const; + + // Closes all WebContentsModalDialogs. + void CloseAllDialogs(); + + // Overridden from content::WebContentsObserver: + virtual void DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) OVERRIDE; + virtual void DidGetIgnoredUIEvent() OVERRIDE; + virtual void WebContentsDestroyed(content::WebContents* tab) OVERRIDE; + + // Delegate for notifying our owner about stuff. Not owned by us. + WebContentsModalDialogManagerDelegate* delegate_; + + // Delegate for native UI-specific functions on the dialog. + scoped_ptr<NativeWebContentsModalDialogManager> native_manager_; + + // All active dialogs. + WebContentsModalDialogList child_dialogs_; + + // True while closing the dialogs on WebContents close. + bool closing_all_dialogs_; + + // A scoped container for notification registries. + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManager); +}; + +} // namespace web_modal + +#endif // COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_ diff --git a/components/web_modal/web_contents_modal_dialog_manager_delegate.cc b/components/web_modal/web_contents_modal_dialog_manager_delegate.cc new file mode 100644 index 0000000..25a777c --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_manager_delegate.cc @@ -0,0 +1,28 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" + +#include <string.h> + +namespace web_modal { + +void WebContentsModalDialogManagerDelegate::SetWebContentsBlocked( + content::WebContents* web_contents, bool blocked) { +} + +WebContentsModalDialogHost* + WebContentsModalDialogManagerDelegate::GetWebContentsModalDialogHost() { + return NULL; +} + +bool WebContentsModalDialogManagerDelegate::IsWebContentsVisible( + content::WebContents* web_contents) { + return true; +} + +WebContentsModalDialogManagerDelegate::~WebContentsModalDialogManagerDelegate( +) {} + +} // namespace web_modal diff --git a/components/web_modal/web_contents_modal_dialog_manager_delegate.h b/components/web_modal/web_contents_modal_dialog_manager_delegate.h new file mode 100644 index 0000000..76f7435 --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_manager_delegate.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_DELEGATE_H_ +#define COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_DELEGATE_H_ + +namespace content { +class WebContents; +} + +namespace gfx { +class Point; +} + +namespace web_modal { + +class WebContentsModalDialogHost; + +class WebContentsModalDialogManagerDelegate { + public: + // Changes the blocked state of |web_contents|. WebContentses are considered + // blocked while displaying a web contents modal dialog. During that time + // renderer host will ignore any UI interaction within WebContents outside of + // the currently displaying dialog. + virtual void SetWebContentsBlocked(content::WebContents* web_contents, + bool blocked); + + // Returns the WebContentsModalDialogHost for use in positioning web contents + // modal dialogs within the browser window. + virtual WebContentsModalDialogHost* GetWebContentsModalDialogHost(); + + // Returns whether the WebContents is currently visible or not. + virtual bool IsWebContentsVisible(content::WebContents* web_contents); + + protected: + virtual ~WebContentsModalDialogManagerDelegate(); +}; + +} // namespace web_modal + +#endif // COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_DELEGATE_H_ diff --git a/components/web_modal/web_contents_modal_dialog_manager_unittest.cc b/components/web_modal/web_contents_modal_dialog_manager_unittest.cc new file mode 100644 index 0000000..613182b --- /dev/null +++ b/components/web_modal/web_contents_modal_dialog_manager_unittest.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/web_modal/native_web_contents_modal_dialog_manager.h" +#include "components/web_modal/web_contents_modal_dialog_manager.h" +#include "content/public/test/test_browser_thread.h" +#include "content/public/test/test_renderer_host.h" +#include "testing/gtest/include/gtest/gtest.h" + +using content::BrowserThread; + +namespace web_modal { + +class WebContentsModalDialogManagerTest + : public content::RenderViewHostTestHarness { + public: + WebContentsModalDialogManagerTest() + : ui_thread_(BrowserThread::UI, &message_loop_) { + } + + virtual void SetUp() { + content::RenderViewHostTestHarness::SetUp(); + WebContentsModalDialogManager::CreateForWebContents(web_contents()); + } + + private: + content::TestBrowserThread ui_thread_; +}; + +class NativeWebContentsModalDialogManagerCloseTest + : public NativeWebContentsModalDialogManager { + public: + NativeWebContentsModalDialogManagerCloseTest( + NativeWebContentsModalDialogManagerDelegate* delegate) + : delegate_(delegate) {} + virtual void ManageDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + } + virtual void ShowDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + } + virtual void HideDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + } + virtual void CloseDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + delegate_->WillClose(dialog); + close_count++; + } + virtual void FocusDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + } + virtual void PulseDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + } + + int close_count; + NativeWebContentsModalDialogManagerDelegate* delegate_; +}; + +NativeWebContentsModalDialogManager* WebContentsModalDialogManager:: +CreateNativeManager( + NativeWebContentsModalDialogManagerDelegate* native_delegate) { + return new NativeWebContentsModalDialogManagerCloseTest(native_delegate); +} + +TEST_F(WebContentsModalDialogManagerTest, WebContentsModalDialogs) { + WebContentsModalDialogManager* web_contents_modal_dialog_manager = + WebContentsModalDialogManager::FromWebContents(web_contents()); + WebContentsModalDialogManager::TestApi test_api( + web_contents_modal_dialog_manager); + + NativeWebContentsModalDialogManagerCloseTest* native_manager = + new NativeWebContentsModalDialogManagerCloseTest( + web_contents_modal_dialog_manager); + native_manager->close_count = 0; + + test_api.ResetNativeManager(native_manager); + + const int kWindowCount = 4; + for (int i = 0; i < kWindowCount; i++) + // WebContentsModalDialogManager treats the NativeWebContentsModalDialog as + // an opaque type, so creating fake NativeWebContentsModalDialogs using + // reinterpret_cast is valid. + web_contents_modal_dialog_manager->ShowDialog( + reinterpret_cast<NativeWebContentsModalDialog>(i)); + EXPECT_EQ(native_manager->close_count, 0); + + test_api.CloseAllDialogs(); + EXPECT_EQ(native_manager->close_count, kWindowCount); +} + +} // namespace web_modal |