15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/first_run/upgrade_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <psapi.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/prefs/pref_service.h" 22bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h" 23bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process_handle.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/metro.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/browser_process.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/first_run/upgrade_util_win.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/shell_integration.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/pref_names.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/browser_distribution.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_constants.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/install_util.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/shell_util.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/util_constants.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_update/google_update_idl.h" 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/ui_base_switches.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetNewerChromeFile(base::FilePath* path) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::DIR_EXE, path)) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *path = path->Append(installer::kChromeNewExe); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InvokeGoogleUpdateForRename() { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IProcessLauncher> ipl; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FAILED(ipl.CreateInstance(__uuidof(ProcessLauncherClass)))) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG_PTR phandle = NULL; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD id = GetCurrentProcessId(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FAILED(ipl->LaunchCmdElevated(dist->GetAppGuid().c_str(), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) google_update::kRegRenameCmdField, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &phandle))) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE handle = HANDLE(phandle); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitForSingleObject(handle, INFINITE); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD exit_code; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetExitCodeProcess(handle, &exit_code); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(handle); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code == installer::RENAME_SUCCESSFUL) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetMetroRelauncherPath(const base::FilePath& chrome_exe, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& version_str) { 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path(chrome_exe.DirName()); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The relauncher is ordinarily in the version directory. When running in a 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // build tree however (where CHROME_VERSION is not set in the environment) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // look for it in Chrome's directory. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!version_str.empty()) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path = path.AppendASCII(version_str); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path.Append(installer::kDelegateExecuteExe); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace upgrade_util { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)const char kRelaunchModeMetro[] = "relaunch.mode.metro"; 940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)const char kRelaunchModeDesktop[] = "relaunch.mode.desktop"; 950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)const char kRelaunchModeDefault[] = "relaunch.mode.default"; 960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// TODO(shrikant): Have a map/array to quickly map enum to strings. 980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)std::string RelaunchModeEnumToString(const RelaunchMode relaunch_mode) { 990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (relaunch_mode == RELAUNCH_MODE_METRO) 1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return kRelaunchModeMetro; 1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (relaunch_mode == RELAUNCH_MODE_DESKTOP) 1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return kRelaunchModeDesktop; 1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // For the purpose of code flow, even in case of wrong value we will 1060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // return default re-launch mode. 1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return kRelaunchModeDefault; 1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)RelaunchMode RelaunchModeStringToEnum(const std::string& relaunch_mode) { 1110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (relaunch_mode == kRelaunchModeMetro) 1120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return RELAUNCH_MODE_METRO; 1130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (relaunch_mode == kRelaunchModeDesktop) 1150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return RELAUNCH_MODE_DESKTOP; 1160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // On Windows 7 if the current browser is in Chrome OS mode, then restart 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // into Chrome OS mode. 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((base::win::GetVersion() == base::win::VERSION_WIN7) && 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CommandLine::ForCurrentProcess()->HasSwitch(switches::kViewerConnect) && 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_browser_process->local_state()->HasPrefPath(prefs::kRelaunchMode)) { 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(ananta) 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // On Windows 8, the delegate execute process looks up the previously 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // launched mode from the registry and relaunches into that mode. We need 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // something similar on Windows 7. For now, set the pref to ensure that 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // we get relaunched into Chrome OS mode. 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_browser_process->local_state()->SetString( 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prefs::kRelaunchMode, upgrade_util::kRelaunchModeMetro); 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return RELAUNCH_MODE_METRO; 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return RELAUNCH_MODE_DEFAULT; 1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool RelaunchChromeHelper(const CommandLine& command_line, 1360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const RelaunchMode& relaunch_mode) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Environment> env(base::Environment::Create()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string version_str; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the version variable and remove it from the environment. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (env->GetVar(chrome::kChromeVersionEnvVar, &version_str)) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env->UnSetVar(chrome::kChromeVersionEnvVar); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_str.clear(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Explicitly make sure to relaunch chrome.exe rather than old_chrome.exe. 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This can happen when old_chrome.exe is launched by a user. 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CommandLine chrome_exe_command_line = command_line; 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome_exe_command_line.SetProgram( 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome_exe.DirName().Append(installer::kChromeExe)); 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (base::win::GetVersion() < base::win::VERSION_WIN8 && 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci relaunch_mode != RELAUNCH_MODE_METRO && 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci relaunch_mode != RELAUNCH_MODE_DESKTOP) 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return base::LaunchProcess(chrome_exe_command_line, 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::LaunchOptions(), NULL); 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // On Windows 8 we always use the delegate_execute for re-launching chrome. 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // On Windows 7 we use delegate_execute for re-launching chrome into Windows 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ASH. 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Pass this Chrome's Start Menu shortcut path to the relauncher so it can re- 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // activate chrome via ShellExecute which will wait until we exit. Since 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ShellExecute does not support handle passing to the child process we create 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // a uniquely named mutex that we aquire and never release. So when we exit, 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Windows marks our mutex as abandoned and the wait is satisfied. The format 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // of the named mutex is important. See DelegateExecuteOperation for more 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // details. 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 mutex_name = 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf(L"chrome.relaunch.%d", ::GetCurrentProcessId()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE mutex = ::CreateMutexW(NULL, TRUE, mutex_name.c_str()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |mutex| handle needs to be leaked. See comment above. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!mutex) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::GetLastError() == ERROR_ALREADY_EXISTS) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Relaunch mutex already exists"; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine relaunch_cmd(CommandLine::NO_PROGRAM); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relaunch_cmd.AppendSwitchPath(switches::kRelaunchShortcut, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellIntegration::GetStartMenuShortcut(chrome_exe)); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relaunch_cmd.AppendSwitchNative(switches::kWaitForMutex, mutex_name); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (relaunch_mode != RELAUNCH_MODE_DEFAULT) { 1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) relaunch_cmd.AppendSwitch(relaunch_mode == RELAUNCH_MODE_METRO? 1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) switches::kForceImmersive : switches::kForceDesktop); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 params(relaunch_cmd.GetCommandLineString()); 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 path(GetMetroRelauncherPath(chrome_exe, version_str).value()); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHELLEXECUTEINFO sei = { sizeof(sei) }; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.fMask = SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_NOCLOSEPROCESS; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.nShow = SW_SHOWNORMAL; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.lpFile = path.c_str(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.lpParameters = params.c_str(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ShellExecuteExW(&sei)) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "ShellExecute failed with " << GetLastError(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD pid = ::GetProcessId(sei.hProcess); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(sei.hProcess); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pid) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The next call appears to be needed if we are relaunching from desktop into 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // metro mode. The observed effect if not done is that chrome starts in metro 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mode but it is not given focus and it gets killed by windows after a few 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // seconds. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::AllowSetForegroundWindow(pid); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RelaunchChromeBrowser(const CommandLine& command_line) { 2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return RelaunchChromeHelper(command_line, RELAUNCH_MODE_DEFAULT); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool RelaunchChromeWithMode(const CommandLine& command_line, 2280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const RelaunchMode& relaunch_mode) { 2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return RelaunchChromeHelper(command_line, relaunch_mode); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsUpdatePendingRestart() { 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath new_chrome_exe; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetNewerChromeFile(&new_chrome_exe)) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return base::PathExists(new_chrome_exe); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SwapNewChromeExeIfPresent() { 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath new_chrome_exe; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetNewerChromeFile(&new_chrome_exe)) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(new_chrome_exe)) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath cur_chrome_exe; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &cur_chrome_exe)) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open up the registry key containing current version and rename information. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool user_install = 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallUtil::IsPerUserInstall(cur_chrome_exe.value().c_str()); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY reg_root = user_install ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution *dist = BrowserDistribution::GetDistribution(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::RegKey key; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key.Open(reg_root, dist->GetVersionKey().c_str(), 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_QUERY_VALUE) == ERROR_SUCCESS) { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First try to rename exe by launching rename command ourselves. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring rename_cmd; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key.ReadValue(google_update::kRegRenameCmdField, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &rename_cmd) == ERROR_SUCCESS) { 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::win::ScopedHandle handle; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.wait = true; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.start_hidden = true; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::LaunchProcess(rename_cmd, options, &handle)) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD exit_code; 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ::GetExitCodeProcess(handle.Get(), &exit_code); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code == installer::RENAME_SUCCESSFUL) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rename didn't work so try to rename by calling Google Update 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InvokeGoogleUpdateForRename(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsRunningOldChrome() { 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This figures out the actual file name that the section containing the 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // mapped exe refers to. This is used instead of GetModuleFileName because the 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // .exe may have been renamed out from under us while we've been running which 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // GetModuleFileName won't notice. 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) wchar_t mapped_file_name[MAX_PATH * 2] = {}; 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!::GetMappedFileName(::GetCurrentProcess(), 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<void*>(::GetModuleHandle(NULL)), 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mapped_file_name, 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) arraysize(mapped_file_name))) { 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath file_name(base::FilePath(mapped_file_name).BaseName()); 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return base::FilePath::CompareEqualIgnoreCase(file_name.value(), 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) installer::kChromeOldExe); 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoUpgradeTasks(const CommandLine& command_line) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The DelegateExecute verb handler finalizes pending in-use updates for 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // metro mode launches, as Chrome cannot be gracefully relaunched when 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // running in this mode. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::IsMetroProcess()) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!SwapNewChromeExeIfPresent() && !IsRunningOldChrome()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At this point the chrome.exe has been swapped with the new one. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RelaunchChromeBrowser(command_line)) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The re-launch fails. Feel free to panic now. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace upgrade_util 314