| OLD | NEW | 
|---|
| 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/logging.h" | 7 #include "base/logging.h" | 
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" | 
| 9 #include "chrome/browser/ui/browser.h" | 9 #include "chrome/browser/ui/browser.h" | 
| 10 #include "chrome/browser/ui/browser_tabstrip.h" | 10 #include "chrome/browser/ui/browser_tabstrip.h" | 
|  | 11 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | 
| 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 12 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
| 12 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" | 13 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" | 
| 13 #include "chrome/common/chrome_notification_types.h" | 14 #include "chrome/common/chrome_notification_types.h" | 
| 14 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" | 
| 15 #include "content/public/browser/notification_source.h" | 16 #include "content/public/browser/notification_source.h" | 
| 16 #include "content/public/browser/notification_types.h" | 17 #include "content/public/browser/notification_types.h" | 
| 17 #include "content/public/browser/render_view_host.h" | 18 #include "content/public/browser/render_view_host.h" | 
| 18 #include "content/public/browser/web_contents.h" | 19 #include "content/public/browser/web_contents.h" | 
| 19 #include "content/public/browser/web_contents_delegate.h" | 20 #include "content/public/browser/web_contents_delegate.h" | 
| 20 | 21 | 
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 215     ClearUnloadState(contents); | 216     ClearUnloadState(contents); | 
| 216 } | 217 } | 
| 217 | 218 | 
| 218 bool UnloadController::DetachWebContents(content::WebContents* contents) { | 219 bool UnloadController::DetachWebContents(content::WebContents* contents) { | 
| 219   int index = browser_->tab_strip_model()->GetIndexOfWebContents(contents); | 220   int index = browser_->tab_strip_model()->GetIndexOfWebContents(contents); | 
| 220   if (index != TabStripModel::kNoTab && | 221   if (index != TabStripModel::kNoTab && | 
| 221       contents->NeedToFireBeforeUnload()) { | 222       contents->NeedToFireBeforeUnload()) { | 
| 222     tabs_needing_unload_ack_.insert(contents); | 223     tabs_needing_unload_ack_.insert(contents); | 
| 223     browser_->tab_strip_model()->DetachWebContentsAt(index); | 224     browser_->tab_strip_model()->DetachWebContentsAt(index); | 
| 224     contents->SetDelegate(detached_delegate_.get()); | 225     contents->SetDelegate(detached_delegate_.get()); | 
| 225     contents->OnUnloadDetachedStarted(); | 226     CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); | 
|  | 227     core_tab_helper->OnUnloadDetachedStarted(); | 
| 226     return true; | 228     return true; | 
| 227   } | 229   } | 
| 228   return false; | 230   return false; | 
| 229 } | 231 } | 
| 230 | 232 | 
| 231 void UnloadController::ProcessPendingTabs() { | 233 void UnloadController::ProcessPendingTabs() { | 
| 232   if (!is_attempting_to_close_browser_) { | 234   if (!is_attempting_to_close_browser_) { | 
| 233     // Because we might invoke this after a delay it's possible for the value of | 235     // Because we might invoke this after a delay it's possible for the value of | 
| 234     // is_attempting_to_close_browser_ to have changed since we scheduled the | 236     // is_attempting_to_close_browser_ to have changed since we scheduled the | 
| 235     // task. | 237     // task. | 
| 236     return; | 238     return; | 
| 237   } | 239   } | 
| 238 | 240 | 
| 239   if (tab_needing_before_unload_ack_ != NULL) { | 241   if (tab_needing_before_unload_ack_ != NULL) { | 
| 240     // Wait for |BeforeUnloadFired| before proceeding. | 242     // Wait for |BeforeUnloadFired| before proceeding. | 
| 241     return; | 243     return; | 
| 242   } | 244   } | 
| 243 | 245 | 
| 244   // Process a beforeunload handler. | 246   // Process a beforeunload handler. | 
| 245   if (!tabs_needing_before_unload_.empty()) { | 247   if (!tabs_needing_before_unload_.empty()) { | 
| 246     WebContentsSet::iterator it = tabs_needing_before_unload_.begin(); | 248     WebContentsSet::iterator it = tabs_needing_before_unload_.begin(); | 
| 247     content::WebContents* contents = *it; | 249     content::WebContents* contents = *it; | 
| 248     tabs_needing_before_unload_.erase(it); | 250     tabs_needing_before_unload_.erase(it); | 
| 249     // Null check render_view_host here as this gets called on a PostTask and | 251     // Null check render_view_host here as this gets called on a PostTask and | 
| 250     // the tab's render_view_host may have been nulled out. | 252     // the tab's render_view_host may have been nulled out. | 
| 251     if (contents->GetRenderViewHost()) { | 253     if (contents->GetRenderViewHost()) { | 
| 252       tab_needing_before_unload_ack_ = contents; | 254       tab_needing_before_unload_ack_ = contents; | 
| 253       contents->OnCloseStarted(); | 255 | 
|  | 256       CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); | 
|  | 257       core_tab_helper->OnCloseStarted(); | 
|  | 258 | 
| 254       contents->GetRenderViewHost()->FirePageBeforeUnload(false); | 259       contents->GetRenderViewHost()->FirePageBeforeUnload(false); | 
| 255     } else { | 260     } else { | 
| 256       ProcessPendingTabs(); | 261       ProcessPendingTabs(); | 
| 257     } | 262     } | 
| 258     return; | 263     return; | 
| 259   } | 264   } | 
| 260 | 265 | 
| 261   // Process all the unload handlers. (The beforeunload handlers have finished.) | 266   // Process all the unload handlers. (The beforeunload handlers have finished.) | 
| 262   if (!tabs_needing_unload_.empty()) { | 267   if (!tabs_needing_unload_.empty()) { | 
| 263     browser_->OnWindowClosing(); | 268     browser_->OnWindowClosing(); | 
| 264 | 269 | 
| 265     // Run unload handlers detached since no more interaction is possible. | 270     // Run unload handlers detached since no more interaction is possible. | 
| 266     WebContentsSet::iterator it = tabs_needing_unload_.begin(); | 271     WebContentsSet::iterator it = tabs_needing_unload_.begin(); | 
| 267     while (it != tabs_needing_unload_.end()) { | 272     while (it != tabs_needing_unload_.end()) { | 
| 268       WebContentsSet::iterator current = it++; | 273       WebContentsSet::iterator current = it++; | 
| 269       content::WebContents* contents = *current; | 274       content::WebContents* contents = *current; | 
| 270       tabs_needing_unload_.erase(current); | 275       tabs_needing_unload_.erase(current); | 
| 271       // Null check render_view_host here as this gets called on a PostTask | 276       // Null check render_view_host here as this gets called on a PostTask | 
| 272       // and the tab's render_view_host may have been nulled out. | 277       // and the tab's render_view_host may have been nulled out. | 
| 273       if (contents->GetRenderViewHost()) { | 278       if (contents->GetRenderViewHost()) { | 
| 274         contents->OnUnloadStarted(); | 279         CoreTabHelper* core_tab_helper = | 
|  | 280             CoreTabHelper::FromWebContents(contents); | 
|  | 281         core_tab_helper->OnUnloadStarted(); | 
| 275         DetachWebContents(contents); | 282         DetachWebContents(contents); | 
| 276         contents->GetRenderViewHost()->ClosePage(); | 283         contents->GetRenderViewHost()->ClosePage(); | 
| 277       } | 284       } | 
| 278     } | 285     } | 
| 279 | 286 | 
| 280     // Get the browser hidden. | 287     // Get the browser hidden. | 
| 281     if (browser_->tab_strip_model()->empty()) { | 288     if (browser_->tab_strip_model()->empty()) { | 
| 282       browser_->TabStripEmpty(); | 289       browser_->TabStripEmpty(); | 
| 283     } else { | 290     } else { | 
| 284       browser_->tab_strip_model()->CloseAllTabs();  // tabs not needing unload | 291       browser_->tab_strip_model()->CloseAllTabs();  // tabs not needing unload | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 306       tab_needing_before_unload_ack_ == NULL && | 313       tab_needing_before_unload_ack_ == NULL && | 
| 307       tabs_needing_unload_.empty() && | 314       tabs_needing_unload_.empty() && | 
| 308       tabs_needing_unload_ack_.empty(); | 315       tabs_needing_unload_ack_.empty(); | 
| 309 } | 316 } | 
| 310 | 317 | 
| 311 void UnloadController::CancelWindowClose() { | 318 void UnloadController::CancelWindowClose() { | 
| 312   // Closing of window can be canceled from a beforeunload handler. | 319   // Closing of window can be canceled from a beforeunload handler. | 
| 313   DCHECK(is_attempting_to_close_browser_); | 320   DCHECK(is_attempting_to_close_browser_); | 
| 314   tabs_needing_before_unload_.clear(); | 321   tabs_needing_before_unload_.clear(); | 
| 315   if (tab_needing_before_unload_ack_ != NULL) { | 322   if (tab_needing_before_unload_ack_ != NULL) { | 
| 316     tab_needing_before_unload_ack_->OnCloseCanceled(); | 323 | 
|  | 324     CoreTabHelper* core_tab_helper = | 
|  | 325         CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_); | 
|  | 326     core_tab_helper->OnCloseCanceled(); | 
| 317     tab_needing_before_unload_ack_ = NULL; | 327     tab_needing_before_unload_ack_ = NULL; | 
| 318   } | 328   } | 
| 319   for (WebContentsSet::iterator it = tabs_needing_unload_.begin(); | 329   for (WebContentsSet::iterator it = tabs_needing_unload_.begin(); | 
| 320        it != tabs_needing_unload_.end(); it++) { | 330        it != tabs_needing_unload_.end(); it++) { | 
| 321     content::WebContents* contents = *it; | 331     content::WebContents* contents = *it; | 
| 322     contents->OnCloseCanceled(); | 332 | 
|  | 333     CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); | 
|  | 334     core_tab_helper->OnCloseCanceled(); | 
| 323   } | 335   } | 
| 324   tabs_needing_unload_.clear(); | 336   tabs_needing_unload_.clear(); | 
| 325 | 337 | 
| 326   // No need to clear tabs_needing_unload_ack_. Those tabs are already detached. | 338   // No need to clear tabs_needing_unload_ack_. Those tabs are already detached. | 
| 327 | 339 | 
| 328   is_attempting_to_close_browser_ = false; | 340   is_attempting_to_close_browser_ = false; | 
| 329 | 341 | 
| 330   content::NotificationService::current()->Notify( | 342   content::NotificationService::current()->Notify( | 
| 331       chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, | 343       chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, | 
| 332       content::Source<Browser>(browser_), | 344       content::Source<Browser>(browser_), | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 357 } | 369 } | 
| 358 | 370 | 
| 359 void UnloadController::PostTaskForProcessPendingTabs() { | 371 void UnloadController::PostTaskForProcessPendingTabs() { | 
| 360   base::MessageLoop::current()->PostTask( | 372   base::MessageLoop::current()->PostTask( | 
| 361       FROM_HERE, | 373       FROM_HERE, | 
| 362       base::Bind(&UnloadController::ProcessPendingTabs, | 374       base::Bind(&UnloadController::ProcessPendingTabs, | 
| 363                  weak_factory_.GetWeakPtr())); | 375                  weak_factory_.GetWeakPtr())); | 
| 364 } | 376 } | 
| 365 | 377 | 
| 366 }  // namespace chrome | 378 }  // namespace chrome | 
| OLD | NEW | 
|---|