[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 1 | // Copyright 2013 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/common/metrics/variations/experiment_labels_win.h" |
| 6 | |
| 7 | #include "base/logging.h" |
| 8 | #include "base/strings/string_number_conversions.h" |
| 9 | #include "base/strings/string_split.h" |
| 10 | #include "base/strings/string_util.h" |
| 11 | #include "chrome/installer/util/google_update_constants.h" |
| 12 | #include "chrome/installer/util/google_update_experiment_util.h" |
| 13 | #include "components/variations/variations_associated_data.h" |
| 14 | |
| 15 | namespace chrome_variations { |
| 16 | |
| 17 | namespace { |
| 18 | |
| 19 | const wchar_t kVariationPrefix[] = L"CrVar"; |
| 20 | |
| 21 | // This method builds a single experiment label for a Chrome Variation, |
| 22 | // including a timestamp that is a year in the future from |current_time|. Since |
| 23 | // multiple headers can be transmitted, |count| is a number that is appended |
| 24 | // after the label key to differentiate the labels. |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 25 | base::string16 CreateSingleExperimentLabel(int count, VariationID id, |
| 26 | const base::Time& current_time) { |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 27 | // Build the parts separately so they can be validated. |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 28 | const base::string16 key = kVariationPrefix + base::IntToString16(count); |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 29 | DCHECK_LE(key.size(), 8U); |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 30 | const base::string16 value = base::IntToString16(id); |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 31 | DCHECK_LE(value.size(), 8U); |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 32 | base::string16 label(key); |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 33 | label += L'='; |
| 34 | label += value; |
| 35 | label += L'|'; |
| 36 | label += installer::BuildExperimentDateString(current_time); |
| 37 | return label; |
| 38 | } |
| 39 | |
| 40 | } // namespace |
| 41 | |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 42 | base::string16 BuildGoogleUpdateExperimentLabel( |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 43 | const base::FieldTrial::ActiveGroups& active_groups) { |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 44 | base::string16 experiment_labels; |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 45 | int counter = 0; |
| 46 | |
| 47 | const base::Time current_time(base::Time::Now()); |
| 48 | |
| 49 | // Find all currently active VariationIDs associated with Google Update. |
| 50 | for (base::FieldTrial::ActiveGroups::const_iterator it = |
| 51 | active_groups.begin(); it != active_groups.end(); ++it) { |
| 52 | const VariationID id = GetGoogleVariationID(GOOGLE_UPDATE_SERVICE, |
| 53 | it->trial_name, it->group_name); |
| 54 | |
| 55 | if (id == EMPTY_ID) |
| 56 | continue; |
| 57 | |
| 58 | if (!experiment_labels.empty()) |
| 59 | experiment_labels += google_update::kExperimentLabelSep; |
| 60 | experiment_labels += CreateSingleExperimentLabel(++counter, id, |
| 61 | current_time); |
| 62 | } |
| 63 | |
| 64 | return experiment_labels; |
| 65 | } |
| 66 | |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 67 | base::string16 ExtractNonVariationLabels(const base::string16& labels) { |
| 68 | base::string16 non_variation_labels; |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 69 | |
| 70 | // First, split everything by the label separator. |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 71 | std::vector<base::string16> entries; |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 72 | base::SplitStringUsingSubstr(labels, google_update::kExperimentLabelSep, |
| 73 | &entries); |
| 74 | |
| 75 | // For each label, keep the ones that do not look like a Variations label. |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 76 | for (std::vector<base::string16>::const_iterator it = entries.begin(); |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 77 | it != entries.end(); ++it) { |
| 78 | if (it->empty() || StartsWith(*it, kVariationPrefix, false)) |
| 79 | continue; |
| 80 | |
| 81 | // Dump the whole thing, including the timestamp. |
| 82 | if (!non_variation_labels.empty()) |
| 83 | non_variation_labels += google_update::kExperimentLabelSep; |
| 84 | non_variation_labels += *it; |
| 85 | } |
| 86 | |
| 87 | return non_variation_labels; |
| 88 | } |
| 89 | |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 90 | base::string16 CombineExperimentLabels(const base::string16& variation_labels, |
| 91 | const base::string16& other_labels) { |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 92 | DCHECK(!StartsWith(variation_labels, google_update::kExperimentLabelSep, |
| 93 | false)); |
| 94 | DCHECK(!EndsWith(variation_labels, google_update::kExperimentLabelSep, |
| 95 | false)); |
| 96 | DCHECK(!StartsWith(other_labels, google_update::kExperimentLabelSep, false)); |
| 97 | DCHECK(!EndsWith(other_labels, google_update::kExperimentLabelSep, false)); |
| 98 | // Note that if either label is empty, a separator is not necessary. |
[email protected] | 428fac1 | 2013-12-05 21:38:49 | [diff] [blame^] | 99 | base::string16 combined_labels = other_labels; |
[email protected] | 2134467 | 2013-11-07 06:04:28 | [diff] [blame] | 100 | if (!other_labels.empty() && !variation_labels.empty()) |
| 101 | combined_labels += google_update::kExperimentLabelSep; |
| 102 | combined_labels += variation_labels; |
| 103 | return combined_labels; |
| 104 | } |
| 105 | |
| 106 | } // namespace chrome_variations |