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

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: improving TestDevToolsOnDevTools test 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
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::RunUnloadEventsHelper( 74 bool FastUnloadController::RunUnloadEventsHelper(
75 content::WebContents* contents) { 75 content::WebContents* contents) {
76 // If there's a devtools window attached to the web contents,
77 // then we would like to run its beforeunload handlers first.
78 if (DevToolsWindow::InterceptPageBeforeUnload(contents)) {
79 return true;
80 }
76 // If the WebContents is not connected yet, then there's no unload 81 // 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. 82 // 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 83 // One case where we hit this is in a tab that has an infinite loop
79 // before load. 84 // before load.
80 if (contents->NeedToFireBeforeUnload()) { 85 if (contents->NeedToFireBeforeUnload()) {
81 // If the page has unload listeners, then we tell the renderer to fire 86 // 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 87 // 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 88 // to proceed closing the page or not, which sends us back to this method
84 // with the NeedToFireBeforeUnload bit cleared. 89 // with the NeedToFireBeforeUnload bit cleared.
85 contents->GetRenderViewHost()->FirePageBeforeUnload(false); 90 contents->GetRenderViewHost()->FirePageBeforeUnload(false);
86 return true; 91 return true;
87 } 92 }
88 return false; 93 return false;
89 } 94 }
90 95
91 bool FastUnloadController::BeforeUnloadFired(content::WebContents* contents, 96 bool FastUnloadController::BeforeUnloadFired(content::WebContents* contents,
92 bool proceed) { 97 bool proceed) {
98 DevToolsWindow* devtools_window =
99 DevToolsWindow::GetInstanceForInspectedRenderViewHost(
100 contents->GetRenderViewHost());
101 if (devtools_window && !proceed)
102 devtools_window->InspectedPageCancelClose();
103
93 if (!is_attempting_to_close_browser_) { 104 if (!is_attempting_to_close_browser_) {
94 if (!proceed) { 105 if (!proceed) {
95 contents->SetClosedByUserGesture(false); 106 contents->SetClosedByUserGesture(false);
96 } else { 107 } else {
97 // No more dialogs are possible, so remove the tab and finish 108 // No more dialogs are possible, so remove the tab and finish
98 // running unload listeners asynchrounously. 109 // running unload listeners asynchrounously.
99 browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents); 110 browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents);
100 DetachWebContents(contents); 111 DetachWebContents(contents);
101 } 112 }
102 return proceed; 113 return proceed;
(...skipping 16 matching lines...) Expand all
119 return false; 130 return false;
120 } 131 }
121 132
122 return true; 133 return true;
123 } 134 }
124 135
125 bool FastUnloadController::ShouldCloseWindow() { 136 bool FastUnloadController::ShouldCloseWindow() {
126 if (HasCompletedUnloadProcessing()) 137 if (HasCompletedUnloadProcessing())
127 return true; 138 return true;
128 139
140 if (browser_->is_devtools() &&
141 DevToolsWindow::ShouldCloseDevToolsBrowser(browser_)) {
142 return true;
143 }
144
129 // The behavior followed here varies based on the current phase of the 145 // The behavior followed here varies based on the current phase of the
130 // operation and whether a batched shutdown is in progress. 146 // operation and whether a batched shutdown is in progress.
131 // 147 //
132 // If there are tabs with outstanding beforeunload handlers: 148 // If there are tabs with outstanding beforeunload handlers:
133 // 1. If a batched shutdown is in progress: return false. 149 // 1. If a batched shutdown is in progress: return false.
134 // This is to prevent interference with batched shutdown already in 150 // This is to prevent interference with batched shutdown already in
135 // progress. 151 // progress.
136 // 2. Otherwise: start sending beforeunload events and return false. 152 // 2. Otherwise: start sending beforeunload events and return false.
137 // 153 //
138 // Otherwise, If there are no tabs with outstanding beforeunload handlers: 154 // Otherwise, If there are no tabs with outstanding beforeunload handlers:
139 // 3. If a batched shutdown is in progress: start sending unload events and 155 // 3. If a batched shutdown is in progress: start sending unload events and
140 // return false. 156 // return false.
141 // 4. Otherwise: return true. 157 // 4. Otherwise: return true.
142 is_attempting_to_close_browser_ = true; 158 is_attempting_to_close_browser_ = true;
143 // Cases 1 and 4. 159 // Cases 1 and 4.
144 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired(); 160 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired();
145 if (need_beforeunload_fired == is_calling_before_unload_handlers()) 161 if (need_beforeunload_fired == is_calling_before_unload_handlers())
146 return !need_beforeunload_fired; 162 return !need_beforeunload_fired;
147 163
148 // Cases 2 and 3. 164 // Cases 2 and 3.
149 on_close_confirmed_.Reset(); 165 on_close_confirmed_.Reset();
150 ProcessPendingTabs(); 166 ProcessPendingTabs();
151 return false; 167 return false;
152 } 168 }
153 169
154 bool FastUnloadController::CallBeforeUnloadHandlers( 170 bool FastUnloadController::CallBeforeUnloadHandlers(
155 const base::Callback<void(bool)>& on_close_confirmed) { 171 const base::Callback<void(bool)>& on_close_confirmed) {
156 if (!TabsNeedBeforeUnloadFired()) 172 // DevTools browser will get its beforeunload events triggered on
173 // inspected tab closing
174 if (browser_->is_devtools() || !TabsNeedBeforeUnloadFired())
157 return false; 175 return false;
158 176
159 on_close_confirmed_ = on_close_confirmed; 177 on_close_confirmed_ = on_close_confirmed;
160 is_attempting_to_close_browser_ = true; 178 is_attempting_to_close_browser_ = true;
161 ProcessPendingTabs(); 179 ProcessPendingTabs();
162 return true; 180 return true;
163 } 181 }
164 182
165 void FastUnloadController::ResetBeforeUnloadHandlers() { 183 void FastUnloadController::ResetBeforeUnloadHandlers() {
166 if (!is_calling_before_unload_handlers()) 184 if (!is_calling_before_unload_handlers())
167 return; 185 return;
168 CancelWindowClose(); 186 CancelWindowClose();
169 } 187 }
170 188
171 bool FastUnloadController::TabsNeedBeforeUnloadFired() { 189 bool FastUnloadController::TabsNeedBeforeUnloadFired() {
172 if (!tabs_needing_before_unload_.empty() || 190 if (!tabs_needing_before_unload_.empty() ||
173 tab_needing_before_unload_ack_ != NULL) 191 tab_needing_before_unload_ack_ != NULL)
174 return true; 192 return true;
175 193
176 if (!is_calling_before_unload_handlers() && !tabs_needing_unload_.empty()) 194 if (!is_calling_before_unload_handlers() && !tabs_needing_unload_.empty())
177 return false; 195 return false;
178 196
179 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) { 197 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
180 content::WebContents* contents = 198 content::WebContents* contents =
181 browser_->tab_strip_model()->GetWebContentsAt(i); 199 browser_->tab_strip_model()->GetWebContentsAt(i);
182 if (!ContainsKey(tabs_needing_unload_, contents) && 200 if (!ContainsKey(tabs_needing_unload_, contents) &&
183 !ContainsKey(tabs_needing_unload_ack_, contents) && 201 !ContainsKey(tabs_needing_unload_ack_, contents) &&
184 tab_needing_before_unload_ack_ != contents && 202 tab_needing_before_unload_ack_ != contents &&
185 contents->NeedToFireBeforeUnload()) 203 DevToolsWindow::NeedToFireBeforeUnload(contents))
vsevik 2013/11/05 08:36:17 contents->NeedToFireBeforeUnload || DevToolsWindow
lushnikov 2013/11/05 12:12:07 Done.
186 tabs_needing_before_unload_.insert(contents); 204 tabs_needing_before_unload_.insert(contents);
187 } 205 }
188 return !tabs_needing_before_unload_.empty(); 206 return !tabs_needing_before_unload_.empty();
189 } 207 }
190 208
191 //////////////////////////////////////////////////////////////////////////////// 209 ////////////////////////////////////////////////////////////////////////////////
192 // FastUnloadController, content::NotificationObserver implementation: 210 // FastUnloadController, content::NotificationObserver implementation:
193 211
194 void FastUnloadController::Observe( 212 void FastUnloadController::Observe(
195 int type, 213 int type,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 content::WebContents* contents = *it; 325 content::WebContents* contents = *it;
308 tabs_needing_before_unload_.erase(it); 326 tabs_needing_before_unload_.erase(it);
309 // Null check render_view_host here as this gets called on a PostTask and 327 // 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. 328 // the tab's render_view_host may have been nulled out.
311 if (contents->GetRenderViewHost()) { 329 if (contents->GetRenderViewHost()) {
312 tab_needing_before_unload_ack_ = contents; 330 tab_needing_before_unload_ack_ = contents;
313 331
314 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); 332 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
315 core_tab_helper->OnCloseStarted(); 333 core_tab_helper->OnCloseStarted();
316 334
317 contents->GetRenderViewHost()->FirePageBeforeUnload(false); 335 if (!DevToolsWindow::InterceptPageBeforeUnload(contents))
336 contents->GetRenderViewHost()->FirePageBeforeUnload(false);
318 } else { 337 } else {
319 ProcessPendingTabs(); 338 ProcessPendingTabs();
320 } 339 }
321 return; 340 return;
322 } 341 }
323 342
324 if (is_calling_before_unload_handlers()) { 343 if (is_calling_before_unload_handlers()) {
325 on_close_confirmed_.Run(true); 344 on_close_confirmed_.Run(true);
326 return; 345 return;
327 } 346 }
328
329 // Process all the unload handlers. (The beforeunload handlers have finished.) 347 // Process all the unload handlers. (The beforeunload handlers have finished.)
330 if (!tabs_needing_unload_.empty()) { 348 if (!tabs_needing_unload_.empty()) {
331 browser_->OnWindowClosing(); 349 browser_->OnWindowClosing();
332 350
333 // Run unload handlers detached since no more interaction is possible. 351 // Run unload handlers detached since no more interaction is possible.
334 WebContentsSet::iterator it = tabs_needing_unload_.begin(); 352 WebContentsSet::iterator it = tabs_needing_unload_.begin();
335 while (it != tabs_needing_unload_.end()) { 353 while (it != tabs_needing_unload_.end()) {
336 WebContentsSet::iterator current = it++; 354 WebContentsSet::iterator current = it++;
337 content::WebContents* contents = *current; 355 content::WebContents* contents = *current;
338 tabs_needing_unload_.erase(current); 356 tabs_needing_unload_.erase(current);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 tab_needing_before_unload_ack_ == NULL && 394 tab_needing_before_unload_ack_ == NULL &&
377 tabs_needing_unload_.empty() && 395 tabs_needing_unload_.empty() &&
378 tabs_needing_unload_ack_.empty(); 396 tabs_needing_unload_ack_.empty();
379 } 397 }
380 398
381 void FastUnloadController::CancelWindowClose() { 399 void FastUnloadController::CancelWindowClose() {
382 // Closing of window can be canceled from a beforeunload handler. 400 // Closing of window can be canceled from a beforeunload handler.
383 DCHECK(is_attempting_to_close_browser_); 401 DCHECK(is_attempting_to_close_browser_);
384 tabs_needing_before_unload_.clear(); 402 tabs_needing_before_unload_.clear();
385 if (tab_needing_before_unload_ack_ != NULL) { 403 if (tab_needing_before_unload_ack_ != NULL) {
386
387 CoreTabHelper* core_tab_helper = 404 CoreTabHelper* core_tab_helper =
388 CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_); 405 CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_);
389 core_tab_helper->OnCloseCanceled(); 406 core_tab_helper->OnCloseCanceled();
407 DevToolsWindow* devtools_window =
vsevik 2013/11/05 08:36:17 Can we extract static method DevToolsWindow::PageC
lushnikov 2013/11/05 12:12:07 Done.
408 DevToolsWindow::GetInstanceForInspectedRenderViewHost(
409 tab_needing_before_unload_ack_->GetRenderViewHost());
410 if (devtools_window)
411 devtools_window->InspectedPageCancelClose();
390 tab_needing_before_unload_ack_ = NULL; 412 tab_needing_before_unload_ack_ = NULL;
391 } 413 }
392 for (WebContentsSet::iterator it = tabs_needing_unload_.begin(); 414 for (WebContentsSet::iterator it = tabs_needing_unload_.begin();
393 it != tabs_needing_unload_.end(); it++) { 415 it != tabs_needing_unload_.end(); it++) {
394 content::WebContents* contents = *it; 416 content::WebContents* contents = *it;
395 417
396 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); 418 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
397 core_tab_helper->OnCloseCanceled(); 419 core_tab_helper->OnCloseCanceled();
420 DevToolsWindow* devtools_window =
421 DevToolsWindow::GetInstanceForInspectedRenderViewHost(
422 contents->GetRenderViewHost());
423 if (devtools_window)
424 devtools_window->InspectedPageCancelClose();
398 } 425 }
399 tabs_needing_unload_.clear(); 426 tabs_needing_unload_.clear();
400 427
401 // No need to clear tabs_needing_unload_ack_. Those tabs are already detached. 428 // No need to clear tabs_needing_unload_ack_. Those tabs are already detached.
402 429
403 if (is_calling_before_unload_handlers()) { 430 if (is_calling_before_unload_handlers()) {
404 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_; 431 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_;
405 on_close_confirmed_.Reset(); 432 on_close_confirmed_.Reset();
406 on_close_confirmed.Run(false); 433 on_close_confirmed.Run(false);
407 } 434 }
(...skipping 30 matching lines...) Expand all
438 } 465 }
439 466
440 void FastUnloadController::PostTaskForProcessPendingTabs() { 467 void FastUnloadController::PostTaskForProcessPendingTabs() {
441 base::MessageLoop::current()->PostTask( 468 base::MessageLoop::current()->PostTask(
442 FROM_HERE, 469 FROM_HERE,
443 base::Bind(&FastUnloadController::ProcessPendingTabs, 470 base::Bind(&FastUnloadController::ProcessPendingTabs,
444 weak_factory_.GetWeakPtr())); 471 weak_factory_.GetWeakPtr()));
445 } 472 }
446 473
447 } // namespace chrome 474 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698