1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/first_run/upgrade_util.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <algorithm> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <string> 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_paths.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/command_line.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/environment.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_path.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_util.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/path_service.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/process_util.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/registry.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/scoped_comptr.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/first_run/upgrade_util_win.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/chrome_constants.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/installer/util/browser_distribution.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/installer/util/google_update_constants.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/installer/util/install_util.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/installer/util/shell_util.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/installer/util/util_constants.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "google_update_idl.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool GetNewerChromeFile(FilePath* path) { 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!PathService::Get(base::DIR_EXE, path)) 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *path = path->Append(installer::kChromeNewExe); 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool InvokeGoogleUpdateForRename() { 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<IProcessLauncher> ipl; 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!FAILED(ipl.CreateInstance(__uuidof(ProcessLauncherClass)))) { 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ULONG_PTR phandle = NULL; 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DWORD id = GetCurrentProcessId(); 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!FAILED(ipl->LaunchCmdElevated(dist->GetAppGuid().c_str(), 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen google_update::kRegRenameCmdField, 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen id, 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &phandle))) { 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HANDLE handle = HANDLE(phandle); 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitForSingleObject(handle, INFINITE); 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DWORD exit_code; 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ::GetExitCodeProcess(handle, &exit_code); 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ::CloseHandle(handle); 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (exit_code == installer::RENAME_SUCCESSFUL) 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace upgrade_util { 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool RelaunchChromeBrowser(const CommandLine& command_line) { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<base::Environment> env(base::Environment::Create()); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen env->UnSetVar(chrome::kChromeVersionEnvVar); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return base::LaunchApp( 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen command_line.command_line_string(), false, false, NULL); 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool IsUpdatePendingRestart() { 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath new_chrome_exe; 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!GetNewerChromeFile(&new_chrome_exe)) 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return file_util::PathExists(new_chrome_exe); 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SwapNewChromeExeIfPresent() { 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath new_chrome_exe; 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!GetNewerChromeFile(&new_chrome_exe)) 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!file_util::PathExists(new_chrome_exe)) 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath cur_chrome_exe; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!PathService::Get(base::FILE_EXE, &cur_chrome_exe)) 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // First try to rename exe by launching rename command ourselves. 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool user_install = 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InstallUtil::IsPerUserInstall(cur_chrome_exe.value().c_str()); 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HKEY reg_root = user_install ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserDistribution *dist = BrowserDistribution::GetDistribution(); 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::RegKey key; 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring rename_cmd; 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if ((key.Open(reg_root, dist->GetVersionKey().c_str(), 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen KEY_READ) == ERROR_SUCCESS) && 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (key.ReadValue(google_update::kRegRenameCmdField, 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &rename_cmd) == ERROR_SUCCESS)) { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ProcessHandle handle; 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (base::LaunchApp(rename_cmd, true, true, &handle)) { 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DWORD exit_code; 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ::GetExitCodeProcess(handle, &exit_code); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ::CloseHandle(handle); 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (exit_code == installer::RENAME_SUCCESSFUL) 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Rename didn't work so try to rename by calling Google Update 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return InvokeGoogleUpdateForRename(); 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DoUpgradeTasks(const CommandLine& command_line) { 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!SwapNewChromeExeIfPresent()) 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // At this point the chrome.exe has been swapped with the new one. 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!RelaunchChromeBrowser(command_line)) { 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The re-launch fails. Feel free to panic now. 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace upgrade_util 125