summaryrefslogtreecommitdiff
path: root/chromium/components/web_modal
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/components/web_modal
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/components/web_modal')
-rw-r--r--chromium/components/web_modal/BUILD.gn63
-rw-r--r--chromium/components/web_modal/DEPS6
-rw-r--r--chromium/components/web_modal/OWNERS1
-rw-r--r--chromium/components/web_modal/modal_dialog_host.cc15
-rw-r--r--chromium/components/web_modal/modal_dialog_host.h44
-rw-r--r--chromium/components/web_modal/single_web_contents_dialog_manager.h80
-rw-r--r--chromium/components/web_modal/test_web_contents_modal_dialog_host.cc36
-rw-r--r--chromium/components/web_modal/test_web_contents_modal_dialog_host.h42
-rw-r--r--chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.cc31
-rw-r--r--chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.h48
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_host.cc12
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_host.h30
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager.cc186
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager.h125
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager_delegate.cc28
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager_delegate.h42
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc363
17 files changed, 1152 insertions, 0 deletions
diff --git a/chromium/components/web_modal/BUILD.gn b/chromium/components/web_modal/BUILD.gn
new file mode 100644
index 00000000000..839715efbd2
--- /dev/null
+++ b/chromium/components/web_modal/BUILD.gn
@@ -0,0 +1,63 @@
+# Copyright 2014 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.
+
+static_library("web_modal") {
+ sources = [
+ "modal_dialog_host.cc",
+ "modal_dialog_host.h",
+ "single_web_contents_dialog_manager.h",
+ "web_contents_modal_dialog_host.cc",
+ "web_contents_modal_dialog_host.h",
+ "web_contents_modal_dialog_manager.cc",
+ "web_contents_modal_dialog_manager.h",
+ "web_contents_modal_dialog_manager_delegate.cc",
+ "web_contents_modal_dialog_manager_delegate.h",
+ ]
+
+ deps = [
+ "//base",
+ "//content/public/browser",
+ "//net",
+ "//skia",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ]
+}
+
+static_library("test_support") {
+ testonly = true
+ sources = [
+ "test_web_contents_modal_dialog_host.cc",
+ "test_web_contents_modal_dialog_host.h",
+ "test_web_contents_modal_dialog_manager_delegate.cc",
+ "test_web_contents_modal_dialog_manager_delegate.h",
+ ]
+
+ public_deps = [
+ ":web_modal",
+ ]
+ deps = [
+ "//base",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ]
+}
+
+if (!is_android && !is_ios) {
+ source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "web_contents_modal_dialog_manager_unittest.cc",
+ ]
+
+ deps = [
+ ":test_support",
+ ":web_modal",
+ "//base",
+ "//content/test:test_support",
+ "//testing/gtest",
+ ]
+ }
+}
diff --git a/chromium/components/web_modal/DEPS b/chromium/components/web_modal/DEPS
new file mode 100644
index 00000000000..3539cc43913
--- /dev/null
+++ b/chromium/components/web_modal/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+content/public/browser",
+ "+content/public/test",
+ "+net/base",
+ "+ui/gfx",
+]
diff --git a/chromium/components/web_modal/OWNERS b/chromium/components/web_modal/OWNERS
new file mode 100644
index 00000000000..12a9b0975ce
--- /dev/null
+++ b/chromium/components/web_modal/OWNERS
@@ -0,0 +1 @@
+wittman@chromium.org
diff --git a/chromium/components/web_modal/modal_dialog_host.cc b/chromium/components/web_modal/modal_dialog_host.cc
new file mode 100644
index 00000000000..61ddbc29a74
--- /dev/null
+++ b/chromium/components/web_modal/modal_dialog_host.cc
@@ -0,0 +1,15 @@
+// Copyright 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/modal_dialog_host.h"
+
+namespace web_modal {
+
+ModalDialogHostObserver::~ModalDialogHostObserver() {
+}
+
+ModalDialogHost::~ModalDialogHost() {
+}
+
+} // namespace web_modal
diff --git a/chromium/components/web_modal/modal_dialog_host.h b/chromium/components/web_modal/modal_dialog_host.h
new file mode 100644
index 00000000000..c7842b3da32
--- /dev/null
+++ b/chromium/components/web_modal/modal_dialog_host.h
@@ -0,0 +1,44 @@
+// Copyright 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_MODAL_DIALOG_HOST_H_
+#define COMPONENTS_WEB_MODAL_MODAL_DIALOG_HOST_H_
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Point;
+class Size;
+} // namespace gfx
+
+namespace web_modal {
+
+// Observer to be implemented to update modal dialogs when the host indicates
+// their position needs to be changed.
+class ModalDialogHostObserver {
+ public:
+ virtual ~ModalDialogHostObserver();
+
+ virtual void OnPositionRequiresUpdate() = 0;
+ virtual void OnHostDestroying() = 0;
+};
+
+// Interface for supporting positioning of modal dialogs over a window/widget.
+class ModalDialogHost {
+ public:
+ virtual ~ModalDialogHost();
+
+ // 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(ModalDialogHostObserver* observer) = 0;
+ virtual void RemoveObserver(ModalDialogHostObserver* observer) = 0;
+};
+
+} // namespace web_modal
+
+#endif // COMPONENTS_WEB_MODAL_MODAL_DIALOG_HOST_H_
diff --git a/chromium/components/web_modal/single_web_contents_dialog_manager.h b/chromium/components/web_modal/single_web_contents_dialog_manager.h
new file mode 100644
index 00000000000..7d85368409d
--- /dev/null
+++ b/chromium/components/web_modal/single_web_contents_dialog_manager.h
@@ -0,0 +1,80 @@
+// Copyright 2014 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_SINGLE_WEB_CONTENTS_DIALOG_MANAGER_H_
+#define COMPONENTS_WEB_MODAL_SINGLE_WEB_CONTENTS_DIALOG_MANAGER_H_
+
+#include "base/macros.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace content {
+class WebContents;
+} // namespace content
+
+namespace web_modal {
+
+class WebContentsModalDialogHost;
+
+// Interface from SingleWebContentsDialogManager to
+// WebContentsModalDialogManager.
+class SingleWebContentsDialogManagerDelegate {
+ public:
+ SingleWebContentsDialogManagerDelegate() {}
+ virtual ~SingleWebContentsDialogManagerDelegate() {}
+
+ virtual content::WebContents* GetWebContents() const = 0;
+
+ // Notify the delegate that the dialog is closing. The native
+ // manager will be deleted before the end of this call.
+ virtual void WillClose(gfx::NativeWindow dialog) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SingleWebContentsDialogManagerDelegate);
+};
+
+// Provides an interface for platform-specific UI implementation for the web
+// contents modal dialog. Each object will manage a single dialog window
+// during its lifecycle.
+//
+// Implementation classes should accept a dialog window at construction time
+// and register to be notified when the dialog is closing, so that it can
+// notify its delegate (WillClose method).
+class SingleWebContentsDialogManager {
+ public:
+ virtual ~SingleWebContentsDialogManager() {}
+
+ // Makes the web contents modal dialog visible. Only one web contents modal
+ // dialog is shown at a time per tab.
+ virtual void Show() = 0;
+
+ // Hides the web contents modal dialog without closing it.
+ virtual void Hide() = 0;
+
+ // Closes the web contents modal dialog.
+ // If this method causes a WillClose() call to the delegate, the manager
+ // will be deleted at the close of that invocation.
+ virtual void Close() = 0;
+
+ // Sets focus on the web contents modal dialog.
+ virtual void Focus() = 0;
+
+ // Runs a pulse animation for the web contents modal dialog.
+ virtual void Pulse() = 0;
+
+ // Called when the host view for the dialog has changed.
+ virtual void HostChanged(WebContentsModalDialogHost* new_host) = 0;
+
+ // Return the dialog under management by this object.
+ virtual gfx::NativeWindow dialog() = 0;
+
+ protected:
+ SingleWebContentsDialogManager() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SingleWebContentsDialogManager);
+};
+
+} // namespace web_modal
+
+#endif // COMPONENTS_WEB_MODAL_SINGLE_WEB_CONTENTS_DIALOG_MANAGER_H_
diff --git a/chromium/components/web_modal/test_web_contents_modal_dialog_host.cc b/chromium/components/web_modal/test_web_contents_modal_dialog_host.cc
new file mode 100644
index 00000000000..28a5d81f1e4
--- /dev/null
+++ b/chromium/components/web_modal/test_web_contents_modal_dialog_host.cc
@@ -0,0 +1,36 @@
+// Copyright 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/test_web_contents_modal_dialog_host.h"
+
+#include "ui/gfx/geometry/point.h"
+
+namespace web_modal {
+
+TestWebContentsModalDialogHost::TestWebContentsModalDialogHost(
+ gfx::NativeView host_view)
+ : host_view_(host_view) {}
+
+TestWebContentsModalDialogHost::~TestWebContentsModalDialogHost() {}
+
+gfx::Size TestWebContentsModalDialogHost::GetMaximumDialogSize() {
+ return max_dialog_size_;
+}
+
+gfx::NativeView TestWebContentsModalDialogHost::GetHostView() const {
+ return host_view_;
+}
+
+gfx::Point TestWebContentsModalDialogHost::GetDialogPosition(
+ const gfx::Size& size) {
+ return gfx::Point();
+}
+
+void TestWebContentsModalDialogHost::AddObserver(
+ ModalDialogHostObserver* observer) {}
+
+void TestWebContentsModalDialogHost::RemoveObserver(
+ ModalDialogHostObserver* observer) {}
+
+} // namespace web_modal
diff --git a/chromium/components/web_modal/test_web_contents_modal_dialog_host.h b/chromium/components/web_modal/test_web_contents_modal_dialog_host.h
new file mode 100644
index 00000000000..8348f68dec1
--- /dev/null
+++ b/chromium/components/web_modal/test_web_contents_modal_dialog_host.h
@@ -0,0 +1,42 @@
+// Copyright 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_TEST_WEB_CONTENTS_MODAL_DIALOG_HOST_H_
+#define COMPONENTS_WEB_MODAL_TEST_WEB_CONTENTS_MODAL_DIALOG_HOST_H_
+
+#include "components/web_modal/web_contents_modal_dialog_host.h"
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace web_modal {
+
+class TestWebContentsModalDialogHost : public WebContentsModalDialogHost {
+ public:
+ explicit TestWebContentsModalDialogHost(gfx::NativeView host_view);
+ ~TestWebContentsModalDialogHost() override;
+
+ // WebContentsModalDialogHost:
+ gfx::Size GetMaximumDialogSize() override;
+ gfx::NativeView GetHostView() const override;
+ gfx::Point GetDialogPosition(const gfx::Size& size) override;
+ void AddObserver(ModalDialogHostObserver* observer) override;
+ void RemoveObserver(ModalDialogHostObserver* observer) override;
+
+ void set_max_dialog_size(const gfx::Size& max_dialog_size) {
+ max_dialog_size_ = max_dialog_size;
+ }
+
+ private:
+ gfx::NativeView host_view_;
+ gfx::Size max_dialog_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestWebContentsModalDialogHost);
+};
+
+} // namespace web_modal
+
+#endif // COMPONENTS_WEB_MODAL_TEST_WEB_CONTENTS_MODAL_DIALOG_HOST_H_
diff --git a/chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.cc b/chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.cc
new file mode 100644
index 00000000000..53c94d2caf9
--- /dev/null
+++ b/chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.cc
@@ -0,0 +1,31 @@
+// Copyright 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/test_web_contents_modal_dialog_manager_delegate.h"
+
+namespace web_modal {
+
+TestWebContentsModalDialogManagerDelegate::
+ TestWebContentsModalDialogManagerDelegate()
+ : web_contents_visible_(true),
+ web_contents_blocked_(false),
+ web_contents_modal_dialog_host_(NULL) {}
+
+void TestWebContentsModalDialogManagerDelegate::SetWebContentsBlocked(
+ content::WebContents* web_contents,
+ bool blocked) {
+ web_contents_blocked_ = blocked;
+}
+
+WebContentsModalDialogHost* TestWebContentsModalDialogManagerDelegate::
+ GetWebContentsModalDialogHost() {
+ return web_contents_modal_dialog_host_;
+}
+
+bool TestWebContentsModalDialogManagerDelegate::IsWebContentsVisible(
+ content::WebContents* web_contents) {
+ return web_contents_visible_;
+}
+
+} // namespace web_modal
diff --git a/chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.h b/chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.h
new file mode 100644
index 00000000000..8221424ae13
--- /dev/null
+++ b/chromium/components/web_modal/test_web_contents_modal_dialog_manager_delegate.h
@@ -0,0 +1,48 @@
+// Copyright 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_TEST_WEB_CONTENTS_MODAL_DIALOG_MANAGER_DELEGATE_H_
+#define COMPONENTS_WEB_MODAL_TEST_WEB_CONTENTS_MODAL_DIALOG_MANAGER_DELEGATE_H_
+
+#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+
+namespace web_modal {
+
+class TestWebContentsModalDialogManagerDelegate
+ : public WebContentsModalDialogManagerDelegate {
+ public:
+ TestWebContentsModalDialogManagerDelegate();
+
+ // WebContentsModalDialogManagerDelegate overrides:
+ void SetWebContentsBlocked(content::WebContents* web_contents,
+ bool blocked) override;
+
+ WebContentsModalDialogHost* GetWebContentsModalDialogHost() override;
+
+ bool IsWebContentsVisible(content::WebContents* web_contents) override;
+
+ void set_web_contents_visible(bool visible) {
+ web_contents_visible_ = visible;
+ }
+
+ void set_web_contents_modal_dialog_host(WebContentsModalDialogHost* host) {
+ web_contents_modal_dialog_host_ = host;
+ }
+
+ bool web_contents_blocked() const { return web_contents_blocked_; }
+
+ private:
+ bool web_contents_visible_;
+ bool web_contents_blocked_;
+ WebContentsModalDialogHost* web_contents_modal_dialog_host_; // Not owned.
+
+ DISALLOW_COPY_AND_ASSIGN(TestWebContentsModalDialogManagerDelegate);
+};
+
+} // namespace web_modal
+
+#endif // COMPONENTS_WEB_MODAL_TEST_WEB_CONTENTS_MODAL_DIALOG_MANAGER_DELEGATE_H_
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_host.cc b/chromium/components/web_modal/web_contents_modal_dialog_host.cc
new file mode 100644
index 00000000000..89913876eb6
--- /dev/null
+++ b/chromium/components/web_modal/web_contents_modal_dialog_host.cc
@@ -0,0 +1,12 @@
+// 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 {
+
+WebContentsModalDialogHost::~WebContentsModalDialogHost() {
+}
+
+} // namespace web_modal
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_host.h b/chromium/components/web_modal/web_contents_modal_dialog_host.h
new file mode 100644
index 00000000000..3ae7c1f58df
--- /dev/null
+++ b/chromium/components/web_modal/web_contents_modal_dialog_host.h
@@ -0,0 +1,30 @@
+// 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 "components/web_modal/modal_dialog_host.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace web_modal {
+
+// Unlike browser modal dialogs, web contents modal dialogs should not be able
+// to draw outside the browser window. WebContentsModalDialogHost adds a
+// GetMaximumDialogSize method in order for positioning code to be able to take
+// this into account.
+class WebContentsModalDialogHost : public ModalDialogHost {
+ public:
+ ~WebContentsModalDialogHost() override;
+
+ // Returns the maximum dimensions a dialog can have.
+ virtual gfx::Size GetMaximumDialogSize() = 0;
+};
+
+} // namespace web_modal
+
+#endif // COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_HOST_H_
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_manager.cc b/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
new file mode 100644
index 00000000000..e940b077a00
--- /dev/null
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
@@ -0,0 +1,186 @@
+// 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 <utility>
+
+#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/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/web_contents.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::SetDelegate(
+ WebContentsModalDialogManagerDelegate* d) {
+ delegate_ = d;
+
+ for (WebContentsModalDialogList::iterator it = child_dialogs_.begin();
+ it != child_dialogs_.end(); it++) {
+ // Delegate can be NULL on Views/Win32 during tab drag.
+ (*it)->manager->HostChanged(d ? d->GetWebContentsModalDialogHost() : NULL);
+ }
+}
+
+void WebContentsModalDialogManager::ShowModalDialog(gfx::NativeWindow dialog) {
+ scoped_ptr<SingleWebContentsDialogManager> mgr(
+ CreateNativeWebModalManager(dialog, this));
+ ShowDialogWithManager(dialog, std::move(mgr));
+}
+
+// TODO(gbillock): Maybe "ShowBubbleWithManager"?
+void WebContentsModalDialogManager::ShowDialogWithManager(
+ gfx::NativeWindow dialog,
+ scoped_ptr<SingleWebContentsDialogManager> manager) {
+ if (delegate_)
+ manager->HostChanged(delegate_->GetWebContentsModalDialogHost());
+ child_dialogs_.push_back(new DialogState(dialog, std::move(manager)));
+
+ if (child_dialogs_.size() == 1) {
+ BlockWebContentsInteraction(true);
+ if (delegate_ && delegate_->IsWebContentsVisible(web_contents()))
+ child_dialogs_.back()->manager->Show();
+ }
+}
+
+bool WebContentsModalDialogManager::IsDialogActive() const {
+ return !child_dialogs_.empty();
+}
+
+void WebContentsModalDialogManager::FocusTopmostDialog() const {
+ DCHECK(!child_dialogs_.empty());
+ child_dialogs_.front()->manager->Focus();
+}
+
+content::WebContents* WebContentsModalDialogManager::GetWebContents() const {
+ return web_contents();
+}
+
+void WebContentsModalDialogManager::WillClose(gfx::NativeWindow dialog) {
+ WebContentsModalDialogList::iterator dlg = FindDialogState(dialog);
+
+ // The Views tab contents modal dialog calls WillClose twice. Ignore the
+ // second invocation.
+ if (dlg == child_dialogs_.end())
+ return;
+
+ bool removed_topmost_dialog = dlg == child_dialogs_.begin();
+ scoped_ptr<DialogState> deleter(*dlg);
+ child_dialogs_.erase(dlg);
+ if (!child_dialogs_.empty() && removed_topmost_dialog &&
+ !closing_all_dialogs_) {
+ child_dialogs_.front()->manager->Show();
+ }
+
+ BlockWebContentsInteraction(!child_dialogs_.empty());
+}
+
+WebContentsModalDialogManager::WebContentsModalDialogManager(
+ content::WebContents* web_contents)
+ : content::WebContentsObserver(web_contents),
+ delegate_(NULL),
+ closing_all_dialogs_(false) {
+}
+
+WebContentsModalDialogManager::DialogState::DialogState(
+ gfx::NativeWindow dialog,
+ scoped_ptr<SingleWebContentsDialogManager> mgr)
+ : dialog(dialog),
+ manager(mgr.release()) {
+}
+
+WebContentsModalDialogManager::DialogState::~DialogState() {}
+
+WebContentsModalDialogManager::WebContentsModalDialogList::iterator
+WebContentsModalDialogManager::FindDialogState(gfx::NativeWindow dialog) {
+ WebContentsModalDialogList::iterator i;
+ for (i = child_dialogs_.begin(); i != child_dialogs_.end(); ++i) {
+ if ((*i)->dialog == dialog)
+ break;
+ }
+
+ return i;
+}
+
+// TODO(gbillock): Move this to Views impl within Show()? It would
+// call WebContents* contents = native_delegate_->GetWebContents(); and
+// then set the block state. Advantage: could restrict some of the
+// WCMDM delegate methods, then, and pass them behind the scenes.
+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->GetWidget()->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()) {
+ child_dialogs_.front()->manager->Close();
+ }
+
+ 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::INCLUDE_PRIVATE_REGISTRIES))
+ CloseAllDialogs();
+}
+
+void WebContentsModalDialogManager::DidGetIgnoredUIEvent() {
+ if (!child_dialogs_.empty()) {
+ child_dialogs_.front()->manager->Focus();
+ }
+}
+
+void WebContentsModalDialogManager::WasShown() {
+ if (!child_dialogs_.empty())
+ child_dialogs_.front()->manager->Show();
+}
+
+void WebContentsModalDialogManager::WasHidden() {
+ if (!child_dialogs_.empty())
+ child_dialogs_.front()->manager->Hide();
+}
+
+void WebContentsModalDialogManager::WebContentsDestroyed() {
+ // 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();
+}
+
+void WebContentsModalDialogManager::DidAttachInterstitialPage() {
+ CloseAllDialogs();
+}
+
+} // namespace web_modal
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_manager.h b/chromium/components/web_modal/web_contents_modal_dialog_manager.h
new file mode 100644
index 00000000000..f5d501116b2
--- /dev/null
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager.h
@@ -0,0 +1,125 @@
+// Copyright 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/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/web_modal/single_web_contents_dialog_manager.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 SingleWebContentsDialogManagerDelegate,
+ public content::WebContentsObserver,
+ public content::WebContentsUserData<WebContentsModalDialogManager> {
+ public:
+ ~WebContentsModalDialogManager() override;
+
+ WebContentsModalDialogManagerDelegate* delegate() const { return delegate_; }
+ void SetDelegate(WebContentsModalDialogManagerDelegate* d);
+
+ static SingleWebContentsDialogManager* CreateNativeWebModalManager(
+ gfx::NativeWindow dialog,
+ SingleWebContentsDialogManagerDelegate* native_delegate);
+
+ // Shows the dialog as a web contents modal dialog. The dialog will notify via
+ // WillClose() when it is being destroyed.
+ void ShowModalDialog(gfx::NativeWindow dialog);
+
+ // Allow clients to supply their own native dialog manager. Suitable for
+ // bubble clients.
+ void ShowDialogWithManager(
+ gfx::NativeWindow dialog,
+ scoped_ptr<SingleWebContentsDialogManager> manager);
+
+ // Returns true if any dialogs are active and not closed.
+ bool IsDialogActive() const;
+
+ // Focus the topmost modal dialog. IsDialogActive() must be true when calling
+ // this function.
+ void FocusTopmostDialog() const;
+
+ // SingleWebContentsDialogManagerDelegate:
+ content::WebContents* GetWebContents() const override;
+ void WillClose(gfx::NativeWindow dialog) override;
+
+ // For testing.
+ class TestApi {
+ public:
+ explicit TestApi(WebContentsModalDialogManager* manager)
+ : manager_(manager) {}
+
+ void CloseAllDialogs() { manager_->CloseAllDialogs(); }
+ void DidAttachInterstitialPage() { manager_->DidAttachInterstitialPage(); }
+ void WebContentsWasShown() { manager_->WasShown(); }
+ void WebContentsWasHidden() { manager_->WasHidden(); }
+
+ private:
+ WebContentsModalDialogManager* manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestApi);
+ };
+
+ private:
+ explicit WebContentsModalDialogManager(content::WebContents* web_contents);
+ friend class content::WebContentsUserData<WebContentsModalDialogManager>;
+
+ struct DialogState {
+ DialogState(gfx::NativeWindow dialog,
+ scoped_ptr<SingleWebContentsDialogManager> manager);
+ ~DialogState();
+
+ gfx::NativeWindow dialog;
+ scoped_ptr<SingleWebContentsDialogManager> manager;
+ };
+
+ typedef std::deque<DialogState*> WebContentsModalDialogList;
+
+ // Utility function to get the dialog state for a dialog.
+ WebContentsModalDialogList::iterator FindDialogState(
+ gfx::NativeWindow dialog);
+
+ // Blocks/unblocks interaction with renderer process.
+ void BlockWebContentsInteraction(bool blocked);
+
+ bool IsWebContentsVisible() const;
+
+ // Closes all WebContentsModalDialogs.
+ void CloseAllDialogs();
+
+ // Overridden from content::WebContentsObserver:
+ void DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) override;
+ void DidGetIgnoredUIEvent() override;
+ void WasShown() override;
+ void WasHidden() override;
+ void WebContentsDestroyed() override;
+ void DidAttachInterstitialPage() override;
+
+ // Delegate for notifying our owner about stuff. Not owned by us.
+ WebContentsModalDialogManagerDelegate* delegate_;
+
+ // All active dialogs.
+ WebContentsModalDialogList child_dialogs_;
+
+ // True while closing the dialogs on WebContents close.
+ bool closing_all_dialogs_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManager);
+};
+
+} // namespace web_modal
+
+#endif // COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_MANAGER_H_
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_manager_delegate.cc b/chromium/components/web_modal/web_contents_modal_dialog_manager_delegate.cc
new file mode 100644
index 00000000000..25a777cf4f5
--- /dev/null
+++ b/chromium/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/chromium/components/web_modal/web_contents_modal_dialog_manager_delegate.h b/chromium/components/web_modal/web_contents_modal_dialog_manager_delegate.h
new file mode 100644
index 00000000000..76f74354de5
--- /dev/null
+++ b/chromium/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/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc b/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc
new file mode 100644
index 00000000000..0cb10999e11
--- /dev/null
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc
@@ -0,0 +1,363 @@
+// 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 <map>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/web_modal/single_web_contents_dialog_manager.h"
+#include "components/web_modal/test_web_contents_modal_dialog_manager_delegate.h"
+#include "content/public/test/test_renderer_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace web_modal {
+
+// Tracks persistent state changes of the native WC-modal dialog manager.
+class NativeManagerTracker {
+ public:
+ enum DialogState {
+ UNKNOWN,
+ NOT_SHOWN,
+ SHOWN,
+ HIDDEN,
+ CLOSED
+ };
+
+ NativeManagerTracker() : state_(UNKNOWN), was_shown_(false) {}
+
+ void SetState(DialogState state) {
+ state_ = state;
+ if (state_ == SHOWN)
+ was_shown_ = true;
+ }
+
+ DialogState state_;
+ bool was_shown_;
+};
+
+NativeManagerTracker unused_tracker;
+
+class TestNativeWebContentsModalDialogManager
+ : public SingleWebContentsDialogManager {
+ public:
+ TestNativeWebContentsModalDialogManager(
+ gfx::NativeWindow dialog,
+ SingleWebContentsDialogManagerDelegate* delegate,
+ NativeManagerTracker* tracker)
+ : delegate_(delegate),
+ dialog_(dialog),
+ tracker_(tracker) {
+ if (tracker_)
+ tracker_->SetState(NativeManagerTracker::NOT_SHOWN);
+ }
+
+ void Show() override {
+ if (tracker_)
+ tracker_->SetState(NativeManagerTracker::SHOWN);
+ }
+ void Hide() override {
+ if (tracker_)
+ tracker_->SetState(NativeManagerTracker::HIDDEN);
+ }
+ void Close() override {
+ if (tracker_)
+ tracker_->SetState(NativeManagerTracker::CLOSED);
+ delegate_->WillClose(dialog_);
+ }
+ void Focus() override {}
+ void Pulse() override {}
+ void HostChanged(WebContentsModalDialogHost* new_host) override {}
+ gfx::NativeWindow dialog() override { return dialog_; }
+
+ void StopTracking() {
+ tracker_ = NULL;
+ }
+
+ private:
+ SingleWebContentsDialogManagerDelegate* delegate_;
+ gfx::NativeWindow dialog_;
+ NativeManagerTracker* tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestNativeWebContentsModalDialogManager);
+};
+
+class WebContentsModalDialogManagerTest
+ : public content::RenderViewHostTestHarness {
+ public:
+ WebContentsModalDialogManagerTest()
+ : next_dialog_id(1),
+ manager(NULL) {
+ }
+
+ void SetUp() override {
+ content::RenderViewHostTestHarness::SetUp();
+
+ delegate.reset(new TestWebContentsModalDialogManagerDelegate);
+ WebContentsModalDialogManager::CreateForWebContents(web_contents());
+ manager = WebContentsModalDialogManager::FromWebContents(web_contents());
+ manager->SetDelegate(delegate.get());
+ test_api.reset(new WebContentsModalDialogManager::TestApi(manager));
+ }
+
+ void TearDown() override {
+ test_api.reset();
+ content::RenderViewHostTestHarness::TearDown();
+ }
+
+ protected:
+ gfx::NativeWindow MakeFakeDialog() {
+ // WebContentsModalDialogManager treats the dialog window as an opaque
+ // type, so creating fake dialog windows using reinterpret_cast is valid.
+ return reinterpret_cast<gfx::NativeWindow>(next_dialog_id++);
+ }
+
+ int next_dialog_id;
+ scoped_ptr<TestWebContentsModalDialogManagerDelegate> delegate;
+ WebContentsModalDialogManager* manager;
+ scoped_ptr<WebContentsModalDialogManager::TestApi> test_api;
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManagerTest);
+};
+
+SingleWebContentsDialogManager*
+WebContentsModalDialogManager::CreateNativeWebModalManager(
+ gfx::NativeWindow dialog,
+ SingleWebContentsDialogManagerDelegate* native_delegate) {
+ NOTREACHED();
+ return new TestNativeWebContentsModalDialogManager(
+ dialog,
+ native_delegate,
+ &unused_tracker);
+}
+
+// Test that the dialog is shown immediately when the delegate indicates the web
+// contents is visible.
+TEST_F(WebContentsModalDialogManagerTest, WebContentsVisible) {
+ // Dialog should be shown while WebContents is visible.
+ const gfx::NativeWindow dialog = MakeFakeDialog();
+
+ NativeManagerTracker tracker;
+ TestNativeWebContentsModalDialogManager* native_manager =
+ new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
+ manager->ShowDialogWithManager(
+ dialog, scoped_ptr<SingleWebContentsDialogManager>(native_manager));
+
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_TRUE(tracker.was_shown_);
+
+ native_manager->StopTracking();
+}
+
+// Test that the dialog is not shown immediately when the delegate indicates the
+// web contents is not visible.
+TEST_F(WebContentsModalDialogManagerTest, WebContentsNotVisible) {
+ // Dialog should not be shown while WebContents is not visible.
+ delegate->set_web_contents_visible(false);
+
+ const gfx::NativeWindow dialog = MakeFakeDialog();
+
+ NativeManagerTracker tracker;
+ TestNativeWebContentsModalDialogManager* native_manager =
+ new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
+ manager->ShowDialogWithManager(
+ dialog, scoped_ptr<SingleWebContentsDialogManager>(native_manager));
+
+ EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker.state_);
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_FALSE(tracker.was_shown_);
+
+ native_manager->StopTracking();
+}
+
+// Test that only the first of multiple dialogs is shown.
+TEST_F(WebContentsModalDialogManagerTest, ShowDialogs) {
+ const gfx::NativeWindow dialog1 = MakeFakeDialog();
+ const gfx::NativeWindow dialog2 = MakeFakeDialog();
+ const gfx::NativeWindow dialog3 = MakeFakeDialog();
+
+ NativeManagerTracker tracker1;
+ NativeManagerTracker tracker2;
+ NativeManagerTracker tracker3;
+ TestNativeWebContentsModalDialogManager* native_manager1 =
+ new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
+ TestNativeWebContentsModalDialogManager* native_manager2 =
+ new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
+ TestNativeWebContentsModalDialogManager* native_manager3 =
+ new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
+ manager->ShowDialogWithManager(
+ dialog1, scoped_ptr<SingleWebContentsDialogManager>(native_manager1));
+ manager->ShowDialogWithManager(
+ dialog2, scoped_ptr<SingleWebContentsDialogManager>(native_manager2));
+ manager->ShowDialogWithManager(
+ dialog3, scoped_ptr<SingleWebContentsDialogManager>(native_manager3));
+
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker1.state_);
+ EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker2.state_);
+ EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker3.state_);
+
+ native_manager1->StopTracking();
+ native_manager2->StopTracking();
+ native_manager3->StopTracking();
+}
+
+// Test that the dialog is shown/hidden when the WebContents is shown/hidden.
+TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
+ const gfx::NativeWindow dialog = MakeFakeDialog();
+
+ NativeManagerTracker tracker;
+ TestNativeWebContentsModalDialogManager* native_manager =
+ new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
+ manager->ShowDialogWithManager(
+ dialog, scoped_ptr<SingleWebContentsDialogManager>(native_manager));
+
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
+
+ test_api->WebContentsWasHidden();
+
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::HIDDEN, tracker.state_);
+
+ test_api->WebContentsWasShown();
+
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
+
+ native_manager->StopTracking();
+}
+
+// Test that attaching an interstitial page closes all dialogs.
+TEST_F(WebContentsModalDialogManagerTest, InterstitialPage) {
+ const gfx::NativeWindow dialog1 = MakeFakeDialog();
+ const gfx::NativeWindow dialog2 = MakeFakeDialog();
+
+ NativeManagerTracker tracker1;
+ NativeManagerTracker tracker2;
+ TestNativeWebContentsModalDialogManager* native_manager1 =
+ new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
+ TestNativeWebContentsModalDialogManager* native_manager2 =
+ new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
+ manager->ShowDialogWithManager(
+ dialog1, scoped_ptr<SingleWebContentsDialogManager>(native_manager1));
+ manager->ShowDialogWithManager(
+ dialog2, scoped_ptr<SingleWebContentsDialogManager>(native_manager2));
+
+ test_api->DidAttachInterstitialPage();
+
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
+
+ EXPECT_TRUE(tracker1.was_shown_);
+ EXPECT_FALSE(tracker2.was_shown_);
+}
+
+
+// Test that the first dialog is always shown, regardless of the order in which
+// dialogs are closed.
+TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) {
+ // The front dialog is always shown regardless of dialog close order.
+ const gfx::NativeWindow dialog1 = MakeFakeDialog();
+ const gfx::NativeWindow dialog2 = MakeFakeDialog();
+ const gfx::NativeWindow dialog3 = MakeFakeDialog();
+ const gfx::NativeWindow dialog4 = MakeFakeDialog();
+
+ NativeManagerTracker tracker1;
+ NativeManagerTracker tracker2;
+ NativeManagerTracker tracker3;
+ NativeManagerTracker tracker4;
+ TestNativeWebContentsModalDialogManager* native_manager1 =
+ new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
+ TestNativeWebContentsModalDialogManager* native_manager2 =
+ new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
+ TestNativeWebContentsModalDialogManager* native_manager3 =
+ new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
+ TestNativeWebContentsModalDialogManager* native_manager4 =
+ new TestNativeWebContentsModalDialogManager(dialog4, manager, &tracker4);
+ manager->ShowDialogWithManager(
+ dialog1, scoped_ptr<SingleWebContentsDialogManager>(native_manager1));
+ manager->ShowDialogWithManager(
+ dialog2, scoped_ptr<SingleWebContentsDialogManager>(native_manager2));
+ manager->ShowDialogWithManager(
+ dialog3, scoped_ptr<SingleWebContentsDialogManager>(native_manager3));
+ manager->ShowDialogWithManager(
+ dialog4, scoped_ptr<SingleWebContentsDialogManager>(native_manager4));
+
+ native_manager1->Close();
+
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
+ EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker3.state_);
+ EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker4.state_);
+
+ native_manager3->Close();
+
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
+ EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker4.state_);
+ EXPECT_FALSE(tracker3.was_shown_);
+
+ native_manager2->Close();
+
+ EXPECT_TRUE(manager->IsDialogActive());
+ EXPECT_TRUE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
+ EXPECT_EQ(NativeManagerTracker::SHOWN, tracker4.state_);
+ EXPECT_FALSE(tracker3.was_shown_);
+
+ native_manager4->Close();
+
+ EXPECT_FALSE(manager->IsDialogActive());
+ EXPECT_FALSE(delegate->web_contents_blocked());
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
+ EXPECT_EQ(NativeManagerTracker::CLOSED, tracker4.state_);
+ EXPECT_TRUE(tracker1.was_shown_);
+ EXPECT_TRUE(tracker2.was_shown_);
+ EXPECT_FALSE(tracker3.was_shown_);
+ EXPECT_TRUE(tracker4.was_shown_);
+}
+
+// Test that CloseAllDialogs does what it says.
+TEST_F(WebContentsModalDialogManagerTest, CloseAllDialogs) {
+ const int kWindowCount = 4;
+ NativeManagerTracker trackers[kWindowCount];
+ TestNativeWebContentsModalDialogManager* native_managers[kWindowCount];
+ for (int i = 0; i < kWindowCount; i++) {
+ const gfx::NativeWindow dialog = MakeFakeDialog();
+ native_managers[i] =
+ new TestNativeWebContentsModalDialogManager(
+ dialog, manager, &(trackers[i]));
+ manager->ShowDialogWithManager(
+ dialog, scoped_ptr<SingleWebContentsDialogManager>(native_managers[i]));
+ }
+
+ for (int i = 0; i < kWindowCount; i++)
+ EXPECT_NE(NativeManagerTracker::CLOSED, trackers[i].state_);
+
+ test_api->CloseAllDialogs();
+
+ EXPECT_FALSE(delegate->web_contents_blocked());
+ EXPECT_FALSE(manager->IsDialogActive());
+ for (int i = 0; i < kWindowCount; i++)
+ EXPECT_EQ(NativeManagerTracker::CLOSED, trackers[i].state_);
+}
+
+} // namespace web_modal