• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/util/google_update_settings.h"
6 
7 #include <algorithm>
8 #include <string>
9 
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "base/time/time.h"
20 #include "base/win/registry.h"
21 #include "base/win/win_util.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/installer/util/app_registration_data.h"
24 #include "chrome/installer/util/browser_distribution.h"
25 #include "chrome/installer/util/channel_info.h"
26 #include "chrome/installer/util/google_update_constants.h"
27 #include "chrome/installer/util/google_update_experiment_util.h"
28 #include "chrome/installer/util/install_util.h"
29 #include "chrome/installer/util/installation_state.h"
30 #include "chrome/installer/util/product.h"
31 
32 using base::win::RegKey;
33 using installer::InstallationState;
34 
35 const wchar_t GoogleUpdateSettings::kPoliciesKey[] =
36     L"SOFTWARE\\Policies\\Google\\Update";
37 const wchar_t GoogleUpdateSettings::kUpdatePolicyValue[] = L"UpdateDefault";
38 const wchar_t GoogleUpdateSettings::kUpdateOverrideValuePrefix[] = L"Update";
39 const wchar_t GoogleUpdateSettings::kCheckPeriodOverrideMinutes[] =
40     L"AutoUpdateCheckPeriodMinutes";
41 
42 // Don't allow update periods longer than six weeks.
43 const int GoogleUpdateSettings::kCheckPeriodOverrideMinutesMax =
44     60 * 24 * 7 * 6;
45 
46 const GoogleUpdateSettings::UpdatePolicy
47 GoogleUpdateSettings::kDefaultUpdatePolicy =
48 #if defined(GOOGLE_CHROME_BUILD)
49     GoogleUpdateSettings::AUTOMATIC_UPDATES;
50 #else
51     GoogleUpdateSettings::UPDATES_DISABLED;
52 #endif
53 
54 namespace {
55 
ReadGoogleUpdateStrKey(const wchar_t * const name,std::wstring * value)56 bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) {
57   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
58   std::wstring reg_path = dist->GetStateKey();
59   RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WOW64_32KEY);
60   if (key.ReadValue(name, value) != ERROR_SUCCESS) {
61     RegKey hklm_key(
62         HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ | KEY_WOW64_32KEY);
63     return (hklm_key.ReadValue(name, value) == ERROR_SUCCESS);
64   }
65   return true;
66 }
67 
68 // Updates a registry key |name| to be |value| for the given |app_reg_data|.
69 // If this is a |system_install|, then update the value under HKLM (istead of
70 // HKCU for user-installs) using a group of keys (one for each OS user) and also
71 // include the method to |aggregate| these values when reporting.
WriteGoogleUpdateStrKeyInternal(const AppRegistrationData & app_reg_data,bool system_install,const wchar_t * const name,const std::wstring & value,const wchar_t * const aggregate)72 bool WriteGoogleUpdateStrKeyInternal(const AppRegistrationData& app_reg_data,
73                                      bool system_install,
74                                      const wchar_t* const name,
75                                      // presubmit: allow wstring
76                                      const std::wstring& value,
77                                      const wchar_t* const aggregate) {
78   const REGSAM kAccess = KEY_SET_VALUE | KEY_WOW64_32KEY;
79   if (system_install) {
80     DCHECK(aggregate);
81     // Machine installs require each OS user to write a unique key under a
82     // named key in HKLM as well as an "aggregation" function that describes
83     // how the values of multiple users are to be combined.
84     std::wstring uniquename;  // presubmit: allow wstring
85     if (!base::win::GetUserSidString(&uniquename)) {
86       NOTREACHED();
87       return false;
88     }
89 
90     base::string16 reg_path(app_reg_data.GetStateMediumKey());
91     reg_path.append(L"\\");
92     reg_path.append(name);
93     RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), kAccess);
94     key.WriteValue(google_update::kRegAggregateMethod, aggregate);
95     return (key.WriteValue(uniquename.c_str(), value.c_str()) == ERROR_SUCCESS);
96   } else {
97     // User installs are easy: just write the values to HKCU tree.
98     RegKey key(HKEY_CURRENT_USER, app_reg_data.GetStateKey().c_str(), kAccess);
99     return (key.WriteValue(name, value.c_str()) == ERROR_SUCCESS);
100   }
101 }
102 
WriteGoogleUpdateStrKey(const wchar_t * const name,const std::wstring & value)103 bool WriteGoogleUpdateStrKey(const wchar_t* const name,
104                              const std::wstring& value) {
105   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
106   return WriteGoogleUpdateStrKeyInternal(
107       dist->GetAppRegistrationData(), false, name, value, NULL);
108 }
109 
ClearGoogleUpdateStrKey(const wchar_t * const name)110 bool ClearGoogleUpdateStrKey(const wchar_t* const name) {
111   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
112   std::wstring reg_path = dist->GetStateKey();
113   RegKey key(HKEY_CURRENT_USER,
114              reg_path.c_str(),
115              KEY_READ | KEY_WRITE | KEY_WOW64_32KEY);
116   std::wstring value;
117   if (key.ReadValue(name, &value) != ERROR_SUCCESS)
118     return false;
119   return (key.WriteValue(name, L"") == ERROR_SUCCESS);
120 }
121 
RemoveGoogleUpdateStrKey(const wchar_t * const name)122 bool RemoveGoogleUpdateStrKey(const wchar_t* const name) {
123   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
124   std::wstring reg_path = dist->GetStateKey();
125   RegKey key(HKEY_CURRENT_USER,
126              reg_path.c_str(),
127              KEY_READ | KEY_WRITE | KEY_WOW64_32KEY);
128   if (!key.HasValue(name))
129     return true;
130   return (key.DeleteValue(name) == ERROR_SUCCESS);
131 }
132 
GetChromeChannelInternal(bool system_install,bool add_multi_modifier,base::string16 * channel)133 bool GetChromeChannelInternal(bool system_install,
134                               bool add_multi_modifier,
135                               base::string16* channel) {
136   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
137 
138   // Shortcut in case this distribution knows what channel it is (canary).
139   if (dist->GetChromeChannel(channel))
140     return true;
141 
142   // Determine whether or not chrome is multi-install. If so, updates are
143   // delivered under the binaries' app guid, so that's where the relevant
144   // channel is found.
145   installer::ProductState state;
146   installer::ChannelInfo channel_info;
147   ignore_result(state.Initialize(system_install, dist));
148   if (!state.is_multi_install()) {
149     // Use the channel info that was just read for this single-install chrome.
150     channel_info = state.channel();
151   } else {
152     // Read the channel info from the binaries' state key.
153     HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
154     dist = BrowserDistribution::GetSpecificDistribution(
155         BrowserDistribution::CHROME_BINARIES);
156     RegKey key(root_key, dist->GetStateKey().c_str(),
157                KEY_READ | KEY_WOW64_32KEY);
158 
159     if (!channel_info.Initialize(key)) {
160       channel->assign(installer::kChromeChannelUnknown);
161       return false;
162     }
163   }
164 
165   if (!channel_info.GetChannelName(channel))
166     channel->assign(installer::kChromeChannelUnknown);
167 
168   // Tag the channel name if this is a multi-install.
169   if (add_multi_modifier && state.is_multi_install()) {
170     if (!channel->empty())
171       channel->push_back(L'-');
172     channel->push_back(L'm');
173   }
174 
175   return true;
176 }
177 
178 // Populates |update_policy| with the UpdatePolicy enum value corresponding to a
179 // DWORD read from the registry and returns true if |value| is within range.
180 // If |value| is out of range, returns false without modifying |update_policy|.
GetUpdatePolicyFromDword(const DWORD value,GoogleUpdateSettings::UpdatePolicy * update_policy)181 bool GetUpdatePolicyFromDword(
182     const DWORD value,
183     GoogleUpdateSettings::UpdatePolicy* update_policy) {
184   switch (value) {
185     case GoogleUpdateSettings::UPDATES_DISABLED:
186     case GoogleUpdateSettings::AUTOMATIC_UPDATES:
187     case GoogleUpdateSettings::MANUAL_UPDATES_ONLY:
188     case GoogleUpdateSettings::AUTO_UPDATES_ONLY:
189       *update_policy = static_cast<GoogleUpdateSettings::UpdatePolicy>(value);
190       return true;
191     default:
192       LOG(WARNING) << "Unexpected update policy override value: " << value;
193   }
194   return false;
195 }
196 
197 // Convenience routine: GoogleUpdateSettings::UpdateDidRunStateForApp()
198 // specialized for Chrome Binaries.
UpdateDidRunStateForBinaries(bool did_run)199 bool UpdateDidRunStateForBinaries(bool did_run) {
200   BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
201       BrowserDistribution::CHROME_BINARIES);
202   return GoogleUpdateSettings::UpdateDidRunStateForApp(
203       dist->GetAppRegistrationData(), did_run);
204 }
205 
206 }  // namespace
207 
IsSystemInstall()208 bool GoogleUpdateSettings::IsSystemInstall() {
209   bool system_install = false;
210   base::FilePath module_dir;
211   if (!PathService::Get(base::DIR_MODULE, &module_dir)) {
212     LOG(WARNING)
213         << "Failed to get directory of module; assuming per-user install.";
214   } else {
215     system_install = !InstallUtil::IsPerUserInstall(module_dir.value().c_str());
216   }
217   return system_install;
218 }
219 
GetCollectStatsConsent()220 bool GoogleUpdateSettings::GetCollectStatsConsent() {
221   return GetCollectStatsConsentAtLevel(IsSystemInstall());
222 }
223 
224 // Older versions of Chrome unconditionally read from HKCU\...\ClientState\...
225 // and then HKLM\...\ClientState\....  This means that system-level Chrome
226 // never checked ClientStateMedium (which has priority according to Google
227 // Update) and gave preference to a value in HKCU (which was never checked by
228 // Google Update).  From now on, Chrome follows Google Update's policy.
GetCollectStatsConsentAtLevel(bool system_install)229 bool GoogleUpdateSettings::GetCollectStatsConsentAtLevel(bool system_install) {
230   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
231 
232   // Consent applies to all products in a multi-install package.
233   if (InstallUtil::IsMultiInstall(dist, system_install)) {
234     dist = BrowserDistribution::GetSpecificDistribution(
235         BrowserDistribution::CHROME_BINARIES);
236   }
237 
238   RegKey key;
239   DWORD value = 0;
240   bool have_value = false;
241   const REGSAM kAccess = KEY_QUERY_VALUE | KEY_WOW64_32KEY;
242 
243   // For system-level installs, try ClientStateMedium first.
244   have_value =
245       system_install &&
246       key.Open(HKEY_LOCAL_MACHINE, dist->GetStateMediumKey().c_str(),
247                kAccess) == ERROR_SUCCESS &&
248       key.ReadValueDW(google_update::kRegUsageStatsField,
249                       &value) == ERROR_SUCCESS;
250 
251   // Otherwise, try ClientState.
252   if (!have_value) {
253     have_value =
254         key.Open(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
255                  dist->GetStateKey().c_str(),
256                  kAccess) == ERROR_SUCCESS &&
257         key.ReadValueDW(google_update::kRegUsageStatsField,
258                         &value) == ERROR_SUCCESS;
259   }
260 
261   // Google Update specifically checks that the value is 1, so we do the same.
262   return have_value && value == 1;
263 }
264 
SetCollectStatsConsent(bool consented)265 bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) {
266   return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented);
267 }
268 
SetCollectStatsConsentAtLevel(bool system_install,bool consented)269 bool GoogleUpdateSettings::SetCollectStatsConsentAtLevel(bool system_install,
270                                                          bool consented) {
271   // Google Update writes and expects 1 for true, 0 for false.
272   DWORD value = consented ? 1 : 0;
273 
274   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
275 
276   // Consent applies to all products in a multi-install package.
277   if (InstallUtil::IsMultiInstall(dist, system_install)) {
278     dist = BrowserDistribution::GetSpecificDistribution(
279         BrowserDistribution::CHROME_BINARIES);
280   }
281 
282   // Write to ClientStateMedium for system-level; ClientState otherwise.
283   HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
284   std::wstring reg_path =
285       system_install ? dist->GetStateMediumKey() : dist->GetStateKey();
286   RegKey key;
287   LONG result = key.Create(
288       root_key, reg_path.c_str(), KEY_SET_VALUE | KEY_WOW64_32KEY);
289   if (result != ERROR_SUCCESS) {
290     LOG(ERROR) << "Failed opening key " << reg_path << " to set "
291                << google_update::kRegUsageStatsField << "; result: " << result;
292   } else {
293     result = key.WriteValue(google_update::kRegUsageStatsField, value);
294     LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed setting "
295         << google_update::kRegUsageStatsField << " in key " << reg_path
296         << "; result: " << result;
297   }
298   return (result == ERROR_SUCCESS);
299 }
300 
GetMetricsId(std::string * metrics_id)301 bool GoogleUpdateSettings::GetMetricsId(std::string* metrics_id) {
302   std::wstring metrics_id_w;
303   bool rv = ReadGoogleUpdateStrKey(google_update::kRegMetricsId, &metrics_id_w);
304   *metrics_id = base::WideToUTF8(metrics_id_w);
305   return rv;
306 }
307 
SetMetricsId(const std::string & metrics_id)308 bool GoogleUpdateSettings::SetMetricsId(const std::string& metrics_id) {
309   std::wstring metrics_id_w = base::UTF8ToWide(metrics_id);
310   return WriteGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id_w);
311 }
312 
313 // EULA consent is only relevant for system-level installs.
SetEULAConsent(const InstallationState & machine_state,BrowserDistribution * dist,bool consented)314 bool GoogleUpdateSettings::SetEULAConsent(
315     const InstallationState& machine_state,
316     BrowserDistribution* dist,
317     bool consented) {
318   DCHECK(dist);
319   const DWORD eula_accepted = consented ? 1 : 0;
320   const REGSAM kAccess = KEY_SET_VALUE | KEY_WOW64_32KEY;
321   std::wstring reg_path = dist->GetStateMediumKey();
322   bool succeeded = true;
323   RegKey key;
324 
325   // Write the consent value into the product's ClientStateMedium key.
326   if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(),
327                  kAccess) != ERROR_SUCCESS ||
328       key.WriteValue(google_update::kRegEULAAceptedField,
329                      eula_accepted) != ERROR_SUCCESS) {
330     succeeded = false;
331   }
332 
333   // If this is a multi-install, also write it into the binaries' key.
334   // --mutli-install is not provided on the command-line, so deduce it from
335   // the product's state.
336   const installer::ProductState* product_state =
337       machine_state.GetProductState(true, dist->GetType());
338   if (product_state != NULL && product_state->is_multi_install()) {
339     dist = BrowserDistribution::GetSpecificDistribution(
340         BrowserDistribution::CHROME_BINARIES);
341     reg_path = dist->GetStateMediumKey();
342     if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(),
343                    kAccess) != ERROR_SUCCESS ||
344         key.WriteValue(google_update::kRegEULAAceptedField,
345                        eula_accepted) != ERROR_SUCCESS) {
346         succeeded = false;
347     }
348   }
349 
350   return succeeded;
351 }
352 
GetLastRunTime()353 int GoogleUpdateSettings::GetLastRunTime() {
354   std::wstring time_s;
355   if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField, &time_s))
356     return -1;
357   int64 time_i;
358   if (!base::StringToInt64(time_s, &time_i))
359     return -1;
360   base::TimeDelta td =
361       base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i);
362   return td.InDays();
363 }
364 
SetLastRunTime()365 bool GoogleUpdateSettings::SetLastRunTime() {
366   int64 time = base::Time::NowFromSystemTime().ToInternalValue();
367   return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField,
368                                  base::Int64ToString16(time));
369 }
370 
RemoveLastRunTime()371 bool GoogleUpdateSettings::RemoveLastRunTime() {
372   return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField);
373 }
374 
GetBrowser(std::wstring * browser)375 bool GoogleUpdateSettings::GetBrowser(std::wstring* browser) {
376   return ReadGoogleUpdateStrKey(google_update::kRegBrowserField, browser);
377 }
378 
GetLanguage(std::wstring * language)379 bool GoogleUpdateSettings::GetLanguage(std::wstring* language) {
380   return ReadGoogleUpdateStrKey(google_update::kRegLangField, language);
381 }
382 
GetBrand(std::wstring * brand)383 bool GoogleUpdateSettings::GetBrand(std::wstring* brand) {
384   return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField, brand);
385 }
386 
GetReactivationBrand(std::wstring * brand)387 bool GoogleUpdateSettings::GetReactivationBrand(std::wstring* brand) {
388   return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField,
389                                 brand);
390 }
391 
GetClient(std::wstring * client)392 bool GoogleUpdateSettings::GetClient(std::wstring* client) {
393   return ReadGoogleUpdateStrKey(google_update::kRegClientField, client);
394 }
395 
SetClient(const std::wstring & client)396 bool GoogleUpdateSettings::SetClient(const std::wstring& client) {
397   return WriteGoogleUpdateStrKey(google_update::kRegClientField, client);
398 }
399 
GetReferral(std::wstring * referral)400 bool GoogleUpdateSettings::GetReferral(std::wstring* referral) {
401   return ReadGoogleUpdateStrKey(google_update::kRegReferralField, referral);
402 }
403 
ClearReferral()404 bool GoogleUpdateSettings::ClearReferral() {
405   return ClearGoogleUpdateStrKey(google_update::kRegReferralField);
406 }
407 
UpdateDidRunStateForApp(const AppRegistrationData & app_reg_data,bool did_run)408 bool GoogleUpdateSettings::UpdateDidRunStateForApp(
409     const AppRegistrationData& app_reg_data,
410     bool did_run) {
411   return WriteGoogleUpdateStrKeyInternal(app_reg_data,
412                                          false, // user level.
413                                          google_update::kRegDidRunField,
414                                          did_run ? L"1" : L"0",
415                                          NULL);
416 }
417 
UpdateDidRunState(bool did_run,bool system_level)418 bool GoogleUpdateSettings::UpdateDidRunState(bool did_run, bool system_level) {
419   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
420   bool result = UpdateDidRunStateForApp(dist->GetAppRegistrationData(),
421                                         did_run);
422   // Update state for binaries, even if the previous call was unsuccessful.
423   if (InstallUtil::IsMultiInstall(dist, system_level))
424     result = UpdateDidRunStateForBinaries(did_run) && result;
425   return result;
426 }
427 
GetChromeChannel(bool system_install)428 base::string16 GoogleUpdateSettings::GetChromeChannel(bool system_install) {
429   base::string16 channel;
430   GetChromeChannelInternal(system_install, false, &channel);
431   return channel;
432 }
433 
GetChromeChannelAndModifiers(bool system_install,base::string16 * channel)434 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(
435     bool system_install,
436     base::string16* channel) {
437   return GetChromeChannelInternal(system_install, true, channel);
438 }
439 
UpdateInstallStatus(bool system_install,installer::ArchiveType archive_type,int install_return_code,const std::wstring & product_guid)440 void GoogleUpdateSettings::UpdateInstallStatus(bool system_install,
441     installer::ArchiveType archive_type, int install_return_code,
442     const std::wstring& product_guid) {
443   DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE ||
444          install_return_code != 0);
445   HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
446 
447   RegKey key;
448   installer::ChannelInfo channel_info;
449   std::wstring reg_key(google_update::kRegPathClientState);
450   reg_key.append(L"\\");
451   reg_key.append(product_guid);
452   LONG result = key.Open(reg_root,
453                          reg_key.c_str(),
454                          KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY);
455   if (result == ERROR_SUCCESS)
456     channel_info.Initialize(key);
457   else if (result != ERROR_FILE_NOT_FOUND)
458     LOG(ERROR) << "Failed to open " << reg_key << "; Error: " << result;
459 
460   if (UpdateGoogleUpdateApKey(archive_type, install_return_code,
461                               &channel_info)) {
462     // We have a modified channel_info value to write.
463     // Create the app's ClientState key if it doesn't already exist.
464     if (!key.Valid()) {
465       result = key.Open(reg_root,
466                         google_update::kRegPathClientState,
467                         KEY_CREATE_SUB_KEY | KEY_WOW64_32KEY);
468       if (result == ERROR_SUCCESS)
469         result = key.CreateKey(product_guid.c_str(),
470                                KEY_SET_VALUE | KEY_WOW64_32KEY);
471 
472       if (result != ERROR_SUCCESS) {
473         LOG(ERROR) << "Failed to create " << reg_key << "; Error: " << result;
474         return;
475       }
476     }
477     if (!channel_info.Write(&key)) {
478       LOG(ERROR) << "Failed to write to application's ClientState key "
479                  << google_update::kRegApField << " = " << channel_info.value();
480     }
481   }
482 }
483 
UpdateGoogleUpdateApKey(installer::ArchiveType archive_type,int install_return_code,installer::ChannelInfo * value)484 bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
485     installer::ArchiveType archive_type, int install_return_code,
486     installer::ChannelInfo* value) {
487   DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE ||
488          install_return_code != 0);
489   bool modified = false;
490 
491   if (archive_type == installer::FULL_ARCHIVE_TYPE || !install_return_code) {
492     if (value->SetFullSuffix(false)) {
493       VLOG(1) << "Removed incremental installer failure key; "
494                  "switching to channel: "
495               << value->value();
496       modified = true;
497     }
498   } else if (archive_type == installer::INCREMENTAL_ARCHIVE_TYPE) {
499     if (value->SetFullSuffix(true)) {
500       VLOG(1) << "Incremental installer failed; switching to channel: "
501               << value->value();
502       modified = true;
503     } else {
504       VLOG(1) << "Incremental installer failure; already on channel: "
505               << value->value();
506     }
507   } else {
508     // It's okay if we don't know the archive type.  In this case, leave the
509     // "-full" suffix as we found it.
510     DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE, archive_type);
511   }
512 
513   if (value->SetMultiFailSuffix(false)) {
514     VLOG(1) << "Removed multi-install failure key; switching to channel: "
515             << value->value();
516     modified = true;
517   }
518 
519   return modified;
520 }
521 
UpdateProfileCounts(int profiles_active,int profiles_signedin)522 void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active,
523                                                int profiles_signedin) {
524   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
525   bool system_install = IsSystemInstall();
526   WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
527                                   system_install,
528                                   google_update::kRegProfilesActive,
529                                   base::Int64ToString16(profiles_active),
530                                   L"sum()");
531   WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
532                                   system_install,
533                                   google_update::kRegProfilesSignedIn,
534                                   base::Int64ToString16(profiles_signedin),
535                                   L"sum()");
536 }
537 
DuplicateGoogleUpdateSystemClientKey()538 int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
539   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
540   std::wstring reg_path = dist->GetStateKey();
541 
542   // Minimum access needed is to be able to write to this key.
543   RegKey reg_key(
544       HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE | KEY_WOW64_32KEY);
545   if (!reg_key.Valid())
546     return 0;
547 
548   HANDLE target_handle = 0;
549   if (!DuplicateHandle(GetCurrentProcess(), reg_key.Handle(),
550                        GetCurrentProcess(), &target_handle, KEY_SET_VALUE,
551                        TRUE, DUPLICATE_SAME_ACCESS)) {
552     return 0;
553   }
554   return reinterpret_cast<int>(target_handle);
555 }
556 
WriteGoogleUpdateSystemClientKey(int handle,const std::wstring & key,const std::wstring & value)557 bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
558     int handle, const std::wstring& key, const std::wstring& value) {
559   HKEY reg_key = reinterpret_cast<HKEY>(reinterpret_cast<void*>(handle));
560   DWORD size = static_cast<DWORD>(value.size()) * sizeof(wchar_t);
561   LSTATUS status = RegSetValueEx(reg_key, key.c_str(), 0, REG_SZ,
562       reinterpret_cast<const BYTE*>(value.c_str()), size);
563   return status == ERROR_SUCCESS;
564 }
565 
GetAppUpdatePolicy(const std::wstring & app_guid,bool * is_overridden)566 GoogleUpdateSettings::UpdatePolicy GoogleUpdateSettings::GetAppUpdatePolicy(
567     const std::wstring& app_guid,
568     bool* is_overridden) {
569   bool found_override = false;
570   UpdatePolicy update_policy = kDefaultUpdatePolicy;
571 
572 #if defined(GOOGLE_CHROME_BUILD)
573   DCHECK(!app_guid.empty());
574   RegKey policy_key;
575 
576   // Google Update Group Policy settings are always in HKLM.
577   // TODO(wfh): Check if policies should go into Wow6432Node or not.
578   if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, KEY_QUERY_VALUE) ==
579           ERROR_SUCCESS) {
580     DWORD value = 0;
581     base::string16 app_update_override(kUpdateOverrideValuePrefix);
582     app_update_override.append(app_guid);
583     // First try to read and comprehend the app-specific override.
584     found_override = (policy_key.ReadValueDW(app_update_override.c_str(),
585                                              &value) == ERROR_SUCCESS &&
586                       GetUpdatePolicyFromDword(value, &update_policy));
587 
588     // Failing that, try to read and comprehend the default override.
589     if (!found_override &&
590         policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS) {
591       GetUpdatePolicyFromDword(value, &update_policy);
592     }
593   }
594 #endif  // defined(GOOGLE_CHROME_BUILD)
595 
596   if (is_overridden != NULL)
597     *is_overridden = found_override;
598 
599   return update_policy;
600 }
601 
602 // static
AreAutoupdatesEnabled(const base::string16 & app_guid)603 bool GoogleUpdateSettings::AreAutoupdatesEnabled(
604     const base::string16& app_guid) {
605   // Check the auto-update check period override. If it is 0 or exceeds the
606   // maximum timeout, then for all intents and purposes auto updates are
607   // disabled.
608   RegKey policy_key;
609   DWORD value = 0;
610   if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey,
611                       KEY_QUERY_VALUE) == ERROR_SUCCESS &&
612       policy_key.ReadValueDW(kCheckPeriodOverrideMinutes,
613                              &value) == ERROR_SUCCESS &&
614       (value == 0 || value > kCheckPeriodOverrideMinutesMax)) {
615     return false;
616   }
617 
618   UpdatePolicy policy = GetAppUpdatePolicy(app_guid, NULL);
619   return (policy == AUTOMATIC_UPDATES || policy == AUTO_UPDATES_ONLY);
620 }
621 
622 // static
ReenableAutoupdatesForApp(const base::string16 & app_guid)623 bool GoogleUpdateSettings::ReenableAutoupdatesForApp(
624     const base::string16& app_guid) {
625 #if defined(GOOGLE_CHROME_BUILD)
626   int needs_reset_count = 0;
627   int did_reset_count = 0;
628 
629   UpdatePolicy update_policy = kDefaultUpdatePolicy;
630   RegKey policy_key;
631   if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey,
632                       KEY_SET_VALUE | KEY_QUERY_VALUE) == ERROR_SUCCESS) {
633     // First check the app-specific override value and reset that if needed.
634     // Note that this intentionally sets the override to AUTOMATIC_UPDATES
635     // even if it was previously AUTO_UPDATES_ONLY. The thinking is that
636     // AUTOMATIC_UPDATES is marginally more likely to let a user update and this
637     // code is only called when a stuck user asks for updates.
638     base::string16 app_update_override(kUpdateOverrideValuePrefix);
639     app_update_override.append(app_guid);
640     DWORD value = 0;
641     bool has_app_update_override =
642         policy_key.ReadValueDW(app_update_override.c_str(),
643                                &value) == ERROR_SUCCESS;
644     if (has_app_update_override &&
645         (!GetUpdatePolicyFromDword(value, &update_policy) ||
646          update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) {
647       ++needs_reset_count;
648       if (policy_key.WriteValue(
649               app_update_override.c_str(),
650               static_cast<DWORD>(GoogleUpdateSettings::AUTOMATIC_UPDATES)) ==
651                   ERROR_SUCCESS) {
652         ++did_reset_count;
653       }
654     }
655 
656     // If there was no app-specific override policy see if there's a global
657     // policy preventing updates and delete it if so.
658     if (!has_app_update_override &&
659         policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS &&
660         (!GetUpdatePolicyFromDword(value, &update_policy) ||
661          update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) {
662       ++needs_reset_count;
663       if (policy_key.DeleteValue(kUpdatePolicyValue) == ERROR_SUCCESS)
664         ++did_reset_count;
665     }
666 
667     // Check the auto-update check period override. If it is 0 or exceeds
668     // the maximum timeout, delete the override value.
669     if (policy_key.ReadValueDW(kCheckPeriodOverrideMinutes,
670                                &value) == ERROR_SUCCESS &&
671         (value == 0 || value > kCheckPeriodOverrideMinutesMax)) {
672       ++needs_reset_count;
673       if (policy_key.DeleteValue(kCheckPeriodOverrideMinutes) == ERROR_SUCCESS)
674         ++did_reset_count;
675     }
676 
677     // Return whether the number of successful resets is the same as the
678     // number of things that appeared to need resetting.
679     return (needs_reset_count == did_reset_count);
680   } else {
681     // For some reason we couldn't open the policy key with the desired
682     // permissions to make changes (the most likely reason is that there is no
683     // policy set). Simply return whether or not we think updates are enabled.
684     return AreAutoupdatesEnabled(app_guid);
685   }
686 
687 #endif
688   // Non Google Chrome isn't going to autoupdate.
689   return true;
690 }
691 
RecordChromeUpdatePolicyHistograms()692 void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() {
693   const bool is_multi_install = InstallUtil::IsMultiInstall(
694       BrowserDistribution::GetDistribution(), IsSystemInstall());
695   const base::string16 app_guid =
696       BrowserDistribution::GetSpecificDistribution(
697           is_multi_install ? BrowserDistribution::CHROME_BINARIES :
698                              BrowserDistribution::CHROME_BROWSER)->GetAppGuid();
699 
700   bool is_overridden = false;
701   const UpdatePolicy update_policy = GetAppUpdatePolicy(app_guid,
702                                                         &is_overridden);
703   UMA_HISTOGRAM_BOOLEAN("GoogleUpdate.UpdatePolicyIsOverridden", is_overridden);
704   UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.EffectivePolicy", update_policy,
705                             UPDATE_POLICIES_COUNT);
706 }
707 
GetUninstallCommandLine(bool system_install)708 base::string16 GoogleUpdateSettings::GetUninstallCommandLine(
709     bool system_install) {
710   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
711   base::string16 cmd_line;
712   RegKey update_key;
713 
714   if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate,
715                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
716     update_key.ReadValue(google_update::kRegUninstallCmdLine, &cmd_line);
717   }
718 
719   return cmd_line;
720 }
721 
GetGoogleUpdateVersion(bool system_install)722 Version GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install) {
723   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
724   base::string16 version;
725   RegKey key;
726 
727   if (key.Open(root_key,
728                google_update::kRegPathGoogleUpdate,
729                KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS &&
730       key.ReadValue(google_update::kRegGoogleUpdateVersion, &version) ==
731           ERROR_SUCCESS) {
732     return Version(base::UTF16ToUTF8(version));
733   }
734 
735   return Version();
736 }
737 
GetGoogleUpdateLastStartedAU(bool system_install)738 base::Time GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
739     bool system_install) {
740   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
741   RegKey update_key;
742 
743   if (update_key.Open(root_key,
744                       google_update::kRegPathGoogleUpdate,
745                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
746     DWORD last_start;
747     if (update_key.ReadValueDW(google_update::kRegLastStartedAUField,
748                                &last_start) == ERROR_SUCCESS) {
749       return base::Time::FromTimeT(last_start);
750     }
751   }
752 
753   return base::Time();
754 }
755 
GetGoogleUpdateLastChecked(bool system_install)756 base::Time GoogleUpdateSettings::GetGoogleUpdateLastChecked(
757     bool system_install) {
758   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
759   RegKey update_key;
760 
761   if (update_key.Open(root_key,
762                       google_update::kRegPathGoogleUpdate,
763                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
764     DWORD last_check;
765     if (update_key.ReadValueDW(google_update::kRegLastCheckedField,
766                                &last_check) == ERROR_SUCCESS) {
767       return base::Time::FromTimeT(last_check);
768     }
769   }
770 
771   return base::Time();
772 }
773 
GetUpdateDetailForApp(bool system_install,const wchar_t * app_guid,ProductData * data)774 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install,
775                                                  const wchar_t* app_guid,
776                                                  ProductData* data) {
777   DCHECK(app_guid);
778   DCHECK(data);
779 
780   bool product_found = false;
781 
782   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
783   base::string16 clientstate_reg_path(google_update::kRegPathClientState);
784   clientstate_reg_path.append(L"\\");
785   clientstate_reg_path.append(app_guid);
786 
787   RegKey clientstate;
788   if (clientstate.Open(root_key,
789                        clientstate_reg_path.c_str(),
790                        KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
791     base::string16 version;
792     DWORD dword_value;
793     if ((clientstate.ReadValueDW(google_update::kRegLastCheckSuccessField,
794                                  &dword_value) == ERROR_SUCCESS) &&
795         (clientstate.ReadValue(google_update::kRegVersionField,
796                                &version) == ERROR_SUCCESS)) {
797       product_found = true;
798       data->version = base::UTF16ToASCII(version);
799       data->last_success = base::Time::FromTimeT(dword_value);
800       data->last_result = 0;
801       data->last_error_code = 0;
802       data->last_extra_code = 0;
803 
804       if (clientstate.ReadValueDW(google_update::kRegLastInstallerResultField,
805                                   &dword_value) == ERROR_SUCCESS) {
806         // Google Update convention is that if an installer writes an result
807         // code that is invalid, it is clamped to an exit code result.
808         const DWORD kMaxValidInstallResult = 4;  // INSTALLER_RESULT_EXIT_CODE
809         data->last_result = std::min(dword_value, kMaxValidInstallResult);
810       }
811       if (clientstate.ReadValueDW(google_update::kRegLastInstallerErrorField,
812                                   &dword_value) == ERROR_SUCCESS) {
813         data->last_error_code = dword_value;
814       }
815       if (clientstate.ReadValueDW(google_update::kRegLastInstallerExtraField,
816                                   &dword_value) == ERROR_SUCCESS) {
817         data->last_extra_code = dword_value;
818       }
819     }
820   }
821 
822   return product_found;
823 }
824 
GetUpdateDetailForGoogleUpdate(bool system_install,ProductData * data)825 bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install,
826                                                           ProductData* data) {
827   return GetUpdateDetailForApp(system_install,
828                                google_update::kGoogleUpdateUpgradeCode,
829                                data);
830 }
831 
GetUpdateDetail(bool system_install,ProductData * data)832 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install,
833                                            ProductData* data) {
834   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
835   return GetUpdateDetailForApp(system_install,
836                                dist->GetAppGuid().c_str(),
837                                data);
838 }
839 
SetExperimentLabels(bool system_install,const base::string16 & experiment_labels)840 bool GoogleUpdateSettings::SetExperimentLabels(
841     bool system_install,
842     const base::string16& experiment_labels) {
843   HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
844 
845   // Use the browser distribution and install level to write to the correct
846   // client state/app guid key.
847   bool success = false;
848   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
849   if (dist->ShouldSetExperimentLabels()) {
850     base::string16 client_state_path(
851         system_install ? dist->GetStateMediumKey() : dist->GetStateKey());
852     RegKey client_state(
853         reg_root, client_state_path.c_str(), KEY_SET_VALUE | KEY_WOW64_32KEY);
854     if (experiment_labels.empty()) {
855       success = client_state.DeleteValue(google_update::kExperimentLabels)
856           == ERROR_SUCCESS;
857     } else {
858       success = client_state.WriteValue(google_update::kExperimentLabels,
859           experiment_labels.c_str()) == ERROR_SUCCESS;
860     }
861   }
862 
863   return success;
864 }
865 
ReadExperimentLabels(bool system_install,base::string16 * experiment_labels)866 bool GoogleUpdateSettings::ReadExperimentLabels(
867     bool system_install,
868     base::string16* experiment_labels) {
869   HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
870 
871   // If this distribution does not set the experiment labels, don't bother
872   // reading.
873   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
874   if (!dist->ShouldSetExperimentLabels())
875     return false;
876 
877   base::string16 client_state_path(
878       system_install ? dist->GetStateMediumKey() : dist->GetStateKey());
879 
880   RegKey client_state;
881   LONG result = client_state.Open(
882       reg_root, client_state_path.c_str(), KEY_QUERY_VALUE | KEY_WOW64_32KEY);
883   if (result == ERROR_SUCCESS) {
884     result = client_state.ReadValue(google_update::kExperimentLabels,
885                                     experiment_labels);
886   }
887 
888   // If the key or value was not present, return the empty string.
889   if (result == ERROR_FILE_NOT_FOUND || result == ERROR_PATH_NOT_FOUND) {
890     experiment_labels->clear();
891     return true;
892   }
893 
894   return result == ERROR_SUCCESS;
895 }
896