1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/web_modal/web_contents_modal_dialog_manager.h"
7 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
8 #include "content/public/browser/navigation_details.h"
9 #include "content/public/browser/navigation_entry.h"
10 #include "content/public/browser/notification_details.h"
11 #include "content/public/browser/notification_source.h"
12 #include "content/public/browser/notification_types.h"
13 #include "content/public/browser/render_view_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_view.h"
16 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
18 using content::WebContents
;
20 DEFINE_WEB_CONTENTS_USER_DATA_KEY(web_modal::WebContentsModalDialogManager
);
24 WebContentsModalDialogManager::~WebContentsModalDialogManager() {
25 DCHECK(child_dialogs_
.empty());
28 void WebContentsModalDialogManager::ShowDialog(
29 NativeWebContentsModalDialog dialog
) {
30 child_dialogs_
.push_back(dialog
);
32 native_manager_
->ManageDialog(dialog
);
34 if (child_dialogs_
.size() == 1) {
35 if (delegate_
&& delegate_
->IsWebContentsVisible(web_contents()))
36 native_manager_
->ShowDialog(dialog
);
37 BlockWebContentsInteraction(true);
41 bool WebContentsModalDialogManager::IsShowingDialog() const {
42 return !child_dialogs_
.empty();
45 void WebContentsModalDialogManager::FocusTopmostDialog() {
46 DCHECK(!child_dialogs_
.empty());
47 native_manager_
->FocusDialog(child_dialogs_
.front());
50 content::WebContents
* WebContentsModalDialogManager::GetWebContents() const {
51 return web_contents();
54 void WebContentsModalDialogManager::WillClose(
55 NativeWebContentsModalDialog dialog
) {
56 WebContentsModalDialogList::iterator
i(
57 std::find(child_dialogs_
.begin(), child_dialogs_
.end(), dialog
));
59 // The Views tab contents modal dialog calls WillClose twice. Ignore the
61 if (i
== child_dialogs_
.end())
64 bool removed_topmost_dialog
= i
== child_dialogs_
.begin();
65 child_dialogs_
.erase(i
);
66 if (!child_dialogs_
.empty() && removed_topmost_dialog
&&
67 !closing_all_dialogs_
)
68 native_manager_
->ShowDialog(child_dialogs_
.front());
70 BlockWebContentsInteraction(!child_dialogs_
.empty());
73 void WebContentsModalDialogManager::Observe(
75 const content::NotificationSource
& source
,
76 const content::NotificationDetails
& details
) {
77 DCHECK(type
== content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED
);
79 if (child_dialogs_
.empty())
82 bool visible
= *content::Details
<bool>(details
).ptr();
84 native_manager_
->ShowDialog(child_dialogs_
.front());
86 native_manager_
->HideDialog(child_dialogs_
.front());
89 WebContentsModalDialogManager::WebContentsModalDialogManager(
90 content::WebContents
* web_contents
)
91 : content::WebContentsObserver(web_contents
),
93 native_manager_(CreateNativeManager(this)),
94 closing_all_dialogs_(false) {
95 DCHECK(native_manager_
);
97 content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED
,
98 content::Source
<content::WebContents
>(web_contents
));
101 void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked
) {
102 WebContents
* contents
= web_contents();
104 // The WebContents has already disconnected.
108 // RenderViewHost may be NULL during shutdown.
109 content::RenderViewHost
* host
= contents
->GetRenderViewHost();
111 host
->SetIgnoreInputEvents(blocked
);
113 delegate_
->SetWebContentsBlocked(contents
, blocked
);
116 void WebContentsModalDialogManager::CloseAllDialogs() {
117 closing_all_dialogs_
= true;
119 // Clear out any dialogs since we are leaving this page entirely.
120 while (!child_dialogs_
.empty())
121 native_manager_
->CloseDialog(child_dialogs_
.front());
123 closing_all_dialogs_
= false;
126 void WebContentsModalDialogManager::DidNavigateMainFrame(
127 const content::LoadCommittedDetails
& details
,
128 const content::FrameNavigateParams
& params
) {
129 // Close constrained windows if necessary.
130 if (!net::registry_controlled_domains::SameDomainOrHost(
131 details
.previous_url
, details
.entry
->GetURL(),
132 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES
))
136 void WebContentsModalDialogManager::DidGetIgnoredUIEvent() {
137 if (!child_dialogs_
.empty())
138 native_manager_
->FocusDialog(child_dialogs_
.front());
141 void WebContentsModalDialogManager::WebContentsDestroyed(WebContents
* tab
) {
142 // First cleanly close all child dialogs.
143 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
144 // some of these to close. CloseAllDialogs is async, so it might get called
145 // twice before it runs.
149 } // namespace web_modal