Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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/experiment_labels.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/strings/string_split.h" | |
| 10 #include "base/strings/stringprintf.h" | |
| 11 | |
| 12 namespace installer { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 constexpr base::StringPiece16::value_type kNameValueSeparator = L'='; | |
| 17 constexpr base::StringPiece16::value_type kValueExpirationSeparator = L'|'; | |
| 18 constexpr base::StringPiece16::value_type kLabelSeparator = L';'; | |
| 19 | |
| 20 // Returns a vector of string pieces, one for each "name=value|expiration" | |
| 21 // group in |value|. | |
| 22 std::vector<base::StringPiece16> Parse(base::StringPiece16 value) { | |
| 23 static constexpr base::char16 kLabelSeparatorString[] = {kLabelSeparator, | |
| 24 L'\0'}; | |
| 25 return base::SplitStringPiece(value, kLabelSeparatorString, | |
| 26 base::TRIM_WHITESPACE, | |
| 27 base::SPLIT_WANT_NONEMPTY); | |
| 28 } | |
| 29 | |
| 30 // Returns an abbreviated day name for a zero-based |day_of_week|. | |
| 31 const wchar_t* AbbreviatedDayOfWeek(int day_of_week) { | |
| 32 // Matches the abbreviated day names from the ICU "en" locale. | |
| 33 static constexpr const wchar_t* kDays[] = {L"Sun", L"Mon", L"Tue", L"Wed", | |
| 34 L"Thu", L"Fri", L"Sat"}; | |
| 35 return kDays[day_of_week]; | |
| 36 } | |
| 37 | |
| 38 // Returns an abbreviated month name for a one-based |month|. | |
| 39 const wchar_t* AbbreviatedMonth(int month) { | |
| 40 // Matches the abbreviated month names from the ICU "en" locale. | |
| 41 static constexpr const wchar_t* kMonths[] = {L"Jan", L"Feb", L"Mar", L"Apr", | |
| 42 L"May", L"Jun", L"Jul", L"Aug", | |
| 43 L"Sep", L"Oct", L"Nov", L"Dec"}; | |
| 44 return kMonths[month - 1]; | |
| 45 } | |
| 46 | |
| 47 // Returns an RFC822-compliant representation of an expiration date that is | |
| 48 // |lifetime| into the future. | |
|
Patrick Monette
2017/05/08 15:27:48
Rewrite comment to use |expiration| instead of |li
grt (UTC plus 2)
2017/05/08 20:15:25
Done.
| |
| 49 base::string16 FormatExpiration(base::Time expiration) { | |
| 50 base::Time::Exploded exploded_time; | |
| 51 expiration.UTCExplode(&exploded_time); | |
| 52 | |
| 53 // "Fri, 14 Aug 2015 16:13:03 GMT" | |
|
Patrick Monette
2017/05/08 15:27:48
It's weird that Omaha uses 4 digits for the year,
grt (UTC plus 2)
2017/05/08 20:15:26
Hmm, yeah. I've added pointers to the relevant Oma
| |
| 54 return base::StringPrintf(L"%ls, %02d %ls %04d %02d:%02d:%02d GMT", | |
| 55 AbbreviatedDayOfWeek(exploded_time.day_of_week), | |
| 56 exploded_time.day_of_month, | |
| 57 AbbreviatedMonth(exploded_time.month), | |
| 58 exploded_time.year, exploded_time.hour, | |
| 59 exploded_time.minute, exploded_time.second); | |
| 60 } | |
| 61 | |
| 62 // Appends "label_name=label_value|expiration" to |label|. | |
| 63 void AppendLabel(base::StringPiece16 label_name, | |
| 64 base::StringPiece16 label_value, | |
| 65 base::Time expiration, | |
| 66 base::string16* label) { | |
|
Patrick Monette
2017/05/08 15:27:48
Is it possible to use reserve() here?
Maybe not g
grt (UTC plus 2)
2017/05/08 20:15:25
Yes We Can!
| |
| 67 label_name.AppendToString(label); | |
| 68 label->push_back(kNameValueSeparator); | |
| 69 label_value.AppendToString(label); | |
| 70 label->push_back(kValueExpirationSeparator); | |
| 71 label->append(FormatExpiration(expiration)); | |
| 72 } | |
| 73 | |
| 74 } // namespace | |
| 75 | |
| 76 ExperimentLabels::ExperimentLabels(const base::string16& value) | |
| 77 : value_(value) {} | |
| 78 | |
| 79 base::StringPiece16 ExperimentLabels::GetValueForLabel( | |
| 80 base::StringPiece16 label_name) const { | |
| 81 DCHECK(!label_name.empty()); | |
| 82 | |
| 83 return FindLabel(label_name).second; | |
| 84 } | |
| 85 | |
| 86 void ExperimentLabels::SetValueForLabel(base::StringPiece16 label_name, | |
| 87 base::StringPiece16 label_value, | |
| 88 base::TimeDelta lifetime) { | |
| 89 DCHECK(!label_name.empty()); | |
| 90 DCHECK(!label_value.empty()); | |
| 91 DCHECK(!lifetime.is_zero()); // Alternatively, delete if lifetime is zero. | |
| 92 | |
| 93 SetValueForLabel(label_name, label_value, base::Time::Now() + lifetime); | |
| 94 } | |
| 95 | |
| 96 void ExperimentLabels::SetValueForLabel(base::StringPiece16 label_name, | |
| 97 base::StringPiece16 label_value, | |
| 98 base::Time expiration) { | |
| 99 DCHECK(!label_name.empty()); | |
| 100 DCHECK(!label_value.empty()); | |
| 101 | |
| 102 LabelAndValue label_and_value = FindLabel(label_name); | |
| 103 if (label_and_value.first.empty()) { | |
| 104 // This label doesn't already exist -- append it to the raw value. | |
| 105 if (!value_.empty()) | |
| 106 value_.push_back(kLabelSeparator); | |
| 107 AppendLabel(label_name, label_value, expiration, &value_); | |
| 108 } else { | |
| 109 // Replace the existing value and expiration. | |
| 110 // Get the stuff before the old label. | |
| 111 base::string16 new_label(value_, 0, | |
| 112 label_and_value.first.data() - value_.data()); | |
| 113 // Append the new label. | |
| 114 AppendLabel(label_name, label_value, expiration, &new_label); | |
| 115 // Find the stuff after the old label and append it. | |
| 116 size_t next_separator = value_.find( | |
| 117 kLabelSeparator, | |
| 118 (label_and_value.second.data() + label_and_value.second.size()) - | |
| 119 value_.data()); | |
| 120 if (next_separator != base::string16::npos) | |
| 121 new_label.append(value_, next_separator, base::string16::npos); | |
| 122 // Presto. | |
| 123 new_label.swap(value_); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 ExperimentLabels::LabelAndValue ExperimentLabels::FindLabel( | |
| 128 base::StringPiece16 label_name) const { | |
| 129 DCHECK(!label_name.empty()); | |
| 130 | |
| 131 std::vector<base::StringPiece16> labels = Parse(value_); | |
| 132 for (const auto& label : labels) { | |
| 133 if (label.size() < label_name.size() + 2 || | |
| 134 !label.starts_with(label_name) || | |
| 135 label[label_name.size()] != kNameValueSeparator) { | |
| 136 continue; | |
| 137 } | |
| 138 size_t value_start = label_name.size() + 1; | |
| 139 size_t value_end = label.find(kValueExpirationSeparator, value_start); | |
| 140 if (value_end == base::StringPiece16::npos) | |
| 141 break; | |
| 142 return std::make_pair(label, | |
| 143 label.substr(value_start, value_end - value_start)); | |
| 144 } | |
| 145 return LabelAndValue(); | |
| 146 } | |
| 147 | |
| 148 } // namespace installer | |
| OLD | NEW |