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

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

Issue 6203006: Attempt at fixing crash in ProcessPendingTabs. With the current code, (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Better comments Created 9 years, 11 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <shellapi.h> 8 #include <shellapi.h>
9 #include <windows.h> 9 #include <windows.h>
10 #endif // OS_WIN 10 #endif // OS_WIN
(...skipping 2820 matching lines...) Expand 10 before | Expand all | Expand 10 after
2831 } 2831 }
2832 } 2832 }
2833 } 2833 }
2834 2834
2835 void Browser::CloseContents(TabContents* source) { 2835 void Browser::CloseContents(TabContents* source) {
2836 if (is_attempting_to_close_browser_) { 2836 if (is_attempting_to_close_browser_) {
2837 // If we're trying to close the browser, just clear the state related to 2837 // If we're trying to close the browser, just clear the state related to
2838 // waiting for unload to fire. Don't actually try to close the tab as it 2838 // waiting for unload to fire. Don't actually try to close the tab as it
2839 // will go down the slow shutdown path instead of the fast path of killing 2839 // will go down the slow shutdown path instead of the fast path of killing
2840 // all the renderer processes. 2840 // all the renderer processes.
2841 ClearUnloadState(source); 2841 ClearUnloadState(source, true);
2842 return; 2842 return;
2843 } 2843 }
2844 2844
2845 int index = tab_handler_->GetTabStripModel()->GetWrapperIndex(source); 2845 int index = tab_handler_->GetTabStripModel()->GetWrapperIndex(source);
2846 if (index == TabStripModel::kNoTab) { 2846 if (index == TabStripModel::kNoTab) {
2847 NOTREACHED() << "CloseContents called for tab not in our strip"; 2847 NOTREACHED() << "CloseContents called for tab not in our strip";
2848 return; 2848 return;
2849 } 2849 }
2850 tab_handler_->GetTabStripModel()->CloseTabContentsAt( 2850 tab_handler_->GetTabStripModel()->CloseTabContentsAt(
2851 index, 2851 index,
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
3192 3192
3193 /////////////////////////////////////////////////////////////////////////////// 3193 ///////////////////////////////////////////////////////////////////////////////
3194 // Browser, NotificationObserver implementation: 3194 // Browser, NotificationObserver implementation:
3195 3195
3196 void Browser::Observe(NotificationType type, 3196 void Browser::Observe(NotificationType type,
3197 const NotificationSource& source, 3197 const NotificationSource& source,
3198 const NotificationDetails& details) { 3198 const NotificationDetails& details) {
3199 switch (type.value) { 3199 switch (type.value) {
3200 case NotificationType::TAB_CONTENTS_DISCONNECTED: 3200 case NotificationType::TAB_CONTENTS_DISCONNECTED:
3201 if (is_attempting_to_close_browser_) { 3201 if (is_attempting_to_close_browser_) {
3202 // Need to do this asynchronously as it will close the tab, which is 3202 // Pass in false so that we delay processing. We need to delay the
3203 // currently on the call stack above us. 3203 // processing as it may close the tab, which is currently on the call
3204 MessageLoop::current()->PostTask( 3204 // stack above us.
3205 FROM_HERE, 3205 ClearUnloadState(Source<TabContents>(source).ptr(), false);
3206 method_factory_.NewRunnableMethod(&Browser::ClearUnloadState,
3207 Source<TabContents>(source).ptr()));
3208 } 3206 }
3209 break; 3207 break;
3210 3208
3211 case NotificationType::SSL_VISIBLE_STATE_CHANGED: 3209 case NotificationType::SSL_VISIBLE_STATE_CHANGED:
3212 // When the current tab's SSL state changes, we need to update the URL 3210 // When the current tab's SSL state changes, we need to update the URL
3213 // bar to reflect the new state. Note that it's possible for the selected 3211 // bar to reflect the new state. Note that it's possible for the selected
3214 // tab contents to be NULL. This is because we listen for all sources 3212 // tab contents to be NULL. This is because we listen for all sources
3215 // (NavigationControllers) for convenience, so the notification could 3213 // (NavigationControllers) for convenience, so the notification could
3216 // actually be for a different window while we're doing asynchronous 3214 // actually be for a different window while we're doing asynchronous
3217 // closing of this one. 3215 // closing of this one.
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
3854 3852
3855 // Process beforeunload tabs first. When that queue is empty, process 3853 // Process beforeunload tabs first. When that queue is empty, process
3856 // unload tabs. 3854 // unload tabs.
3857 if (!tabs_needing_before_unload_fired_.empty()) { 3855 if (!tabs_needing_before_unload_fired_.empty()) {
3858 TabContents* tab = *(tabs_needing_before_unload_fired_.begin()); 3856 TabContents* tab = *(tabs_needing_before_unload_fired_.begin());
3859 // Null check render_view_host here as this gets called on a PostTask and 3857 // Null check render_view_host here as this gets called on a PostTask and
3860 // the tab's render_view_host may have been nulled out. 3858 // the tab's render_view_host may have been nulled out.
3861 if (tab->render_view_host()) { 3859 if (tab->render_view_host()) {
3862 tab->render_view_host()->FirePageBeforeUnload(false); 3860 tab->render_view_host()->FirePageBeforeUnload(false);
3863 } else { 3861 } else {
3864 ClearUnloadState(tab); 3862 ClearUnloadState(tab, true);
3865 } 3863 }
3866 } else if (!tabs_needing_unload_fired_.empty()) { 3864 } else if (!tabs_needing_unload_fired_.empty()) {
3867 // We've finished firing all beforeunload events and can proceed with unload 3865 // We've finished firing all beforeunload events and can proceed with unload
3868 // events. 3866 // events.
3869 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting 3867 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
3870 // somewhere around here so that we have accurate measurements of shutdown 3868 // somewhere around here so that we have accurate measurements of shutdown
3871 // time. 3869 // time.
3872 // TODO(ojan): We can probably fire all the unload events in parallel and 3870 // TODO(ojan): We can probably fire all the unload events in parallel and
3873 // get a perf benefit from that in the cases where the tab hangs in it's 3871 // get a perf benefit from that in the cases where the tab hangs in it's
3874 // unload handler or takes a long time to page in. 3872 // unload handler or takes a long time to page in.
3875 TabContents* tab = *(tabs_needing_unload_fired_.begin()); 3873 TabContents* tab = *(tabs_needing_unload_fired_.begin());
3876 // Null check render_view_host here as this gets called on a PostTask and 3874 // Null check render_view_host here as this gets called on a PostTask and
3877 // the tab's render_view_host may have been nulled out. 3875 // the tab's render_view_host may have been nulled out.
3878 if (tab->render_view_host()) { 3876 if (tab->render_view_host()) {
3879 tab->render_view_host()->ClosePage(false, -1, -1); 3877 tab->render_view_host()->ClosePage(false, -1, -1);
3880 } else { 3878 } else {
3881 ClearUnloadState(tab); 3879 ClearUnloadState(tab, true);
3882 } 3880 }
3883 } else { 3881 } else {
3884 NOTREACHED(); 3882 NOTREACHED();
3885 } 3883 }
3886 } 3884 }
3887 3885
3888 bool Browser::HasCompletedUnloadProcessing() const { 3886 bool Browser::HasCompletedUnloadProcessing() const {
3889 return is_attempting_to_close_browser_ && 3887 return is_attempting_to_close_browser_ &&
3890 tabs_needing_before_unload_fired_.empty() && 3888 tabs_needing_before_unload_fired_.empty() &&
3891 tabs_needing_unload_fired_.empty(); 3889 tabs_needing_unload_fired_.empty();
(...skipping 19 matching lines...) Expand all
3911 DCHECK(is_attempting_to_close_browser_); 3909 DCHECK(is_attempting_to_close_browser_);
3912 3910
3913 UnloadListenerSet::iterator iter = std::find(set->begin(), set->end(), tab); 3911 UnloadListenerSet::iterator iter = std::find(set->begin(), set->end(), tab);
3914 if (iter != set->end()) { 3912 if (iter != set->end()) {
3915 set->erase(iter); 3913 set->erase(iter);
3916 return true; 3914 return true;
3917 } 3915 }
3918 return false; 3916 return false;
3919 } 3917 }
3920 3918
3921 void Browser::ClearUnloadState(TabContents* tab) { 3919 void Browser::ClearUnloadState(TabContents* tab, bool process_now) {
3922 // Closing of browser could be canceled (via IsClosingPermitted) between the 3920 // Closing of browser could be canceled (via IsClosingPermitted) between the
3923 // time when request was initiated and when this method is called, so check 3921 // time when request was initiated and when this method is called, so check
3924 // for is_attempting_to_close_browser_ flag before proceeding. 3922 // for is_attempting_to_close_browser_ flag before proceeding.
3925 if (is_attempting_to_close_browser_) { 3923 if (is_attempting_to_close_browser_) {
3926 RemoveFromSet(&tabs_needing_before_unload_fired_, tab); 3924 RemoveFromSet(&tabs_needing_before_unload_fired_, tab);
3927 RemoveFromSet(&tabs_needing_unload_fired_, tab); 3925 RemoveFromSet(&tabs_needing_unload_fired_, tab);
3928 ProcessPendingTabs(); 3926 if (process_now) {
3927 ProcessPendingTabs();
3928 } else {
3929 MessageLoop::current()->PostTask(
3930 FROM_HERE,
3931 method_factory_.NewRunnableMethod(&Browser::ProcessPendingTabs));
3932 }
3929 } 3933 }
3930 } 3934 }
3931 3935
3932
3933 /////////////////////////////////////////////////////////////////////////////// 3936 ///////////////////////////////////////////////////////////////////////////////
3934 // Browser, In-progress download termination handling (private): 3937 // Browser, In-progress download termination handling (private):
3935 3938
3936 void Browser::CheckDownloadsInProgress(bool* normal_downloads_are_present, 3939 void Browser::CheckDownloadsInProgress(bool* normal_downloads_are_present,
3937 bool* incognito_downloads_are_present) { 3940 bool* incognito_downloads_are_present) {
3938 *normal_downloads_are_present = false; 3941 *normal_downloads_are_present = false;
3939 *incognito_downloads_are_present = false; 3942 *incognito_downloads_are_present = false;
3940 3943
3941 // If there are no download in-progress, our job is done. 3944 // If there are no download in-progress, our job is done.
3942 DownloadManager* download_manager = NULL; 3945 DownloadManager* download_manager = NULL;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
4081 } 4084 }
4082 4085
4083 contents->tab_contents()->set_delegate(NULL); 4086 contents->tab_contents()->set_delegate(NULL);
4084 RemoveScheduledUpdatesFor(contents->tab_contents()); 4087 RemoveScheduledUpdatesFor(contents->tab_contents());
4085 4088
4086 if (find_bar_controller_.get() && 4089 if (find_bar_controller_.get() &&
4087 index == tab_handler_->GetTabStripModel()->selected_index()) { 4090 index == tab_handler_->GetTabStripModel()->selected_index()) {
4088 find_bar_controller_->ChangeTabContents(NULL); 4091 find_bar_controller_->ChangeTabContents(NULL);
4089 } 4092 }
4090 4093
4094 if (is_attempting_to_close_browser_) {
4095 // If this is the last tab with unload handlers, then ProcessPendingTabs
4096 // would call back into the TabStripModel (which is invoking this method on
4097 // us). Avoid that by passing in false so that the call to
4098 // ProcessPendingTabs is delayed.
4099 ClearUnloadState(contents->tab_contents(), false);
4100 }
4101
4091 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED, 4102 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
4092 Source<TabContentsWrapper>(contents)); 4103 Source<TabContentsWrapper>(contents));
4093 } 4104 }
4094 4105
4095 // static 4106 // static
4096 void Browser::RegisterAppPrefs(const std::string& app_name) { 4107 void Browser::RegisterAppPrefs(const std::string& app_name) {
4097 // A set of apps that we've already started. 4108 // A set of apps that we've already started.
4098 static std::set<std::string>* g_app_names = NULL; 4109 static std::set<std::string>* g_app_names = NULL;
4099 4110
4100 if (!g_app_names) 4111 if (!g_app_names)
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 // The page transition below is only for the purpose of inserting the tab. 4248 // The page transition below is only for the purpose of inserting the tab.
4238 browser->AddTab(view_source_contents, PageTransition::LINK); 4249 browser->AddTab(view_source_contents, PageTransition::LINK);
4239 } 4250 }
4240 4251
4241 if (profile_->HasSessionService()) { 4252 if (profile_->HasSessionService()) {
4242 SessionService* session_service = profile_->GetSessionService(); 4253 SessionService* session_service = profile_->GetSessionService();
4243 if (session_service) 4254 if (session_service)
4244 session_service->TabRestored(&view_source_contents->controller(), false); 4255 session_service->TabRestored(&view_source_contents->controller(), false);
4245 } 4256 }
4246 } 4257 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698