Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: common/app_registry_utils.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/app_registry_utils.h ('k') | common/app_registry_utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2010 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 #include "omaha/common/app_registry_utils.h"
17 #include "omaha/base/constants.h"
18 #include "omaha/base/debug.h"
19 #include "omaha/base/logging.h"
20 #include "omaha/base/reg_key.h"
21 #include "omaha/base/utils.h"
22 #include "omaha/common/config_manager.h"
23 #include "omaha/common/const_goopdate.h"
24 #include "omaha/common/experiment_labels.h"
25
26 namespace omaha {
27
28 namespace app_registry_utils {
29
30 CString GetAppClientsKey(bool is_machine, const CString& app_guid) {
31 return AppendRegKeyPath(
32 ConfigManager::Instance()->registry_clients(is_machine),
33 app_guid);
34 }
35
36 CString GetAppClientStateKey(bool is_machine, const CString& app_guid) {
37 return AppendRegKeyPath(
38 ConfigManager::Instance()->registry_client_state(is_machine),
39 app_guid);
40 }
41
42 CString GetAppClientStateMediumKey(bool is_machine, const CString& app_guid) {
43 ASSERT1(is_machine);
44 UNREFERENCED_PARAMETER(is_machine);
45 return AppendRegKeyPath(
46 ConfigManager::Instance()->machine_registry_client_state_medium(),
47 app_guid);
48 }
49
50 // The EULA is assumed to be accepted unless eualaccepted=0 in the ClientState
51 // key. For machine apps in this case, eulaccepted=1 in ClientStateMedium also
52 // indicates acceptance and the value in ClientState is updated.
53 bool IsAppEulaAccepted(bool is_machine,
54 const CString& app_guid,
55 bool require_explicit_acceptance) {
56 const CString state_key = GetAppClientStateKey(is_machine, app_guid);
57
58 DWORD eula_accepted = 0;
59 if (SUCCEEDED(RegKey::GetValue(state_key,
60 kRegValueEulaAccepted,
61 &eula_accepted))) {
62 if (0 != eula_accepted) {
63 return true;
64 }
65 } else {
66 if (!require_explicit_acceptance) {
67 return true;
68 }
69 }
70
71 if (!is_machine) {
72 return false;
73 }
74
75 eula_accepted = 0;
76 if (SUCCEEDED(RegKey::GetValue(
77 GetAppClientStateMediumKey(is_machine, app_guid),
78 kRegValueEulaAccepted,
79 &eula_accepted))) {
80 if (0 == eula_accepted) {
81 return false;
82 }
83 } else {
84 return false;
85 }
86
87 VERIFY1(SUCCEEDED(RegKey::SetValue(state_key,
88 kRegValueEulaAccepted,
89 eula_accepted)));
90 return true;
91 }
92
93 // Does not need to set ClientStateMedium.
94 HRESULT SetAppEulaNotAccepted(bool is_machine, const CString& app_guid) {
95 return RegKey::SetValue(GetAppClientStateKey(is_machine, app_guid),
96 kRegValueEulaAccepted,
97 static_cast<DWORD>(0));
98 }
99
100 // Deletes eulaaccepted from ClientState and ClientStateMedium.
101 HRESULT ClearAppEulaNotAccepted(bool is_machine, const CString& app_guid) {
102 const CString state_key = GetAppClientStateKey(is_machine, app_guid);
103 if (RegKey::HasKey(state_key)) {
104 HRESULT hr = RegKey::DeleteValue(state_key, kRegValueEulaAccepted);
105 if (FAILED(hr)) {
106 return hr;
107 }
108 }
109
110 if (!is_machine) {
111 return S_OK;
112 }
113
114 const CString state_medium_key =
115 GetAppClientStateMediumKey(is_machine, app_guid);
116 if (RegKey::HasKey(state_medium_key)) {
117 HRESULT hr = RegKey::DeleteValue(state_medium_key, kRegValueEulaAccepted);
118 if (FAILED(hr)) {
119 return hr;
120 }
121 }
122
123 return S_OK;
124 }
125
126 // For machine apps, ClientStateMedium takes precedence.
127 // Does not propogate the ClientStateMedium value to ClientState.
128 bool AreAppUsageStatsEnabled(bool is_machine, const CString& app_guid) {
129 if (is_machine) {
130 DWORD stats_enabled = 0;
131 if (SUCCEEDED(RegKey::GetValue(GetAppClientStateMediumKey(is_machine,
132 app_guid),
133 kRegValueUsageStats,
134 &stats_enabled))) {
135 return (TRISTATE_TRUE == stats_enabled);
136 }
137 }
138
139 DWORD stats_enabled = 0;
140 if (SUCCEEDED(RegKey::GetValue(GetAppClientStateKey(is_machine, app_guid),
141 kRegValueUsageStats,
142 &stats_enabled))) {
143 return (TRISTATE_TRUE == stats_enabled);
144 }
145
146 return false;
147 }
148
149 // Does nothing if usage_stats_enable is TRISTATE_NONE.
150 // For machine apps, clears ClientStateMedium because the app may be reading it
151 // if present.
152 HRESULT SetUsageStatsEnable(bool is_machine,
153 const CString& app_guid,
154 Tristate usage_stats_enable) {
155 if (TRISTATE_NONE == usage_stats_enable) {
156 return S_OK;
157 }
158
159 const DWORD stats_enabled = (TRISTATE_TRUE == usage_stats_enable) ? 1 : 0;
160
161 HRESULT hr = RegKey::SetValue(GetAppClientStateKey(is_machine, app_guid),
162 kRegValueUsageStats,
163 stats_enabled);
164 if (FAILED(hr)) {
165 CORE_LOG(LW, (_T("[Failed to set usagestats][0x%08x]"), hr));
166 return hr;
167 }
168
169 if (!is_machine) {
170 return S_OK;
171 }
172
173 const CString state_medium_key =
174 GetAppClientStateMediumKey(is_machine, app_guid);
175 if (RegKey::HasKey(state_medium_key)) {
176 hr = RegKey::DeleteValue(state_medium_key, kRegValueUsageStats);
177 if (FAILED(hr)) {
178 return hr;
179 }
180 }
181
182 return S_OK;
183 }
184
185 // Google Update does not have a referral_id. Everything else is the same as for
186 // apps.
187 HRESULT SetGoogleUpdateBranding(const CString& client_state_key_path,
188 const CString& brand_code,
189 const CString& client_id) {
190 HRESULT hr(SetAppBranding(client_state_key_path,
191 brand_code,
192 client_id,
193 CString()));
194
195 if (FAILED(hr)) {
196 return hr;
197 }
198
199 RegKey state_key;
200 hr = state_key.Open(client_state_key_path);
201 if (FAILED(hr)) {
202 return hr;
203 }
204
205 // Legacy support for older versions that do not write the FirstInstallTime.
206 // This code ensures that FirstInstallTime always has a valid non-zero value.
207 DWORD install_time(0);
208 if (FAILED(state_key.GetValue(kRegValueInstallTimeSec, &install_time)) ||
209 !install_time) {
210 const DWORD now = Time64ToInt32(GetCurrent100NSTime());
211 VERIFY1(SUCCEEDED(state_key.SetValue(kRegValueInstallTimeSec, now)));
212 CORE_LOG(L3, (_T("[InstallTime missing. Setting it here.][%u]"), now));
213 }
214
215 return S_OK;
216 }
217
218 // Branding information is only written if a brand code is not already present.
219 // We should only write it if this is the first install of Omaha to avoid giving
220 // undue credit to a later installer source. Writing a default brand code
221 // prevents future branded installations from setting their brand.
222 // As suggested by PSO, there is no default client ID.
223 // Assumes the specified Client State key has been created.
224 HRESULT SetAppBranding(const CString& client_state_key_path,
225 const CString& brand_code,
226 const CString& client_id,
227 const CString& referral_id) {
228 CORE_LOG(L3, (_T("[app_registry_utils::SetAppBranding][%s][%s][%s][%s]"),
229 client_state_key_path, brand_code, client_id, referral_id));
230
231 if (brand_code.GetLength() > kBrandIdLength) {
232 return E_INVALIDARG;
233 }
234
235 RegKey state_key;
236 HRESULT hr = state_key.Create(client_state_key_path);
237 if (FAILED(hr)) {
238 return hr;
239 }
240
241 CString existing_brand_code;
242 hr = state_key.GetValue(kRegValueBrandCode, &existing_brand_code);
243 if (!existing_brand_code.IsEmpty()) {
244 ASSERT1(SUCCEEDED(hr));
245 if (existing_brand_code.GetLength() > kBrandIdLength) {
246 // Bug 1358852: Brand code garbled with one click.
247 VERIFY1(SUCCEEDED(state_key.SetValue(kRegValueBrandCode,
248 existing_brand_code.Left(kBrandIdLength))));
249 }
250 return S_OK;
251 }
252
253 const TCHAR* brand_code_to_write = brand_code.IsEmpty() ?
254 kDefaultGoogleUpdateBrandCode :
255 brand_code;
256 hr = state_key.SetValue(kRegValueBrandCode, brand_code_to_write);
257 if (FAILED(hr)) {
258 return hr;
259 }
260
261 if (!client_id.IsEmpty()) {
262 hr = state_key.SetValue(kRegValueClientId, client_id);
263 if (FAILED(hr)) {
264 return hr;
265 }
266 }
267
268 if (!referral_id.IsEmpty()) {
269 hr = state_key.SetValue(kRegValueReferralId, referral_id);
270 if (FAILED(hr)) {
271 return hr;
272 }
273 }
274
275 const DWORD now = Time64ToInt32(GetCurrent100NSTime());
276 VERIFY1(SUCCEEDED(state_key.SetValue(kRegValueInstallTimeSec, now)));
277
278 return S_OK;
279 }
280
281 void PersistSuccessfulInstall(const CString& client_state_key_path,
282 bool is_update,
283 bool is_offline) {
284 CORE_LOG(L3,
285 (_T("[app_registry_utils::PersistSuccessfulInstall][%s][%d][%d]"),
286 client_state_key_path, is_update, is_offline));
287 ASSERT1(!is_update || !is_offline);
288
289 ClearUpdateAvailableStats(client_state_key_path);
290
291 if (!is_offline) {
292 // TODO(omaha): the semantics of this function are confusing in the
293 // case of recording a successful update check. Omaha knows
294 // precisely when an update check with the server is being made and it
295 // can call PersistSuccessfulUpdateCheck without making any other
296 // assumptions.
297 //
298 // Assumes that all updates are online.
299 PersistSuccessfulUpdateCheck(client_state_key_path);
300 }
301
302 if (is_update) {
303 const DWORD now = Time64ToInt32(GetCurrent100NSTime());
304 VERIFY1(SUCCEEDED(RegKey::SetValue(client_state_key_path,
305 kRegValueLastUpdateTimeSec,
306 now)));
307 }
308 }
309
310 void PersistSuccessfulUpdateCheck(const CString& client_state_key_path) {
311 CORE_LOG(L3, (_T("[app_registry_utils::PersistSuccessfulUpdateCheck][%s]"),
312 client_state_key_path));
313 const DWORD now = Time64ToInt32(GetCurrent100NSTime());
314 VERIFY1(SUCCEEDED(RegKey::SetValue(client_state_key_path,
315 kRegValueLastSuccessfulCheckSec,
316 now)));
317 }
318
319 void ClearUpdateAvailableStats(const CString& client_state_key_path) {
320 CORE_LOG(L3, (_T("[app_registry_utils::ClearUpdateAvailableStats][%s]"),
321 client_state_key_path));
322
323 RegKey state_key;
324 HRESULT hr = state_key.Open(client_state_key_path);
325 if (FAILED(hr)) {
326 return;
327 }
328
329 VERIFY1(SUCCEEDED(state_key.DeleteValue(kRegValueUpdateAvailableCount)));
330 VERIFY1(SUCCEEDED(state_key.DeleteValue(kRegValueUpdateAvailableSince)));
331 }
332
333 HRESULT GetNumClients(bool is_machine, size_t* num_clients) {
334 ASSERT1(num_clients);
335 RegKey reg_key;
336 HKEY root_key = is_machine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
337 HRESULT hr = reg_key.Open(root_key, GOOPDATE_REG_RELATIVE_CLIENTS, KEY_READ);
338 if (FAILED(hr)) {
339 return hr;
340 }
341 DWORD num_subkeys(0);
342 LONG error = ::RegQueryInfoKey(reg_key.Key(), NULL, NULL, NULL, &num_subkeys,
343 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
344 if (error != ERROR_SUCCESS) {
345 return HRESULT_FROM_WIN32(error);
346 }
347 *num_clients = num_subkeys;
348 return S_OK;
349 }
350
351 // Reads pv value from Clients key.
352 void GetAppVersion(bool is_machine, const CString& app_id, CString* pv) {
353 ASSERT1(pv);
354 RegKey key;
355 CString key_name = GetAppClientsKey(is_machine, app_id);
356 HRESULT hr = key.Open(key_name, KEY_READ);
357 if (SUCCEEDED(hr)) {
358 key.GetValue(kRegValueProductVersion, pv);
359 }
360 }
361
362 // Reads the following values from the registry:
363 // ClientState key
364 // pv
365 // ap
366 // lang
367 // brand
368 // client
369 // iid
370 // experiment
371 void GetClientStateData(bool is_machine,
372 const CString& app_id,
373 CString* pv,
374 CString* ap,
375 CString* lang,
376 CString* brand_code,
377 CString* client_id,
378 CString* iid,
379 CString* experiment_labels) {
380 RegKey key;
381
382 CString key_name = GetAppClientStateKey(is_machine, app_id);
383 HRESULT hr = key.Open(key_name, KEY_READ);
384 if (FAILED(hr)) {
385 return;
386 }
387
388 if (pv) {
389 key.GetValue(kRegValueProductVersion, pv);
390 }
391 if (ap) {
392 key.GetValue(kRegValueAdditionalParams, ap);
393 }
394 if (lang) {
395 key.GetValue(kRegValueLanguage, lang);
396 }
397 if (brand_code) {
398 key.GetValue(kRegValueBrandCode, brand_code);
399 }
400 if (client_id) {
401 key.GetValue(kRegValueClientId, client_id);
402 }
403 if (iid) {
404 key.GetValue(kRegValueInstallationId, iid);
405 }
406 if (experiment_labels) {
407 key.GetValue(kRegValueExperimentLabels, experiment_labels);
408 }
409 }
410
411 HRESULT GetUninstalledApps(bool is_machine,
412 std::vector<CString>* app_ids) {
413 ASSERT1(app_ids);
414
415 RegKey client_state_key;
416 HRESULT hr = client_state_key.Open(
417 ConfigManager::Instance()->registry_client_state(is_machine),
418 KEY_READ);
419 if (FAILED(hr)) {
420 return hr;
421 }
422
423 int num_sub_keys = client_state_key.GetSubkeyCount();
424 for (int i = 0; i < num_sub_keys; ++i) {
425 CString app_id;
426 hr = client_state_key.GetSubkeyNameAt(i, &app_id);
427 if (FAILED(hr)) {
428 continue;
429 }
430
431 // If the app is not registered, treat it as uninstalled.
432 if (!RegKey::HasValue(
433 app_registry_utils::GetAppClientsKey(is_machine, app_id),
434 kRegValueProductVersion)) {
435 app_ids->push_back(app_id);
436 }
437 }
438
439 return S_OK;
440 }
441
442 HRESULT RemoveClientState(bool is_machine, const CString& app_guid) {
443 const CString state_key = GetAppClientStateKey(is_machine, app_guid);
444 HRESULT state_hr = RegKey::DeleteKey(state_key, true);
445 if (!is_machine) {
446 return state_hr;
447 }
448
449 const CString state_medium_key = GetAppClientStateMediumKey(is_machine,
450 app_guid);
451 HRESULT state_medium_hr = RegKey::DeleteKey(state_medium_key, true);
452 return FAILED(state_hr) ? state_hr : state_medium_hr;
453 }
454
455 void RemoveClientStateForApps(bool is_machine,
456 const std::vector<CString>& apps) {
457 std::vector<CString>::const_iterator it;
458 for (it = apps.begin(); it != apps.end(); ++it) {
459 RemoveClientState(is_machine, *it);
460 }
461 }
462
463 HRESULT GetExperimentLabels(bool is_machine, const CString& app_id,
464 CString* labels_out) {
465 ASSERT1(!app_id.IsEmpty());
466 ASSERT1(labels_out);
467
468 const CString state_key = GetAppClientStateKey(is_machine, app_id);
469 if (!RegKey::HasValue(state_key, kRegValueExperimentLabels)) {
470 return S_OK;
471 }
472
473 return RegKey::GetValue(state_key, kRegValueExperimentLabels, labels_out);
474 }
475
476 HRESULT SetExperimentLabels(bool is_machine, const CString& app_id,
477 const CString& new_labels) {
478 ASSERT1(!app_id.IsEmpty());
479 ASSERT1(ExperimentLabels::IsStringValidLabelSet(new_labels));
480
481 return RegKey::SetValue(GetAppClientStateKey(is_machine, app_id),
482 kRegValueExperimentLabels,
483 new_labels);
484 }
485
486 } // namespace app_registry_utils
487
488 } // namespace omaha
OLDNEW
« no previous file with comments | « common/app_registry_utils.h ('k') | common/app_registry_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698