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

Side by Side Diff: chrome/browser/ui/fast_unload_controller.cc

Issue 23835007: DevTools: Do not close devtools if there are dirty files in workspace (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win compile Created 7 years, 1 month 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/ui/fast_unload_controller.h" 5 #include "chrome/browser/ui/fast_unload_controller.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h" 8 #include "base/message_loop/message_loop.h"
9 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/devtools/devtools_window.h" 10 #include "chrome/browser/devtools/devtools_window.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 } 64 }
65 65
66 bool FastUnloadController::CanCloseContents(content::WebContents* contents) { 66 bool FastUnloadController::CanCloseContents(content::WebContents* contents) {
67 // Don't try to close the tab when the whole browser is being closed, since 67 // Don't try to close the tab when the whole browser is being closed, since
68 // that avoids the fast shutdown path where we just kill all the renderers. 68 // that avoids the fast shutdown path where we just kill all the renderers.
69 return !is_attempting_to_close_browser_ || 69 return !is_attempting_to_close_browser_ ||
70 is_calling_before_unload_handlers(); 70 is_calling_before_unload_handlers();
71 } 71 }
72 72
73 // static 73 // static
74 bool FastUnloadController::CanFastShutdownWebContents(
75 content::WebContents* contents) {
jeremy 2013/11/07 14:18:34 Can you please provide a comment on what fastshutd
lushnikov 2013/11/07 17:18:10 Do you think this one is needed? Looks like it cou
jeremy 2013/11/10 12:50:29 There are way too many moving parts here and for s
76 return DevToolsWindow::GetInstanceForInspectedRenderViewHost(
77 contents->GetRenderViewHost()) == NULL;
78 }
79
80 // static
74 bool FastUnloadController::RunUnloadEventsHelper( 81 bool FastUnloadController::RunUnloadEventsHelper(
75 content::WebContents* contents) { 82 content::WebContents* contents) {
83 // If there's a devtools window attached to the web contents,
84 // then we would like to run its beforeunload handlers first.
jeremy 2013/11/07 14:18:34 Please point to the comment that explains why.
lushnikov 2013/11/07 17:18:10 Done.
85 if (DevToolsWindow::InterceptPageBeforeUnload(contents)) {
jeremy 2013/11/10 12:50:29 2 things are unclear from this callsite: * Does In
86 return true;
87 }
76 // If the WebContents is not connected yet, then there's no unload 88 // If the WebContents is not connected yet, then there's no unload
77 // handler we can fire even if the WebContents has an unload listener. 89 // handler we can fire even if the WebContents has an unload listener.
78 // One case where we hit this is in a tab that has an infinite loop 90 // One case where we hit this is in a tab that has an infinite loop
79 // before load. 91 // before load.
80 if (contents->NeedToFireBeforeUnload()) { 92 if (contents->NeedToFireBeforeUnload()) {
81 // If the page has unload listeners, then we tell the renderer to fire 93 // If the page has unload listeners, then we tell the renderer to fire
82 // them. Once they have fired, we'll get a message back saying whether 94 // them. Once they have fired, we'll get a message back saying whether
83 // to proceed closing the page or not, which sends us back to this method 95 // to proceed closing the page or not, which sends us back to this method
84 // with the NeedToFireBeforeUnload bit cleared. 96 // with the NeedToFireBeforeUnload bit cleared.
85 contents->GetRenderViewHost()->FirePageBeforeUnload(false); 97 contents->GetRenderViewHost()->FirePageBeforeUnload(false);
86 return true; 98 return true;
87 } 99 }
88 return false; 100 return false;
89 } 101 }
90 102
91 bool FastUnloadController::BeforeUnloadFired(content::WebContents* contents, 103 bool FastUnloadController::BeforeUnloadFired(content::WebContents* contents,
92 bool proceed) { 104 bool proceed) {
105 if (!proceed)
106 DevToolsWindow::PageClosingCanceled(contents);
107
93 if (!is_attempting_to_close_browser_) { 108 if (!is_attempting_to_close_browser_) {
94 if (!proceed) { 109 if (!proceed) {
95 contents->SetClosedByUserGesture(false); 110 contents->SetClosedByUserGesture(false);
96 } else { 111 } else {
97 // No more dialogs are possible, so remove the tab and finish 112 // No more dialogs are possible, so remove the tab and finish
98 // running unload listeners asynchrounously. 113 // running unload listeners asynchrounously.
99 browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents); 114 browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents);
100 DetachWebContents(contents); 115 DetachWebContents(contents);
101 } 116 }
102 return proceed; 117 return proceed;
(...skipping 16 matching lines...) Expand all
119 return false; 134 return false;
120 } 135 }
121 136
122 return true; 137 return true;
123 } 138 }
124 139
125 bool FastUnloadController::ShouldCloseWindow() { 140 bool FastUnloadController::ShouldCloseWindow() {
126 if (HasCompletedUnloadProcessing()) 141 if (HasCompletedUnloadProcessing())
127 return true; 142 return true;
128 143
144 if (browser_->is_devtools() &&
145 DevToolsWindow::ShouldCloseDevToolsBrowser(browser_)) {
146 return true;
147 }
148
129 // The behavior followed here varies based on the current phase of the 149 // The behavior followed here varies based on the current phase of the
130 // operation and whether a batched shutdown is in progress. 150 // operation and whether a batched shutdown is in progress.
131 // 151 //
132 // If there are tabs with outstanding beforeunload handlers: 152 // If there are tabs with outstanding beforeunload handlers:
133 // 1. If a batched shutdown is in progress: return false. 153 // 1. If a batched shutdown is in progress: return false.
134 // This is to prevent interference with batched shutdown already in 154 // This is to prevent interference with batched shutdown already in
135 // progress. 155 // progress.
136 // 2. Otherwise: start sending beforeunload events and return false. 156 // 2. Otherwise: start sending beforeunload events and return false.
137 // 157 //
138 // Otherwise, If there are no tabs with outstanding beforeunload handlers: 158 // Otherwise, If there are no tabs with outstanding beforeunload handlers:
139 // 3. If a batched shutdown is in progress: start sending unload events and 159 // 3. If a batched shutdown is in progress: start sending unload events and
140 // return false. 160 // return false.
141 // 4. Otherwise: return true. 161 // 4. Otherwise: return true.
142 is_attempting_to_close_browser_ = true; 162 is_attempting_to_close_browser_ = true;
143 // Cases 1 and 4. 163 // Cases 1 and 4.
144 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired(); 164 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired();
145 if (need_beforeunload_fired == is_calling_before_unload_handlers()) 165 if (need_beforeunload_fired == is_calling_before_unload_handlers())
146 return !need_beforeunload_fired; 166 return !need_beforeunload_fired;
147 167
148 // Cases 2 and 3. 168 // Cases 2 and 3.
149 on_close_confirmed_.Reset(); 169 on_close_confirmed_.Reset();
150 ProcessPendingTabs(); 170 ProcessPendingTabs();
151 return false; 171 return false;
152 } 172 }
153 173
154 bool FastUnloadController::CallBeforeUnloadHandlers( 174 bool FastUnloadController::CallBeforeUnloadHandlers(
155 const base::Callback<void(bool)>& on_close_confirmed) { 175 const base::Callback<void(bool)>& on_close_confirmed) {
156 if (!TabsNeedBeforeUnloadFired()) 176 // DevTools browser will get its beforeunload events triggered on
177 // inspected tab closing
jeremy 2013/11/07 14:18:34 will get -> gets
lushnikov 2013/11/07 17:18:10 Done.
178 if (browser_->is_devtools() || !TabsNeedBeforeUnloadFired())
157 return false; 179 return false;
158 180
159 on_close_confirmed_ = on_close_confirmed; 181 on_close_confirmed_ = on_close_confirmed;
160 is_attempting_to_close_browser_ = true; 182 is_attempting_to_close_browser_ = true;
161 ProcessPendingTabs(); 183 ProcessPendingTabs();
162 return true; 184 return true;
163 } 185 }
164 186
165 void FastUnloadController::ResetBeforeUnloadHandlers() { 187 void FastUnloadController::ResetBeforeUnloadHandlers() {
166 if (!is_calling_before_unload_handlers()) 188 if (!is_calling_before_unload_handlers())
167 return; 189 return;
168 CancelWindowClose(); 190 CancelWindowClose();
169 } 191 }
170 192
171 bool FastUnloadController::TabsNeedBeforeUnloadFired() { 193 bool FastUnloadController::TabsNeedBeforeUnloadFired() {
172 if (!tabs_needing_before_unload_.empty() || 194 if (!tabs_needing_before_unload_.empty() ||
173 tab_needing_before_unload_ack_ != NULL) 195 tab_needing_before_unload_ack_ != NULL)
174 return true; 196 return true;
175 197
176 if (!is_calling_before_unload_handlers() && !tabs_needing_unload_.empty()) 198 if (!is_calling_before_unload_handlers() && !tabs_needing_unload_.empty())
177 return false; 199 return false;
178 200
179 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) { 201 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
180 content::WebContents* contents = 202 content::WebContents* contents =
181 browser_->tab_strip_model()->GetWebContentsAt(i); 203 browser_->tab_strip_model()->GetWebContentsAt(i);
182 if (!ContainsKey(tabs_needing_unload_, contents) && 204 if (!ContainsKey(tabs_needing_unload_, contents) &&
183 !ContainsKey(tabs_needing_unload_ack_, contents) && 205 !ContainsKey(tabs_needing_unload_ack_, contents) &&
184 tab_needing_before_unload_ack_ != contents && 206 tab_needing_before_unload_ack_ != contents &&
185 contents->NeedToFireBeforeUnload()) 207 (contents->NeedToFireBeforeUnload() ||
208 DevToolsWindow::NeedToFireBeforeUnload(contents)))
jeremy 2013/11/07 14:18:34 This expression is already kind of crazy - can we
lushnikov 2013/11/07 17:18:10 Done.
186 tabs_needing_before_unload_.insert(contents); 209 tabs_needing_before_unload_.insert(contents);
187 } 210 }
188 return !tabs_needing_before_unload_.empty(); 211 return !tabs_needing_before_unload_.empty();
189 } 212 }
190 213
191 //////////////////////////////////////////////////////////////////////////////// 214 ////////////////////////////////////////////////////////////////////////////////
192 // FastUnloadController, content::NotificationObserver implementation: 215 // FastUnloadController, content::NotificationObserver implementation:
193 216
194 void FastUnloadController::Observe( 217 void FastUnloadController::Observe(
195 int type, 218 int type,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 content::WebContents* contents = *it; 330 content::WebContents* contents = *it;
308 tabs_needing_before_unload_.erase(it); 331 tabs_needing_before_unload_.erase(it);
309 // Null check render_view_host here as this gets called on a PostTask and 332 // Null check render_view_host here as this gets called on a PostTask and
310 // the tab's render_view_host may have been nulled out. 333 // the tab's render_view_host may have been nulled out.
311 if (contents->GetRenderViewHost()) { 334 if (contents->GetRenderViewHost()) {
312 tab_needing_before_unload_ack_ = contents; 335 tab_needing_before_unload_ack_ = contents;
313 336
314 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); 337 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
315 core_tab_helper->OnCloseStarted(); 338 core_tab_helper->OnCloseStarted();
316 339
317 contents->GetRenderViewHost()->FirePageBeforeUnload(false); 340 if (!DevToolsWindow::InterceptPageBeforeUnload(contents))
jeremy 2013/11/07 14:18:34 I don't really think this method name conveys what
lushnikov 2013/11/07 17:18:10 Done.
341 contents->GetRenderViewHost()->FirePageBeforeUnload(false);
318 } else { 342 } else {
319 ProcessPendingTabs(); 343 ProcessPendingTabs();
320 } 344 }
321 return; 345 return;
322 } 346 }
323 347
324 if (is_calling_before_unload_handlers()) { 348 if (is_calling_before_unload_handlers()) {
325 on_close_confirmed_.Run(true); 349 on_close_confirmed_.Run(true);
326 return; 350 return;
327 } 351 }
328
329 // Process all the unload handlers. (The beforeunload handlers have finished.) 352 // Process all the unload handlers. (The beforeunload handlers have finished.)
330 if (!tabs_needing_unload_.empty()) { 353 if (!tabs_needing_unload_.empty()) {
331 browser_->OnWindowClosing(); 354 browser_->OnWindowClosing();
332 355
333 // Run unload handlers detached since no more interaction is possible. 356 // Run unload handlers detached since no more interaction is possible.
334 WebContentsSet::iterator it = tabs_needing_unload_.begin(); 357 WebContentsSet::iterator it = tabs_needing_unload_.begin();
335 while (it != tabs_needing_unload_.end()) { 358 while (it != tabs_needing_unload_.end()) {
336 WebContentsSet::iterator current = it++; 359 WebContentsSet::iterator current = it++;
337 content::WebContents* contents = *current; 360 content::WebContents* contents = *current;
338 tabs_needing_unload_.erase(current); 361 tabs_needing_unload_.erase(current);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 tab_needing_before_unload_ack_ == NULL && 399 tab_needing_before_unload_ack_ == NULL &&
377 tabs_needing_unload_.empty() && 400 tabs_needing_unload_.empty() &&
378 tabs_needing_unload_ack_.empty(); 401 tabs_needing_unload_ack_.empty();
379 } 402 }
380 403
381 void FastUnloadController::CancelWindowClose() { 404 void FastUnloadController::CancelWindowClose() {
382 // Closing of window can be canceled from a beforeunload handler. 405 // Closing of window can be canceled from a beforeunload handler.
383 DCHECK(is_attempting_to_close_browser_); 406 DCHECK(is_attempting_to_close_browser_);
384 tabs_needing_before_unload_.clear(); 407 tabs_needing_before_unload_.clear();
385 if (tab_needing_before_unload_ack_ != NULL) { 408 if (tab_needing_before_unload_ack_ != NULL) {
386
387 CoreTabHelper* core_tab_helper = 409 CoreTabHelper* core_tab_helper =
388 CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_); 410 CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_);
389 core_tab_helper->OnCloseCanceled(); 411 core_tab_helper->OnCloseCanceled();
412 DevToolsWindow::PageClosingCanceled(tab_needing_before_unload_ack_);
jeremy 2013/11/07 14:18:34 *OnPageCloseCanceled() ?
lushnikov 2013/11/07 17:18:10 Done.
390 tab_needing_before_unload_ack_ = NULL; 413 tab_needing_before_unload_ack_ = NULL;
391 } 414 }
392 for (WebContentsSet::iterator it = tabs_needing_unload_.begin(); 415 for (WebContentsSet::iterator it = tabs_needing_unload_.begin();
393 it != tabs_needing_unload_.end(); it++) { 416 it != tabs_needing_unload_.end(); it++) {
394 content::WebContents* contents = *it; 417 content::WebContents* contents = *it;
395 418
396 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); 419 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
397 core_tab_helper->OnCloseCanceled(); 420 core_tab_helper->OnCloseCanceled();
421 DevToolsWindow::PageClosingCanceled(contents);
398 } 422 }
399 tabs_needing_unload_.clear(); 423 tabs_needing_unload_.clear();
400 424
401 // No need to clear tabs_needing_unload_ack_. Those tabs are already detached. 425 // No need to clear tabs_needing_unload_ack_. Those tabs are already detached.
402 426
403 if (is_calling_before_unload_handlers()) { 427 if (is_calling_before_unload_handlers()) {
404 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_; 428 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_;
405 on_close_confirmed_.Reset(); 429 on_close_confirmed_.Reset();
406 on_close_confirmed.Run(false); 430 on_close_confirmed.Run(false);
407 } 431 }
(...skipping 30 matching lines...) Expand all
438 } 462 }
439 463
440 void FastUnloadController::PostTaskForProcessPendingTabs() { 464 void FastUnloadController::PostTaskForProcessPendingTabs() {
441 base::MessageLoop::current()->PostTask( 465 base::MessageLoop::current()->PostTask(
442 FROM_HERE, 466 FROM_HERE,
443 base::Bind(&FastUnloadController::ProcessPendingTabs, 467 base::Bind(&FastUnloadController::ProcessPendingTabs,
444 weak_factory_.GetWeakPtr())); 468 weak_factory_.GetWeakPtr()));
445 } 469 }
446 470
447 } // namespace chrome 471 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698