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