| OLD | NEW |
| (Empty) |
| 1 // Copyright 2011 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 | |
| 16 // Utility class to manage a set of experiment labels. Experiment labels | |
| 17 // are a set of key/value pairs used to track an install's "membership" in | |
| 18 // A/B experiment groups issued by the Omaha server. Keys are strings with | |
| 19 // a limited character set (Perl \w, plus a few characters), while values | |
| 20 // consist of a string and an expiration date. Label sets are stored per-app | |
| 21 // and transmitted to the server as part of requests (pings / update checks), | |
| 22 // and a delta is potentially returned from the server with each response. | |
| 23 // | |
| 24 // Experiment labels are serialized with key/value separated by an equals, and | |
| 25 // value/expiration by a pipe symbol; the expiration is represented in RFC822 | |
| 26 // format. For example: "test_key=test_value|Fri, 14 Aug 2015 16:13:03 GMT". | |
| 27 // If an app participates in multiple experiments simultaneously, labels are | |
| 28 // concatenated with semicolon delimiters. | |
| 29 | |
| 30 #ifndef OMAHA_COMMON_EXPERIMENT_LABELS_H_ | |
| 31 #define OMAHA_COMMON_EXPERIMENT_LABELS_H_ | |
| 32 | |
| 33 #include <atlstr.h> | |
| 34 | |
| 35 #include <map> | |
| 36 #include <utility> | |
| 37 | |
| 38 #include "base/basictypes.h" | |
| 39 #include "omaha/base/time.h" | |
| 40 | |
| 41 namespace omaha { | |
| 42 | |
| 43 class ExperimentLabels { | |
| 44 public: | |
| 45 ExperimentLabels(); | |
| 46 ~ExperimentLabels(); | |
| 47 | |
| 48 // Returns the number of labels in the store. | |
| 49 int NumLabels() const; | |
| 50 | |
| 51 // Returns true if a label with this key exists in the store. | |
| 52 bool ContainsKey(const CString& key) const; | |
| 53 | |
| 54 // Returns the contents of the Nth label in the experiment set. Output | |
| 55 // parameters are allowed to be NULL. If index is out of range, asserts | |
| 56 // on a debug build. | |
| 57 // | |
| 58 // NOTE: This method is O(n), and indexes are not stable with respect to | |
| 59 // insertion order; it should not be called from any hot path. Unit tests | |
| 60 // and diagnostic tools should use this to enumerate keys. | |
| 61 void GetLabelByIndex(int index, | |
| 62 CString* key, | |
| 63 CString* value, | |
| 64 time64* expiration) const; | |
| 65 | |
| 66 // If a label with this key exists, returns true and writes the value and | |
| 67 // expiration to the output parameters. Output parameters are allowed | |
| 68 // to be NULL. If no such key exists, returns false and leaves the outputs | |
| 69 // unchanged. | |
| 70 bool FindLabelByKey(const CString& key, | |
| 71 CString* value, | |
| 72 time64* expiration) const; | |
| 73 | |
| 74 // Attempts to set a label in the store, either adding a new one or updating | |
| 75 // the value/expiration of an existing one. Returns true on success. | |
| 76 bool SetLabel(const CString& key, const CString& value, time64 expiration); | |
| 77 | |
| 78 // Clears a label in the store. Returns true if a label with that key exists | |
| 79 // (it is removed); returns false if no label with that key exists. | |
| 80 bool ClearLabel(const CString& key); | |
| 81 | |
| 82 // Removes any labels from the store whose expiration dates have passed. | |
| 83 void ExpireLabels(); | |
| 84 | |
| 85 // Removes all labels from the store. | |
| 86 void ClearAllLabels(); | |
| 87 | |
| 88 // Concatenates and emits all labels in the store in an XML-friendly format. | |
| 89 CString Serialize() const; | |
| 90 | |
| 91 // Replaces the current contents of the store with new labels from an | |
| 92 // XML-friendly string. On success, returns true; the store reflects the | |
| 93 // input exactly, with all prior contents are lost. On failure, returns | |
| 94 // false and the store's contents are unchanged. | |
| 95 bool Deserialize(const CString& label_list); | |
| 96 | |
| 97 // Applies the contents of a label list as a delta against the current | |
| 98 // contents of the store. On success, returns true, and: | |
| 99 // * Any expired labels in the list are deleted from the store. | |
| 100 // * Unexpired labels in the list will be added to the store. If any keys | |
| 101 // already exist in the store, they are overwritten with the input. | |
| 102 // * Labels that are in the store but not in the input are left unmodified. | |
| 103 // On failure, returns false, and the store's contents are unchanged. | |
| 104 // This function's behavior is not modified by SetPreserveExpiredLabels()! | |
| 105 bool DeserializeAndApplyDelta(const CString& label_list); | |
| 106 | |
| 107 // Modifies the store's handling of labels with expiration dates in the past. | |
| 108 // By default, SetLabel() will fail to add expired labels, Deserialize() will | |
| 109 // silently discard them, and Serialize() will not emit them. Following a | |
| 110 // call to SetPreserveExpiredLabels(true), these functions will accept and/or | |
| 111 // include expired labels. | |
| 112 void SetPreserveExpiredLabels(bool preserve); | |
| 113 | |
| 114 // Serializes a set of experiment labels to application data in the Registry. | |
| 115 HRESULT WriteToRegistry(bool is_machine, const CString& app_id); | |
| 116 | |
| 117 // Deserializes a set of experiment labels from the Registry. | |
| 118 HRESULT ReadFromRegistry(bool is_machine, const CString& app_id); | |
| 119 | |
| 120 // Returns true if the supplied string is a valid experiment label set. | |
| 121 static bool IsStringValidLabelSet(const CString& label_list); | |
| 122 | |
| 123 private: | |
| 124 typedef std::map<CString, std::pair<CString, time64> > LabelMap; | |
| 125 | |
| 126 // Returns true if all characters are in the range [a-zA-Z0-9_\-+,: ]. | |
| 127 // (Perl \w, plus the punctuation necessary for RFC822 dates.) | |
| 128 static bool IsLabelContentValid(const CString& str); | |
| 129 | |
| 130 // Given an input string of the form "key=value|rfc822_date", converts it | |
| 131 // into separate key, value, and integer expiration dates. | |
| 132 static bool SplitCombinedLabel(const CString& combined, | |
| 133 CString* key, | |
| 134 CString* value, | |
| 135 time64* expiration); | |
| 136 | |
| 137 // Splits an input string and applies it against an existing internal map. | |
| 138 static bool DoDeserialize(LabelMap* map, | |
| 139 const CString& label_list, | |
| 140 bool accept_expired); | |
| 141 | |
| 142 LabelMap labels_; | |
| 143 bool preserve_expired_; | |
| 144 | |
| 145 DISALLOW_COPY_AND_ASSIGN(ExperimentLabels); | |
| 146 }; | |
| 147 | |
| 148 } // namespace omaha | |
| 149 | |
| 150 #endif // OMAHA_COMMON_EXPERIMENT_LABELS_H_ | |
| 151 | |
| OLD | NEW |