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 |