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

Side by Side Diff: chrome/browser/ui/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 test typos 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 (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 "chrome/browser/ui/unload_controller.h" 5 #include "chrome/browser/ui/unload_controller.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/devtools/devtools_window.h" 9 #include "chrome/browser/devtools/devtools_window.h"
10 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/browser.h"
(...skipping 25 matching lines...) Expand all
36 // Don't try to close the tab when the whole browser is being closed, since 36 // Don't try to close the tab when the whole browser is being closed, since
37 // that avoids the fast shutdown path where we just kill all the renderers. 37 // that avoids the fast shutdown path where we just kill all the renderers.
38 if (is_attempting_to_close_browser_) 38 if (is_attempting_to_close_browser_)
39 ClearUnloadState(contents, true); 39 ClearUnloadState(contents, true);
40 return !is_attempting_to_close_browser_ || 40 return !is_attempting_to_close_browser_ ||
41 is_calling_before_unload_handlers(); 41 is_calling_before_unload_handlers();
42 } 42 }
43 43
44 // static 44 // static
45 bool UnloadController::RunUnloadEventsHelper(content::WebContents* contents) { 45 bool UnloadController::RunUnloadEventsHelper(content::WebContents* contents) {
46 // If there's a devtools window attached to the web contents,
47 // then we would like to run its beforeunload handlers first.
48 if (DevToolsWindow::InterceptPageBeforeUnload(contents)) {
49 return true;
50 }
46 // If the WebContents is not connected yet, then there's no unload 51 // If the WebContents is not connected yet, then there's no unload
47 // handler we can fire even if the WebContents has an unload listener. 52 // handler we can fire even if the WebContents has an unload listener.
48 // One case where we hit this is in a tab that has an infinite loop 53 // One case where we hit this is in a tab that has an infinite loop
49 // before load. 54 // before load.
50 if (contents->NeedToFireBeforeUnload()) { 55 if (contents->NeedToFireBeforeUnload()) {
51 // If the page has unload listeners, then we tell the renderer to fire 56 // If the page has unload listeners, then we tell the renderer to fire
52 // them. Once they have fired, we'll get a message back saying whether 57 // them. Once they have fired, we'll get a message back saying whether
53 // to proceed closing the page or not, which sends us back to this method 58 // to proceed closing the page or not, which sends us back to this method
54 // with the NeedToFireBeforeUnload bit cleared. 59 // with the NeedToFireBeforeUnload bit cleared.
55 contents->GetRenderViewHost()->FirePageBeforeUnload(false); 60 contents->GetRenderViewHost()->FirePageBeforeUnload(false);
56 return true; 61 return true;
57 } 62 }
58 return false; 63 return false;
59 } 64 }
60 65
61 bool UnloadController::BeforeUnloadFired(content::WebContents* contents, 66 bool UnloadController::BeforeUnloadFired(content::WebContents* contents,
62 bool proceed) { 67 bool proceed) {
68 if (!proceed)
69 DevToolsWindow::PageClosingCanceled(contents);
70
63 if (!is_attempting_to_close_browser_) { 71 if (!is_attempting_to_close_browser_) {
64 if (!proceed) 72 if (!proceed)
65 contents->SetClosedByUserGesture(false); 73 contents->SetClosedByUserGesture(false);
66 return proceed; 74 return proceed;
67 } 75 }
68 76
69 if (!proceed) { 77 if (!proceed) {
70 CancelWindowClose(); 78 CancelWindowClose();
71 contents->SetClosedByUserGesture(false); 79 contents->SetClosedByUserGesture(false);
72 return false; 80 return false;
(...skipping 10 matching lines...) Expand all
83 return false; 91 return false;
84 } 92 }
85 93
86 return true; 94 return true;
87 } 95 }
88 96
89 bool UnloadController::ShouldCloseWindow() { 97 bool UnloadController::ShouldCloseWindow() {
90 if (HasCompletedUnloadProcessing()) 98 if (HasCompletedUnloadProcessing())
91 return true; 99 return true;
92 100
101 if (browser_->is_devtools() &&
102 DevToolsWindow::ShouldCloseDevToolsBrowser(browser_)) {
103 return true;
104 }
105
93 // The behavior followed here varies based on the current phase of the 106 // The behavior followed here varies based on the current phase of the
94 // operation and whether a batched shutdown is in progress. 107 // operation and whether a batched shutdown is in progress.
95 // 108 //
96 // If there are tabs with outstanding beforeunload handlers: 109 // If there are tabs with outstanding beforeunload handlers:
97 // 1. If a batched shutdown is in progress: return false. 110 // 1. If a batched shutdown is in progress: return false.
98 // This is to prevent interference with batched shutdown already in 111 // This is to prevent interference with batched shutdown already in
99 // progress. 112 // progress.
100 // 2. Otherwise: start sending beforeunload events and return false. 113 // 2. Otherwise: start sending beforeunload events and return false.
101 // 114 //
102 // Otherwise, If there are no tabs with outstanding beforeunload handlers: 115 // Otherwise, If there are no tabs with outstanding beforeunload handlers:
103 // 3. If a batched shutdown is in progress: start sending unload events and 116 // 3. If a batched shutdown is in progress: start sending unload events and
104 // return false. 117 // return false.
105 // 4. Otherwise: return true. 118 // 4. Otherwise: return true.
106 is_attempting_to_close_browser_ = true; 119 is_attempting_to_close_browser_ = true;
107 // Cases 1 and 4. 120 // Cases 1 and 4.
108 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired(); 121 bool need_beforeunload_fired = TabsNeedBeforeUnloadFired();
109 if (need_beforeunload_fired == is_calling_before_unload_handlers()) 122 if (need_beforeunload_fired == is_calling_before_unload_handlers())
110 return !need_beforeunload_fired; 123 return !need_beforeunload_fired;
111 124
112 // Cases 2 and 3. 125 // Cases 2 and 3.
113 on_close_confirmed_.Reset(); 126 on_close_confirmed_.Reset();
114 ProcessPendingTabs(); 127 ProcessPendingTabs();
115 return false; 128 return false;
116 } 129 }
117 130
118 bool UnloadController::CallBeforeUnloadHandlers( 131 bool UnloadController::CallBeforeUnloadHandlers(
119 const base::Callback<void(bool)>& on_close_confirmed) { 132 const base::Callback<void(bool)>& on_close_confirmed) {
120 if (HasCompletedUnloadProcessing() || !TabsNeedBeforeUnloadFired()) 133 // DevTools browser will get its beforeunload events triggered on
134 // inspected tab closing
135 if (browser_->is_devtools() || HasCompletedUnloadProcessing() ||
136 !TabsNeedBeforeUnloadFired())
121 return false; 137 return false;
122 138
123 is_attempting_to_close_browser_ = true; 139 is_attempting_to_close_browser_ = true;
124 on_close_confirmed_ = on_close_confirmed; 140 on_close_confirmed_ = on_close_confirmed;
125 141
126 ProcessPendingTabs(); 142 ProcessPendingTabs();
127 return true; 143 return true;
128 } 144 }
129 145
130 void UnloadController::ResetBeforeUnloadHandlers() { 146 void UnloadController::ResetBeforeUnloadHandlers() {
131 if (!is_calling_before_unload_handlers()) 147 if (!is_calling_before_unload_handlers())
132 return; 148 return;
133 CancelWindowClose(); 149 CancelWindowClose();
134 } 150 }
135 151
136 bool UnloadController::TabsNeedBeforeUnloadFired() { 152 bool UnloadController::TabsNeedBeforeUnloadFired() {
137 if (tabs_needing_before_unload_fired_.empty()) { 153 if (tabs_needing_before_unload_fired_.empty()) {
138 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) { 154 for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
139 content::WebContents* contents = 155 content::WebContents* contents =
140 browser_->tab_strip_model()->GetWebContentsAt(i); 156 browser_->tab_strip_model()->GetWebContentsAt(i);
141 if (!ContainsKey(tabs_needing_unload_fired_, contents) && 157 if (!ContainsKey(tabs_needing_unload_fired_, contents) &&
142 contents->NeedToFireBeforeUnload()) { 158 (contents->NeedToFireBeforeUnload() ||
159 DevToolsWindow::NeedToFireBeforeUnload(contents))) {
143 tabs_needing_before_unload_fired_.insert(contents); 160 tabs_needing_before_unload_fired_.insert(contents);
144 } 161 }
145 } 162 }
146 } 163 }
147 return !tabs_needing_before_unload_fired_.empty(); 164 return !tabs_needing_before_unload_fired_.empty();
148 } 165 }
149 166
150 //////////////////////////////////////////////////////////////////////////////// 167 ////////////////////////////////////////////////////////////////////////////////
151 // UnloadController, content::NotificationObserver implementation: 168 // UnloadController, content::NotificationObserver implementation:
152 169
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 } 246 }
230 247
231 // Process beforeunload tabs first. When that queue is empty, process 248 // Process beforeunload tabs first. When that queue is empty, process
232 // unload tabs. 249 // unload tabs.
233 if (!tabs_needing_before_unload_fired_.empty()) { 250 if (!tabs_needing_before_unload_fired_.empty()) {
234 content::WebContents* web_contents = 251 content::WebContents* web_contents =
235 *(tabs_needing_before_unload_fired_.begin()); 252 *(tabs_needing_before_unload_fired_.begin());
236 // Null check render_view_host here as this gets called on a PostTask and 253 // Null check render_view_host here as this gets called on a PostTask and
237 // the tab's render_view_host may have been nulled out. 254 // the tab's render_view_host may have been nulled out.
238 if (web_contents->GetRenderViewHost()) { 255 if (web_contents->GetRenderViewHost()) {
239 web_contents->GetRenderViewHost()->FirePageBeforeUnload(false); 256 if (!DevToolsWindow::InterceptPageBeforeUnload(web_contents))
257 web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
240 } else { 258 } else {
241 ClearUnloadState(web_contents, true); 259 ClearUnloadState(web_contents, true);
242 } 260 }
243 } else if (is_calling_before_unload_handlers()) { 261 } else if (is_calling_before_unload_handlers()) {
244 on_close_confirmed_.Run(true); 262 on_close_confirmed_.Run(true);
245 } else if (!tabs_needing_unload_fired_.empty()) { 263 } else if (!tabs_needing_unload_fired_.empty()) {
246 // We've finished firing all beforeunload events and can proceed with unload 264 // We've finished firing all beforeunload events and can proceed with unload
247 // events. 265 // events.
248 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting 266 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
249 // somewhere around here so that we have accurate measurements of shutdown 267 // somewhere around here so that we have accurate measurements of shutdown
(...skipping 17 matching lines...) Expand all
267 bool UnloadController::HasCompletedUnloadProcessing() const { 285 bool UnloadController::HasCompletedUnloadProcessing() const {
268 return is_attempting_to_close_browser_ && 286 return is_attempting_to_close_browser_ &&
269 tabs_needing_before_unload_fired_.empty() && 287 tabs_needing_before_unload_fired_.empty() &&
270 tabs_needing_unload_fired_.empty(); 288 tabs_needing_unload_fired_.empty();
271 } 289 }
272 290
273 void UnloadController::CancelWindowClose() { 291 void UnloadController::CancelWindowClose() {
274 // Closing of window can be canceled from a beforeunload handler. 292 // Closing of window can be canceled from a beforeunload handler.
275 DCHECK(is_attempting_to_close_browser_); 293 DCHECK(is_attempting_to_close_browser_);
276 tabs_needing_before_unload_fired_.clear(); 294 tabs_needing_before_unload_fired_.clear();
295 for (UnloadListenerSet::iterator it = tabs_needing_unload_fired_.begin();
296 it != tabs_needing_unload_fired_.end(); ++it) {
297 DevToolsWindow::PageClosingCanceled(*it);
298 }
277 tabs_needing_unload_fired_.clear(); 299 tabs_needing_unload_fired_.clear();
278 if (is_calling_before_unload_handlers()) { 300 if (is_calling_before_unload_handlers()) {
279 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_; 301 base::Callback<void(bool)> on_close_confirmed = on_close_confirmed_;
280 on_close_confirmed_.Reset(); 302 on_close_confirmed_.Reset();
281 on_close_confirmed.Run(false); 303 on_close_confirmed.Run(false);
282 } 304 }
283 is_attempting_to_close_browser_ = false; 305 is_attempting_to_close_browser_ = false;
284 306
285 content::NotificationService::current()->Notify( 307 content::NotificationService::current()->Notify(
286 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 308 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
(...skipping 24 matching lines...) Expand all
311 } else { 333 } else {
312 base::MessageLoop::current()->PostTask( 334 base::MessageLoop::current()->PostTask(
313 FROM_HERE, 335 FROM_HERE,
314 base::Bind(&UnloadController::ProcessPendingTabs, 336 base::Bind(&UnloadController::ProcessPendingTabs,
315 weak_factory_.GetWeakPtr())); 337 weak_factory_.GetWeakPtr()));
316 } 338 }
317 } 339 }
318 } 340 }
319 341
320 } // namespace chrome 342 } // namespace chrome
OLDNEW
« chrome/browser/ui/tabs/tab_strip_model.cc ('K') | « chrome/browser/ui/tabs/tab_strip_model.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698