Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: components/web_modal/web_contents_modal_dialog_manager.cc

Issue 17500003: Close web contents modal dialogs on content load start (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix crash accepting OS X report form warning dialog Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/web_modal/web_contents_modal_dialog_manager.h" 5 #include "components/web_modal/web_contents_modal_dialog_manager.h"
6 6
7 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" 7 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
8 #include "content/public/browser/navigation_details.h" 8 #include "content/public/browser/navigation_details.h"
9 #include "content/public/browser/navigation_entry.h" 9 #include "content/public/browser/navigation_entry.h"
10 #include "content/public/browser/notification_details.h" 10 #include "content/public/browser/notification_details.h"
11 #include "content/public/browser/notification_source.h" 11 #include "content/public/browser/notification_source.h"
12 #include "content/public/browser/notification_types.h" 12 #include "content/public/browser/notification_types.h"
13 #include "content/public/browser/render_view_host.h" 13 #include "content/public/browser/render_view_host.h"
14 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_view.h" 15 #include "content/public/browser/web_contents_view.h"
16 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
17 16
18 using content::WebContents; 17 using content::WebContents;
19 18
20 DEFINE_WEB_CONTENTS_USER_DATA_KEY(web_modal::WebContentsModalDialogManager); 19 DEFINE_WEB_CONTENTS_USER_DATA_KEY(web_modal::WebContentsModalDialogManager);
21 20
22 namespace web_modal { 21 namespace web_modal {
23 22
24 WebContentsModalDialogManager::~WebContentsModalDialogManager() { 23 WebContentsModalDialogManager::~WebContentsModalDialogManager() {
25 DCHECK(child_dialogs_.empty()); 24 DCHECK(child_dialogs_.empty());
26 } 25 }
27 26
28 void WebContentsModalDialogManager::ShowDialog( 27 void WebContentsModalDialogManager::ShowDialog(
29 NativeWebContentsModalDialog dialog) { 28 NativeWebContentsModalDialog dialog) {
30 child_dialogs_.push_back(dialog); 29 child_dialogs_.push_back(DialogState(dialog));
31 30
32 native_manager_->ManageDialog(dialog); 31 native_manager_->ManageDialog(dialog);
33 32
34 if (child_dialogs_.size() == 1) { 33 if (child_dialogs_.size() == 1) {
35 if (delegate_ && delegate_->IsWebContentsVisible(web_contents())) 34 if (delegate_ && delegate_->IsWebContentsVisible(web_contents()))
36 native_manager_->ShowDialog(dialog); 35 native_manager_->ShowDialog(dialog);
37 BlockWebContentsInteraction(true); 36 BlockWebContentsInteraction(true);
38 } 37 }
39 } 38 }
40 39
41 bool WebContentsModalDialogManager::IsShowingDialog() const { 40 bool WebContentsModalDialogManager::IsShowingDialog() const {
42 return !child_dialogs_.empty(); 41 return !child_dialogs_.empty();
43 } 42 }
44 43
45 void WebContentsModalDialogManager::FocusTopmostDialog() { 44 void WebContentsModalDialogManager::FocusTopmostDialog() {
46 DCHECK(!child_dialogs_.empty()); 45 DCHECK(!child_dialogs_.empty());
47 native_manager_->FocusDialog(child_dialogs_.front()); 46 native_manager_->FocusDialog(child_dialogs_.front().dialog);
47 }
48
49 void WebContentsModalDialogManager::SetInhibitCloseOnLoadStart(
50 NativeWebContentsModalDialog dialog,
51 bool inhibit) {
52 WebContentsModalDialogList::iterator loc = FindDialogState(dialog);
53 DCHECK(loc != child_dialogs_.end());
54 loc->inhibit_close_on_load_start = true;
48 } 55 }
49 56
50 content::WebContents* WebContentsModalDialogManager::GetWebContents() const { 57 content::WebContents* WebContentsModalDialogManager::GetWebContents() const {
51 return web_contents(); 58 return web_contents();
52 } 59 }
53 60
54 void WebContentsModalDialogManager::WillClose( 61 void WebContentsModalDialogManager::WillClose(
55 NativeWebContentsModalDialog dialog) { 62 NativeWebContentsModalDialog dialog) {
56 WebContentsModalDialogList::iterator i( 63 WebContentsModalDialogList::iterator i = FindDialogState(dialog);
57 std::find(child_dialogs_.begin(), child_dialogs_.end(), dialog));
58 64
59 // The Views tab contents modal dialog calls WillClose twice. Ignore the 65 // The Views tab contents modal dialog calls WillClose twice. Ignore the
60 // second invocation. 66 // second invocation.
61 if (i == child_dialogs_.end()) 67 if (i == child_dialogs_.end())
62 return; 68 return;
63 69
64 bool removed_topmost_dialog = i == child_dialogs_.begin(); 70 bool removed_topmost_dialog = i == child_dialogs_.begin();
65 child_dialogs_.erase(i); 71 child_dialogs_.erase(i);
66 if (!child_dialogs_.empty() && removed_topmost_dialog && 72 if (!child_dialogs_.empty() && removed_topmost_dialog &&
67 !closing_all_dialogs_) 73 !closing_all_dialogs_)
68 native_manager_->ShowDialog(child_dialogs_.front()); 74 native_manager_->ShowDialog(child_dialogs_.front().dialog);
69 75
70 BlockWebContentsInteraction(!child_dialogs_.empty()); 76 BlockWebContentsInteraction(!child_dialogs_.empty());
71 } 77 }
72 78
73 void WebContentsModalDialogManager::Observe( 79 void WebContentsModalDialogManager::Observe(
74 int type, 80 int type,
75 const content::NotificationSource& source, 81 const content::NotificationSource& source,
76 const content::NotificationDetails& details) { 82 const content::NotificationDetails& details) {
77 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED); 83 if (type == content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED) {
84 if (child_dialogs_.empty())
85 return;
78 86
79 if (child_dialogs_.empty()) 87 bool visible = *content::Details<bool>(details).ptr();
80 return; 88 if (visible)
81 89 native_manager_->ShowDialog(child_dialogs_.front().dialog);
82 bool visible = *content::Details<bool>(details).ptr(); 90 else
83 if (visible) 91 native_manager_->HideDialog(child_dialogs_.front().dialog);
84 native_manager_->ShowDialog(child_dialogs_.front()); 92 } else if (type == content::NOTIFICATION_LOAD_START) {
85 else 93 if (!child_dialogs_.empty() &&
86 native_manager_->HideDialog(child_dialogs_.front()); 94 !child_dialogs_.front().inhibit_close_on_load_start)
95 native_manager_->CloseDialog(child_dialogs_.front().dialog);
96 }
87 } 97 }
88 98
89 WebContentsModalDialogManager::WebContentsModalDialogManager( 99 WebContentsModalDialogManager::WebContentsModalDialogManager(
90 content::WebContents* web_contents) 100 content::WebContents* web_contents)
91 : content::WebContentsObserver(web_contents), 101 : content::WebContentsObserver(web_contents),
92 delegate_(NULL), 102 delegate_(NULL),
93 native_manager_(CreateNativeManager(this)), 103 native_manager_(CreateNativeManager(this)),
94 closing_all_dialogs_(false) { 104 closing_all_dialogs_(false) {
95 DCHECK(native_manager_); 105 DCHECK(native_manager_);
106 content::NavigationController* controller =
107 &GetWebContents()->GetController();
108 registrar_.Add(this,
109 content::NOTIFICATION_LOAD_START,
110 content::Source<content::NavigationController>(controller));
96 registrar_.Add(this, 111 registrar_.Add(this,
97 content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, 112 content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
98 content::Source<content::WebContents>(web_contents)); 113 content::Source<content::WebContents>(web_contents));
99 } 114 }
100 115
116 WebContentsModalDialogManager::DialogState::DialogState(
117 NativeWebContentsModalDialog dialog)
118 : dialog(dialog),
119 inhibit_close_on_load_start(false) {
120 }
121
122 WebContentsModalDialogManager::WebContentsModalDialogList::iterator
123 WebContentsModalDialogManager::FindDialogState(
124 NativeWebContentsModalDialog dialog) {
125 WebContentsModalDialogList::iterator i;
126 for (i = child_dialogs_.begin(); i != child_dialogs_.end(); ++i) {
127 if (i->dialog == dialog)
128 break;
129 }
130
131 return i;
132 }
133
101 void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked) { 134 void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked) {
102 WebContents* contents = web_contents(); 135 WebContents* contents = web_contents();
103 if (!contents) { 136 if (!contents) {
104 // The WebContents has already disconnected. 137 // The WebContents has already disconnected.
105 return; 138 return;
106 } 139 }
107 140
108 // RenderViewHost may be NULL during shutdown. 141 // RenderViewHost may be NULL during shutdown.
109 content::RenderViewHost* host = contents->GetRenderViewHost(); 142 content::RenderViewHost* host = contents->GetRenderViewHost();
110 if (host) 143 if (host)
111 host->SetIgnoreInputEvents(blocked); 144 host->SetIgnoreInputEvents(blocked);
112 if (delegate_) 145 if (delegate_)
113 delegate_->SetWebContentsBlocked(contents, blocked); 146 delegate_->SetWebContentsBlocked(contents, blocked);
114 } 147 }
115 148
116 void WebContentsModalDialogManager::CloseAllDialogs() { 149 void WebContentsModalDialogManager::CloseAllDialogs() {
117 closing_all_dialogs_ = true; 150 closing_all_dialogs_ = true;
118 151
119 // Clear out any dialogs since we are leaving this page entirely. 152 // Clear out any dialogs since we are leaving this page entirely.
120 while (!child_dialogs_.empty()) 153 while (!child_dialogs_.empty())
121 native_manager_->CloseDialog(child_dialogs_.front()); 154 native_manager_->CloseDialog(child_dialogs_.front().dialog);
122 155
123 closing_all_dialogs_ = false; 156 closing_all_dialogs_ = false;
124 } 157 }
125 158
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))
133 CloseAllDialogs();
134 }
135
136 void WebContentsModalDialogManager::DidGetIgnoredUIEvent() { 159 void WebContentsModalDialogManager::DidGetIgnoredUIEvent() {
137 if (!child_dialogs_.empty()) 160 if (!child_dialogs_.empty())
138 native_manager_->FocusDialog(child_dialogs_.front()); 161 native_manager_->FocusDialog(child_dialogs_.front().dialog);
139 } 162 }
140 163
141 void WebContentsModalDialogManager::WebContentsDestroyed(WebContents* tab) { 164 void WebContentsModalDialogManager::WebContentsDestroyed(WebContents* tab) {
142 // First cleanly close all child dialogs. 165 // First cleanly close all child dialogs.
143 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked 166 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
144 // some of these to close. CloseAllDialogs is async, so it might get called 167 // some of these to close. CloseAllDialogs is async, so it might get called
145 // twice before it runs. 168 // twice before it runs.
146 CloseAllDialogs(); 169 CloseAllDialogs();
147 } 170 }
148 171
149 } // namespace web_modal 172 } // namespace web_modal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698