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/gcapi/gcapi_omaha_experiment.h" 6 7 #include "base/basictypes.h" 8 #include "base/strings/string_split.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/time/time.h" 13 #include "chrome/installer/gcapi/gcapi.h" 14 #include "chrome/installer/util/google_update_constants.h" 15 #include "chrome/installer/util/google_update_experiment_util.h" 16 #include "chrome/installer/util/google_update_settings.h" 17 18 namespace { 19 20 // Returns the number of weeks since 2/3/2003. 21 int GetCurrentRlzWeek(const base::Time& current_time) { 22 base::Time::Exploded february_third_2003_exploded = 23 {2003, 2, 1, 3, 0, 0, 0, 0}; 24 base::Time f = base::Time::FromUTCExploded(february_third_2003_exploded); 25 base::TimeDelta delta = current_time - f; 26 return delta.InDays() / 7; 27 } 28 29 bool SetExperimentLabel(const wchar_t* brand_code, 30 const base::string16& label, 31 int shell_mode) { 32 if (!brand_code) { 33 return false; 34 } 35 36 const bool system_level = shell_mode == GCAPI_INVOKED_UAC_ELEVATION; 37 38 base::string16 original_labels; 39 if (!GoogleUpdateSettings::ReadExperimentLabels(system_level, 40 &original_labels)) { 41 return false; 42 } 43 44 // Split the original labels by the label separator. 45 std::vector<base::string16> entries; 46 base::SplitString(original_labels, google_update::kExperimentLabelSeparator, 47 &entries); 48 49 // Keep all labels, but the one we want to add/replace. 50 base::string16 new_labels; 51 for (std::vector<base::string16>::const_iterator it = entries.begin(); 52 it != entries.end(); ++it) { 53 if (!it->empty() && !StartsWith(*it, label + L"=", true)) { 54 new_labels += *it; 55 new_labels += google_update::kExperimentLabelSeparator; 56 } 57 } 58 59 new_labels.append( 60 gcapi_internals::GetGCAPIExperimentLabel(brand_code, label)); 61 62 return GoogleUpdateSettings::SetExperimentLabels(system_level, 63 new_labels); 64 } 65 66 } // namespace 67 68 namespace gcapi_internals { 69 70 const wchar_t kReactivationLabel[] = L"reacbrand"; 71 const wchar_t kRelaunchLabel[] = L"relaunchbrand"; 72 73 base::string16 GetGCAPIExperimentLabel(const wchar_t* brand_code, 74 const base::string16& label) { 75 // Keeps a fixed time state for this GCAPI instance; this makes tests reliable 76 // when crossing time boundaries on the system clock and doesn't otherwise 77 // affect results of this short lived binary. 78 static time_t instance_time_value = 0; 79 if (instance_time_value == 0) 80 instance_time_value = base::Time::Now().ToTimeT(); 81 82 base::Time instance_time = base::Time::FromTimeT(instance_time_value); 83 84 base::string16 gcapi_experiment_label; 85 base::SStringPrintf(&gcapi_experiment_label, 86 L"%ls=%ls_%d|%ls", 87 label.c_str(), 88 brand_code, 89 GetCurrentRlzWeek(instance_time), 90 installer::BuildExperimentDateString( 91 instance_time).c_str()); 92 return gcapi_experiment_label; 93 } 94 95 } // namespace gcapi_internals 96 97 bool SetReactivationExperimentLabels(const wchar_t* brand_code, 98 int shell_mode) { 99 return SetExperimentLabel(brand_code, gcapi_internals::kReactivationLabel, 100 shell_mode); 101 } 102 103 bool SetRelaunchExperimentLabels(const wchar_t* brand_code, int shell_mode) { 104 return SetExperimentLabel(brand_code, gcapi_internals::kRelaunchLabel, 105 shell_mode); 106 } 107