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

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

Issue 10749002: Move unload handling off Browser onto its own class, UnloadController. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months 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
« no previous file with comments | « chrome/browser/ui/browser.h ('k') | chrome/browser/ui/unload_controller.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/browser.h" 5 #include "chrome/browser/ui/browser.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <windows.h> 8 #include <windows.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #endif // OS_WIN 10 #endif // OS_WIN
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 #include "chrome/browser/ui/search/search_model.h" 128 #include "chrome/browser/ui/search/search_model.h"
129 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" 129 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
130 #include "chrome/browser/ui/singleton_tabs.h" 130 #include "chrome/browser/ui/singleton_tabs.h"
131 #include "chrome/browser/ui/status_bubble.h" 131 #include "chrome/browser/ui/status_bubble.h"
132 #include "chrome/browser/ui/sync/browser_synced_window_delegate.h" 132 #include "chrome/browser/ui/sync/browser_synced_window_delegate.h"
133 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" 133 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
134 #include "chrome/browser/ui/tab_contents/tab_contents.h" 134 #include "chrome/browser/ui/tab_contents/tab_contents.h"
135 #include "chrome/browser/ui/tabs/dock_info.h" 135 #include "chrome/browser/ui/tabs/dock_info.h"
136 #include "chrome/browser/ui/tabs/tab_menu_model.h" 136 #include "chrome/browser/ui/tabs/tab_menu_model.h"
137 #include "chrome/browser/ui/tabs/tab_strip_model.h" 137 #include "chrome/browser/ui/tabs/tab_strip_model.h"
138 #include "chrome/browser/ui/unload_controller.h"
138 #include "chrome/browser/ui/web_applications/web_app_ui.h" 139 #include "chrome/browser/ui/web_applications/web_app_ui.h"
139 #include "chrome/browser/ui/webui/feedback_ui.h" 140 #include "chrome/browser/ui/webui/feedback_ui.h"
140 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" 141 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
141 #include "chrome/browser/ui/webui/signin/login_ui_service.h" 142 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
142 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" 143 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
143 #include "chrome/browser/ui/window_sizer/window_sizer.h" 144 #include "chrome/browser/ui/window_sizer/window_sizer.h"
144 #include "chrome/browser/upgrade_detector.h" 145 #include "chrome/browser/upgrade_detector.h"
145 #include "chrome/browser/web_applications/web_app.h" 146 #include "chrome/browser/web_applications/web_app.h"
146 #include "chrome/common/chrome_constants.h" 147 #include "chrome/common/chrome_constants.h"
147 #include "chrome/common/chrome_notification_types.h" 148 #include "chrome/common/chrome_notification_types.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 // Browser, Constructors, Creation, Showing: 296 // Browser, Constructors, Creation, Showing:
296 297
297 Browser::Browser(Type type, Profile* profile) 298 Browser::Browser(Type type, Profile* profile)
298 : type_(type), 299 : type_(type),
299 profile_(profile), 300 profile_(profile),
300 window_(NULL), 301 window_(NULL),
301 ALLOW_THIS_IN_INITIALIZER_LIST( 302 ALLOW_THIS_IN_INITIALIZER_LIST(
302 tab_strip_model_(new TabStripModel(this, profile))), 303 tab_strip_model_(new TabStripModel(this, profile))),
303 app_type_(APP_TYPE_HOST), 304 app_type_(APP_TYPE_HOST),
304 chrome_updater_factory_(this), 305 chrome_updater_factory_(this),
305 is_attempting_to_close_browser_(false),
306 cancel_download_confirmation_state_(NOT_PROMPTED), 306 cancel_download_confirmation_state_(NOT_PROMPTED),
307 initial_show_state_(ui::SHOW_STATE_DEFAULT), 307 initial_show_state_(ui::SHOW_STATE_DEFAULT),
308 is_session_restore_(false), 308 is_session_restore_(false),
309 ALLOW_THIS_IN_INITIALIZER_LIST(
310 unload_controller_(new chrome::UnloadController(this))),
309 weak_factory_(this), 311 weak_factory_(this),
310 ALLOW_THIS_IN_INITIALIZER_LIST( 312 ALLOW_THIS_IN_INITIALIZER_LIST(
311 content_setting_bubble_model_delegate_( 313 content_setting_bubble_model_delegate_(
312 new BrowserContentSettingBubbleModelDelegate(this))), 314 new BrowserContentSettingBubbleModelDelegate(this))),
313 ALLOW_THIS_IN_INITIALIZER_LIST( 315 ALLOW_THIS_IN_INITIALIZER_LIST(
314 toolbar_model_delegate_( 316 toolbar_model_delegate_(
315 new BrowserToolbarModelDelegate(this))), 317 new BrowserToolbarModelDelegate(this))),
316 ALLOW_THIS_IN_INITIALIZER_LIST( 318 ALLOW_THIS_IN_INITIALIZER_LIST(
317 tab_restore_service_delegate_( 319 tab_restore_service_delegate_(
318 new BrowserTabRestoreServiceDelegate(this))), 320 new BrowserTabRestoreServiceDelegate(this))),
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 } 570 }
569 } 571 }
570 572
571 /////////////////////////////////////////////////////////////////////////////// 573 ///////////////////////////////////////////////////////////////////////////////
572 // Browser, OnBeforeUnload handling: 574 // Browser, OnBeforeUnload handling:
573 575
574 bool Browser::ShouldCloseWindow() { 576 bool Browser::ShouldCloseWindow() {
575 if (!CanCloseWithInProgressDownloads()) 577 if (!CanCloseWithInProgressDownloads())
576 return false; 578 return false;
577 579
578 if (HasCompletedUnloadProcessing()) 580 return unload_controller_->ShouldCloseWindow();
579 return true; 581 }
580 582
581 is_attempting_to_close_browser_ = true; 583 bool Browser::IsAttemptingToCloseBrowser() const {
582 584 return unload_controller_->is_attempting_to_close_browser();
583 if (!TabsNeedBeforeUnloadFired())
584 return true;
585
586 ProcessPendingTabs();
587 return false;
588 } 585 }
589 586
590 void Browser::OnWindowClosing() { 587 void Browser::OnWindowClosing() {
591 if (!ShouldCloseWindow()) 588 if (!ShouldCloseWindow())
592 return; 589 return;
593 590
594 bool exiting = false; 591 bool exiting = false;
595 592
596 // Application should shutdown on last window close if the user is explicitly 593 // Application should shutdown on last window close if the user is explicitly
597 // trying to quit, or if there is nothing keeping the browser alive (such as 594 // trying to quit, or if there is nothing keeping the browser alive (such as
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 // Show the download page so the user can figure-out what downloads are still 659 // Show the download page so the user can figure-out what downloads are still
663 // in-progress. 660 // in-progress.
664 chrome::ShowDownloads(this); 661 chrome::ShowDownloads(this);
665 } 662 }
666 663
667 Browser::DownloadClosePreventionType Browser::OkToCloseWithInProgressDownloads( 664 Browser::DownloadClosePreventionType Browser::OkToCloseWithInProgressDownloads(
668 int* num_downloads_blocking) const { 665 int* num_downloads_blocking) const {
669 DCHECK(num_downloads_blocking); 666 DCHECK(num_downloads_blocking);
670 *num_downloads_blocking = 0; 667 *num_downloads_blocking = 0;
671 668
672 if (is_attempting_to_close_browser_) 669 if (IsAttemptingToCloseBrowser())
673 return DOWNLOAD_CLOSE_OK; 670 return DOWNLOAD_CLOSE_OK;
674 671
675 // If we're not running a full browser process with a profile manager 672 // If we're not running a full browser process with a profile manager
676 // (testing), it's ok to close the browser. 673 // (testing), it's ok to close the browser.
677 if (!g_browser_process->profile_manager()) 674 if (!g_browser_process->profile_manager())
678 return DOWNLOAD_CLOSE_OK; 675 return DOWNLOAD_CLOSE_OK;
679 676
680 int total_download_count = DownloadService::DownloadCountAllProfiles(); 677 int total_download_count = DownloadService::DownloadCountAllProfiles();
681 if (total_download_count == 0) 678 if (total_download_count == 0)
682 return DOWNLOAD_CLOSE_OK; // No downloads; can definitely close. 679 return DOWNLOAD_CLOSE_OK; // No downloads; can definitely close.
683 680
684 // Figure out how many windows are open total, and associated with this 681 // Figure out how many windows are open total, and associated with this
685 // profile, that are relevant for the ok-to-close decision. 682 // profile, that are relevant for the ok-to-close decision.
686 int profile_window_count = 0; 683 int profile_window_count = 0;
687 int total_window_count = 0; 684 int total_window_count = 0;
688 for (BrowserList::const_iterator iter = BrowserList::begin(); 685 for (BrowserList::const_iterator iter = BrowserList::begin();
689 iter != BrowserList::end(); ++iter) { 686 iter != BrowserList::end(); ++iter) {
690 // Don't count this browser window or any other in the process of closing. 687 // Don't count this browser window or any other in the process of closing.
691 Browser* const browser = *iter; 688 Browser* const browser = *iter;
692 // Check is_attempting_to_close_browser_ as window closing may be 689 // Window closing may be delayed, and windows that are in the process of
693 // delayed, and windows that are in the process of closing don't 690 // closing don't count against our totals.
694 // count against our totals. 691 if (browser == this || browser->IsAttemptingToCloseBrowser())
695 if (browser == this || browser->is_attempting_to_close_browser_)
696 continue; 692 continue;
697 693
698 if ((*iter)->profile() == profile()) 694 if ((*iter)->profile() == profile())
699 profile_window_count++; 695 profile_window_count++;
700 total_window_count++; 696 total_window_count++;
701 } 697 }
702 698
703 // If there aren't any other windows, we're at browser shutdown, 699 // If there aren't any other windows, we're at browser shutdown,
704 // which would cancel all current downloads. 700 // which would cancel all current downloads.
705 if (total_window_count == 0) { 701 if (total_window_count == 0) {
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 bool foreground) { 1166 bool foreground) {
1171 SetAsDelegate(contents, this); 1167 SetAsDelegate(contents, this);
1172 contents->restore_tab_helper()->SetWindowID(session_id()); 1168 contents->restore_tab_helper()->SetWindowID(session_id());
1173 1169
1174 SyncHistoryWithTabs(index); 1170 SyncHistoryWithTabs(index);
1175 1171
1176 // Make sure the loading state is updated correctly, otherwise the throbber 1172 // Make sure the loading state is updated correctly, otherwise the throbber
1177 // won't start if the page is loading. 1173 // won't start if the page is loading.
1178 LoadingStateChanged(contents->web_contents()); 1174 LoadingStateChanged(contents->web_contents());
1179 1175
1180 // If the tab crashes in the beforeunload or unload handler, it won't be
1181 // able to ack. But we know we can close it.
1182 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
1183 content::Source<WebContents>(contents->web_contents()));
1184
1185 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED, 1176 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED,
1186 content::Source<WebContents>(contents->web_contents())); 1177 content::Source<WebContents>(contents->web_contents()));
1187 1178
1188 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_DETACHED, 1179 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_DETACHED,
1189 content::Source<WebContents>(contents->web_contents())); 1180 content::Source<WebContents>(contents->web_contents()));
1190 } 1181 }
1191 1182
1192 void Browser::TabClosingAt(TabStripModel* tab_strip_model, 1183 void Browser::TabClosingAt(TabStripModel* tab_strip_model,
1193 TabContents* contents, 1184 TabContents* contents,
1194 int index) { 1185 int index) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1343 1334
1344 void Browser::TabStripEmpty() { 1335 void Browser::TabStripEmpty() {
1345 // Close the frame after we return to the message loop (not immediately, 1336 // Close the frame after we return to the message loop (not immediately,
1346 // otherwise it will destroy this object before the stack has a chance to 1337 // otherwise it will destroy this object before the stack has a chance to
1347 // cleanly unwind.) 1338 // cleanly unwind.)
1348 // Note: This will be called several times if TabStripEmpty is called several 1339 // Note: This will be called several times if TabStripEmpty is called several
1349 // times. This is because it does not close the window if tabs are 1340 // times. This is because it does not close the window if tabs are
1350 // still present. 1341 // still present.
1351 MessageLoop::current()->PostTask( 1342 MessageLoop::current()->PostTask(
1352 FROM_HERE, base::Bind(&Browser::CloseFrame, weak_factory_.GetWeakPtr())); 1343 FROM_HERE, base::Bind(&Browser::CloseFrame, weak_factory_.GetWeakPtr()));
1353 // Set is_attempting_to_close_browser_ here, so that extensions, etc, do not
1354 // attempt to add tabs to the browser before it closes.
1355 is_attempting_to_close_browser_ = true;
1356 } 1344 }
1357 1345
1358 bool Browser::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, 1346 bool Browser::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
1359 bool* is_keyboard_shortcut) { 1347 bool* is_keyboard_shortcut) {
1360 // Escape exits tabbed fullscreen mode. 1348 // Escape exits tabbed fullscreen mode.
1361 // TODO(koz): Write a test for this http://crbug.com/100441. 1349 // TODO(koz): Write a test for this http://crbug.com/100441.
1362 if (event.windowsKeyCode == 27 && 1350 if (event.windowsKeyCode == 27 &&
1363 fullscreen_controller_->HandleUserPressedEscape()) { 1351 fullscreen_controller_->HandleUserPressedEscape()) {
1364 return true; 1352 return true;
1365 } 1353 }
1366 return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut); 1354 return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
1367 } 1355 }
1368 1356
1369 void Browser::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { 1357 void Browser::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
1370 window()->HandleKeyboardEvent(event); 1358 window()->HandleKeyboardEvent(event);
1371 } 1359 }
1372 1360
1373 void Browser::OnAcceptFullscreenPermission( 1361 void Browser::OnAcceptFullscreenPermission(
1374 const GURL& url, 1362 const GURL& url,
1375 FullscreenExitBubbleType bubble_type) { 1363 FullscreenExitBubbleType bubble_type) {
1376 fullscreen_controller_->OnAcceptFullscreenPermission(url, bubble_type); 1364 fullscreen_controller_->OnAcceptFullscreenPermission(url, bubble_type);
1377 } 1365 }
1378 1366
1379 void Browser::OnDenyFullscreenPermission(FullscreenExitBubbleType bubble_type) { 1367 void Browser::OnDenyFullscreenPermission(FullscreenExitBubbleType bubble_type) {
1380 fullscreen_controller_->OnDenyFullscreenPermission(bubble_type); 1368 fullscreen_controller_->OnDenyFullscreenPermission(bubble_type);
1381 } 1369 }
1382 1370
1383 bool Browser::TabsNeedBeforeUnloadFired() { 1371 bool Browser::TabsNeedBeforeUnloadFired() {
1384 if (tabs_needing_before_unload_fired_.empty()) { 1372 return unload_controller_->TabsNeedBeforeUnloadFired();
1385 for (int i = 0; i < tab_count(); ++i) {
1386 WebContents* contents = chrome::GetTabContentsAt(this, i)->web_contents();
1387 if (contents->NeedToFireBeforeUnload())
1388 tabs_needing_before_unload_fired_.insert(contents);
1389 }
1390 }
1391 return !tabs_needing_before_unload_fired_.empty();
1392 } 1373 }
1393 1374
1394 bool Browser::IsFullscreenForTabOrPending() const { 1375 bool Browser::IsFullscreenForTabOrPending() const {
1395 return fullscreen_controller_->IsFullscreenForTabOrPending(); 1376 return fullscreen_controller_->IsFullscreenForTabOrPending();
1396 } 1377 }
1397 1378
1398 bool Browser::IsMouseLocked() const { 1379 bool Browser::IsMouseLocked() const {
1399 return fullscreen_controller_->IsMouseLocked(); 1380 return fullscreen_controller_->IsMouseLocked();
1400 } 1381 }
1401 1382
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 command_controller_->LoadingStateChanged(is_loading, false); 1486 command_controller_->LoadingStateChanged(is_loading, false);
1506 if (GetStatusBubble()) { 1487 if (GetStatusBubble()) {
1507 GetStatusBubble()->SetStatus( 1488 GetStatusBubble()->SetStatus(
1508 chrome::GetActiveTabContents(this)->core_tab_helper()-> 1489 chrome::GetActiveTabContents(this)->core_tab_helper()->
1509 GetStatusText()); 1490 GetStatusText());
1510 } 1491 }
1511 } 1492 }
1512 } 1493 }
1513 1494
1514 void Browser::CloseContents(WebContents* source) { 1495 void Browser::CloseContents(WebContents* source) {
1515 if (is_attempting_to_close_browser_) { 1496 if (unload_controller_->CanCloseContents(source))
1516 // If we're trying to close the browser, just clear the state related to 1497 chrome::CloseWebContents(this, source);
1517 // waiting for unload to fire. Don't actually try to close the tab as it
1518 // will go down the slow shutdown path instead of the fast path of killing
1519 // all the renderer processes.
1520 ClearUnloadState(source, true);
1521 return;
1522 }
1523
1524 chrome::CloseWebContents(this, source);
1525 } 1498 }
1526 1499
1527 void Browser::MoveContents(WebContents* source, const gfx::Rect& pos) { 1500 void Browser::MoveContents(WebContents* source, const gfx::Rect& pos) {
1528 if (!IsPopupOrPanel(source)) { 1501 if (!IsPopupOrPanel(source)) {
1529 NOTREACHED() << "moving invalid browser type"; 1502 NOTREACHED() << "moving invalid browser type";
1530 return; 1503 return;
1531 } 1504 }
1532 window_->SetBounds(pos); 1505 window_->SetBounds(pos);
1533 } 1506 }
1534 1507
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 return is_app(); 1553 return is_app();
1581 } 1554 }
1582 1555
1583 gfx::Rect Browser::GetRootWindowResizerRect() const { 1556 gfx::Rect Browser::GetRootWindowResizerRect() const {
1584 return window_->GetRootWindowResizerRect(); 1557 return window_->GetRootWindowResizerRect();
1585 } 1558 }
1586 1559
1587 void Browser::BeforeUnloadFired(WebContents* web_contents, 1560 void Browser::BeforeUnloadFired(WebContents* web_contents,
1588 bool proceed, 1561 bool proceed,
1589 bool* proceed_to_fire_unload) { 1562 bool* proceed_to_fire_unload) {
1590 if (!is_attempting_to_close_browser_) { 1563 *proceed_to_fire_unload =
1591 *proceed_to_fire_unload = proceed; 1564 unload_controller_->BeforeUnloadFired(web_contents, proceed);
1592 if (!proceed)
1593 web_contents->SetClosedByUserGesture(false);
1594 return;
1595 }
1596
1597 if (!proceed) {
1598 CancelWindowClose();
1599 *proceed_to_fire_unload = false;
1600 web_contents->SetClosedByUserGesture(false);
1601 return;
1602 }
1603
1604 if (RemoveFromSet(&tabs_needing_before_unload_fired_, web_contents)) {
1605 // Now that beforeunload has fired, put the tab on the queue to fire
1606 // unload.
1607 tabs_needing_unload_fired_.insert(web_contents);
1608 ProcessPendingTabs();
1609 // We want to handle firing the unload event ourselves since we want to
1610 // fire all the beforeunload events before attempting to fire the unload
1611 // events should the user cancel closing the browser.
1612 *proceed_to_fire_unload = false;
1613 return;
1614 }
1615
1616 *proceed_to_fire_unload = true;
1617 } 1565 }
1618 1566
1619 void Browser::SetFocusToLocationBar(bool select_all) { 1567 void Browser::SetFocusToLocationBar(bool select_all) {
1620 // Two differences between this and FocusLocationBar(): 1568 // Two differences between this and FocusLocationBar():
1621 // (1) This doesn't get recorded in user metrics, since it's called 1569 // (1) This doesn't get recorded in user metrics, since it's called
1622 // internally. 1570 // internally.
1623 // (2) This checks whether the location bar can be focused, and if not, clears 1571 // (2) This checks whether the location bar can be focused, and if not, clears
1624 // the focus. FocusLocationBar() is only reached when the location bar is 1572 // the focus. FocusLocationBar() is only reached when the location bar is
1625 // focusable, but this may be reached at other times, e.g. while in 1573 // focusable, but this may be reached at other times, e.g. while in
1626 // fullscreen mode, where we need to leave focus in a consistent state. 1574 // fullscreen mode, where we need to leave focus in a consistent state.
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
2034 false)); 1982 false));
2035 } 1983 }
2036 1984
2037 /////////////////////////////////////////////////////////////////////////////// 1985 ///////////////////////////////////////////////////////////////////////////////
2038 // Browser, content::NotificationObserver implementation: 1986 // Browser, content::NotificationObserver implementation:
2039 1987
2040 void Browser::Observe(int type, 1988 void Browser::Observe(int type,
2041 const content::NotificationSource& source, 1989 const content::NotificationSource& source,
2042 const content::NotificationDetails& details) { 1990 const content::NotificationDetails& details) {
2043 switch (type) { 1991 switch (type) {
2044 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
2045 if (is_attempting_to_close_browser_) {
2046 // Pass in false so that we delay processing. We need to delay the
2047 // processing as it may close the tab, which is currently on the call
2048 // stack above us.
2049 ClearUnloadState(content::Source<WebContents>(source).ptr(), false);
2050 }
2051 break;
2052
2053 case content::NOTIFICATION_SSL_VISIBLE_STATE_CHANGED: 1992 case content::NOTIFICATION_SSL_VISIBLE_STATE_CHANGED:
2054 // When the current tab's SSL state changes, we need to update the URL 1993 // When the current tab's SSL state changes, we need to update the URL
2055 // bar to reflect the new state. Note that it's possible for the selected 1994 // bar to reflect the new state. Note that it's possible for the selected
2056 // tab contents to be NULL. This is because we listen for all sources 1995 // tab contents to be NULL. This is because we listen for all sources
2057 // (NavigationControllers) for convenience, so the notification could 1996 // (NavigationControllers) for convenience, so the notification could
2058 // actually be for a different window while we're doing asynchronous 1997 // actually be for a different window while we're doing asynchronous
2059 // closing of this one. 1998 // closing of this one.
2060 if (chrome::GetActiveWebContents(this) && 1999 if (chrome::GetActiveWebContents(this) &&
2061 &chrome::GetActiveWebContents(this)->GetController() == 2000 &chrome::GetActiveWebContents(this)->GetController() ==
2062 content::Source<NavigationController>(source).ptr()) 2001 content::Source<NavigationController>(source).ptr())
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
2389 session_service->SetPinnedState( 2328 session_service->SetPinnedState(
2390 session_id(), 2329 session_id(),
2391 tab->restore_tab_helper()->session_id(), 2330 tab->restore_tab_helper()->session_id(),
2392 tab_strip_model_->IsTabPinned(i)); 2331 tab_strip_model_->IsTabPinned(i));
2393 } 2332 }
2394 } 2333 }
2395 } 2334 }
2396 } 2335 }
2397 2336
2398 /////////////////////////////////////////////////////////////////////////////// 2337 ///////////////////////////////////////////////////////////////////////////////
2399 // Browser, OnBeforeUnload handling (private):
2400
2401 void Browser::ProcessPendingTabs() {
2402 if (!is_attempting_to_close_browser_) {
2403 // Because we might invoke this after a delay it's possible for the value of
2404 // is_attempting_to_close_browser_ to have changed since we scheduled the
2405 // task.
2406 return;
2407 }
2408
2409 if (HasCompletedUnloadProcessing()) {
2410 // We've finished all the unload events and can proceed to close the
2411 // browser.
2412 OnWindowClosing();
2413 return;
2414 }
2415
2416 // Process beforeunload tabs first. When that queue is empty, process
2417 // unload tabs.
2418 if (!tabs_needing_before_unload_fired_.empty()) {
2419 WebContents* web_contents = *(tabs_needing_before_unload_fired_.begin());
2420 // Null check render_view_host here as this gets called on a PostTask and
2421 // the tab's render_view_host may have been nulled out.
2422 if (web_contents->GetRenderViewHost()) {
2423 web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
2424 } else {
2425 ClearUnloadState(web_contents, true);
2426 }
2427 } else if (!tabs_needing_unload_fired_.empty()) {
2428 // We've finished firing all beforeunload events and can proceed with unload
2429 // events.
2430 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
2431 // somewhere around here so that we have accurate measurements of shutdown
2432 // time.
2433 // TODO(ojan): We can probably fire all the unload events in parallel and
2434 // get a perf benefit from that in the cases where the tab hangs in it's
2435 // unload handler or takes a long time to page in.
2436 WebContents* web_contents = *(tabs_needing_unload_fired_.begin());
2437 // Null check render_view_host here as this gets called on a PostTask and
2438 // the tab's render_view_host may have been nulled out.
2439 if (web_contents->GetRenderViewHost()) {
2440 web_contents->GetRenderViewHost()->ClosePage();
2441 } else {
2442 ClearUnloadState(web_contents, true);
2443 }
2444 } else {
2445 NOTREACHED();
2446 }
2447 }
2448
2449 bool Browser::HasCompletedUnloadProcessing() const {
2450 return is_attempting_to_close_browser_ &&
2451 tabs_needing_before_unload_fired_.empty() &&
2452 tabs_needing_unload_fired_.empty();
2453 }
2454
2455 void Browser::CancelWindowClose() {
2456 // Closing of window can be canceled from a beforeunload handler.
2457 DCHECK(is_attempting_to_close_browser_);
2458 tabs_needing_before_unload_fired_.clear();
2459 tabs_needing_unload_fired_.clear();
2460 is_attempting_to_close_browser_ = false;
2461
2462 content::NotificationService::current()->Notify(
2463 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
2464 content::Source<Browser>(this),
2465 content::NotificationService::NoDetails());
2466 }
2467
2468 bool Browser::RemoveFromSet(UnloadListenerSet* set, WebContents* web_contents) {
2469 DCHECK(is_attempting_to_close_browser_);
2470
2471 UnloadListenerSet::iterator iter =
2472 std::find(set->begin(), set->end(), web_contents);
2473 if (iter != set->end()) {
2474 set->erase(iter);
2475 return true;
2476 }
2477 return false;
2478 }
2479
2480 void Browser::ClearUnloadState(WebContents* web_contents, bool process_now) {
2481 if (is_attempting_to_close_browser_) {
2482 RemoveFromSet(&tabs_needing_before_unload_fired_, web_contents);
2483 RemoveFromSet(&tabs_needing_unload_fired_, web_contents);
2484 if (process_now) {
2485 ProcessPendingTabs();
2486 } else {
2487 MessageLoop::current()->PostTask(
2488 FROM_HERE,
2489 base::Bind(&Browser::ProcessPendingTabs, weak_factory_.GetWeakPtr()));
2490 }
2491 }
2492 }
2493
2494 ///////////////////////////////////////////////////////////////////////////////
2495 // Browser, In-progress download termination handling (private): 2338 // Browser, In-progress download termination handling (private):
2496 2339
2497 bool Browser::CanCloseWithInProgressDownloads() { 2340 bool Browser::CanCloseWithInProgressDownloads() {
2498 // If we've prompted, we need to hear from the user before we 2341 // If we've prompted, we need to hear from the user before we
2499 // can close. 2342 // can close.
2500 if (cancel_download_confirmation_state_ != NOT_PROMPTED) 2343 if (cancel_download_confirmation_state_ != NOT_PROMPTED)
2501 return cancel_download_confirmation_state_ != WAITING_FOR_RESPONSE; 2344 return cancel_download_confirmation_state_ != WAITING_FOR_RESPONSE;
2502 2345
2503 int num_downloads_blocking; 2346 int num_downloads_blocking;
2504 if (DOWNLOAD_CLOSE_OK == 2347 if (DOWNLOAD_CLOSE_OK ==
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2552 SyncHistoryWithTabs(0); 2395 SyncHistoryWithTabs(0);
2553 } 2396 }
2554 2397
2555 SetAsDelegate(contents, NULL); 2398 SetAsDelegate(contents, NULL);
2556 RemoveScheduledUpdatesFor(contents->web_contents()); 2399 RemoveScheduledUpdatesFor(contents->web_contents());
2557 2400
2558 if (find_bar_controller_.get() && index == active_index()) { 2401 if (find_bar_controller_.get() && index == active_index()) {
2559 find_bar_controller_->ChangeTabContents(NULL); 2402 find_bar_controller_->ChangeTabContents(NULL);
2560 } 2403 }
2561 2404
2562 if (is_attempting_to_close_browser_) {
2563 // If this is the last tab with unload handlers, then ProcessPendingTabs
2564 // would call back into the TabStripModel (which is invoking this method on
2565 // us). Avoid that by passing in false so that the call to
2566 // ProcessPendingTabs is delayed.
2567 ClearUnloadState(contents->web_contents(), false);
2568 }
2569
2570 // Stop observing search model changes for this tab. 2405 // Stop observing search model changes for this tab.
2571 search_delegate_->OnTabDetached(contents); 2406 search_delegate_->OnTabDetached(contents);
2572 2407
2573 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED, 2408 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED,
2574 content::Source<WebContents>(contents->web_contents())); 2409 content::Source<WebContents>(contents->web_contents()));
2575 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_DETACHED, 2410 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_DETACHED,
2576 content::Source<WebContents>(contents->web_contents())); 2411 content::Source<WebContents>(contents->web_contents()));
2577 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
2578 content::Source<WebContents>(contents->web_contents()));
2579 } 2412 }
2580 2413
2581 bool Browser::SupportsWindowFeatureImpl(WindowFeature feature, 2414 bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
2582 bool check_fullscreen) const { 2415 bool check_fullscreen) const {
2583 // On Mac, fullscreen mode has most normal things (in a slide-down panel). On 2416 // On Mac, fullscreen mode has most normal things (in a slide-down panel). On
2584 // other platforms, we hide some controls when in fullscreen mode. 2417 // other platforms, we hide some controls when in fullscreen mode.
2585 bool hide_ui_for_fullscreen = false; 2418 bool hide_ui_for_fullscreen = false;
2586 #if !defined(OS_MACOSX) 2419 #if !defined(OS_MACOSX)
2587 hide_ui_for_fullscreen = check_fullscreen && window_ && 2420 hide_ui_for_fullscreen = check_fullscreen && window_ &&
2588 window_->IsFullscreen(); 2421 window_->IsFullscreen();
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2731 if (contents && !allow_js_access) { 2564 if (contents && !allow_js_access) {
2732 contents->web_contents()->GetController().LoadURL( 2565 contents->web_contents()->GetController().LoadURL(
2733 target_url, 2566 target_url,
2734 content::Referrer(), 2567 content::Referrer(),
2735 content::PAGE_TRANSITION_LINK, 2568 content::PAGE_TRANSITION_LINK,
2736 std::string()); // No extra headers. 2569 std::string()); // No extra headers.
2737 } 2570 }
2738 2571
2739 return contents != NULL; 2572 return contents != NULL;
2740 } 2573 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/browser.h ('k') | chrome/browser/ui/unload_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698