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

Side by Side Diff: chrome/installer/util/experiment_labels.cc

Issue 2872583002: Adding ExperimentLabels helper class. (Closed)
Patch Set: Created 3 years, 7 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
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698