Extract SIGPIPE ignoring code to a common place.
[chromium-blink-merge.git] / chrome / installer / launcher_support / chrome_launcher_support.cc
blobd6ec9d65cfd9b5e88b4e91921cc64a78063bfa1b
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.
5 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
7 #include <windows.h>
8 #include <tchar.h>
10 #include "base/command_line.h"
11 #include "base/file_path.h"
12 #include "base/file_util.h"
13 #include "base/logging.h"
14 #include "base/string16.h"
15 #include "base/win/registry.h"
17 #ifndef OFFICIAL_BUILD
18 #include "base/path_service.h"
19 #endif
21 namespace chrome_launcher_support {
23 namespace {
25 // TODO(huangs) Refactor the constants: http://crbug.com/148538
26 const wchar_t kGoogleRegClientStateKey[] =
27 L"Software\\Google\\Update\\ClientState";
29 // Copied from binaries_installer_internal.cc
30 const wchar_t kAppHostAppId[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}";
32 // Copied from chrome_appid.cc.
33 const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
35 // Copied from google_chrome_distribution.cc.
36 const wchar_t kBrowserAppGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
38 // Copied from util_constants.cc.
39 const wchar_t kChromeAppHostExe[] = L"app_host.exe";
40 const char kChromeAppLauncher[] = "app-launcher";
41 const wchar_t kChromeExe[] = L"chrome.exe";
42 const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
43 const wchar_t kUninstallStringField[] = L"UninstallString";
45 #ifndef OFFICIAL_BUILD
46 FilePath GetDevelopmentExe(const wchar_t* exe_file) {
47 FilePath current_directory;
48 if (PathService::Get(base::DIR_EXE, &current_directory)) {
49 FilePath chrome_exe_path(current_directory.Append(exe_file));
50 if (file_util::PathExists(chrome_exe_path))
51 return chrome_exe_path;
53 return FilePath();
55 #endif
57 // Reads a string value from the specified product's "ClientState" registry key.
58 // Returns true iff the value is present and successfully read.
59 bool GetClientStateValue(InstallationLevel level,
60 const wchar_t* app_guid,
61 const wchar_t* value_name,
62 string16* value) {
63 HKEY root_key = (level == USER_LEVEL_INSTALLATION) ?
64 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
65 string16 subkey(kGoogleRegClientStateKey);
66 subkey.append(1, L'\\').append(app_guid);
67 base::win::RegKey reg_key;
68 if (reg_key.Open(root_key, subkey.c_str(),
69 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
70 if (reg_key.ReadValue(value_name, value) == ERROR_SUCCESS) {
71 return true;
74 return false;
77 bool IsAppLauncherEnabledAtLevel(InstallationLevel level) {
78 string16 uninstall_arguments;
79 if (GetClientStateValue(level,
80 kAppHostAppId,
81 kUninstallArgumentsField,
82 &uninstall_arguments)) {
83 return CommandLine::FromString(L"dummy.exe " + uninstall_arguments)
84 .HasSwitch(kChromeAppLauncher) &&
85 !GetAppHostPathForInstallationLevel(level).empty();
87 return false;
90 // Reads the path to setup.exe from the value "UninstallString" within the
91 // specified product's "ClientState" registry key. Returns an empty FilePath if
92 // an error occurs or the product is not installed at the specified level.
93 FilePath GetSetupExeFromRegistry(InstallationLevel level,
94 const wchar_t* app_guid) {
95 string16 uninstall;
96 if (GetClientStateValue(level, app_guid, kUninstallStringField, &uninstall)) {
97 FilePath setup_exe_path(uninstall);
98 if (file_util::PathExists(setup_exe_path))
99 return setup_exe_path;
101 return FilePath();
104 // Returns the path to an installed |exe_file| (e.g. chrome.exe, app_host.exe)
105 // at the specified level, given |setup_exe_path| from Omaha client state.
106 // Returns empty FilePath if none found, or if |setup_exe_path| is empty.
107 FilePath FindExeRelativeToSetupExe(const FilePath setup_exe_path,
108 const wchar_t* exe_file) {
109 if (!setup_exe_path.empty()) {
110 // The uninstall path contains the path to setup.exe, which is two levels
111 // down from |exe_file|. Move up two levels (plus one to drop the file
112 // name) and look for chrome.exe from there.
113 FilePath exe_path(
114 setup_exe_path.DirName().DirName().DirName().Append(exe_file));
115 if (file_util::PathExists(exe_path))
116 return exe_path;
117 // By way of mild future proofing, look up one to see if there's a
118 // |exe_file| in the version directory
119 exe_path = setup_exe_path.DirName().DirName().Append(exe_file);
120 if (file_util::PathExists(exe_path))
121 return exe_path;
123 return FilePath();
126 } // namespace
128 FilePath GetSetupExeForInstallationLevel(InstallationLevel level) {
129 // Look in the registry for Chrome Binaries first.
130 FilePath setup_exe_path(GetSetupExeFromRegistry(level, kBinariesAppGuid));
131 // If the above fails, look in the registry for Chrome next.
132 if (setup_exe_path.empty())
133 setup_exe_path = GetSetupExeFromRegistry(level, kBrowserAppGuid);
134 // If we fail again, then setup_exe_path would be empty.
135 return setup_exe_path;
138 FilePath GetChromePathForInstallationLevel(InstallationLevel level) {
139 return FindExeRelativeToSetupExe(
140 GetSetupExeForInstallationLevel(level), kChromeExe);
143 FilePath GetAppHostPathForInstallationLevel(InstallationLevel level) {
144 return FindExeRelativeToSetupExe(
145 GetSetupExeFromRegistry(level, kAppHostAppId), kChromeAppHostExe);
148 FilePath GetAnyChromePath() {
149 FilePath chrome_path;
150 #ifndef OFFICIAL_BUILD
151 // For development mode, chrome.exe should be in same dir as the stub.
152 chrome_path = GetDevelopmentExe(kChromeExe);
153 #endif
154 if (chrome_path.empty())
155 chrome_path = GetChromePathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION);
156 if (chrome_path.empty())
157 chrome_path = GetChromePathForInstallationLevel(USER_LEVEL_INSTALLATION);
158 return chrome_path;
161 FilePath GetAnyAppHostPath() {
162 FilePath app_host_path;
163 #ifndef OFFICIAL_BUILD
164 // For development mode, app_host.exe should be in same dir as chrome.exe.
165 app_host_path = GetDevelopmentExe(kChromeAppHostExe);
166 #endif
167 if (app_host_path.empty()) {
168 app_host_path = GetAppHostPathForInstallationLevel(
169 SYSTEM_LEVEL_INSTALLATION);
171 if (app_host_path.empty())
172 app_host_path = GetAppHostPathForInstallationLevel(USER_LEVEL_INSTALLATION);
173 return app_host_path;
176 bool IsAppHostPresent() {
177 FilePath app_host_exe = GetAnyAppHostPath();
178 return !app_host_exe.empty();
181 bool IsAppLauncherPresent() {
182 return IsAppLauncherEnabledAtLevel(USER_LEVEL_INSTALLATION) ||
183 IsAppLauncherEnabledAtLevel(SYSTEM_LEVEL_INSTALLATION);
186 } // namespace chrome_launcher_support