Chromium Code Reviews| Index: chrome/browser/first_run/upgrade_util_win.cc |
| =================================================================== |
| --- chrome/browser/first_run/upgrade_util_win.cc (revision 153562) |
| +++ chrome/browser/first_run/upgrade_util_win.cc (working copy) |
| @@ -17,9 +17,11 @@ |
| #include "base/process_util.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| +#include "base/stringprintf.h" |
| #include "base/win/metro.h" |
| #include "base/win/registry.h" |
| #include "base/win/scoped_comptr.h" |
| +#include "base/win/windows_version.h" |
| #include "chrome/browser/first_run/upgrade_util_win.h" |
| #include "chrome/browser/shell_integration.h" |
| #include "chrome/common/chrome_constants.h" |
| @@ -79,19 +81,20 @@ |
| namespace upgrade_util { |
| -bool RelaunchChromeBrowser(const CommandLine& command_line) { |
| +bool RelaunchChromehelper(const CommandLine& command_line, bool mode_switch) { |
| scoped_ptr<base::Environment> env(base::Environment::Create()); |
| std::string version_str; |
| - |
|
grt (UTC plus 2)
2012/09/05 01:40:51
this was my favorite blank line in all of chrome.
cpu_(ooo_6.6-7.5)
2012/09/05 22:20:07
My bad! done.
On 2012/09/05 01:40:51, grt wrote:
|
| // Get the version variable and remove it from the environment. |
| if (env->GetVar(chrome::kChromeVersionEnvVar, &version_str)) |
| env->UnSetVar(chrome::kChromeVersionEnvVar); |
| else |
| version_str.clear(); |
| - if (!base::win::IsMetroProcess()) |
| + if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| return base::LaunchProcess(command_line, base::LaunchOptions(), NULL); |
| + // On Windows 8 we always use the delegate_execute for re-launching chrome. |
| + // |
| // Pass this Chrome's Start Menu shortcut path and handle to the relauncher. |
|
grt (UTC plus 2)
2012/09/05 01:40:51
please update comment since a handle is no longer
cpu_(ooo_6.6-7.5)
2012/09/05 22:20:07
Done.
|
| // The relauncher will wait for this Chrome to exit then reactivate it by |
| // way of the Start Menu shortcut. |
| @@ -101,33 +104,68 @@ |
| return false; |
| } |
| - // Get a handle to this process that can be passed to the relauncher. |
| - HANDLE current_process = GetCurrentProcess(); |
| - base::win::ScopedHandle process_handle; |
| - if (!::DuplicateHandle(current_process, current_process, current_process, |
| - process_handle.Receive(), SYNCHRONIZE, TRUE, 0)) { |
| - DPCHECK(false); |
| + // We need to use ShellExecute to do the relaunch, but it does not support |
| + // handle inheritance so the relauncher can wait for our exit. So we create a |
|
grt (UTC plus 2)
2012/09/05 01:40:51
suggest changing " so the relauncher can wait for
cpu_(ooo_6.6-7.5)
2012/09/05 22:20:07
Done.
|
| + // uniquely named mutex that we aquire and never release. So when we exit, |
| + // windows marks our mutex as abandoned. |
| + string16 mutex_name = |
| + base::StringPrintf(L"chrome.relaunch.%d", ::GetCurrentProcessId()); |
| + HANDLE mutex = ::CreateMutexW(NULL, TRUE, mutex_name.c_str()); |
| + // The |mutex| handle needs to be leaked. See comment above. |
| + if (!mutex) { |
| + NOTREACHED(); |
| return false; |
| } |
| + if (::GetLastError() == ERROR_ALREADY_EXISTS) { |
| + NOTREACHED() << "Relaunch mutex already exists"; |
| + return false; |
| + } |
| - // Make the command line for the relauncher. |
| - CommandLine relaunch_cmd(GetMetroRelauncherPath(chrome_exe, version_str)); |
| + CommandLine relaunch_cmd(CommandLine::NO_PROGRAM); |
| relaunch_cmd.AppendSwitchPath(switches::kRelaunchShortcut, |
| ShellIntegration::GetStartMenuShortcut(chrome_exe)); |
| - relaunch_cmd.AppendSwitchNative(switches::kWaitForHandle, |
| - base::UintToString16(reinterpret_cast<uint32>(process_handle.Get()))); |
| + relaunch_cmd.AppendSwitchNative(switches::kWaitForMutex, mutex_name); |
| - base::LaunchOptions launch_options; |
| - launch_options.inherit_handles = true; |
| - if (!base::LaunchProcess(relaunch_cmd, launch_options, NULL)) { |
| - DPLOG(ERROR) << "Failed to launch relauncher \"" |
| - << relaunch_cmd.GetCommandLineString() << "\""; |
| + const char* flag; |
| + if (base::win::IsMetroProcess()) |
| + flag = mode_switch ? switches::kForceDesktop : switches::kForceImmersive; |
| + else |
| + flag = mode_switch ? switches::kForceImmersive : switches::kForceDesktop; |
| + relaunch_cmd.AppendSwitch(flag); |
| + |
| + string16 params(relaunch_cmd.GetCommandLineString()); |
| + string16 path(GetMetroRelauncherPath(chrome_exe, version_str).value()); |
| + |
| + SHELLEXECUTEINFO sei = { sizeof(sei) }; |
| + sei.fMask = SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_NOCLOSEPROCESS; |
| + sei.nShow = SW_SHOWNORMAL; |
| + sei.lpFile = path.c_str(); |
| + sei.lpParameters = params.c_str(); |
| + |
| + if (!::ShellExecuteExW(&sei)) { |
| + NOTREACHED() << "ShellExecute failed with " << GetLastError(); |
| return false; |
| } |
| - |
| + DWORD pid = ::GetProcessId(sei.hProcess); |
| + CloseHandle(sei.hProcess); |
| + if (!pid) |
| + return false; |
| + // The next call appears to be needed if we are relaunching from desktop into |
| + // metro mode. The observed effect if not done is that chrome starts in metro |
| + // mode but it is not given focus and it gets killed by windows after a few |
| + // seconds. |
| + ::AllowSetForegroundWindow(pid); |
| return true; |
| } |
| +bool RelaunchChromeBrowser(const CommandLine& command_line) { |
| + return RelaunchChromehelper(command_line, false); |
| +} |
| + |
| +bool RelaunchChromeWithModeSwitch(const CommandLine& command_line) { |
| + return RelaunchChromehelper(command_line, true); |
| +} |
| + |
| bool IsUpdatePendingRestart() { |
| FilePath new_chrome_exe; |
| if (!GetNewerChromeFile(&new_chrome_exe)) |