| 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/chrome_browser_main_win.h" | 5 #include "chrome/browser/chrome_browser_main_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <shellapi.h> | 8 #include <shellapi.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 void WarnAboutMinimumSystemRequirements() { | 67 void WarnAboutMinimumSystemRequirements() { |
| 68 if (base::win::GetVersion() < base::win::VERSION_XP) { | 68 if (base::win::GetVersion() < base::win::VERSION_XP) { |
| 69 // Display a warning message if the user is running chrome on Windows 2000. | 69 // Display a warning message if the user is running chrome on Windows 2000. |
| 70 const string16 text = | 70 const string16 text = |
| 71 l10n_util::GetStringUTF16(IDS_UNSUPPORTED_OS_PRE_WIN_XP); | 71 l10n_util::GetStringUTF16(IDS_UNSUPPORTED_OS_PRE_WIN_XP); |
| 72 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | 72 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); |
| 73 ui::MessageBox(NULL, text, caption, MB_OK | MB_ICONWARNING | MB_TOPMOST); | 73 ui::MessageBox(NULL, text, caption, MB_OK | MB_ICONWARNING | MB_TOPMOST); |
| 74 } | 74 } |
| 75 } | 75 } |
| 76 | 76 |
| 77 #if !defined(USE_AURA) | |
| 78 void ShowMissingLocaleMessageBox() { | |
| 79 ui::MessageBox(NULL, ASCIIToUTF16(chrome_browser::kMissingLocaleDataMessage), | |
| 80 ASCIIToUTF16(chrome_browser::kMissingLocaleDataTitle), | |
| 81 MB_OK | MB_ICONERROR | MB_TOPMOST); | |
| 82 } | |
| 83 #endif | |
| 84 | |
| 85 void RecordBrowserStartupTime() { | 77 void RecordBrowserStartupTime() { |
| 86 // Calculate the time that has elapsed from our own process creation. | 78 // Calculate the time that has elapsed from our own process creation. |
| 87 FILETIME creation_time = {}; | 79 FILETIME creation_time = {}; |
| 88 FILETIME ignore = {}; | 80 FILETIME ignore = {}; |
| 89 ::GetProcessTimes(::GetCurrentProcess(), &creation_time, &ignore, &ignore, | 81 ::GetProcessTimes(::GetCurrentProcess(), &creation_time, &ignore, &ignore, |
| 90 &ignore); | 82 &ignore); |
| 91 | 83 |
| 92 RecordPreReadExperimentTime("Startup.BrowserMessageLoopStartTime", | 84 RecordPreReadExperimentTime("Startup.BrowserMessageLoopStartTime", |
| 93 base::Time::Now() - base::Time::FromFileTime(creation_time)); | 85 base::Time::Now() - base::Time::FromFileTime(creation_time)); |
| 94 } | 86 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 if (!ShellUtil::RemoveChromeDesktopShortcut(dist, ShellUtil::CURRENT_USER, | 126 if (!ShellUtil::RemoveChromeDesktopShortcut(dist, ShellUtil::CURRENT_USER, |
| 135 false)) | 127 false)) |
| 136 VLOG(1) << "Failed to delete desktop shortcut."; | 128 VLOG(1) << "Failed to delete desktop shortcut."; |
| 137 if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist, | 129 if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist, |
| 138 ShellUtil::CURRENT_USER)) | 130 ShellUtil::CURRENT_USER)) |
| 139 VLOG(1) << "Failed to delete quick launch shortcut."; | 131 VLOG(1) << "Failed to delete quick launch shortcut."; |
| 140 } | 132 } |
| 141 return ret; | 133 return ret; |
| 142 } | 134 } |
| 143 | 135 |
| 144 // Prepares the localized strings that are going to be displayed to | 136 // ChromeBrowserMainPartsWin --------------------------------------------------- |
| 145 // the user if the browser process dies. These strings are stored in the | |
| 146 // environment block so they are accessible in the early stages of the | |
| 147 // chrome executable's lifetime. | |
| 148 void PrepareRestartOnCrashEnviroment(const CommandLine& parsed_command_line) { | |
| 149 // Clear this var so child processes don't show the dialog by default. | |
| 150 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
| 151 env->UnSetVar(env_vars::kShowRestart); | |
| 152 | 137 |
| 153 // For non-interactive tests we don't restart on crash. | 138 ChromeBrowserMainPartsWin::ChromeBrowserMainPartsWin( |
| 154 if (env->HasVar(env_vars::kHeadless)) | 139 const MainFunctionParams& parameters) |
| 155 return; | 140 : ChromeBrowserMainParts(parameters) { |
| 156 | |
| 157 // If the known command-line test options are used we don't create the | |
| 158 // environment block which means we don't get the restart dialog. | |
| 159 if (parsed_command_line.HasSwitch(switches::kBrowserCrashTest) || | |
| 160 parsed_command_line.HasSwitch(switches::kBrowserAssertTest) || | |
| 161 parsed_command_line.HasSwitch(switches::kNoErrorDialogs)) | |
| 162 return; | |
| 163 | |
| 164 // The encoding we use for the info is "title|context|direction" where | |
| 165 // direction is either env_vars::kRtlLocale or env_vars::kLtrLocale depending | |
| 166 // on the current locale. | |
| 167 string16 dlg_strings(l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_TITLE)); | |
| 168 dlg_strings.push_back('|'); | |
| 169 string16 adjusted_string( | |
| 170 l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_CONTENT)); | |
| 171 base::i18n::AdjustStringForLocaleDirection(&adjusted_string); | |
| 172 dlg_strings.append(adjusted_string); | |
| 173 dlg_strings.push_back('|'); | |
| 174 dlg_strings.append(ASCIIToUTF16( | |
| 175 base::i18n::IsRTL() ? env_vars::kRtlLocale : env_vars::kLtrLocale)); | |
| 176 | |
| 177 env->SetVar(env_vars::kRestartInfo, UTF16ToUTF8(dlg_strings)); | |
| 178 } | 141 } |
| 179 | 142 |
| 180 void RegisterApplicationRestart(const CommandLine& parsed_command_line) { | 143 void ChromeBrowserMainPartsWin::PreMainMessageLoopStart() { |
| 181 DCHECK(base::win::GetVersion() >= base::win::VERSION_VISTA); | 144 if (!parameters().ui_task) { |
| 182 base::ScopedNativeLibrary library(FilePath(L"kernel32.dll")); | 145 // Make sure that we know how to handle exceptions from the message loop. |
| 183 // Get the function pointer for RegisterApplicationRestart. | 146 InitializeWindowProcExceptions(); |
| 184 RegisterApplicationRestartProc register_application_restart = | |
| 185 static_cast<RegisterApplicationRestartProc>( | |
| 186 library.GetFunctionPointer("RegisterApplicationRestart")); | |
| 187 if (!register_application_restart) { | |
| 188 LOG(WARNING) << "Cannot find RegisterApplicationRestart in kernel32.dll"; | |
| 189 return; | |
| 190 } | 147 } |
| 191 // The Windows Restart Manager expects a string of command line flags only, | 148 } |
| 192 // without the program. | |
| 193 CommandLine command_line(CommandLine::NO_PROGRAM); | |
| 194 command_line.AppendArguments(parsed_command_line, false); | |
| 195 if (!command_line.HasSwitch(switches::kRestoreLastSession)) | |
| 196 command_line.AppendSwitch(switches::kRestoreLastSession); | |
| 197 if (command_line.GetCommandLineString().length() > RESTART_MAX_CMD_LINE) { | |
| 198 LOG(WARNING) << "Command line too long for RegisterApplicationRestart"; | |
| 199 return; | |
| 200 } | |
| 201 | 149 |
| 202 // Restart Chrome if the computer is restarted as the result of an update. | 150 void ChromeBrowserMainPartsWin::ShowMissingLocaleMessageBox() { |
| 203 // This could be extended to handle crashes, hangs, and patches. | 151 ui::MessageBox(NULL, ASCIIToUTF16(chrome_browser::kMissingLocaleDataMessage), |
| 204 HRESULT hr = register_application_restart( | 152 ASCIIToUTF16(chrome_browser::kMissingLocaleDataTitle), |
| 205 command_line.GetCommandLineString().c_str(), | 153 MB_OK | MB_ICONERROR | MB_TOPMOST); |
| 206 RESTART_NO_CRASH | RESTART_NO_HANG | RESTART_NO_PATCH); | |
| 207 DCHECK(SUCCEEDED(hr)) << "RegisterApplicationRestart failed."; | |
| 208 } | 154 } |
| 209 | 155 |
| 210 // This method handles the --hide-icons and --show-icons command line options | 156 // This method handles the --hide-icons and --show-icons command line options |
| 211 // for chrome that get triggered by Windows from registry entries | 157 // for chrome that get triggered by Windows from registry entries |
| 212 // HideIconsCommand & ShowIconsCommand. Chrome doesn't support hide icons | 158 // HideIconsCommand & ShowIconsCommand. Chrome doesn't support hide icons |
| 213 // functionality so we just ask the users if they want to uninstall Chrome. | 159 // functionality so we just ask the users if they want to uninstall Chrome. |
| 214 int HandleIconsCommands(const CommandLine& parsed_command_line) { | 160 int ChromeBrowserMainPartsWin::HandleIconsCommands() { |
| 215 if (parsed_command_line.HasSwitch(switches::kHideIcons)) { | 161 if (parsed_command_line().HasSwitch(switches::kHideIcons)) { |
| 216 string16 cp_applet; | 162 string16 cp_applet; |
| 217 base::win::Version version = base::win::GetVersion(); | 163 base::win::Version version = base::win::GetVersion(); |
| 218 if (version >= base::win::VERSION_VISTA) { | 164 if (version >= base::win::VERSION_VISTA) { |
| 219 cp_applet.assign(L"Programs and Features"); // Windows Vista and later. | 165 cp_applet.assign(L"Programs and Features"); // Windows Vista and later. |
| 220 } else if (version >= base::win::VERSION_XP) { | 166 } else if (version >= base::win::VERSION_XP) { |
| 221 cp_applet.assign(L"Add/Remove Programs"); // Windows XP. | 167 cp_applet.assign(L"Add/Remove Programs"); // Windows XP. |
| 222 } else { | 168 } else { |
| 223 return chrome::RESULT_CODE_UNSUPPORTED_PARAM; // Not supported | 169 return chrome::RESULT_CODE_UNSUPPORTED_PARAM; // Not supported |
| 224 } | 170 } |
| 225 | 171 |
| 226 const string16 msg = | 172 const string16 msg = |
| 227 l10n_util::GetStringFUTF16(IDS_HIDE_ICONS_NOT_SUPPORTED, cp_applet); | 173 l10n_util::GetStringFUTF16(IDS_HIDE_ICONS_NOT_SUPPORTED, cp_applet); |
| 228 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | 174 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); |
| 229 const UINT flags = MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST; | 175 const UINT flags = MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST; |
| 230 if (IDOK == ui::MessageBox(NULL, msg, caption, flags)) | 176 if (IDOK == ui::MessageBox(NULL, msg, caption, flags)) |
| 231 ShellExecute(NULL, NULL, L"appwiz.cpl", NULL, NULL, SW_SHOWNORMAL); | 177 ShellExecute(NULL, NULL, L"appwiz.cpl", NULL, NULL, SW_SHOWNORMAL); |
| 232 | 178 |
| 233 // Exit as we are not launching the browser. | 179 // Exit as we are not launching the browser. |
| 234 return content::RESULT_CODE_NORMAL_EXIT; | 180 return content::RESULT_CODE_NORMAL_EXIT; |
| 235 } | 181 } |
| 236 // We don't hide icons so we shouldn't do anything special to show them | 182 // We don't hide icons so we shouldn't do anything special to show them |
| 237 return chrome::RESULT_CODE_UNSUPPORTED_PARAM; | 183 return chrome::RESULT_CODE_UNSUPPORTED_PARAM; |
| 238 } | 184 } |
| 239 | 185 |
| 240 // Check if there is any machine level Chrome installed on the current | 186 // Check if there is any machine level Chrome installed on the current |
| 241 // machine. If yes and the current Chrome process is user level, we do not | 187 // machine. If yes and the current Chrome process is user level, we do not |
| 242 // allow the user level Chrome to run. So we notify the user and uninstall | 188 // allow the user level Chrome to run. So we notify the user and uninstall |
| 243 // user level Chrome. | 189 // user level Chrome. |
| 244 bool CheckMachineLevelInstall() { | 190 bool ChromeBrowserMainPartsWin::CheckMachineLevelInstall() { |
| 245 // TODO(tommi): Check if using the default distribution is always the right | 191 // TODO(tommi): Check if using the default distribution is always the right |
| 246 // thing to do. | 192 // thing to do. |
| 247 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 193 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 248 scoped_ptr<Version> version(InstallUtil::GetChromeVersion(dist, true)); | 194 scoped_ptr<Version> version(InstallUtil::GetChromeVersion(dist, true)); |
| 249 if (version.get()) { | 195 if (version.get()) { |
| 250 FilePath exe_path; | 196 FilePath exe_path; |
| 251 PathService::Get(base::DIR_EXE, &exe_path); | 197 PathService::Get(base::DIR_EXE, &exe_path); |
| 252 std::wstring exe = exe_path.value(); | 198 std::wstring exe = exe_path.value(); |
| 253 FilePath user_exe_path(installer::GetChromeInstallPath(false, dist)); | 199 FilePath user_exe_path(installer::GetChromeInstallPath(false, dist)); |
| 254 if (FilePath::CompareEqualIgnoreCase(exe, user_exe_path.value())) { | 200 if (FilePath::CompareEqualIgnoreCase(exe, user_exe_path.value())) { |
| 255 const string16 text = | 201 const string16 text = |
| 256 l10n_util::GetStringUTF16(IDS_MACHINE_LEVEL_INSTALL_CONFLICT); | 202 l10n_util::GetStringUTF16(IDS_MACHINE_LEVEL_INSTALL_CONFLICT); |
| 257 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | 203 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); |
| 258 const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST; | 204 const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST; |
| 259 ui::MessageBox(NULL, text, caption, flags); | 205 ui::MessageBox(NULL, text, caption, flags); |
| 260 CommandLine uninstall_cmd( | 206 CommandLine uninstall_cmd( |
| 261 InstallUtil::GetChromeUninstallCmd(false, dist->GetType())); | 207 InstallUtil::GetChromeUninstallCmd(false, dist->GetType())); |
| 262 if (!uninstall_cmd.GetProgram().empty()) { | 208 if (!uninstall_cmd.GetProgram().empty()) { |
| 263 uninstall_cmd.AppendSwitch(installer::switches::kForceUninstall); | 209 uninstall_cmd.AppendSwitch(installer::switches::kForceUninstall); |
| 264 uninstall_cmd.AppendSwitch( | 210 uninstall_cmd.AppendSwitch( |
| 265 installer::switches::kDoNotRemoveSharedItems); | 211 installer::switches::kDoNotRemoveSharedItems); |
| 266 base::LaunchProcess(uninstall_cmd, base::LaunchOptions(), NULL); | 212 base::LaunchProcess(uninstall_cmd, base::LaunchOptions(), NULL); |
| 267 } | 213 } |
| 268 return true; | 214 return true; |
| 269 } | 215 } |
| 270 } | 216 } |
| 271 return false; | 217 return false; |
| 272 } | 218 } |
| 273 | 219 |
| 274 // ChromeBrowserMainPartsWin --------------------------------------------------- | 220 // Prepares the localized strings that are going to be displayed to |
| 221 // the user if the browser process dies. These strings are stored in the |
| 222 // environment block so they are accessible in the early stages of the |
| 223 // chrome executable's lifetime. |
| 224 void ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment() { |
| 225 // Clear this var so child processes don't show the dialog by default. |
| 226 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 227 env->UnSetVar(env_vars::kShowRestart); |
| 275 | 228 |
| 276 ChromeBrowserMainPartsWin::ChromeBrowserMainPartsWin( | 229 // For non-interactive tests we don't restart on crash. |
| 277 const MainFunctionParams& parameters) | 230 if (env->HasVar(env_vars::kHeadless)) |
| 278 : ChromeBrowserMainParts(parameters) { | 231 return; |
| 232 |
| 233 // If the known command-line test options are used we don't create the |
| 234 // environment block which means we don't get the restart dialog. |
| 235 if (parsed_command_line().HasSwitch(switches::kBrowserCrashTest) || |
| 236 parsed_command_line().HasSwitch(switches::kBrowserAssertTest) || |
| 237 parsed_command_line().HasSwitch(switches::kNoErrorDialogs)) |
| 238 return; |
| 239 |
| 240 // The encoding we use for the info is "title|context|direction" where |
| 241 // direction is either env_vars::kRtlLocale or env_vars::kLtrLocale depending |
| 242 // on the current locale. |
| 243 string16 dlg_strings(l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_TITLE)); |
| 244 dlg_strings.push_back('|'); |
| 245 string16 adjusted_string( |
| 246 l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_CONTENT)); |
| 247 base::i18n::AdjustStringForLocaleDirection(&adjusted_string); |
| 248 dlg_strings.append(adjusted_string); |
| 249 dlg_strings.push_back('|'); |
| 250 dlg_strings.append(ASCIIToUTF16( |
| 251 base::i18n::IsRTL() ? env_vars::kRtlLocale : env_vars::kLtrLocale)); |
| 252 |
| 253 env->SetVar(env_vars::kRestartInfo, UTF16ToUTF8(dlg_strings)); |
| 279 } | 254 } |
| 280 | 255 |
| 281 void ChromeBrowserMainPartsWin::PreMainMessageLoopStart() { | 256 void ChromeBrowserMainPartsWin::RegisterApplicationRestart() { |
| 282 if (!parameters().ui_task) { | 257 DCHECK(base::win::GetVersion() >= base::win::VERSION_VISTA); |
| 283 // Make sure that we know how to handle exceptions from the message loop. | 258 base::ScopedNativeLibrary library(FilePath(L"kernel32.dll")); |
| 284 InitializeWindowProcExceptions(); | 259 // Get the function pointer for RegisterApplicationRestart. |
| 260 RegisterApplicationRestartProc register_application_restart = |
| 261 static_cast<RegisterApplicationRestartProc>( |
| 262 library.GetFunctionPointer("RegisterApplicationRestart")); |
| 263 if (!register_application_restart) { |
| 264 LOG(WARNING) << "Cannot find RegisterApplicationRestart in kernel32.dll"; |
| 265 return; |
| 285 } | 266 } |
| 267 // The Windows Restart Manager expects a string of command line flags only, |
| 268 // without the program. |
| 269 CommandLine command_line(CommandLine::NO_PROGRAM); |
| 270 command_line.AppendArguments(parsed_command_line(), false); |
| 271 if (!command_line.HasSwitch(switches::kRestoreLastSession)) |
| 272 command_line.AppendSwitch(switches::kRestoreLastSession); |
| 273 if (command_line.GetCommandLineString().length() > RESTART_MAX_CMD_LINE) { |
| 274 LOG(WARNING) << "Command line too long for RegisterApplicationRestart"; |
| 275 return; |
| 276 } |
| 277 |
| 278 // Restart Chrome if the computer is restarted as the result of an update. |
| 279 // This could be extended to handle crashes, hangs, and patches. |
| 280 HRESULT hr = register_application_restart( |
| 281 command_line.GetCommandLineString().c_str(), |
| 282 RESTART_NO_CRASH | RESTART_NO_HANG | RESTART_NO_PATCH); |
| 283 DCHECK(SUCCEEDED(hr)) << "RegisterApplicationRestart failed."; |
| 286 } | 284 } |
| OLD | NEW |