blob: 4ed9f394cd494aa71b7a1ab0aaf23cf44ac4d573 [file] [log] [blame]
[email protected]6bd15132012-02-14 22:29:031// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]5c9587c2008-12-09 21:20:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]e6b5bc22011-09-08 22:01:565#include "chrome/browser/chrome_browser_main_win.h"
[email protected]5c9587c2008-12-09 21:20:166
[email protected]71b73f02011-04-06 15:57:297#include <windows.h>
[email protected]e0785902011-05-19 23:34:178#include <shellapi.h>
[email protected]4a0765a2009-05-08 23:12:259
[email protected]c83dd912010-04-06 18:50:5110#include <algorithm>
11
[email protected]5c9587c2008-12-09 21:20:1612#include "base/command_line.h"
[email protected]ae0f0772010-08-13 04:54:1013#include "base/environment.h"
[email protected]7cf1b6ce2010-03-20 06:37:0114#include "base/i18n/rtl.h"
[email protected]3b63f8f42011-03-28 01:54:1515#include "base/memory/scoped_ptr.h"
[email protected]5c9587c2008-12-09 21:20:1616#include "base/path_service.h"
[email protected]e0785902011-05-19 23:34:1717#include "base/scoped_native_library.h"
[email protected]c7480942011-11-08 19:18:2718#include "base/string_number_conversions.h"
[email protected]be1ce6a72010-08-03 14:35:2219#include "base/utf_string_conversions.h"
[email protected]3e138642012-04-12 23:07:2220#include "base/win/metro.h"
[email protected]935aa542010-10-15 01:59:1521#include "base/win/windows_version.h"
[email protected]ecb924c2011-03-17 00:34:0922#include "base/win/wrapped_window_proc.h"
[email protected]a3abd5572011-04-15 02:09:3323#include "chrome/browser/browser_util_win.h"
[email protected]820735792010-07-29 23:40:0124#include "chrome/browser/first_run/first_run.h"
[email protected]b83575d2012-04-25 18:35:0825#include "chrome/browser/media_gallery/media_device_notifications_window_win.h"
[email protected]cd1adc22009-01-16 01:29:2226#include "chrome/browser/metrics/metrics_service.h"
[email protected]f8b2ca32011-11-22 14:58:2327#include "chrome/browser/profiles/profile_info_cache.h"
28#include "chrome/browser/profiles/profile_shortcut_manager_win.h"
[email protected]89944cf2012-04-21 14:21:1229#include "chrome/browser/simple_message_box.h"
[email protected]71b73f02011-04-06 15:57:2930#include "chrome/browser/ui/browser_list.h"
[email protected]9e790bd2011-01-10 23:48:5431#include "chrome/browser/ui/views/uninstall_view.h"
[email protected]ecb924c2011-03-17 00:34:0932#include "chrome/common/chrome_constants.h"
[email protected]1fcfb202011-07-19 19:53:1433#include "chrome/common/chrome_result_codes.h"
[email protected]5c9587c2008-12-09 21:20:1634#include "chrome/common/chrome_switches.h"
35#include "chrome/common/env_vars.h"
[email protected]bf6117c7e2010-12-01 06:00:2536#include "chrome/installer/util/browser_distribution.h"
[email protected]5c9587c2008-12-09 21:20:1637#include "chrome/installer/util/helper.h"
38#include "chrome/installer/util/install_util.h"
39#include "chrome/installer/util/shell_util.h"
[email protected]4573fbd2011-10-31 20:25:1840#include "content/public/common/main_function_params.h"
[email protected]c7480942011-11-08 19:18:2741#include "grit/app_locale_settings.h"
[email protected]34ac8f32009-02-22 23:03:2742#include "grit/chromium_strings.h"
43#include "grit/generated_resources.h"
[email protected]c051a1b2011-01-21 23:30:1744#include "ui/base/l10n/l10n_util.h"
[email protected]c7480942011-11-08 19:18:2745#include "ui/base/l10n/l10n_util_win.h"
[email protected]8a6aaa72012-04-20 20:53:5846#include "ui/base/ui_base_switches.h"
[email protected]3455af4e2012-03-12 15:35:1247#include "ui/base/win/message_box_win.h"
[email protected]c7480942011-11-08 19:18:2748#include "ui/gfx/platform_font_win.h"
[email protected]477ae052011-11-18 23:53:5749#include "ui/views/focus/accelerator_handler.h"
[email protected]c13be0d2011-11-22 02:09:5850#include "ui/views/widget/widget.h"
[email protected]5c9587c2008-12-09 21:20:1651
[email protected]0fd23af2011-02-20 06:33:0452namespace {
[email protected]ecb924c2011-03-17 00:34:0953
[email protected]a08ba822011-02-20 07:45:4754typedef HRESULT (STDAPICALLTYPE* RegisterApplicationRestartProc)(
[email protected]0fd23af2011-02-20 06:33:0455 const wchar_t* command_line,
56 DWORD flags);
[email protected]ecb924c2011-03-17 00:34:0957
58void InitializeWindowProcExceptions() {
59 // Get the breakpad pointer from chrome.exe
60 base::win::WinProcExceptionFilter exception_filter =
61 reinterpret_cast<base::win::WinProcExceptionFilter>(
62 ::GetProcAddress(::GetModuleHandle(
63 chrome::kBrowserProcessExecutableName),
64 "CrashForException"));
65 exception_filter = base::win::SetWinProcExceptionFilter(exception_filter);
66 DCHECK(!exception_filter);
67}
[email protected]c7480942011-11-08 19:18:2768
69// gfx::Font callbacks
70void AdjustUIFont(LOGFONT* logfont) {
71 l10n_util::AdjustUIFont(logfont);
72}
73
74int GetMinimumFontSize() {
75 int min_font_size;
76 base::StringToInt(l10n_util::GetStringUTF16(IDS_MINIMUM_UI_FONT_SIZE),
77 &min_font_size);
78 return min_font_size;
79}
80
[email protected]0fd23af2011-02-20 06:33:0481} // namespace
82
[email protected]1152b7e2009-09-14 03:26:0383void RecordBreakpadStatusUMA(MetricsService* metrics) {
[email protected]1152b7e2009-09-14 03:26:0384 metrics->RecordBreakpadHasDebugger(TRUE == ::IsDebuggerPresent());
85}
86
[email protected]34f73fb2010-03-24 20:50:3487void WarnAboutMinimumSystemRequirements() {
[email protected]935aa542010-10-15 01:59:1588 if (base::win::GetVersion() < base::win::VERSION_XP) {
[email protected]89944cf2012-04-21 14:21:1289 const string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
90 const string16 message =
[email protected]0f26d7b2011-01-05 19:10:4491 l10n_util::GetStringUTF16(IDS_UNSUPPORTED_OS_PRE_WIN_XP);
[email protected]5c61cc92012-04-23 02:00:3992 browser::ShowWarningMessageBox(NULL, title, message);
[email protected]5c9587c2008-12-09 21:20:1693 }
[email protected]5c9587c2008-12-09 21:20:1694}
95
[email protected]45d72762011-04-15 18:58:2096void RecordBrowserStartupTime() {
97 // Calculate the time that has elapsed from our own process creation.
98 FILETIME creation_time = {};
99 FILETIME ignore = {};
100 ::GetProcessTimes(::GetCurrentProcess(), &creation_time, &ignore, &ignore,
101 &ignore);
102
[email protected]28f576f2011-08-26 20:46:55103 RecordPreReadExperimentTime("Startup.BrowserMessageLoopStartTime",
104 base::Time::Now() - base::Time::FromFileTime(creation_time));
[email protected]45d72762011-04-15 18:58:20105}
106
[email protected]4df8786f2009-04-17 13:24:57107int AskForUninstallConfirmation() {
[email protected]1fcfb202011-07-19 19:53:14108 int ret = content::RESULT_CODE_NORMAL_EXIT;
[email protected]956b3d32011-09-28 09:38:48109 views::Widget::CreateWindow(new UninstallView(&ret))->Show();
[email protected]047f6222009-07-29 23:34:56110 views::AcceleratorHandler accelerator_handler;
[email protected]4d6285312011-10-24 07:19:51111 MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
[email protected]4df8786f2009-04-17 13:24:57112 return ret;
[email protected]5c9587c2008-12-09 21:20:16113}
114
[email protected]53c38d232009-02-13 20:52:18115void ShowCloseBrowserFirstMessageBox() {
[email protected]89944cf2012-04-21 14:21:12116 const string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
117 const string16 message = l10n_util::GetStringUTF16(IDS_UNINSTALL_CLOSE_APP);
[email protected]5c61cc92012-04-23 02:00:39118 browser::ShowWarningMessageBox(NULL, title, message);
[email protected]53c38d232009-02-13 20:52:18119}
120
121int DoUninstallTasks(bool chrome_still_running) {
[email protected]a173cc92009-08-20 23:26:37122 // We want to show a warning to user (and exit) if Chrome is already running
123 // *before* we show the uninstall confirmation dialog box. But while the
124 // uninstall confirmation dialog is up, user might start Chrome, so we
125 // check once again after user acknowledges Uninstall dialog.
[email protected]53c38d232009-02-13 20:52:18126 if (chrome_still_running) {
127 ShowCloseBrowserFirstMessageBox();
[email protected]1fcfb202011-07-19 19:53:14128 return chrome::RESULT_CODE_UNINSTALL_CHROME_ALIVE;
[email protected]53c38d232009-02-13 20:52:18129 }
[email protected]4df8786f2009-04-17 13:24:57130 int ret = AskForUninstallConfirmation();
[email protected]a3abd5572011-04-15 02:09:33131 if (browser_util::IsBrowserAlreadyRunning()) {
[email protected]a173cc92009-08-20 23:26:37132 ShowCloseBrowserFirstMessageBox();
[email protected]1fcfb202011-07-19 19:53:14133 return chrome::RESULT_CODE_UNINSTALL_CHROME_ALIVE;
[email protected]a173cc92009-08-20 23:26:37134 }
135
[email protected]1fcfb202011-07-19 19:53:14136 if (ret != chrome::RESULT_CODE_UNINSTALL_USER_CANCEL) {
[email protected]4df8786f2009-04-17 13:24:57137 // The following actions are just best effort.
[email protected]8e96e502010-10-21 20:57:12138 VLOG(1) << "Executing uninstall actions";
[email protected]dfa08b042011-12-28 23:07:21139 if (!first_run::RemoveSentinel())
[email protected]8e96e502010-10-21 20:57:12140 VLOG(1) << "Failed to delete sentinel file.";
[email protected]4df8786f2009-04-17 13:24:57141 // We want to remove user level shortcuts and we only care about the ones
142 // created by us and not by the installer so |alternate| is false.
[email protected]bf6117c7e2010-12-01 06:00:25143 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
[email protected]2e1a4a82012-04-06 19:23:11144 if (!ShellUtil::RemoveChromeDesktopShortcut(
145 dist, ShellUtil::CURRENT_USER, ShellUtil::SHORTCUT_NO_OPTIONS)) {
[email protected]8e96e502010-10-21 20:57:12146 VLOG(1) << "Failed to delete desktop shortcut.";
[email protected]f8b2ca32011-11-22 14:58:23147 }
148 if (!ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames(
149 ProfileShortcutManagerWin::GenerateShortcutsFromProfiles(
150 ProfileInfoCache::GetProfileNames()))) {
151 VLOG(1) << "Failed to delete desktop profiles shortcuts.";
152 }
[email protected]bf6117c7e2010-12-01 06:00:25153 if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist,
[email protected]f8b2ca32011-11-22 14:58:23154 ShellUtil::CURRENT_USER)) {
[email protected]8e96e502010-10-21 20:57:12155 VLOG(1) << "Failed to delete quick launch shortcut.";
[email protected]f8b2ca32011-11-22 14:58:23156 }
[email protected]4df8786f2009-04-17 13:24:57157 }
[email protected]5c9587c2008-12-09 21:20:16158 return ret;
159}
160
[email protected]b48c9182011-10-26 18:03:30161// ChromeBrowserMainPartsWin ---------------------------------------------------
162
163ChromeBrowserMainPartsWin::ChromeBrowserMainPartsWin(
[email protected]4573fbd2011-10-31 20:25:18164 const content::MainFunctionParams& parameters)
[email protected]b48c9182011-10-26 18:03:30165 : ChromeBrowserMainParts(parameters) {
[email protected]3e138642012-04-12 23:07:22166 if (base::win::GetMetroModule()) {
167 CommandLine::ForCurrentProcess()->AppendSwitch(
[email protected]1ac11e92012-04-24 21:31:04168 switches::kTouchOptimizedUI);
[email protected]3e138642012-04-12 23:07:22169 }
[email protected]b48c9182011-10-26 18:03:30170}
171
[email protected]b83575d2012-04-25 18:35:08172ChromeBrowserMainPartsWin::~ChromeBrowserMainPartsWin() {
173}
174
[email protected]c7480942011-11-08 19:18:27175void ChromeBrowserMainPartsWin::ToolkitInitialized() {
176 ChromeBrowserMainParts::ToolkitInitialized();
177 gfx::PlatformFontWin::adjust_font_callback = &AdjustUIFont;
178 gfx::PlatformFontWin::get_minimum_font_size_callback = &GetMinimumFontSize;
179}
180
[email protected]b48c9182011-10-26 18:03:30181void ChromeBrowserMainPartsWin::PreMainMessageLoopStart() {
[email protected]c7480942011-11-08 19:18:27182 ChromeBrowserMainParts::PreMainMessageLoopStart();
[email protected]716476c2011-12-29 00:07:03183 if (!parameters().ui_task) {
[email protected]b48c9182011-10-26 18:03:30184 // Make sure that we know how to handle exceptions from the message loop.
185 InitializeWindowProcExceptions();
186 }
[email protected]b83575d2012-04-25 18:35:08187 media_device_notifications_window_.reset(
188 new chrome::MediaDeviceNotificationsWindowWin());
[email protected]b48c9182011-10-26 18:03:30189}
190
191// static
192void ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment(
193 const CommandLine& parsed_command_line) {
[email protected]5c9587c2008-12-09 21:20:16194 // Clear this var so child processes don't show the dialog by default.
[email protected]ae0f0772010-08-13 04:54:10195 scoped_ptr<base::Environment> env(base::Environment::Create());
196 env->UnSetVar(env_vars::kShowRestart);
[email protected]5c9587c2008-12-09 21:20:16197
198 // For non-interactive tests we don't restart on crash.
[email protected]ae0f0772010-08-13 04:54:10199 if (env->HasVar(env_vars::kHeadless))
[email protected]5c9587c2008-12-09 21:20:16200 return;
201
202 // If the known command-line test options are used we don't create the
203 // environment block which means we don't get the restart dialog.
204 if (parsed_command_line.HasSwitch(switches::kBrowserCrashTest) ||
205 parsed_command_line.HasSwitch(switches::kBrowserAssertTest) ||
206 parsed_command_line.HasSwitch(switches::kNoErrorDialogs))
207 return;
208
209 // The encoding we use for the info is "title|context|direction" where
210 // direction is either env_vars::kRtlLocale or env_vars::kLtrLocale depending
211 // on the current locale.
[email protected]6baca1a2010-08-14 00:17:05212 string16 dlg_strings(l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_TITLE));
213 dlg_strings.push_back('|');
[email protected]1c53ffde12010-08-17 22:40:31214 string16 adjusted_string(
215 l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_CONTENT));
[email protected]c32d31e2010-11-24 07:27:42216 base::i18n::AdjustStringForLocaleDirection(&adjusted_string);
[email protected]6baca1a2010-08-14 00:17:05217 dlg_strings.append(adjusted_string);
218 dlg_strings.push_back('|');
219 dlg_strings.append(ASCIIToUTF16(
220 base::i18n::IsRTL() ? env_vars::kRtlLocale : env_vars::kLtrLocale));
[email protected]5c9587c2008-12-09 21:20:16221
[email protected]6baca1a2010-08-14 00:17:05222 env->SetVar(env_vars::kRestartInfo, UTF16ToUTF8(dlg_strings));
[email protected]5c9587c2008-12-09 21:20:16223}
224
[email protected]b48c9182011-10-26 18:03:30225// static
226void ChromeBrowserMainPartsWin::RegisterApplicationRestart(
227 const CommandLine& parsed_command_line) {
[email protected]0fd23af2011-02-20 06:33:04228 DCHECK(base::win::GetVersion() >= base::win::VERSION_VISTA);
229 base::ScopedNativeLibrary library(FilePath(L"kernel32.dll"));
230 // Get the function pointer for RegisterApplicationRestart.
[email protected]a08ba822011-02-20 07:45:47231 RegisterApplicationRestartProc register_application_restart =
232 static_cast<RegisterApplicationRestartProc>(
233 library.GetFunctionPointer("RegisterApplicationRestart"));
[email protected]7b672752011-07-07 06:39:15234 if (!register_application_restart) {
235 LOG(WARNING) << "Cannot find RegisterApplicationRestart in kernel32.dll";
236 return;
237 }
[email protected]0fd23af2011-02-20 06:33:04238 // The Windows Restart Manager expects a string of command line flags only,
239 // without the program.
240 CommandLine command_line(CommandLine::NO_PROGRAM);
[email protected]a40ca4302011-05-14 01:10:24241 command_line.AppendArguments(parsed_command_line, false);
[email protected]0fd23af2011-02-20 06:33:04242 if (!command_line.HasSwitch(switches::kRestoreLastSession))
243 command_line.AppendSwitch(switches::kRestoreLastSession);
[email protected]0fd23af2011-02-20 06:33:04244
245 // Restart Chrome if the computer is restarted as the result of an update.
246 // This could be extended to handle crashes, hangs, and patches.
[email protected]9dc12406b2011-03-03 15:50:30247 HRESULT hr = register_application_restart(
[email protected]61a4c6f2011-07-20 04:54:52248 command_line.GetCommandLineString().c_str(),
[email protected]0fd23af2011-02-20 06:33:04249 RESTART_NO_CRASH | RESTART_NO_HANG | RESTART_NO_PATCH);
[email protected]ffd31712012-03-10 18:38:14250 if (FAILED(hr)) {
[email protected]e85646a12012-03-10 20:01:13251 if (hr == E_INVALIDARG) {
252 LOG(WARNING) << "Command line too long for RegisterApplicationRestart";
253 } else {
254 NOTREACHED() << "RegisterApplicationRestart failed. hr: " << hr <<
255 ", command_line: " << command_line.GetCommandLineString();
256 }
[email protected]ffd31712012-03-10 18:38:14257 }
[email protected]0fd23af2011-02-20 06:33:04258}
259
[email protected]b48c9182011-10-26 18:03:30260void ChromeBrowserMainPartsWin::ShowMissingLocaleMessageBox() {
261 ui::MessageBox(NULL, ASCIIToUTF16(chrome_browser::kMissingLocaleDataMessage),
262 ASCIIToUTF16(chrome_browser::kMissingLocaleDataTitle),
263 MB_OK | MB_ICONERROR | MB_TOPMOST);
264}
265
266// static
267int ChromeBrowserMainPartsWin::HandleIconsCommands(
268 const CommandLine& parsed_command_line) {
[email protected]5c9587c2008-12-09 21:20:16269 if (parsed_command_line.HasSwitch(switches::kHideIcons)) {
[email protected]0f26d7b2011-01-05 19:10:44270 string16 cp_applet;
[email protected]935aa542010-10-15 01:59:15271 base::win::Version version = base::win::GetVersion();
272 if (version >= base::win::VERSION_VISTA) {
[email protected]5c9587c2008-12-09 21:20:16273 cp_applet.assign(L"Programs and Features"); // Windows Vista and later.
[email protected]935aa542010-10-15 01:59:15274 } else if (version >= base::win::VERSION_XP) {
[email protected]5c9587c2008-12-09 21:20:16275 cp_applet.assign(L"Add/Remove Programs"); // Windows XP.
276 } else {
[email protected]1fcfb202011-07-19 19:53:14277 return chrome::RESULT_CODE_UNSUPPORTED_PARAM; // Not supported
[email protected]5c9587c2008-12-09 21:20:16278 }
279
[email protected]0f26d7b2011-01-05 19:10:44280 const string16 msg =
281 l10n_util::GetStringFUTF16(IDS_HIDE_ICONS_NOT_SUPPORTED, cp_applet);
282 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
[email protected]5c9587c2008-12-09 21:20:16283 const UINT flags = MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST;
[email protected]75b68052011-02-03 06:01:16284 if (IDOK == ui::MessageBox(NULL, msg, caption, flags))
[email protected]5c9587c2008-12-09 21:20:16285 ShellExecute(NULL, NULL, L"appwiz.cpl", NULL, NULL, SW_SHOWNORMAL);
[email protected]1fcfb202011-07-19 19:53:14286
287 // Exit as we are not launching the browser.
288 return content::RESULT_CODE_NORMAL_EXIT;
[email protected]5c9587c2008-12-09 21:20:16289 }
290 // We don't hide icons so we shouldn't do anything special to show them
[email protected]1fcfb202011-07-19 19:53:14291 return chrome::RESULT_CODE_UNSUPPORTED_PARAM;
[email protected]5c9587c2008-12-09 21:20:16292}
293
[email protected]b48c9182011-10-26 18:03:30294// static
295bool ChromeBrowserMainPartsWin::CheckMachineLevelInstall() {
[email protected]bf6117c7e2010-12-01 06:00:25296 // TODO(tommi): Check if using the default distribution is always the right
297 // thing to do.
298 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
[email protected]1db1b492010-12-16 19:03:37299 scoped_ptr<Version> version(InstallUtil::GetChromeVersion(dist, true));
[email protected]5c9587c2008-12-09 21:20:16300 if (version.get()) {
[email protected]b9696482010-11-30 23:56:18301 FilePath exe_path;
302 PathService::Get(base::DIR_EXE, &exe_path);
303 std::wstring exe = exe_path.value();
[email protected]bf6117c7e2010-12-01 06:00:25304 FilePath user_exe_path(installer::GetChromeInstallPath(false, dist));
305 if (FilePath::CompareEqualIgnoreCase(exe, user_exe_path.value())) {
[email protected]0f26d7b2011-01-05 19:10:44306 const string16 text =
307 l10n_util::GetStringUTF16(IDS_MACHINE_LEVEL_INSTALL_CONFLICT);
308 const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
[email protected]5c9587c2008-12-09 21:20:16309 const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST;
[email protected]75b68052011-02-03 06:01:16310 ui::MessageBox(NULL, text, caption, flags);
[email protected]e5fbd4962011-02-11 16:30:43311 CommandLine uninstall_cmd(
312 InstallUtil::GetChromeUninstallCmd(false, dist->GetType()));
313 if (!uninstall_cmd.GetProgram().empty()) {
[email protected]74ca0442010-12-15 14:44:50314 uninstall_cmd.AppendSwitch(installer::switches::kForceUninstall);
[email protected]e6124ad52010-11-15 04:17:52315 uninstall_cmd.AppendSwitch(
[email protected]74ca0442010-12-15 14:44:50316 installer::switches::kDoNotRemoveSharedItems);
[email protected]e5992182011-07-15 16:47:02317 base::LaunchProcess(uninstall_cmd, base::LaunchOptions(), NULL);
[email protected]5c9587c2008-12-09 21:20:16318 }
319 return true;
320 }
321 }
322 return false;
323}