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