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

Unified Diff: chrome/installer/util/experiment_labels.cc

Issue 2872583002: Adding ExperimentLabels helper class. (Closed)
Patch Set: pmonette comments 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/installer/util/experiment_labels.h ('k') | chrome/installer/util/experiment_labels_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/util/experiment_labels.cc
diff --git a/chrome/installer/util/experiment_labels.cc b/chrome/installer/util/experiment_labels.cc
new file mode 100644
index 0000000000000000000000000000000000000000..de30328ed51b2b03631db8503e0bda3036ab06dc
--- /dev/null
+++ b/chrome/installer/util/experiment_labels.cc
@@ -0,0 +1,150 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/installer/util/experiment_labels.h"
+
+#include <vector>
+
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+
+namespace installer {
+
+namespace {
+
+constexpr base::StringPiece16::value_type kNameValueSeparator = L'=';
+constexpr base::StringPiece16::value_type kValueExpirationSeparator = L'|';
+constexpr base::StringPiece16::value_type kLabelSeparator = L';';
+
+// Returns a vector of string pieces, one for each "name=value|expiration"
+// group in |value|.
+std::vector<base::StringPiece16> Parse(base::StringPiece16 value) {
+ static constexpr base::char16 kLabelSeparatorString[] = {kLabelSeparator,
+ L'\0'};
+ return base::SplitStringPiece(value, kLabelSeparatorString,
+ base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
+}
+
+// Returns an abbreviated day name for a zero-based |day_of_week|.
+const wchar_t* AbbreviatedDayOfWeek(int day_of_week) {
+ // Matches the abbreviated day names from the ICU "en" locale.
+ static constexpr const wchar_t* kDays[] = {L"Sun", L"Mon", L"Tue", L"Wed",
+ L"Thu", L"Fri", L"Sat"};
+ return kDays[day_of_week];
+}
+
+// Returns an abbreviated month name for a one-based |month|.
+const wchar_t* AbbreviatedMonth(int month) {
+ // Matches the abbreviated month names from the ICU "en" locale.
+ static constexpr const wchar_t* kMonths[] = {L"Jan", L"Feb", L"Mar", L"Apr",
+ L"May", L"Jun", L"Jul", L"Aug",
+ L"Sep", L"Oct", L"Nov", L"Dec"};
+ return kMonths[month - 1];
+}
+
+// Returns a formatted string given a date that is compatible with Omaha (see
+// https://github.com/google/omaha/blob/master/omaha/base/time.cc#L132).
+base::string16 FormatDate(base::Time date) {
+ base::Time::Exploded exploded_time;
+ date.UTCExplode(&exploded_time);
+
+ // "Fri, 14 Aug 2015 16:13:03 GMT"
+ return base::StringPrintf(L"%ls, %02d %ls %04d %02d:%02d:%02d GMT",
+ AbbreviatedDayOfWeek(exploded_time.day_of_week),
+ exploded_time.day_of_month,
+ AbbreviatedMonth(exploded_time.month),
+ exploded_time.year, exploded_time.hour,
+ exploded_time.minute, exploded_time.second);
+}
+
+// Appends "label_name=label_value|expiration" to |label|.
+void AppendLabel(base::StringPiece16 label_name,
+ base::StringPiece16 label_value,
+ base::Time expiration,
+ base::string16* label) {
+ // 29 characters for the expiration date plus the two separators makes 31.
+ label->reserve(label->size() + label_name.size() + label_value.size() + 31);
+ label_name.AppendToString(label);
+ label->push_back(kNameValueSeparator);
+ label_value.AppendToString(label);
+ label->push_back(kValueExpirationSeparator);
+ label->append(FormatDate(expiration));
+}
+
+} // namespace
+
+ExperimentLabels::ExperimentLabels(const base::string16& value)
+ : value_(value) {}
+
+base::StringPiece16 ExperimentLabels::GetValueForLabel(
+ base::StringPiece16 label_name) const {
+ DCHECK(!label_name.empty());
+
+ return FindLabel(label_name).second;
+}
+
+void ExperimentLabels::SetValueForLabel(base::StringPiece16 label_name,
+ base::StringPiece16 label_value,
+ base::TimeDelta lifetime) {
+ DCHECK(!label_name.empty());
+ DCHECK(!label_value.empty());
+ DCHECK(!lifetime.is_zero());
+
+ SetValueForLabel(label_name, label_value, base::Time::Now() + lifetime);
+}
+
+void ExperimentLabels::SetValueForLabel(base::StringPiece16 label_name,
+ base::StringPiece16 label_value,
+ base::Time expiration) {
+ DCHECK(!label_name.empty());
+ DCHECK(!label_value.empty());
+
+ LabelAndValue label_and_value = FindLabel(label_name);
+ if (label_and_value.first.empty()) {
+ // This label doesn't already exist -- append it to the raw value.
+ if (!value_.empty())
+ value_.push_back(kLabelSeparator);
+ AppendLabel(label_name, label_value, expiration, &value_);
+ } else {
+ // Replace the existing value and expiration.
+ // Get the stuff before the old label.
+ base::string16 new_label(value_, 0,
+ label_and_value.first.data() - value_.data());
+ // Append the new label.
+ AppendLabel(label_name, label_value, expiration, &new_label);
+ // Find the stuff after the old label and append it.
+ size_t next_separator = value_.find(
+ kLabelSeparator,
+ (label_and_value.second.data() + label_and_value.second.size()) -
+ value_.data());
+ if (next_separator != base::string16::npos)
+ new_label.append(value_, next_separator, base::string16::npos);
+ // Presto.
+ new_label.swap(value_);
+ }
+}
+
+ExperimentLabels::LabelAndValue ExperimentLabels::FindLabel(
+ base::StringPiece16 label_name) const {
+ DCHECK(!label_name.empty());
+
+ std::vector<base::StringPiece16> labels = Parse(value_);
+ for (const auto& label : labels) {
+ if (label.size() < label_name.size() + 2 ||
+ !label.starts_with(label_name) ||
+ label[label_name.size()] != kNameValueSeparator) {
+ continue;
+ }
+ size_t value_start = label_name.size() + 1;
+ size_t value_end = label.find(kValueExpirationSeparator, value_start);
+ if (value_end == base::StringPiece16::npos)
+ break;
+ return std::make_pair(label,
+ label.substr(value_start, value_end - value_start));
+ }
+ return LabelAndValue();
+}
+
+} // namespace installer
« no previous file with comments | « chrome/installer/util/experiment_labels.h ('k') | chrome/installer/util/experiment_labels_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698