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

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: addressed comments 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 if (!proceed)
99 DevToolsWindow::PageCancelClose(contents);
100
93 if (!is_attempting_to_close_browser_) { 101 if (!is_attempting_to_close_browser_) {
94 if (!proceed) { 102 if (!proceed) {
95 contents->SetClosedByUserGesture(false); 103 contents->SetClosedByUserGesture(false);
96 } else { 104 } else {
97 // No more dialogs are possible, so remove the tab and finish 105 // No more dialogs are possible, so remove the tab and finish
98 // running unload listeners asynchrounously. 106 // running unload listeners asynchrounously.
99 browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents); 107 browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents);
100 DetachWebContents(contents); 108 DetachWebContents(contents);
101 } 109 }
102 return proceed; 110 return proceed;
(...skipping 16 matching lines...) Expand all
119 return false; 127 return false;
120 } 128 }
121 129
122 return true; 130 return true;
123 } 131 }
124 132
125 bool FastUnloadController::ShouldCloseWindow() { 133 bool FastUnloadController::ShouldCloseWindow() {
126 if (HasCompletedUnloadProcessing()) 134 if (HasCompletedUnloadProcessing())
127 return true; 135 return true;
128 136
137 if (browser_->is_devtools() &&
138 DevToolsWindow::ShouldCloseDevToolsBrowser(browser_)) {
139 return true;
140 }
141
129 // The behavior followed here varies based on the current phase of the 142 // The behavior followed here varies based on the current phase of the
130 // operation and whether a batched shutdown is in progress. 143 // operation and whether a batched shutdown is in progress.
131 // 144 //
132 // If there are tabs with outstanding beforeunload handlers: 145 // If there are tabs with outstanding beforeunload handlers:
133 // 1. If a batched shutdown is in progress: return false. 146 // 1. If a batched shutdown is in progress: return false.
134 // This is to prevent interference with batched shutdown already in 147 // This is to prevent interference with batched shutdown already in
135 // progress. 148 // progress.
136 // 2. Otherwise: start sending beforeunload events and return false. 149 // 2. Otherwise: start sending beforeunload events and return false.
137 // 150 //
138 // Otherwise, If there are no tabs with outstanding beforeunload handlers: 151 // Otherwise, If there are no tabs with outstanding beforeunload handlers:
139 // 3. If a batched shutdown is in progress: start sending unload events and 152 // 3. If a batched shutdown is in progress: start sending unload events and
140 // return false. 153 // return false.
141 // 4. Otherwise: return true. 154 // 4. Otherwise: return true.
142 is_attempting_to_close_browser_ = true; 155 is_attempting_to_close_browser_ = true;
143 // Cases 1 and 4. 156 // Cases 1 and 4.
144 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired(); 157 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired();
145 if (need_beforeunload_fired == is_calling_before_unload_handlers()) 158 if (need_beforeunload_fired == is_calling_before_unload_handlers())
146 return !need_beforeunload_fired; 159 return !need_beforeunload_fired;
147 160
148 // Cases 2 and 3. 161 // Cases 2 and 3.
149 on_close_confirmed_.Reset(); 162 on_close_confirmed_.Reset();
150 ProcessPendingTabs(); 163 ProcessPendingTabs();
151 return false; 164 return false;
152 } 165 }
153 166
154 bool FastUnloadController::CallBeforeUnloadHandlers( 167 bool FastUnloadController::CallBeforeUnloadHandlers(
155 const base::Callback<void(bool)>& on_close_confirmed) { 168 const base::Callback<void(bool)>& on_close_confirmed) {
156 if (!TabsNeedBeforeUnloadFired()) 169 // DevTools browser will get its beforeunload events triggered on
170 // inspected tab closing
171 if (browser_->is_devtools() || !TabsNeedBeforeUnloadFired())
157 return false; 172 return false;
158 173
159 on_close_confirmed_ = on_close_confirmed; 174 on_close_confirmed_ = on_close_confirmed;
160 is_attempting_to_close_browser_ = true; 175 is_attempting_to_close_browser_ = true;
161 ProcessPendingTabs(); 176 ProcessPendingTabs();
162 return true; 177 return true;
163 } 178 }
164 179
165 void FastUnloadController::ResetBeforeUnloadHandlers() { 180 void FastUnloadController::ResetBeforeUnloadHandlers() {
166 if (!is_calling_before_unload_handlers()) 181 if (!is_calling_before_unload_handlers())
167 return; 182 return;
168 CancelWindowClose(); 183 CancelWindowClose();
169 } 184 }
170 185
171 bool FastUnloadController::TabsNeedBeforeUnloadFired() { 186 bool FastUnloadController::TabsNeedBeforeUnloadFired() {
172 if (!tabs_needing_before_unload_.empty() || 187 if (!tabs_needing_before_unload_.empty() ||
173 tab_needing_before_unload_ack_ != NULL) 188 tab_needing_before_unload_ack_ != NULL)
174 return true; 189 return true;
175 190
176 if (!is_calling_before_unload_handlers() && !tabs_needing_unload_.empty()) 191 if (!is_calling_before_unload_handlers() && !tabs_needing_unload_.empty())
177 return false; 192 return false;
178 193
179 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) { 194 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
180 content::WebContents* contents = 195 content::WebContents* contents =
181 browser_->tab_strip_model()->GetWebContentsAt(i); 196 browser_->tab_strip_model()->GetWebContentsAt(i);
182 if (!ContainsKey(tabs_needing_unload_, contents) && 197 if (!ContainsKey(tabs_needing_unload_, contents) &&
183 !ContainsKey(tabs_needing_unload_ack_, contents) && 198 !ContainsKey(tabs_needing_unload_ack_, contents) &&
184 tab_needing_before_unload_ack_ != contents && 199 tab_needing_before_unload_ack_ != contents &&
185 contents->NeedToFireBeforeUnload()) 200 (contents->NeedToFireBeforeUnload() ||
201 DevToolsWindow::NeedToFireBeforeUnload(contents)))
186 tabs_needing_before_unload_.insert(contents); 202 tabs_needing_before_unload_.insert(contents);
187 } 203 }
188 return !tabs_needing_before_unload_.empty(); 204 return !tabs_needing_before_unload_.empty();
189 } 205 }
190 206
191 //////////////////////////////////////////////////////////////////////////////// 207 ////////////////////////////////////////////////////////////////////////////////
192 // FastUnloadController, content::NotificationObserver implementation: 208 // FastUnloadController, content::NotificationObserver implementation:
193 209
194 void FastUnloadController::Observe( 210 void FastUnloadController::Observe(
195 int type, 211 int type,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 content::WebContents* contents = *it; 323 content::WebContents* contents = *it;
308 tabs_needing_before_unload_.erase(it); 324 tabs_needing_before_unload_.erase(it);
309 // Null check render_view_host here as this gets called on a PostTask and 325 // 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. 326 // the tab's render_view_host may have been nulled out.
311 if (contents->GetRenderViewHost()) { 327 if (contents->GetRenderViewHost()) {
312 tab_needing_before_unload_ack_ = contents; 328 tab_needing_before_unload_ack_ = contents;
313 329
314 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); 330 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
315 core_tab_helper->OnCloseStarted(); 331 core_tab_helper->OnCloseStarted();
316 332
317 contents->GetRenderViewHost()->FirePageBeforeUnload(false); 333 if (!DevToolsWindow::InterceptPageBeforeUnload(contents))
334 contents->GetRenderViewHost()->FirePageBeforeUnload(false);
318 } else { 335 } else {
319 ProcessPendingTabs(); 336 ProcessPendingTabs();
320 } 337 }
321 return; 338 return;
322 } 339 }
323 340
324 if (is_calling_before_unload_handlers()) { 341 if (is_calling_before_unload_handlers()) {
325 on_close_confirmed_.Run(true); 342 on_close_confirmed_.Run(true);
326 return; 343 return;
327 } 344 }
328
329 // Process all the unload handlers. (The beforeunload handlers have finished.) 345 // Process all the unload handlers. (The beforeunload handlers have finished.)
330 if (!tabs_needing_unload_.empty()) { 346 if (!tabs_needing_unload_.empty()) {
331 browser_->OnWindowClosing(); 347 browser_->OnWindowClosing();
332 348
333 // Run unload handlers detached since no more interaction is possible. 349 // Run unload handlers detached since no more interaction is possible.
334 WebContentsSet::iterator it = tabs_needing_unload_.begin(); 350 WebContentsSet::iterator it = tabs_needing_unload_.begin();
335 while (it != tabs_needing_unload_.end()) { 351 while (it != tabs_needing_unload_.end()) {
336 WebContentsSet::iterator current = it++; 352 WebContentsSet::iterator current = it++;
337 content::WebContents* contents = *current; 353 content::WebContents* contents = *current;
338 tabs_needing_unload_.erase(current); 354 tabs_needing_unload_.erase(current);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 tab_needing_before_unload_ack_ == NULL && 392 tab_needing_before_unload_ack_ == NULL &&
377 tabs_needing_unload_.empty() && 393 tabs_needing_unload_.empty() &&
378 tabs_needing_unload_ack_.empty(); 394 tabs_needing_unload_ack_.empty();
379 } 395 }
380 396
381 void FastUnloadController::CancelWindowClose() { 397 void FastUnloadController::CancelWindowClose() {
382 // Closing of window can be canceled from a beforeunload handler. 398 // Closing of window can be canceled from a beforeunload handler.
383 DCHECK(is_attempting_to_close_browser_); 399 DCHECK(is_attempting_to_close_browser_);
384 tabs_needing_before_unload_.clear(); 400 tabs_needing_before_unload_.clear();
385 if (tab_needing_before_unload_ack_ != NULL) { 401 if (tab_needing_before_unload_ack_ != NULL) {
386
387 CoreTabHelper* core_tab_helper = 402 CoreTabHelper* core_tab_helper =
388 CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_); 403 CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_);
389 core_tab_helper->OnCloseCanceled(); 404 core_tab_helper->OnCloseCanceled();
405 DevToolsWindow::PageCancelClose(tab_needing_before_unload_ack_);
390 tab_needing_before_unload_ack_ = NULL; 406 tab_needing_before_unload_ack_ = NULL;
391 } 407 }
392 for (WebContentsSet::iterator it = tabs_needing_unload_.begin(); 408 for (WebContentsSet::iterator it = tabs_needing_unload_.begin();
393 it != tabs_needing_unload_.end(); it++) { 409 it != tabs_needing_unload_.end(); it++) {
394 content::WebContents* contents = *it; 410 content::WebContents* contents = *it;
395 411
396 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); 412 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
397 core_tab_helper->OnCloseCanceled(); 413 core_tab_helper->OnCloseCanceled();
414 DevToolsWindow::PageCancelClose(contents);
398 } 415 }
399 tabs_needing_unload_.clear(); 416 tabs_needing_unload_.clear();
400 417
401 // No need to clear tabs_needing_unload_ack_. Those tabs are already detached. 418 // No need to clear tabs_needing_unload_ack_. Those tabs are already detached.
402 419
403 if (is_calling_before_unload_handlers()) { 420 if (is_calling_before_unload_handlers()) {
404 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_; 421 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_;
405 on_close_confirmed_.Reset(); 422 on_close_confirmed_.Reset();
406 on_close_confirmed.Run(false); 423 on_close_confirmed.Run(false);
407 } 424 }
(...skipping 30 matching lines...) Expand all
438 } 455 }
439 456
440 void FastUnloadController::PostTaskForProcessPendingTabs() { 457 void FastUnloadController::PostTaskForProcessPendingTabs() {
441 base::MessageLoop::current()->PostTask( 458 base::MessageLoop::current()->PostTask(
442 FROM_HERE, 459 FROM_HERE,
443 base::Bind(&FastUnloadController::ProcessPendingTabs, 460 base::Bind(&FastUnloadController::ProcessPendingTabs,
444 weak_factory_.GetWeakPtr())); 461 weak_factory_.GetWeakPtr()));
445 } 462 }
446 463
447 } // namespace chrome 464 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698