Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome_elf / chrome_elf_util.cc
1 // Copyright 2014 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_elf/chrome_elf_util.h"
6
7 #include <windows.h>
8
9 #include "base/macros.h"
10 #include "base/strings/string16.h"
11
12 namespace {
13
14 const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState";
15 const wchar_t kRegPathClientStateMedium[] =
16     L"Software\\Google\\Update\\ClientStateMedium";
17 #if defined(GOOGLE_CHROME_BUILD)
18 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome";
19 #else
20 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Chromium";
21 #endif  // defined(GOOGLE_CHROME_BUILD)
22
23 const wchar_t kRegValueUsageStats[] = L"usagestats";
24 const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
25 const wchar_t kMetricsReportingEnabled[] =L"MetricsReportingEnabled";
26
27 const wchar_t kAppGuidCanary[] =
28     L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
29 const wchar_t kAppGuidGoogleChrome[] =
30     L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
31 const wchar_t kAppGuidGoogleBinaries[] =
32     L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
33
34 bool ReadKeyValueString(bool system_install, const wchar_t* key_path,
35                         const wchar_t* guid, const wchar_t* value_to_read,
36                         base::string16* value_out) {
37   HKEY key = NULL;
38   value_out->clear();
39
40   base::string16 full_key_path(key_path);
41   full_key_path.append(1, L'\\');
42   full_key_path.append(guid);
43
44   if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
45                      full_key_path.c_str(), 0,
46                      KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) !=
47                      ERROR_SUCCESS) {
48     return false;
49   }
50
51   const size_t kMaxStringLength = 1024;
52   wchar_t raw_value[kMaxStringLength] = {};
53   DWORD size = sizeof(raw_value);
54   DWORD type = REG_SZ;
55   LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type,
56                                   reinterpret_cast<LPBYTE>(raw_value), &size);
57
58   if (result == ERROR_SUCCESS) {
59     if (type != REG_SZ || (size & 1) != 0) {
60       result = ERROR_NOT_SUPPORTED;
61     } else if (size == 0) {
62       *raw_value = L'\0';
63     } else if (raw_value[size / sizeof(wchar_t) - 1] != L'\0') {
64       if ((size / sizeof(wchar_t)) < kMaxStringLength)
65         raw_value[size / sizeof(wchar_t)] = L'\0';
66       else
67         result = ERROR_MORE_DATA;
68     }
69   }
70
71   if (result == ERROR_SUCCESS)
72     *value_out = raw_value;
73
74   ::RegCloseKey(key);
75
76   return result == ERROR_SUCCESS;
77 }
78
79 bool ReadKeyValueDW(bool system_install, const wchar_t* key_path,
80                     base::string16 guid, const wchar_t* value_to_read,
81                     DWORD* value_out) {
82   HKEY key = NULL;
83   *value_out = 0;
84
85   base::string16 full_key_path(key_path);
86   full_key_path.append(1, L'\\');
87   full_key_path.append(guid);
88
89   if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
90                      full_key_path.c_str(), 0,
91                      KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) !=
92                      ERROR_SUCCESS) {
93     return false;
94   }
95
96   DWORD size = sizeof(*value_out);
97   DWORD type = REG_DWORD;
98   LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type,
99                                   reinterpret_cast<BYTE*>(value_out), &size);
100
101   ::RegCloseKey(key);
102
103   return result == ERROR_SUCCESS && size == sizeof(*value_out);
104 }
105
106 }  // namespace
107
108 bool IsCanary(const wchar_t* exe_path) {
109   return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL;
110 }
111
112 bool IsSystemInstall(const wchar_t* exe_path) {
113   wchar_t program_dir[MAX_PATH] = {};
114   DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir,
115                                        arraysize(program_dir));
116   if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret))
117     return true;
118
119   ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir,
120                                  arraysize(program_dir));
121   if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret))
122     return true;
123
124   return false;
125 }
126
127 bool IsMultiInstall(bool is_system_install) {
128   base::string16 args;
129   if (!ReadKeyValueString(is_system_install, kRegPathClientState,
130                           kAppGuidGoogleChrome, kUninstallArgumentsField,
131                           &args)) {
132     return false;
133   }
134   return args.find(L"--multi-install") != base::string16::npos;
135 }
136
137 bool AreUsageStatsEnabled(const wchar_t* exe_path) {
138   bool enabled = true;
139   bool controlled_by_policy = ReportingIsEnforcedByPolicy(&enabled);
140
141   if (controlled_by_policy && !enabled)
142     return false;
143
144   bool system_install = IsSystemInstall(exe_path);
145   base::string16 app_guid;
146
147   if (IsCanary(exe_path)) {
148     app_guid = kAppGuidCanary;
149   } else {
150     app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries :
151                                                 kAppGuidGoogleChrome;
152   }
153
154   DWORD out_value = 0;
155   if (system_install &&
156       ReadKeyValueDW(system_install, kRegPathClientStateMedium, app_guid,
157                      kRegValueUsageStats, &out_value)) {
158     return out_value == 1;
159   }
160
161   return ReadKeyValueDW(system_install, kRegPathClientState, app_guid,
162                         kRegValueUsageStats, &out_value) && out_value == 1;
163 }
164
165 bool ReportingIsEnforcedByPolicy(bool* breakpad_enabled) {
166   HKEY key = NULL;
167   DWORD value = 0;
168   BYTE* value_bytes = reinterpret_cast<BYTE*>(&value);
169   DWORD size = sizeof(value);
170   DWORD type = REG_DWORD;
171
172   if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kRegPathChromePolicy, 0,
173                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
174     if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type,
175                           value_bytes, &size) == ERROR_SUCCESS) {
176       *breakpad_enabled = value != 0;
177     }
178     ::RegCloseKey(key);
179     return size == sizeof(value);
180   }
181
182   if (::RegOpenKeyEx(HKEY_CURRENT_USER, kRegPathChromePolicy, 0,
183                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
184     if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type,
185                           value_bytes, &size) == ERROR_SUCCESS) {
186       *breakpad_enabled = value != 0;
187     }
188     ::RegCloseKey(key);
189     return size == sizeof(value);
190   }
191
192   return false;
193 }
194
195 bool IsNonBrowserProcess() {
196   typedef bool (*IsSandboxedProcessFunc)();
197   IsSandboxedProcessFunc is_sandboxed_process_func =
198       reinterpret_cast<IsSandboxedProcessFunc>(
199           GetProcAddress(GetModuleHandle(NULL), "IsSandboxedProcess"));
200   bool is_sandboxed_process =
201       is_sandboxed_process_func && is_sandboxed_process_func();
202
203   // TODO(robertshield): Drop the command line check when we drop support for
204   // enabling chrome_elf in unsandboxed processes.
205   wchar_t* command_line = GetCommandLine();
206   bool has_process_type_flag = command_line && wcsstr(command_line, L"--type");
207
208   return (has_process_type_flag || is_sandboxed_process);
209 }