OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "rlz/win/lib/rlz_value_store_registry.h" | 5 #include "rlz/chromeos/lib/rlz_value_store_chromeos.h" |
6 | 6 |
7 #include "base/win/registry.h" | 7 #include "base/file_path.h" |
8 #include "base/stringprintf.h" | 8 #include "base/file_util.h" |
9 #include "base/utf_string_conversions.h" | 9 #include "base/logging.h" |
10 #include "rlz/lib/assert.h" | 10 #include "base/memory/singleton.h" |
| 11 #include "base/prefs/json_pref_store.h" |
| 12 #include "base/sequenced_task_runner.h" |
| 13 #include "base/string_number_conversions.h" |
| 14 #include "base/values.h" |
11 #include "rlz/lib/lib_values.h" | 15 #include "rlz/lib/lib_values.h" |
| 16 #include "rlz/lib/recursive_lock.h" |
12 #include "rlz/lib/rlz_lib.h" | 17 #include "rlz/lib/rlz_lib.h" |
13 #include "rlz/lib/string_utils.h" | |
14 #include "rlz/win/lib/registry_util.h" | |
15 | 18 |
16 namespace rlz_lib { | 19 namespace rlz_lib { |
17 | 20 |
18 namespace { | 21 namespace { |
19 | 22 |
20 // | 23 // Product names. |
21 // Registry keys: | 24 const char kProductChrome[] = "chrome"; |
22 // | 25 const char kProductOther[] = "other"; |
23 // RLZ's are stored as: | 26 |
24 // <AccessPointName> = <RLZ value> @ kRootKey\kLibKeyName\kRlzsSubkeyName. | 27 // Key names. |
25 // | 28 const char kPingTimeKey[] = "ping_time"; |
26 // Events are stored as: | 29 const char kAccessPointKey[] = "access_points"; |
27 // <AccessPointName><EventName> = 1 @ | 30 const char kProductEventKey[] = "product_events"; |
28 // HKCU\kLibKeyName\kEventsSubkeyName\GetProductName(product). | 31 const char kStatefulEventKey[] = "stateful_events"; |
29 // | 32 |
30 // The OEM Deal Confirmation Code (DCC) is stored as | 33 // Brand name used when there is no supplementary brand name. |
31 // kDccValueName = <DCC value> @ HKLM\kLibKeyName | 34 const char kNoSupplementaryBrand[] = "_"; |
32 // | 35 |
33 // The last ping time, per product is stored as: | 36 // RLZ store filename. |
34 // GetProductName(product) = <last ping time> @ | 37 const FilePath::CharType kRLZDataFileName[] = FILE_PATH_LITERAL("RLZ Data"); |
35 // HKCU\kLibKeyName\kPingTimesSubkeyName. | 38 |
36 // | 39 // RLZ store path for testing. |
37 // The server does not care about any of these constants. | 40 FilePath g_testing_rlz_store_path_; |
38 // | 41 |
39 const char kLibKeyName[] = "Software\\Google\\Common\\Rlz"; | 42 // Returns file path of the RLZ storage. |
40 const wchar_t kGoogleKeyName[] = L"Software\\Google"; | 43 FilePath GetRlzStorePath() { |
41 const wchar_t kGoogleCommonKeyName[] = L"Software\\Google\\Common"; | 44 return g_testing_rlz_store_path_.empty() ? |
42 const char kRlzsSubkeyName[] = "RLZs"; | 45 file_util::GetHomeDir().Append(kRLZDataFileName) : |
43 const char kEventsSubkeyName[] = "Events"; | 46 g_testing_rlz_store_path_.Append(kRLZDataFileName); |
44 const char kStatefulEventsSubkeyName[] = "StatefulEvents"; | 47 } |
45 const char kPingTimesSubkeyName[] = "PTimes"; | 48 |
46 | 49 // Returns the dictionary key for storing access point-related prefs. |
47 std::wstring GetWideProductName(Product product) { | 50 std::string GetKeyName(std::string key, AccessPoint access_point) { |
48 return ASCIIToWide(GetProductName(product)); | 51 std::string brand = SupplementaryBranding::GetBrand(); |
49 } | 52 if (brand.empty()) |
50 | 53 brand = kNoSupplementaryBrand; |
51 void AppendBrandToString(std::string* str) { | 54 return key + "." + GetAccessPointName(access_point) + "." + brand; |
52 std::string brand(SupplementaryBranding::GetBrand()); | 55 } |
53 if (!brand.empty()) | 56 |
54 base::StringAppendF(str, "\\_%s", brand.c_str()); | 57 // Returns the dictionary key for storing product-related prefs. |
55 } | 58 std::string GetKeyName(std::string key, Product product) { |
56 | 59 std::string brand = SupplementaryBranding::GetBrand(); |
57 // Function to get the specific registry keys. | 60 if (brand.empty()) |
58 bool GetRegKey(const char* name, REGSAM access, base::win::RegKey* key) { | 61 brand = kNoSupplementaryBrand; |
59 std::string key_location; | 62 return key + "." + GetProductName(product) + "." + brand; |
60 base::StringAppendF(&key_location, "%s\\%s", kLibKeyName, name); | |
61 AppendBrandToString(&key_location); | |
62 | |
63 LONG ret = ERROR_SUCCESS; | |
64 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) { | |
65 ret = key->Create(HKEY_CURRENT_USER, ASCIIToWide(key_location).c_str(), | |
66 access); | |
67 } else { | |
68 ret = key->Open(HKEY_CURRENT_USER, ASCIIToWide(key_location).c_str(), | |
69 access); | |
70 } | |
71 | |
72 return ret == ERROR_SUCCESS; | |
73 } | |
74 | |
75 bool GetPingTimesRegKey(REGSAM access, base::win::RegKey* key) { | |
76 return GetRegKey(kPingTimesSubkeyName, access, key); | |
77 } | |
78 | |
79 | |
80 bool GetEventsRegKey(const char* event_type, | |
81 const rlz_lib::Product* product, | |
82 REGSAM access, base::win::RegKey* key) { | |
83 std::string key_location; | |
84 base::StringAppendF(&key_location, "%s\\%s", kLibKeyName, | |
85 event_type); | |
86 AppendBrandToString(&key_location); | |
87 | |
88 if (product != NULL) { | |
89 std::string product_name = GetProductName(*product); | |
90 if (product_name.empty()) | |
91 return false; | |
92 | |
93 base::StringAppendF(&key_location, "\\%s", product_name.c_str()); | |
94 } | |
95 | |
96 LONG ret = ERROR_SUCCESS; | |
97 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) { | |
98 ret = key->Create(HKEY_CURRENT_USER, ASCIIToWide(key_location).c_str(), | |
99 access); | |
100 } else { | |
101 ret = key->Open(HKEY_CURRENT_USER, ASCIIToWide(key_location).c_str(), | |
102 access); | |
103 } | |
104 | |
105 return ret == ERROR_SUCCESS; | |
106 } | |
107 | |
108 bool GetAccessPointRlzsRegKey(REGSAM access, base::win::RegKey* key) { | |
109 return GetRegKey(kRlzsSubkeyName, access, key); | |
110 } | |
111 | |
112 bool ClearAllProductEventValues(rlz_lib::Product product, const char* key) { | |
113 std::wstring product_name = GetWideProductName(product); | |
114 if (product_name.empty()) | |
115 return false; | |
116 | |
117 base::win::RegKey reg_key; | |
118 GetEventsRegKey(key, NULL, KEY_WRITE, ®_key); | |
119 reg_key.DeleteKey(product_name.c_str()); | |
120 | |
121 // Verify that the value no longer exists. | |
122 base::win::RegKey product_events( | |
123 reg_key.Handle(), product_name.c_str(), KEY_READ); | |
124 if (product_events.Valid()) { | |
125 ASSERT_STRING("ClearAllProductEvents: Key deletion failed"); | |
126 return false; | |
127 } | |
128 | |
129 return true; | |
130 } | |
131 | |
132 // Deletes a registry key if it exists and has no subkeys or values. | |
133 // TODO: Move this to a registry_utils file and add unittest. | |
134 bool DeleteKeyIfEmpty(HKEY root_key, const wchar_t* key_name) { | |
135 if (!key_name) { | |
136 ASSERT_STRING("DeleteKeyIfEmpty: key_name is NULL"); | |
137 return false; | |
138 } else { // Scope needed for RegKey | |
139 base::win::RegKey key(root_key, key_name, KEY_READ); | |
140 if (!key.Valid()) | |
141 return true; // Key does not exist - nothing to do. | |
142 | |
143 base::win::RegistryKeyIterator key_iter(root_key, key_name); | |
144 if (key_iter.SubkeyCount() > 0) | |
145 return true; // Not empty, so nothing to do | |
146 | |
147 base::win::RegistryValueIterator value_iter(root_key, key_name); | |
148 if (value_iter.ValueCount() > 0) | |
149 return true; // Not empty, so nothing to do | |
150 } | |
151 | |
152 // The key is empty - delete it now. | |
153 base::win::RegKey key(root_key, L"", KEY_WRITE); | |
154 return key.DeleteKey(key_name) == ERROR_SUCCESS; | |
155 } | 63 } |
156 | 64 |
157 } // namespace | 65 } // namespace |
158 | 66 |
159 // static | 67 // static |
160 std::wstring RlzValueStoreRegistry::GetWideLibKeyName() { | 68 base::SequencedTaskRunner* RlzValueStoreChromeOS::io_task_runner_ = NULL; |
161 return ASCIIToWide(kLibKeyName); | 69 |
162 } | 70 // static |
163 | 71 bool RlzValueStoreChromeOS::created_; |
164 bool RlzValueStoreRegistry::HasAccess(AccessType type) { | 72 |
165 return HasUserKeyAccess(type == kWriteAccess); | 73 // static |
166 } | 74 RlzValueStoreChromeOS* RlzValueStoreChromeOS::GetInstance() { |
167 | 75 return Singleton<RlzValueStoreChromeOS>::get(); |
168 bool RlzValueStoreRegistry::WritePingTime(Product product, int64 time) { | 76 } |
169 base::win::RegKey key; | 77 |
170 std::wstring product_name = GetWideProductName(product); | 78 // static |
171 return GetPingTimesRegKey(KEY_WRITE, &key) && | 79 void RlzValueStoreChromeOS::SetIOTaskRunner( |
172 key.WriteValue(product_name.c_str(), &time, sizeof(time), | 80 base::SequencedTaskRunner* io_task_runner) { |
173 REG_QWORD) == ERROR_SUCCESS; | 81 io_task_runner_ = io_task_runner; |
174 } | 82 // Make sure |io_task_runner_| lives until constructor is called. |
175 | 83 io_task_runner_->AddRef(); |
176 bool RlzValueStoreRegistry::ReadPingTime(Product product, int64* time) { | 84 } |
177 base::win::RegKey key; | 85 |
178 std::wstring product_name = GetWideProductName(product); | 86 // static |
179 return GetPingTimesRegKey(KEY_READ, &key) && | 87 void RlzValueStoreChromeOS::ResetForTesting() { |
180 key.ReadInt64(product_name.c_str(), time) == ERROR_SUCCESS; | 88 // Make sure we don't create an instance if it didn't exist. |
181 } | 89 if (created_) |
182 | 90 GetInstance()->ReadPrefs(); |
183 bool RlzValueStoreRegistry::ClearPingTime(Product product) { | 91 } |
184 base::win::RegKey key; | 92 |
185 GetPingTimesRegKey(KEY_WRITE, &key); | 93 RlzValueStoreChromeOS::RlzValueStoreChromeOS() { |
186 | 94 ReadPrefs(); |
187 std::wstring product_name = GetWideProductName(product); | 95 created_ = true; |
188 key.DeleteValue(product_name.c_str()); | 96 } |
189 | 97 |
190 // Verify deletion. | 98 RlzValueStoreChromeOS::~RlzValueStoreChromeOS() { |
191 uint64 value; | 99 } |
192 DWORD size = sizeof(value); | 100 |
193 if (key.ReadValue( | 101 bool RlzValueStoreChromeOS::HasAccess(AccessType type) { |
194 product_name.c_str(), &value, &size, NULL) == ERROR_SUCCESS) { | 102 return type == kReadAccess || !rlz_store_->ReadOnly(); |
195 ASSERT_STRING("RlzValueStoreRegistry::ClearPingTime: Failed to delete."); | 103 } |
196 return false; | 104 |
197 } | 105 bool RlzValueStoreChromeOS::WritePingTime(Product product, int64 time) { |
198 | 106 std::string value = base::Int64ToString(time); |
199 return true; | 107 rlz_store_->SetValue(GetKeyName(kPingTimeKey, product), |
200 } | 108 base::Value::CreateStringValue(value)); |
201 | 109 return true; |
202 bool RlzValueStoreRegistry::WriteAccessPointRlz(AccessPoint access_point, | 110 } |
| 111 |
| 112 bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64* time) { |
| 113 const base::Value* value = NULL; |
| 114 rlz_store_->GetValue(GetKeyName(kPingTimeKey, product), &value); |
| 115 std::string s_value; |
| 116 return value && value->GetAsString(&s_value) && |
| 117 base::StringToInt64(s_value, time); |
| 118 } |
| 119 |
| 120 bool RlzValueStoreChromeOS::ClearPingTime(Product product) { |
| 121 rlz_store_->RemoveValue(GetKeyName(kPingTimeKey, product)); |
| 122 return true; |
| 123 } |
| 124 |
| 125 bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point, |
203 const char* new_rlz) { | 126 const char* new_rlz) { |
204 const char* access_point_name = GetAccessPointName(access_point); | 127 rlz_store_->SetValue( |
205 if (!access_point_name) | 128 GetKeyName(kAccessPointKey, access_point), |
206 return false; | 129 base::Value::CreateStringValue(new_rlz)); |
207 | 130 return true; |
208 std::wstring access_point_name_wide(ASCIIToWide(access_point_name)); | 131 } |
209 base::win::RegKey key; | 132 |
210 GetAccessPointRlzsRegKey(KEY_WRITE, &key); | 133 bool RlzValueStoreChromeOS::ReadAccessPointRlz(AccessPoint access_point, |
211 | |
212 if (!RegKeyWriteValue(key, access_point_name_wide.c_str(), new_rlz)) { | |
213 ASSERT_STRING("SetAccessPointRlz: Could not write the new RLZ value"); | |
214 return false; | |
215 } | |
216 return true; | |
217 } | |
218 | |
219 bool RlzValueStoreRegistry::ReadAccessPointRlz(AccessPoint access_point, | |
220 char* rlz, | 134 char* rlz, |
221 size_t rlz_size) { | 135 size_t rlz_size) { |
222 const char* access_point_name = GetAccessPointName(access_point); | 136 const base::Value* value = NULL; |
223 if (!access_point_name) | 137 rlz_store_->GetValue( |
| 138 GetKeyName(kAccessPointKey, access_point), &value); |
| 139 std::string s_value; |
| 140 if (value) |
| 141 value->GetAsString(&s_value); |
| 142 if (s_value.size() < rlz_size) { |
| 143 strncpy(rlz, s_value.c_str(), rlz_size); |
| 144 return true; |
| 145 } |
| 146 if (rlz_size > 0) |
| 147 *rlz = '\0'; |
| 148 return false; |
| 149 } |
| 150 |
| 151 bool RlzValueStoreChromeOS::ClearAccessPointRlz(AccessPoint access_point) { |
| 152 rlz_store_->RemoveValue( |
| 153 GetKeyName(kAccessPointKey, access_point)); |
| 154 return true; |
| 155 } |
| 156 |
| 157 bool RlzValueStoreChromeOS::AddProductEvent(Product product, |
| 158 const char* event_rlz) { |
| 159 return AddValueToList(GetKeyName(kProductEventKey, product), |
| 160 base::Value::CreateStringValue(event_rlz)); |
| 161 } |
| 162 |
| 163 bool RlzValueStoreChromeOS::ReadProductEvents( |
| 164 Product product, |
| 165 std::vector<std::string>* events) { |
| 166 base::ListValue* events_list = GetList(GetKeyName(kProductEventKey, product)); |
| 167 if (!events_list) |
224 return false; | 168 return false; |
225 | 169 events->clear(); |
226 size_t size = rlz_size; | 170 for (size_t i = 0; i < events_list->GetSize(); ++i) { |
227 base::win::RegKey key; | 171 std::string event; |
228 GetAccessPointRlzsRegKey(KEY_READ, &key); | 172 if (events_list->GetString(i, &event)) |
229 if (!RegKeyReadValue(key, ASCIIToWide(access_point_name).c_str(), | 173 events->push_back(event); |
230 rlz, &size)) { | 174 } |
231 rlz[0] = 0; | 175 return true; |
232 if (size > rlz_size) { | 176 } |
233 ASSERT_STRING("GetAccessPointRlz: Insufficient buffer size"); | 177 |
234 return false; | 178 bool RlzValueStoreChromeOS::ClearProductEvent(Product product, |
235 } | 179 const char* event_rlz) { |
236 } | 180 base::StringValue event_value(event_rlz); |
237 return true; | 181 return RemoveValueFromList(GetKeyName(kProductEventKey, product), |
238 } | 182 event_value); |
239 | 183 } |
240 bool RlzValueStoreRegistry::ClearAccessPointRlz(AccessPoint access_point) { | 184 |
241 const char* access_point_name = GetAccessPointName(access_point); | 185 bool RlzValueStoreChromeOS::ClearAllProductEvents(Product product) { |
242 if (!access_point_name) | 186 rlz_store_->RemoveValue(GetKeyName(kProductEventKey, product)); |
| 187 return true; |
| 188 } |
| 189 |
| 190 bool RlzValueStoreChromeOS::AddStatefulEvent(Product product, |
| 191 const char* event_rlz) { |
| 192 return AddValueToList(GetKeyName(kStatefulEventKey, product), |
| 193 base::Value::CreateStringValue(event_rlz)); |
| 194 } |
| 195 |
| 196 bool RlzValueStoreChromeOS::IsStatefulEvent(Product product, |
| 197 const char* event_rlz) { |
| 198 base::ListValue* events_list = |
| 199 GetList(GetKeyName(kStatefulEventKey, product)); |
| 200 base::StringValue event_value(event_rlz); |
| 201 return events_list && events_list->Find(event_value) != events_list->end(); |
| 202 } |
| 203 |
| 204 bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) { |
| 205 rlz_store_->RemoveValue(GetKeyName(kStatefulEventKey, product)); |
| 206 return true; |
| 207 } |
| 208 |
| 209 void RlzValueStoreChromeOS::CollectGarbage() { |
| 210 NOTIMPLEMENTED(); |
| 211 } |
| 212 |
| 213 void RlzValueStoreChromeOS::ReadPrefs() { |
| 214 DCHECK(io_task_runner_) |
| 215 << "Calling GetInstance or ResetForTesting before SetIOTaskRunner?"; |
| 216 rlz_store_ = new JsonPrefStore(GetRlzStorePath(), io_task_runner_); |
| 217 rlz_store_->ReadPrefs(); |
| 218 switch (rlz_store_->GetReadError()) { |
| 219 case PersistentPrefStore::PREF_READ_ERROR_NONE: |
| 220 case PersistentPrefStore::PREF_READ_ERROR_NO_FILE: |
| 221 break; |
| 222 default: |
| 223 LOG(ERROR) << "Error read RLZ store: " << rlz_store_->GetReadError(); |
| 224 } |
| 225 // Restore refcount modified by SetIOTaskRunner(). |
| 226 io_task_runner_->Release(); |
| 227 io_task_runner_ = NULL; |
| 228 } |
| 229 |
| 230 base::ListValue* RlzValueStoreChromeOS::GetList(std::string list_name) { |
| 231 base::Value* list_value = NULL; |
| 232 rlz_store_->GetMutableValue(list_name, &list_value); |
| 233 base::ListValue* list = NULL; |
| 234 if (!list_value || !list_value->GetAsList(&list)) |
| 235 return NULL; |
| 236 return list; |
| 237 } |
| 238 |
| 239 bool RlzValueStoreChromeOS::AddValueToList(std::string list_name, |
| 240 base::Value* value) { |
| 241 base::ListValue* list = GetList(list_name); |
| 242 if (!list) { |
| 243 list = new base::ListValue; |
| 244 rlz_store_->SetValue(list_name, list); |
| 245 } |
| 246 if (list->AppendIfNotPresent(value)) |
| 247 rlz_store_->ReportValueChanged(list_name); |
| 248 return true; |
| 249 } |
| 250 |
| 251 bool RlzValueStoreChromeOS::RemoveValueFromList(std::string list_name, |
| 252 const base::Value& value) { |
| 253 base::ListValue* list = GetList(list_name); |
| 254 if (!list) |
243 return false; | 255 return false; |
244 | 256 rlz_store_->MarkNeedsEmptyValue(list_name); |
245 std::wstring access_point_name_wide(ASCIIToWide(access_point_name)); | 257 size_t index; |
246 base::win::RegKey key; | 258 if (list->Remove(value, &index)) |
247 GetAccessPointRlzsRegKey(KEY_WRITE, &key); | 259 rlz_store_->ReportValueChanged(list_name); |
248 | 260 return true; |
249 key.DeleteValue(access_point_name_wide.c_str()); | 261 } |
250 | 262 |
251 // Verify deletion. | 263 |
252 DWORD value; | 264 ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() |
253 if (key.ReadValueDW(access_point_name_wide.c_str(), &value) == | 265 : store_(RlzValueStoreChromeOS::GetInstance()) { |
254 ERROR_SUCCESS) { | 266 DCHECK(store_->CalledOnValidThread()); |
255 ASSERT_STRING("SetAccessPointRlz: Could not clear the RLZ value."); | |
256 return false; | |
257 } | |
258 return true; | |
259 } | |
260 | |
261 bool RlzValueStoreRegistry::AddProductEvent(Product product, | |
262 const char* event_rlz) { | |
263 std::wstring event_rlz_wide(ASCIIToWide(event_rlz)); | |
264 base::win::RegKey reg_key; | |
265 GetEventsRegKey(kEventsSubkeyName, &product, KEY_WRITE, ®_key); | |
266 if (reg_key.WriteValue(event_rlz_wide.c_str(), 1) != ERROR_SUCCESS) { | |
267 ASSERT_STRING("AddProductEvent: Could not write the new event value"); | |
268 return false; | |
269 } | |
270 | |
271 return true; | |
272 } | |
273 | |
274 bool RlzValueStoreRegistry::ReadProductEvents(Product product, | |
275 std::vector<std::string>* events) { | |
276 // Open the events key. | |
277 base::win::RegKey events_key; | |
278 GetEventsRegKey(kEventsSubkeyName, &product, KEY_READ, &events_key); | |
279 if (!events_key.Valid()) | |
280 return false; | |
281 | |
282 // Append the events to the buffer. | |
283 int num_values = 0; | |
284 LONG result = ERROR_SUCCESS; | |
285 for (num_values = 0; result == ERROR_SUCCESS; ++num_values) { | |
286 // Max 32767 bytes according to MSDN, but we never use that much. | |
287 const size_t kMaxValueNameLength = 2048; | |
288 char buffer[kMaxValueNameLength]; | |
289 DWORD size = arraysize(buffer); | |
290 | |
291 result = RegEnumValueA(events_key.Handle(), num_values, buffer, &size, | |
292 NULL, NULL, NULL, NULL); | |
293 if (result == ERROR_SUCCESS) | |
294 events->push_back(std::string(buffer)); | |
295 } | |
296 | |
297 return result == ERROR_NO_MORE_ITEMS; | |
298 } | |
299 | |
300 bool RlzValueStoreRegistry::ClearProductEvent(Product product, | |
301 const char* event_rlz) { | |
302 std::wstring event_rlz_wide(ASCIIToWide(event_rlz)); | |
303 base::win::RegKey key; | |
304 GetEventsRegKey(kEventsSubkeyName, &product, KEY_WRITE, &key); | |
305 key.DeleteValue(event_rlz_wide.c_str()); | |
306 | |
307 // Verify deletion. | |
308 DWORD value; | |
309 if (key.ReadValueDW(event_rlz_wide.c_str(), &value) == ERROR_SUCCESS) { | |
310 ASSERT_STRING("ClearProductEvent: Could not delete the event value."); | |
311 return false; | |
312 } | |
313 | |
314 return true; | |
315 } | |
316 | |
317 bool RlzValueStoreRegistry::ClearAllProductEvents(Product product) { | |
318 return ClearAllProductEventValues(product, kEventsSubkeyName); | |
319 } | |
320 | |
321 bool RlzValueStoreRegistry::AddStatefulEvent(Product product, | |
322 const char* event_rlz) { | |
323 base::win::RegKey key; | |
324 std::wstring event_rlz_wide(ASCIIToWide(event_rlz)); | |
325 if (!GetEventsRegKey(kStatefulEventsSubkeyName, &product, KEY_WRITE, &key) || | |
326 key.WriteValue(event_rlz_wide.c_str(), 1) != ERROR_SUCCESS) { | |
327 ASSERT_STRING( | |
328 "AddStatefulEvent: Could not write the new stateful event"); | |
329 return false; | |
330 } | |
331 | |
332 return true; | |
333 } | |
334 | |
335 bool RlzValueStoreRegistry::IsStatefulEvent(Product product, | |
336 const char* event_rlz) { | |
337 DWORD value; | |
338 base::win::RegKey key; | |
339 GetEventsRegKey(kStatefulEventsSubkeyName, &product, KEY_READ, &key); | |
340 std::wstring event_rlz_wide(ASCIIToWide(event_rlz)); | |
341 return key.ReadValueDW(event_rlz_wide.c_str(), &value) == ERROR_SUCCESS; | |
342 } | |
343 | |
344 bool RlzValueStoreRegistry::ClearAllStatefulEvents(Product product) { | |
345 return ClearAllProductEventValues(product, kStatefulEventsSubkeyName); | |
346 } | |
347 | |
348 void RlzValueStoreRegistry::CollectGarbage() { | |
349 // Delete each of the known subkeys if empty. | |
350 const char* subkeys[] = { | |
351 kRlzsSubkeyName, | |
352 kEventsSubkeyName, | |
353 kStatefulEventsSubkeyName, | |
354 kPingTimesSubkeyName | |
355 }; | |
356 | |
357 for (int i = 0; i < arraysize(subkeys); i++) { | |
358 std::string subkey_name; | |
359 base::StringAppendF(&subkey_name, "%s\\%s", kLibKeyName, subkeys[i]); | |
360 AppendBrandToString(&subkey_name); | |
361 | |
362 VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, | |
363 ASCIIToWide(subkey_name).c_str())); | |
364 } | |
365 | |
366 // Delete the library key and its parents too now if empty. | |
367 VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, GetWideLibKeyName().c_str())); | |
368 VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, kGoogleCommonKeyName)); | |
369 VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, kGoogleKeyName)); | |
370 } | |
371 | |
372 ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() { | |
373 if (!lock_.failed()) | |
374 store_.reset(new RlzValueStoreRegistry); | |
375 } | 267 } |
376 | 268 |
377 ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() { | 269 ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() { |
378 } | 270 } |
379 | 271 |
380 RlzValueStore* ScopedRlzValueStoreLock::GetStore() { | 272 RlzValueStore* ScopedRlzValueStoreLock::GetStore() { |
381 return store_.get(); | 273 return store_; |
382 } | 274 } |
| 275 |
| 276 namespace testing { |
| 277 |
| 278 void SetRlzStoreDirectory(const FilePath& directory) { |
| 279 g_testing_rlz_store_path_ = directory; |
| 280 } |
| 281 |
| 282 } // namespace testing |
383 | 283 |
384 } // namespace rlz_lib | 284 } // namespace rlz_lib |
OLD | NEW |