chrome_launcher_support.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 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/installer/launcher_support/chrome_launcher_support.h" 6 7#include <windows.h> 8#include <tchar.h> 9#include "base/file_path.h" 10#include "base/file_util.h" 11#include "base/logging.h" 12#include "base/string16.h" 13#include "base/win/registry.h" 14 15#ifndef OFFICIAL_BUILD 16#include "base/path_service.h" 17#endif 18 19namespace chrome_launcher_support { 20 21namespace { 22 23// TODO(huangs) Refactor the constants: http://crbug.com/148538 24const wchar_t kGoogleRegClientStateKey[] = 25 L"Software\\Google\\Update\\ClientState"; 26 27// Copied from binaries_installer_internal.cc 28const wchar_t kAppHostAppId[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}"; 29 30// Copied from chrome_appid.cc. 31const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; 32 33// Copied from google_chrome_distribution.cc. 34const wchar_t kBrowserAppGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 35 36// Copied from util_constants.cc. 37const wchar_t kChromeAppHostExe[] = L"app_host.exe"; 38const wchar_t kChromeExe[] = L"chrome.exe"; 39const wchar_t kUninstallStringField[] = L"UninstallString"; 40 41#ifndef OFFICIAL_BUILD 42FilePath GetDevelopmentExe(const wchar_t* exe_file) { 43 FilePath current_directory; 44 if (PathService::Get(base::DIR_EXE, ¤t_directory)) { 45 FilePath chrome_exe_path(current_directory.Append(exe_file)); 46 if (file_util::PathExists(chrome_exe_path)) 47 return chrome_exe_path; 48 } 49 return FilePath(); 50} 51#endif 52 53// Reads the path to setup.exe from the value "UninstallString" within the 54// specified product's "ClientState" registry key. Returns an empty FilePath if 55// an error occurs or the product is not installed at the specified level. 56FilePath GetSetupExeFromRegistry(InstallationLevel level, 57 const wchar_t* app_guid) { 58 HKEY root_key = (level == USER_LEVEL_INSTALLATION) ? 59 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 60 string16 subkey(kGoogleRegClientStateKey); 61 subkey.append(1, L'\\').append(app_guid); 62 base::win::RegKey reg_key; 63 if (reg_key.Open(root_key, subkey.c_str(), 64 KEY_QUERY_VALUE) == ERROR_SUCCESS) { 65 string16 uninstall; 66 if (reg_key.ReadValue(kUninstallStringField, &uninstall) == ERROR_SUCCESS) { 67 FilePath setup_exe_path(uninstall); 68 if (file_util::PathExists(setup_exe_path)) 69 return setup_exe_path; 70 } 71 } 72 return FilePath(); 73} 74 75// Returns the path to an installed |exe_file| (e.g. chrome.exe, app_host.exe) 76// at the specified level, given |setup_exe_path| from Omaha client state. 77// Returns empty FilePath if none found, or if |setup_exe_path| is empty. 78FilePath FindExeRelativeToSetupExe(const FilePath setup_exe_path, 79 const wchar_t* exe_file) { 80 if (!setup_exe_path.empty()) { 81 // The uninstall path contains the path to setup.exe, which is two levels 82 // down from |exe_file|. Move up two levels (plus one to drop the file 83 // name) and look for chrome.exe from there. 84 FilePath exe_path( 85 setup_exe_path.DirName().DirName().DirName().Append(exe_file)); 86 if (file_util::PathExists(exe_path)) 87 return exe_path; 88 // By way of mild future proofing, look up one to see if there's a 89 // |exe_file| in the version directory 90 exe_path = setup_exe_path.DirName().DirName().Append(exe_file); 91 if (file_util::PathExists(exe_path)) 92 return exe_path; 93 } 94 return FilePath(); 95} 96 97} // namespace 98 99FilePath GetSetupExeForInstallationLevel(InstallationLevel level) { 100 // Look in the registry for Chrome Binaries first. 101 FilePath setup_exe_path(GetSetupExeFromRegistry(level, kBinariesAppGuid)); 102 // If the above fails, look in the registry for Chrome next. 103 if (setup_exe_path.empty()) 104 setup_exe_path = GetSetupExeFromRegistry(level, kBrowserAppGuid); 105 // If we fail again, then setup_exe_path would be empty. 106 return setup_exe_path; 107} 108 109FilePath GetChromePathForInstallationLevel(InstallationLevel level) { 110 return FindExeRelativeToSetupExe( 111 GetSetupExeForInstallationLevel(level), kChromeExe); 112} 113 114FilePath GetAppHostPathForInstallationLevel(InstallationLevel level) { 115 return FindExeRelativeToSetupExe( 116 GetSetupExeFromRegistry(level, kAppHostAppId), kChromeAppHostExe); 117} 118 119FilePath GetAnyChromePath() { 120 FilePath chrome_path; 121#ifndef OFFICIAL_BUILD 122 // For development mode, chrome.exe should be in same dir as the stub. 123 chrome_path = GetDevelopmentExe(kChromeExe); 124#endif 125 if (chrome_path.empty()) 126 chrome_path = GetChromePathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION); 127 if (chrome_path.empty()) 128 chrome_path = GetChromePathForInstallationLevel(USER_LEVEL_INSTALLATION); 129 return chrome_path; 130} 131 132FilePath GetAnyAppHostPath() { 133 FilePath app_host_path; 134#ifndef OFFICIAL_BUILD 135 // For development mode, app_host.exe should be in same dir as chrome.exe. 136 app_host_path = GetDevelopmentExe(kChromeAppHostExe); 137#endif 138 if (app_host_path.empty()) { 139 app_host_path = GetAppHostPathForInstallationLevel( 140 SYSTEM_LEVEL_INSTALLATION); 141 } 142 if (app_host_path.empty()) 143 app_host_path = GetAppHostPathForInstallationLevel(USER_LEVEL_INSTALLATION); 144 return app_host_path; 145} 146 147bool IsAppHostPresent() { 148 FilePath app_host_exe = GetAnyAppHostPath(); 149 return !app_host_exe.empty(); 150} 151 152} // namespace chrome_launcher_support 153