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

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

Issue 7466033: Fix warning prompting on closing a window that will cancel downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merged up to latest (mostly around DownloadService changes. Created 9 years, 2 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 <windows.h> 8 #include <windows.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #endif // OS_WIN 10 #endif // OS_WIN
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <string> 13 #include <string>
14 14
15 #include "base/base_paths.h" 15 #include "base/base_paths.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/metrics/field_trial.h" 18 #include "base/metrics/field_trial.h"
19 #include "base/metrics/histogram.h" 19 #include "base/metrics/histogram.h"
20 #include "base/path_service.h" 20 #include "base/path_service.h"
21 #include "base/string_number_conversions.h" 21 #include "base/string_number_conversions.h"
22 #include "base/string_util.h"
22 #include "base/stringprintf.h" 23 #include "base/stringprintf.h"
23 #include "base/string_util.h"
24 #include "base/threading/thread.h" 24 #include "base/threading/thread.h"
25 #include "base/threading/thread_restrictions.h" 25 #include "base/threading/thread_restrictions.h"
26 #include "base/time.h" 26 #include "base/time.h"
27 #include "base/utf_string_conversions.h" 27 #include "base/utf_string_conversions.h"
28 #include "chrome/app/chrome_command_ids.h" 28 #include "chrome/app/chrome_command_ids.h"
29 #include "chrome/browser/autofill/autofill_manager.h" 29 #include "chrome/browser/autofill/autofill_manager.h"
30 #include "chrome/browser/autofill/personal_data_manager_factory.h" 30 #include "chrome/browser/autofill/personal_data_manager_factory.h"
31 #include "chrome/browser/background/background_contents_service.h" 31 #include "chrome/browser/background/background_contents_service.h"
32 #include "chrome/browser/bookmarks/bookmark_model.h" 32 #include "chrome/browser/bookmarks/bookmark_model.h"
33 #include "chrome/browser/bookmarks/bookmark_utils.h" 33 #include "chrome/browser/bookmarks/bookmark_utils.h"
34 #include "chrome/browser/browser_process.h" 34 #include "chrome/browser/browser_process.h"
35 #include "chrome/browser/browser_shutdown.h" 35 #include "chrome/browser/browser_shutdown.h"
36 #include "chrome/browser/character_encoding.h" 36 #include "chrome/browser/character_encoding.h"
37 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 37 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
38 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg ate.h" 38 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg ate.h"
39 #include "chrome/browser/debugger/devtools_toggle_action.h" 39 #include "chrome/browser/debugger/devtools_toggle_action.h"
40 #include "chrome/browser/debugger/devtools_window.h" 40 #include "chrome/browser/debugger/devtools_window.h"
41 #include "chrome/browser/download/chrome_download_manager_delegate.h" 41 #include "chrome/browser/download/chrome_download_manager_delegate.h"
42 #include "chrome/browser/download/download_item_model.h" 42 #include "chrome/browser/download/download_item_model.h"
43 #include "chrome/browser/download/download_service.h" 43 #include "chrome/browser/download/download_service.h"
44 #include "chrome/browser/download/download_service.h"
44 #include "chrome/browser/download/download_service_factory.h" 45 #include "chrome/browser/download/download_service_factory.h"
45 #include "chrome/browser/download/download_started_animation.h" 46 #include "chrome/browser/download/download_started_animation.h"
46 #include "chrome/browser/extensions/crx_installer.h" 47 #include "chrome/browser/extensions/crx_installer.h"
47 #include "chrome/browser/extensions/default_apps_trial.h" 48 #include "chrome/browser/extensions/default_apps_trial.h"
48 #include "chrome/browser/extensions/extension_browser_event_router.h" 49 #include "chrome/browser/extensions/extension_browser_event_router.h"
49 #include "chrome/browser/extensions/extension_disabled_infobar_delegate.h" 50 #include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
50 #include "chrome/browser/extensions/extension_host.h" 51 #include "chrome/browser/extensions/extension_host.h"
51 #include "chrome/browser/extensions/extension_prefs.h" 52 #include "chrome/browser/extensions/extension_prefs.h"
52 #include "chrome/browser/extensions/extension_service.h" 53 #include "chrome/browser/extensions/extension_service.h"
53 #include "chrome/browser/extensions/extension_tab_helper.h" 54 #include "chrome/browser/extensions/extension_tab_helper.h"
(...skipping 13 matching lines...) Expand all
67 #include "chrome/browser/notifications/notification_ui_manager.h" 68 #include "chrome/browser/notifications/notification_ui_manager.h"
68 #include "chrome/browser/platform_util.h" 69 #include "chrome/browser/platform_util.h"
69 #include "chrome/browser/prefs/incognito_mode_prefs.h" 70 #include "chrome/browser/prefs/incognito_mode_prefs.h"
70 #include "chrome/browser/prefs/pref_service.h" 71 #include "chrome/browser/prefs/pref_service.h"
71 #include "chrome/browser/prerender/prerender_tab_helper.h" 72 #include "chrome/browser/prerender/prerender_tab_helper.h"
72 #include "chrome/browser/printing/background_printing_manager.h" 73 #include "chrome/browser/printing/background_printing_manager.h"
73 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h" 74 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
74 #include "chrome/browser/printing/print_preview_tab_controller.h" 75 #include "chrome/browser/printing/print_preview_tab_controller.h"
75 #include "chrome/browser/printing/print_view_manager.h" 76 #include "chrome/browser/printing/print_view_manager.h"
76 #include "chrome/browser/profiles/profile.h" 77 #include "chrome/browser/profiles/profile.h"
78 #include "chrome/browser/profiles/profile_manager.h"
77 #include "chrome/browser/sessions/restore_tab_helper.h" 79 #include "chrome/browser/sessions/restore_tab_helper.h"
78 #include "chrome/browser/sessions/session_service.h" 80 #include "chrome/browser/sessions/session_service.h"
79 #include "chrome/browser/sessions/session_service_factory.h" 81 #include "chrome/browser/sessions/session_service_factory.h"
80 #include "chrome/browser/sessions/session_types.h" 82 #include "chrome/browser/sessions/session_types.h"
81 #include "chrome/browser/sessions/tab_restore_service.h" 83 #include "chrome/browser/sessions/tab_restore_service.h"
82 #include "chrome/browser/sessions/tab_restore_service_factory.h" 84 #include "chrome/browser/sessions/tab_restore_service_factory.h"
83 #include "chrome/browser/sync/profile_sync_service.h" 85 #include "chrome/browser/sync/profile_sync_service.h"
84 #include "chrome/browser/sync/sync_ui_util.h" 86 #include "chrome/browser/sync/sync_ui_util.h"
85 #include "chrome/browser/tab_closeable_state_watcher.h" 87 #include "chrome/browser/tab_closeable_state_watcher.h"
86 #include "chrome/browser/tab_contents/background_contents.h" 88 #include "chrome/browser/tab_contents/background_contents.h"
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 1032
1031 // Sets the confirmation state to NOT_PROMPTED so that if the user tries to 1033 // Sets the confirmation state to NOT_PROMPTED so that if the user tries to
1032 // close again we'll show the warning again. 1034 // close again we'll show the warning again.
1033 cancel_download_confirmation_state_ = NOT_PROMPTED; 1035 cancel_download_confirmation_state_ = NOT_PROMPTED;
1034 1036
1035 // Show the download page so the user can figure-out what downloads are still 1037 // Show the download page so the user can figure-out what downloads are still
1036 // in-progress. 1038 // in-progress.
1037 ShowDownloadsTab(); 1039 ShowDownloadsTab();
1038 } 1040 }
1039 1041
1042 Browser::DownloadClosePreventionType Browser::OkToCloseWithInProgressDownloads(
1043 int* num_downloads_blocking) const {
1044 DCHECK(num_downloads_blocking);
1045
achuithb 2011/10/13 23:05:08 I'd set *num_downloads_blocking to 0 here since an
Randy Smith (Not in Mondays) 2011/10/14 00:37:41 Done.
1046 if (is_attempting_to_close_browser_)
1047 return DOWNLOAD_CLOSE_OK;
1048
1049 // If we're not running a full browser process with a profile manager
1050 // (testing), it's ok to close the browser.
1051 if (!g_browser_process->profile_manager())
1052 return DOWNLOAD_CLOSE_OK;
1053
1054 int total_download_count = DownloadService::TotalDownloadCount();
1055 if (total_download_count == 0)
1056 return DOWNLOAD_CLOSE_OK; // No downloads; can definitely close.
1057
achuithb 2011/10/13 23:05:08 Have you considered combining the above 3 conditio
Randy Smith (Not in Mondays) 2011/10/14 00:37:41 My preference is for it being the way it is now; I
achuithb 2011/10/14 19:22:10 That's fine.
1058 // Let's figure out if we are the last window for our profile, and
1059 // the last window period.
1060 // Note that we cannot just use BrowserList::GetBrowserCount as browser
1061 // windows closing is delayed and the returned count might include windows
1062 // that are being closed.
1063 // The browser allowed to be closed only if both of the following are true:
1064 // 1. There are no downloads present for any profile or it is not the
1065 // last Browser.
1066 // 2. (Incognito Browser) There are no incognito downloads associated with
1067 // the Browser's profile or it is not the last Browser associated with
1068 // that profile.
1069 // Note the lack of parallelism: regular profiles are kept around until
1070 // browser close, whereas incognito profiles are destroyed on last
1071 // associated window close.
1072 int profile_window_count = 0;
achuithb 2011/10/13 23:05:08 Does it make sense to move lines 1072-1085 into a
Randy Smith (Not in Mondays) 2011/10/14 00:37:41 Huh. I don't have that feeling about it. The *lo
achuithb 2011/10/14 19:22:10 Yup, definitely better since it fits on my 15" scr
1073 int total_window_count = 0;
1074 for (BrowserList::const_iterator iter = BrowserList::begin();
1075 iter != BrowserList::end(); ++iter) {
1076 // Don't count this browser window or any other in the process of closing.
1077 Browser* const browser = *iter;
1078 if (browser == this ||
1079 browser->is_attempting_to_close_browser_)
sky 2011/10/13 20:23:43 nit: move this up to the previous line.
achuithb 2011/10/13 23:05:08 You lost the condition to guard against counting p
Randy Smith (Not in Mondays) 2011/10/14 00:37:41 Done.
Randy Smith (Not in Mondays) 2011/10/14 00:37:41 Yes. See earlier comment on this CL @ http://cod
1080 continue;
1081
1082 if ((*iter)->profile() == profile())
1083 profile_window_count++;
1084 total_window_count++;
1085 }
1086
1087 // If there aren't any other windows, we're at browser shutdown.
1088 if (total_window_count == 0) {
1089 *num_downloads_blocking = total_download_count;
1090 return DOWNLOAD_CLOSE_BROWSER_SHUTDOWN;
1091 }
1092
1093 // If there aren't any other windows on our profile, we're an incognito
1094 // profile, and there are downloads associated with that profile,
1095 // indicate that.
1096 DownloadService* download_service =
1097 DownloadServiceFactory::GetForProfile(profile());
1098 if (profile_window_count == 0 && download_service->DownloadCount() > 0 &&
1099 profile()->IsOffTheRecord()) {
1100 *num_downloads_blocking = download_service->DownloadCount();
1101 return DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE;
1102 }
1103
1104 // Those are the only conditions under which we will block shutdown.
1105 return DOWNLOAD_CLOSE_OK;
1106 }
1107
1040 //////////////////////////////////////////////////////////////////////////////// 1108 ////////////////////////////////////////////////////////////////////////////////
1041 // Browser, TabStripModel pass-thrus: 1109 // Browser, TabStripModel pass-thrus:
1042 1110
1043 int Browser::tab_count() const { 1111 int Browser::tab_count() const {
1044 return tab_handler_->GetTabStripModel()->count(); 1112 return tab_handler_->GetTabStripModel()->count();
1045 } 1113 }
1046 1114
1047 int Browser::active_index() const { 1115 int Browser::active_index() const {
1048 return tab_handler_->GetTabStripModel()->active_index(); 1116 return tab_handler_->GetTabStripModel()->active_index();
1049 } 1117 }
(...skipping 3795 matching lines...) Expand 10 before | Expand all | Expand 10 after
4845 MessageLoop::current()->PostTask( 4913 MessageLoop::current()->PostTask(
4846 FROM_HERE, 4914 FROM_HERE,
4847 method_factory_.NewRunnableMethod(&Browser::ProcessPendingTabs)); 4915 method_factory_.NewRunnableMethod(&Browser::ProcessPendingTabs));
4848 } 4916 }
4849 } 4917 }
4850 } 4918 }
4851 4919
4852 /////////////////////////////////////////////////////////////////////////////// 4920 ///////////////////////////////////////////////////////////////////////////////
4853 // Browser, In-progress download termination handling (private): 4921 // Browser, In-progress download termination handling (private):
4854 4922
4855 void Browser::CheckDownloadsInProgress(bool* normal_downloads_are_present,
4856 bool* incognito_downloads_are_present) {
4857 *normal_downloads_are_present = false;
4858 *incognito_downloads_are_present = false;
4859
4860 // If there are no download in-progress, our job is done.
4861 DownloadManager* download_manager = NULL;
4862 DownloadService* download_service =
4863 DownloadServiceFactory::GetForProfile(profile());
4864 // But first we need to check for the existence of the download manager, as
4865 // GetDownloadManager() will unnecessarily try to create one if it does not
4866 // exist.
4867 if (download_service->HasCreatedDownloadManager())
4868 download_manager = download_service->GetDownloadManager();
4869 if (profile()->IsOffTheRecord()) {
4870 // Browser is incognito and so download_manager if present is for incognito
4871 // downloads.
4872 *incognito_downloads_are_present =
4873 (download_manager && download_manager->in_progress_count() != 0);
4874 // Check original profile.
4875 DownloadService* download_service = DownloadServiceFactory::GetForProfile(
4876 profile()->GetOriginalProfile());
4877 if (download_service->HasCreatedDownloadManager())
4878 download_manager = download_service->GetDownloadManager();
4879 }
4880
4881 *normal_downloads_are_present =
4882 (download_manager && download_manager->in_progress_count() != 0);
4883 }
4884
4885 bool Browser::CanCloseWithInProgressDownloads() { 4923 bool Browser::CanCloseWithInProgressDownloads() {
4886 if (cancel_download_confirmation_state_ != NOT_PROMPTED) { 4924 if (cancel_download_confirmation_state_ != NOT_PROMPTED) {
achuithb 2011/10/13 23:05:08 I know this is not your code, but do you think you
Randy Smith (Not in Mondays) 2011/10/14 00:37:41 I agree with you, but I'm reluctant to make a chan
Randy Smith (Not in Mondays) 2011/10/14 16:13:03 Done.
4887 if (cancel_download_confirmation_state_ == WAITING_FOR_RESPONSE) { 4925 if (cancel_download_confirmation_state_ == WAITING_FOR_RESPONSE) {
4888 // We need to hear from the user before we can close. 4926 // We need to hear from the user before we can close.
4889 return false; 4927 return false;
4890 } 4928 }
4891 // RESPONSE_RECEIVED case, the user decided to go along with the closing. 4929 // RESPONSE_RECEIVED case, the user decided to go along with the closing.
4892 return true; 4930 return true;
4893 } 4931 }
4894 // Indicated that normal (non-incognito) downloads are pending. 4932
4895 bool normal_downloads_are_present = false; 4933 int num_downloads_blocking;
4896 bool incognito_downloads_are_present = false; 4934 if (DOWNLOAD_CLOSE_OK ==
4897 CheckDownloadsInProgress(&normal_downloads_are_present, 4935 OkToCloseWithInProgressDownloads(&num_downloads_blocking))
4898 &incognito_downloads_are_present);
4899 if (!normal_downloads_are_present && !incognito_downloads_are_present)
4900 return true; 4936 return true;
4901 4937
4902 if (is_attempting_to_close_browser_) 4938 // Closing this window will kill some downloads; prompt to make sure
4903 return true; 4939 // that's ok.
4904
4905 if ((!normal_downloads_are_present && !profile()->IsOffTheRecord()) ||
4906 (!incognito_downloads_are_present && profile()->IsOffTheRecord()))
4907 return true;
4908
4909 // Let's figure out if we are the last window for our profile.
4910 // Note that we cannot just use BrowserList::GetBrowserCount as browser
4911 // windows closing is delayed and the returned count might include windows
4912 // that are being closed.
4913 // The browser allowed to be closed only if:
4914 // 1. It is a regular browser and there are no regular downloads present or
4915 // this is not the last regular browser window.
4916 // 2. It is an incognito browser and there are no incognito downloads present
4917 // or this is not the last incognito browser window.
4918 int count = 0;
4919 for (BrowserList::const_iterator iter = BrowserList::begin();
4920 iter != BrowserList::end(); ++iter) {
4921 // Don't count this browser window or any other in the process of closing.
4922 // Only consider tabbed browser windows, not popups.
4923 Browser* const browser = *iter;
4924 if (browser == this
4925 || browser->is_attempting_to_close_browser_
4926 || !browser->is_type_tabbed())
4927 continue;
4928
4929 // Verify that this is not the last non-incognito or incognito browser,
4930 // depending on the pending downloads.
4931 if (normal_downloads_are_present && !profile()->IsOffTheRecord() &&
4932 browser->profile()->IsOffTheRecord())
4933 continue;
4934 if (incognito_downloads_are_present && profile()->IsOffTheRecord() &&
4935 !browser->profile()->IsOffTheRecord())
4936 continue;
4937
4938 // We test the original profile, because an incognito browser window keeps
4939 // the original profile alive (and its DownloadManager).
4940 // We also need to test explicitly the profile directly so that 2 incognito
4941 // profiles count as a match.
4942 if ((*iter)->profile() == profile() ||
4943 (*iter)->profile()->GetOriginalProfile() == profile())
4944 count++;
4945 }
4946 if (count > 0)
4947 return true;
4948
4949 cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE; 4940 cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE;
4950 window_->ConfirmBrowserCloseWithPendingDownloads(); 4941 window_->ConfirmBrowserCloseWithPendingDownloads();
4951 4942
4952 // Return false so the browser does not close. We'll close if the user 4943 // Return false so the browser does not close. We'll close if the user
4953 // confirms in the dialog. 4944 // confirms in the dialog.
4954 return false; 4945 return false;
4955 } 4946 }
4956 4947
4957 /////////////////////////////////////////////////////////////////////////////// 4948 ///////////////////////////////////////////////////////////////////////////////
4958 // Browser, Assorted utility functions (private): 4949 // Browser, Assorted utility functions (private):
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
5287 window_->GetLocationBar()->ShowFirstRunBubble(bubble_type); 5278 window_->GetLocationBar()->ShowFirstRunBubble(bubble_type);
5288 } else if (is_type_tabbed()) { 5279 } else if (is_type_tabbed()) {
5289 GlobalErrorService* service = 5280 GlobalErrorService* service =
5290 GlobalErrorServiceFactory::GetForProfile(profile()); 5281 GlobalErrorServiceFactory::GetForProfile(profile());
5291 GlobalError* error = service->GetFirstGlobalErrorWithBubbleView(); 5282 GlobalError* error = service->GetFirstGlobalErrorWithBubbleView();
5292 if (error) { 5283 if (error) {
5293 error->ShowBubbleView(this); 5284 error->ShowBubbleView(this);
5294 } 5285 }
5295 } 5286 }
5296 } 5287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698