ServiceWorker: Make the path restriction check more stabilized (1/2)
[chromium-blink-merge.git] / components / web_modal / web_contents_modal_dialog_manager.cc
blobf81a9d729cf5138994c203947ee09e331ddc0332
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/render_view_host.h"
11 #include "content/public/browser/web_contents.h"
12 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14 using content::WebContents;
16 DEFINE_WEB_CONTENTS_USER_DATA_KEY(web_modal::WebContentsModalDialogManager);
18 namespace web_modal {
20 WebContentsModalDialogManager::~WebContentsModalDialogManager() {
21 DCHECK(child_dialogs_.empty());
24 void WebContentsModalDialogManager::SetDelegate(
25 WebContentsModalDialogManagerDelegate* d) {
26 delegate_ = d;
28 for (WebContentsModalDialogList::iterator it = child_dialogs_.begin();
29 it != child_dialogs_.end(); it++) {
30 // Delegate can be NULL on Views/Win32 during tab drag.
31 (*it)->manager->HostChanged(d ? d->GetWebContentsModalDialogHost() : NULL);
35 void WebContentsModalDialogManager::ShowModalDialog(
36 NativeWebContentsModalDialog dialog) {
37 scoped_ptr<SingleWebContentsDialogManager> mgr(
38 CreateNativeWebModalManager(dialog, this));
39 ShowDialogWithManager(dialog, mgr.Pass());
42 // TODO(gbillock): Maybe "ShowBubbleWithManager"?
43 void WebContentsModalDialogManager::ShowDialogWithManager(
44 NativeWebContentsModalDialog dialog,
45 scoped_ptr<SingleWebContentsDialogManager> manager) {
46 if (delegate_)
47 manager->HostChanged(delegate_->GetWebContentsModalDialogHost());
48 child_dialogs_.push_back(new DialogState(dialog, manager.Pass()));
50 if (child_dialogs_.size() == 1) {
51 BlockWebContentsInteraction(true);
52 if (delegate_ && delegate_->IsWebContentsVisible(web_contents()))
53 child_dialogs_.back()->manager->Show();
57 bool WebContentsModalDialogManager::IsDialogActive() const {
58 return !child_dialogs_.empty();
61 void WebContentsModalDialogManager::FocusTopmostDialog() const {
62 DCHECK(!child_dialogs_.empty());
63 child_dialogs_.front()->manager->Focus();
66 content::WebContents* WebContentsModalDialogManager::GetWebContents() const {
67 return web_contents();
70 void WebContentsModalDialogManager::WillClose(
71 NativeWebContentsModalDialog dialog) {
72 WebContentsModalDialogList::iterator dlg = FindDialogState(dialog);
74 // The Views tab contents modal dialog calls WillClose twice. Ignore the
75 // second invocation.
76 if (dlg == child_dialogs_.end())
77 return;
79 bool removed_topmost_dialog = dlg == child_dialogs_.begin();
80 scoped_ptr<DialogState> deleter(*dlg);
81 child_dialogs_.erase(dlg);
82 if (!child_dialogs_.empty() && removed_topmost_dialog &&
83 !closing_all_dialogs_) {
84 child_dialogs_.front()->manager->Show();
87 BlockWebContentsInteraction(!child_dialogs_.empty());
90 WebContentsModalDialogManager::WebContentsModalDialogManager(
91 content::WebContents* web_contents)
92 : content::WebContentsObserver(web_contents),
93 delegate_(NULL),
94 closing_all_dialogs_(false) {
97 WebContentsModalDialogManager::DialogState::DialogState(
98 NativeWebContentsModalDialog dialog,
99 scoped_ptr<SingleWebContentsDialogManager> mgr)
100 : dialog(dialog),
101 manager(mgr.release()) {
104 WebContentsModalDialogManager::DialogState::~DialogState() {}
106 WebContentsModalDialogManager::WebContentsModalDialogList::iterator
107 WebContentsModalDialogManager::FindDialogState(
108 NativeWebContentsModalDialog dialog) {
109 WebContentsModalDialogList::iterator i;
110 for (i = child_dialogs_.begin(); i != child_dialogs_.end(); ++i) {
111 if ((*i)->dialog == dialog)
112 break;
115 return i;
118 // TODO(gbillock): Move this to Views impl within Show()? It would
119 // call WebContents* contents = native_delegate_->GetWebContents(); and
120 // then set the block state. Advantage: could restrict some of the
121 // WCMDM delegate methods, then, and pass them behind the scenes.
122 void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked) {
123 WebContents* contents = web_contents();
124 if (!contents) {
125 // The WebContents has already disconnected.
126 return;
129 // RenderViewHost may be NULL during shutdown.
130 content::RenderViewHost* host = contents->GetRenderViewHost();
131 if (host)
132 host->SetIgnoreInputEvents(blocked);
133 if (delegate_)
134 delegate_->SetWebContentsBlocked(contents, blocked);
137 void WebContentsModalDialogManager::CloseAllDialogs() {
138 closing_all_dialogs_ = true;
140 // Clear out any dialogs since we are leaving this page entirely.
141 while (!child_dialogs_.empty()) {
142 child_dialogs_.front()->manager->Close();
145 closing_all_dialogs_ = false;
148 void WebContentsModalDialogManager::DidNavigateMainFrame(
149 const content::LoadCommittedDetails& details,
150 const content::FrameNavigateParams& params) {
151 // Close constrained windows if necessary.
152 if (!net::registry_controlled_domains::SameDomainOrHost(
153 details.previous_url, details.entry->GetURL(),
154 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
155 CloseAllDialogs();
158 void WebContentsModalDialogManager::DidGetIgnoredUIEvent() {
159 if (!child_dialogs_.empty()) {
160 child_dialogs_.front()->manager->Focus();
164 void WebContentsModalDialogManager::WasShown() {
165 if (!child_dialogs_.empty())
166 child_dialogs_.front()->manager->Show();
169 void WebContentsModalDialogManager::WasHidden() {
170 if (!child_dialogs_.empty())
171 child_dialogs_.front()->manager->Hide();
174 void WebContentsModalDialogManager::WebContentsDestroyed() {
175 // First cleanly close all child dialogs.
176 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
177 // some of these to close. CloseAllDialogs is async, so it might get called
178 // twice before it runs.
179 CloseAllDialogs();
182 void WebContentsModalDialogManager::DidAttachInterstitialPage() {
183 // TODO(wittman): Test closing on interstitial webui works properly on Mac.
184 #if defined(USE_AURA)
185 CloseAllDialogs();
186 #endif
189 } // namespace web_modal