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/chromeos/lib/rlz_value_store_chromeos.h" | 5 #include "rlz/chromeos/lib/rlz_value_store_chromeos.h" |
6 | 6 |
7 #include "base/file_path.h" | |
8 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/important_file_writer.h" |
| 9 #include "base/json/json_file_value_serializer.h" |
| 10 #include "base/json/json_string_value_serializer.h" |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "base/memory/singleton.h" | |
11 #include "base/prefs/json_pref_store.h" | |
12 #include "base/sequenced_task_runner.h" | 12 #include "base/sequenced_task_runner.h" |
13 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "rlz/lib/lib_values.h" | 15 #include "rlz/lib/lib_values.h" |
16 #include "rlz/lib/recursive_lock.h" | 16 #include "rlz/lib/recursive_cross_process_lock_posix.h" |
17 #include "rlz/lib/rlz_lib.h" | 17 #include "rlz/lib/rlz_lib.h" |
18 | 18 |
19 namespace rlz_lib { | 19 namespace rlz_lib { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // Product names. | 23 // Product names. |
24 const char kProductChrome[] = "chrome"; | 24 const char kProductChrome[] = "chrome"; |
25 const char kProductOther[] = "other"; | 25 const char kProductOther[] = "other"; |
26 | 26 |
27 // Key names. | 27 // Key names. |
28 const char kPingTimeKey[] = "ping_time"; | 28 const char kPingTimeKey[] = "ping_time"; |
29 const char kAccessPointKey[] = "access_points"; | 29 const char kAccessPointKey[] = "access_points"; |
30 const char kProductEventKey[] = "product_events"; | 30 const char kProductEventKey[] = "product_events"; |
31 const char kStatefulEventKey[] = "stateful_events"; | 31 const char kStatefulEventKey[] = "stateful_events"; |
32 | 32 |
33 // Brand name used when there is no supplementary brand name. | 33 // Brand name used when there is no supplementary brand name. |
34 const char kNoSupplementaryBrand[] = "_"; | 34 const char kNoSupplementaryBrand[] = "_"; |
35 | 35 |
36 // RLZ store filename. | 36 // RLZ store filename. |
37 const FilePath::CharType kRLZDataFileName[] = FILE_PATH_LITERAL("RLZ Data"); | 37 const FilePath::CharType kRLZDataFileName[] = FILE_PATH_LITERAL("RLZ Data"); |
38 | 38 |
| 39 // RLZ store lock filename |
| 40 const FilePath::CharType kRLZLockFileName[] = |
| 41 FILE_PATH_LITERAL("RLZ Data.lock"); |
| 42 |
39 // RLZ store path for testing. | 43 // RLZ store path for testing. |
40 FilePath g_testing_rlz_store_path_; | 44 FilePath g_testing_rlz_store_path_; |
41 | 45 |
42 // Returns file path of the RLZ storage. | 46 // Returns file path of the RLZ storage. |
43 FilePath GetRlzStorePath() { | 47 FilePath GetRlzStorePath() { |
44 return g_testing_rlz_store_path_.empty() ? | 48 return g_testing_rlz_store_path_.empty() ? |
45 file_util::GetHomeDir().Append(kRLZDataFileName) : | 49 file_util::GetHomeDir().Append(kRLZDataFileName) : |
46 g_testing_rlz_store_path_.Append(kRLZDataFileName); | 50 g_testing_rlz_store_path_.Append(kRLZDataFileName); |
47 } | 51 } |
48 | 52 |
| 53 // Returns file path of the RLZ storage lock file. |
| 54 FilePath GetRlzStoreLockPath() { |
| 55 return g_testing_rlz_store_path_.empty() ? |
| 56 file_util::GetHomeDir().Append(kRLZLockFileName) : |
| 57 g_testing_rlz_store_path_.Append(kRLZLockFileName); |
| 58 } |
| 59 |
49 // Returns the dictionary key for storing access point-related prefs. | 60 // Returns the dictionary key for storing access point-related prefs. |
50 std::string GetKeyName(std::string key, AccessPoint access_point) { | 61 std::string GetKeyName(std::string key, AccessPoint access_point) { |
51 std::string brand = SupplementaryBranding::GetBrand(); | 62 std::string brand = SupplementaryBranding::GetBrand(); |
52 if (brand.empty()) | 63 if (brand.empty()) |
53 brand = kNoSupplementaryBrand; | 64 brand = kNoSupplementaryBrand; |
54 return key + "." + GetAccessPointName(access_point) + "." + brand; | 65 return key + "." + GetAccessPointName(access_point) + "." + brand; |
55 } | 66 } |
56 | 67 |
57 // Returns the dictionary key for storing product-related prefs. | 68 // Returns the dictionary key for storing product-related prefs. |
58 std::string GetKeyName(std::string key, Product product) { | 69 std::string GetKeyName(std::string key, Product product) { |
59 std::string brand = SupplementaryBranding::GetBrand(); | 70 std::string brand = SupplementaryBranding::GetBrand(); |
60 if (brand.empty()) | 71 if (brand.empty()) |
61 brand = kNoSupplementaryBrand; | 72 brand = kNoSupplementaryBrand; |
62 return key + "." + GetProductName(product) + "." + brand; | 73 return key + "." + GetProductName(product) + "." + brand; |
63 } | 74 } |
64 | 75 |
65 } // namespace | 76 } // namespace |
66 | 77 |
67 // static | 78 RlzValueStoreChromeOS::RlzValueStoreChromeOS(const FilePath& store_path) |
68 base::SequencedTaskRunner* RlzValueStoreChromeOS::io_task_runner_ = NULL; | 79 : rlz_store_(new base::DictionaryValue), |
69 | 80 store_path_(store_path), |
70 // static | 81 read_only_(true) { |
71 bool RlzValueStoreChromeOS::created_; | 82 ReadStore(); |
72 | |
73 // static | |
74 RlzValueStoreChromeOS* RlzValueStoreChromeOS::GetInstance() { | |
75 return Singleton<RlzValueStoreChromeOS>::get(); | |
76 } | |
77 | |
78 // static | |
79 void RlzValueStoreChromeOS::SetIOTaskRunner( | |
80 base::SequencedTaskRunner* io_task_runner) { | |
81 io_task_runner_ = io_task_runner; | |
82 // Make sure |io_task_runner_| lives until constructor is called. | |
83 io_task_runner_->AddRef(); | |
84 } | |
85 | |
86 // static | |
87 void RlzValueStoreChromeOS::ResetForTesting() { | |
88 // Make sure we don't create an instance if it didn't exist. | |
89 if (created_) | |
90 GetInstance()->ReadPrefs(); | |
91 } | |
92 | |
93 // static | |
94 void RlzValueStoreChromeOS::Cleanup() { | |
95 if (created_) | |
96 GetInstance()->rlz_store_ = NULL; | |
97 } | |
98 | |
99 RlzValueStoreChromeOS::RlzValueStoreChromeOS() { | |
100 ReadPrefs(); | |
101 created_ = true; | |
102 } | 83 } |
103 | 84 |
104 RlzValueStoreChromeOS::~RlzValueStoreChromeOS() { | 85 RlzValueStoreChromeOS::~RlzValueStoreChromeOS() { |
| 86 WriteStore(); |
105 } | 87 } |
106 | 88 |
107 bool RlzValueStoreChromeOS::HasAccess(AccessType type) { | 89 bool RlzValueStoreChromeOS::HasAccess(AccessType type) { |
108 return type == kReadAccess || !rlz_store_->ReadOnly(); | 90 DCHECK(CalledOnValidThread()); |
| 91 return type == kReadAccess || !read_only_; |
109 } | 92 } |
110 | 93 |
111 bool RlzValueStoreChromeOS::WritePingTime(Product product, int64 time) { | 94 bool RlzValueStoreChromeOS::WritePingTime(Product product, int64 time) { |
112 std::string value = base::Int64ToString(time); | 95 DCHECK(CalledOnValidThread()); |
113 rlz_store_->SetValue(GetKeyName(kPingTimeKey, product), | 96 rlz_store_->SetString(GetKeyName(kPingTimeKey, product), |
114 base::Value::CreateStringValue(value)); | 97 base::Int64ToString(time)); |
115 return true; | 98 return true; |
116 } | 99 } |
117 | 100 |
118 bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64* time) { | 101 bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64* time) { |
119 const base::Value* value = NULL; | 102 DCHECK(CalledOnValidThread()); |
120 rlz_store_->GetValue(GetKeyName(kPingTimeKey, product), &value); | 103 std::string ping_time; |
121 std::string s_value; | 104 return rlz_store_->GetString(GetKeyName(kPingTimeKey, product), &ping_time) && |
122 return value && value->GetAsString(&s_value) && | 105 base::StringToInt64(ping_time, time); |
123 base::StringToInt64(s_value, time); | |
124 } | 106 } |
125 | 107 |
126 bool RlzValueStoreChromeOS::ClearPingTime(Product product) { | 108 bool RlzValueStoreChromeOS::ClearPingTime(Product product) { |
127 rlz_store_->RemoveValue(GetKeyName(kPingTimeKey, product)); | 109 DCHECK(CalledOnValidThread()); |
| 110 rlz_store_->Remove(GetKeyName(kPingTimeKey, product), NULL); |
128 return true; | 111 return true; |
129 } | 112 } |
130 | 113 |
131 bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point, | 114 bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point, |
132 const char* new_rlz) { | 115 const char* new_rlz) { |
133 rlz_store_->SetValue( | 116 DCHECK(CalledOnValidThread()); |
134 GetKeyName(kAccessPointKey, access_point), | 117 rlz_store_->SetString( |
135 base::Value::CreateStringValue(new_rlz)); | 118 GetKeyName(kAccessPointKey, access_point), new_rlz); |
136 return true; | 119 return true; |
137 } | 120 } |
138 | 121 |
139 bool RlzValueStoreChromeOS::ReadAccessPointRlz(AccessPoint access_point, | 122 bool RlzValueStoreChromeOS::ReadAccessPointRlz(AccessPoint access_point, |
140 char* rlz, | 123 char* rlz, |
141 size_t rlz_size) { | 124 size_t rlz_size) { |
142 const base::Value* value = NULL; | 125 DCHECK(CalledOnValidThread()); |
143 rlz_store_->GetValue( | 126 std::string rlz_value; |
144 GetKeyName(kAccessPointKey, access_point), &value); | 127 rlz_store_->GetString(GetKeyName(kAccessPointKey, access_point), &rlz_value); |
145 std::string s_value; | 128 if (rlz_value.size() < rlz_size) { |
146 if (value) | 129 strncpy(rlz, rlz_value.c_str(), rlz_size); |
147 value->GetAsString(&s_value); | |
148 if (s_value.size() < rlz_size) { | |
149 strncpy(rlz, s_value.c_str(), rlz_size); | |
150 return true; | 130 return true; |
151 } | 131 } |
152 if (rlz_size > 0) | 132 if (rlz_size > 0) |
153 *rlz = '\0'; | 133 *rlz = '\0'; |
154 return false; | 134 return false; |
155 } | 135 } |
156 | 136 |
157 bool RlzValueStoreChromeOS::ClearAccessPointRlz(AccessPoint access_point) { | 137 bool RlzValueStoreChromeOS::ClearAccessPointRlz(AccessPoint access_point) { |
158 rlz_store_->RemoveValue( | 138 DCHECK(CalledOnValidThread()); |
159 GetKeyName(kAccessPointKey, access_point)); | 139 rlz_store_->Remove(GetKeyName(kAccessPointKey, access_point), NULL); |
160 return true; | 140 return true; |
161 } | 141 } |
162 | 142 |
163 bool RlzValueStoreChromeOS::AddProductEvent(Product product, | 143 bool RlzValueStoreChromeOS::AddProductEvent(Product product, |
164 const char* event_rlz) { | 144 const char* event_rlz) { |
| 145 DCHECK(CalledOnValidThread()); |
165 return AddValueToList(GetKeyName(kProductEventKey, product), | 146 return AddValueToList(GetKeyName(kProductEventKey, product), |
166 base::Value::CreateStringValue(event_rlz)); | 147 base::Value::CreateStringValue(event_rlz)); |
167 } | 148 } |
168 | 149 |
169 bool RlzValueStoreChromeOS::ReadProductEvents( | 150 bool RlzValueStoreChromeOS::ReadProductEvents( |
170 Product product, | 151 Product product, |
171 std::vector<std::string>* events) { | 152 std::vector<std::string>* events) { |
172 base::ListValue* events_list = GetList(GetKeyName(kProductEventKey, product)); | 153 DCHECK(CalledOnValidThread()); |
173 if (!events_list) | 154 base::ListValue* events_list = NULL; ; |
| 155 if (!rlz_store_->GetList(GetKeyName(kProductEventKey, product), &events_list)) |
174 return false; | 156 return false; |
175 events->clear(); | 157 events->clear(); |
176 for (size_t i = 0; i < events_list->GetSize(); ++i) { | 158 for (size_t i = 0; i < events_list->GetSize(); ++i) { |
177 std::string event; | 159 std::string event; |
178 if (events_list->GetString(i, &event)) | 160 if (events_list->GetString(i, &event)) |
179 events->push_back(event); | 161 events->push_back(event); |
180 } | 162 } |
181 return true; | 163 return true; |
182 } | 164 } |
183 | 165 |
184 bool RlzValueStoreChromeOS::ClearProductEvent(Product product, | 166 bool RlzValueStoreChromeOS::ClearProductEvent(Product product, |
185 const char* event_rlz) { | 167 const char* event_rlz) { |
| 168 DCHECK(CalledOnValidThread()); |
186 base::StringValue event_value(event_rlz); | 169 base::StringValue event_value(event_rlz); |
187 return RemoveValueFromList(GetKeyName(kProductEventKey, product), | 170 return RemoveValueFromList(GetKeyName(kProductEventKey, product), |
188 event_value); | 171 event_value); |
189 } | 172 } |
190 | 173 |
191 bool RlzValueStoreChromeOS::ClearAllProductEvents(Product product) { | 174 bool RlzValueStoreChromeOS::ClearAllProductEvents(Product product) { |
192 rlz_store_->RemoveValue(GetKeyName(kProductEventKey, product)); | 175 DCHECK(CalledOnValidThread()); |
| 176 rlz_store_->Remove(GetKeyName(kProductEventKey, product), NULL); |
193 return true; | 177 return true; |
194 } | 178 } |
195 | 179 |
196 bool RlzValueStoreChromeOS::AddStatefulEvent(Product product, | 180 bool RlzValueStoreChromeOS::AddStatefulEvent(Product product, |
197 const char* event_rlz) { | 181 const char* event_rlz) { |
| 182 DCHECK(CalledOnValidThread()); |
198 return AddValueToList(GetKeyName(kStatefulEventKey, product), | 183 return AddValueToList(GetKeyName(kStatefulEventKey, product), |
199 base::Value::CreateStringValue(event_rlz)); | 184 base::Value::CreateStringValue(event_rlz)); |
200 } | 185 } |
201 | 186 |
202 bool RlzValueStoreChromeOS::IsStatefulEvent(Product product, | 187 bool RlzValueStoreChromeOS::IsStatefulEvent(Product product, |
203 const char* event_rlz) { | 188 const char* event_rlz) { |
204 base::ListValue* events_list = | 189 DCHECK(CalledOnValidThread()); |
205 GetList(GetKeyName(kStatefulEventKey, product)); | |
206 base::StringValue event_value(event_rlz); | 190 base::StringValue event_value(event_rlz); |
207 return events_list && events_list->Find(event_value) != events_list->end(); | 191 base::ListValue* events_list = NULL; |
| 192 return rlz_store_->GetList(GetKeyName(kStatefulEventKey, product), |
| 193 &events_list) && |
| 194 events_list->Find(event_value) != events_list->end(); |
208 } | 195 } |
209 | 196 |
210 bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) { | 197 bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) { |
211 rlz_store_->RemoveValue(GetKeyName(kStatefulEventKey, product)); | 198 DCHECK(CalledOnValidThread()); |
| 199 rlz_store_->Remove(GetKeyName(kStatefulEventKey, product), NULL); |
212 return true; | 200 return true; |
213 } | 201 } |
214 | 202 |
215 void RlzValueStoreChromeOS::CollectGarbage() { | 203 void RlzValueStoreChromeOS::CollectGarbage() { |
| 204 DCHECK(CalledOnValidThread()); |
216 NOTIMPLEMENTED(); | 205 NOTIMPLEMENTED(); |
217 } | 206 } |
218 | 207 |
219 void RlzValueStoreChromeOS::ReadPrefs() { | 208 void RlzValueStoreChromeOS::ReadStore() { |
220 DCHECK(io_task_runner_) | 209 int error_code = 0; |
221 << "Calling GetInstance or ResetForTesting before SetIOTaskRunner?"; | 210 std::string error_msg; |
222 rlz_store_ = new JsonPrefStore(GetRlzStorePath(), io_task_runner_); | 211 JSONFileValueSerializer serializer(store_path_); |
223 rlz_store_->ReadPrefs(); | 212 scoped_ptr<base::Value> value( |
224 switch (rlz_store_->GetReadError()) { | 213 serializer.Deserialize(&error_code, &error_msg)); |
225 case PersistentPrefStore::PREF_READ_ERROR_NONE: | 214 switch (error_code) { |
226 case PersistentPrefStore::PREF_READ_ERROR_NO_FILE: | 215 case JSONFileValueSerializer::JSON_NO_SUCH_FILE: |
| 216 read_only_ = false; |
| 217 break; |
| 218 case JSONFileValueSerializer::JSON_NO_ERROR: |
| 219 read_only_ = false; |
| 220 rlz_store_.reset(static_cast<base::DictionaryValue*>(value.release())); |
227 break; | 221 break; |
228 default: | 222 default: |
229 LOG(ERROR) << "Error read RLZ store: " << rlz_store_->GetReadError(); | 223 LOG(ERROR) << "Error reading RLZ store: " << error_msg; |
230 } | 224 } |
231 // Restore refcount modified by SetIOTaskRunner(). | |
232 io_task_runner_->Release(); | |
233 io_task_runner_ = NULL; | |
234 } | 225 } |
235 | 226 |
236 base::ListValue* RlzValueStoreChromeOS::GetList(std::string list_name) { | 227 void RlzValueStoreChromeOS::WriteStore() { |
237 base::Value* list_value = NULL; | 228 std::string json_data; |
238 rlz_store_->GetMutableValue(list_name, &list_value); | 229 JSONStringValueSerializer serializer(&json_data); |
239 base::ListValue* list = NULL; | 230 serializer.set_pretty_print(true); |
240 if (!list_value || !list_value->GetAsList(&list)) | 231 scoped_ptr<DictionaryValue> copy(rlz_store_->DeepCopyWithoutEmptyChildren()); |
241 return NULL; | 232 if (!serializer.Serialize(*copy.get())) { |
242 return list; | 233 LOG(ERROR) << "Failed to serialize RLZ data"; |
| 234 NOTREACHED(); |
| 235 return; |
| 236 } |
| 237 if (!base::ImportantFileWriter::WriteFileAtomically(store_path_, json_data)) |
| 238 LOG(ERROR) << "Error writing RLZ store"; |
243 } | 239 } |
244 | 240 |
245 bool RlzValueStoreChromeOS::AddValueToList(std::string list_name, | 241 bool RlzValueStoreChromeOS::AddValueToList(std::string list_name, |
246 base::Value* value) { | 242 base::Value* value) { |
247 base::ListValue* list = GetList(list_name); | 243 base::ListValue* list_value = NULL; |
248 if (!list) { | 244 if (!rlz_store_->GetList(list_name, &list_value)) { |
249 list = new base::ListValue; | 245 list_value = new base::ListValue; |
250 rlz_store_->SetValue(list_name, list); | 246 rlz_store_->Set(list_name, list_value); |
251 } | 247 } |
252 if (list->AppendIfNotPresent(value)) | 248 list_value->AppendIfNotPresent(value); |
253 rlz_store_->ReportValueChanged(list_name); | |
254 return true; | 249 return true; |
255 } | 250 } |
256 | 251 |
257 bool RlzValueStoreChromeOS::RemoveValueFromList(std::string list_name, | 252 bool RlzValueStoreChromeOS::RemoveValueFromList(std::string list_name, |
258 const base::Value& value) { | 253 const base::Value& value) { |
259 base::ListValue* list = GetList(list_name); | 254 base::ListValue* list_value = NULL; |
260 if (!list) | 255 if (!rlz_store_->GetList(list_name, &list_value)) |
261 return false; | 256 return false; |
262 rlz_store_->MarkNeedsEmptyValue(list_name); | |
263 size_t index; | 257 size_t index; |
264 if (list->Remove(value, &index)) | 258 list_value->Remove(value, &index); |
265 rlz_store_->ReportValueChanged(list_name); | |
266 return true; | 259 return true; |
267 } | 260 } |
268 | 261 |
| 262 namespace { |
269 | 263 |
270 ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() | 264 // RlzValueStoreChromeOS keeps its data in memory and only writes it to disk |
271 : store_(RlzValueStoreChromeOS::GetInstance()) { | 265 // when ScopedRlzValueStoreLock goes out of scope. Hence, if several |
| 266 // ScopedRlzValueStoreLocks are nested, they all need to use the same store |
| 267 // object. |
| 268 |
| 269 RecursiveCrossProcessLock g_recursive_lock = |
| 270 RECURSIVE_CROSS_PROCESS_LOCK_INITIALIZER; |
| 271 |
| 272 // This counts the nesting depth of |ScopedRlzValueStoreLock|. |
| 273 int g_lock_depth = 0; |
| 274 |
| 275 // This is the shared store object. Non-|NULL| only when |g_lock_depth > 0|. |
| 276 RlzValueStoreChromeOS* g_store = NULL; |
| 277 |
| 278 } // namespace |
| 279 |
| 280 ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() { |
| 281 bool got_cross_process_lock = |
| 282 g_recursive_lock.TryGetCrossProcessLock(GetRlzStoreLockPath()); |
| 283 // At this point, we hold the in-process lock, no matter the value of |
| 284 // |got_cross_process_lock|. |
| 285 |
| 286 ++g_lock_depth; |
| 287 if (!got_cross_process_lock) { |
| 288 // Acquiring cross-process lock failed, so simply return here. |
| 289 // In-process lock will be released in dtor. |
| 290 DCHECK(!g_store); |
| 291 return; |
| 292 } |
| 293 |
| 294 if (g_lock_depth > 1) { |
| 295 // Reuse the already existing store object. |
| 296 DCHECK(g_store); |
| 297 store_.reset(g_store); |
| 298 return; |
| 299 } |
| 300 |
| 301 // This is the topmost lock, create a new store object. |
| 302 DCHECK(!g_store); |
| 303 g_store = new RlzValueStoreChromeOS(GetRlzStorePath()); |
| 304 store_.reset(g_store); |
272 } | 305 } |
273 | 306 |
274 ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() { | 307 ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() { |
| 308 --g_lock_depth; |
| 309 DCHECK(g_lock_depth >= 0); |
| 310 |
| 311 if (g_lock_depth > 0) { |
| 312 // Other locks are still using store_, so don't free it yet. |
| 313 ignore_result(store_.release()); |
| 314 return; |
| 315 } |
| 316 |
| 317 g_store = NULL; |
| 318 |
| 319 g_recursive_lock.ReleaseLock(); |
275 } | 320 } |
276 | 321 |
277 RlzValueStore* ScopedRlzValueStoreLock::GetStore() { | 322 RlzValueStore* ScopedRlzValueStoreLock::GetStore() { |
278 return store_; | 323 return store_.get(); |
279 } | 324 } |
280 | 325 |
281 namespace testing { | 326 namespace testing { |
282 | 327 |
283 void SetRlzStoreDirectory(const FilePath& directory) { | 328 void SetRlzStoreDirectory(const FilePath& directory) { |
284 g_testing_rlz_store_path_ = directory; | 329 g_testing_rlz_store_path_ = directory; |
285 } | 330 } |
286 | 331 |
| 332 std::string RlzStoreFilenameStr() { |
| 333 return GetRlzStorePath().value(); |
| 334 } |
| 335 |
287 } // namespace testing | 336 } // namespace testing |
288 | 337 |
289 } // namespace rlz_lib | 338 } // namespace rlz_lib |
OLD | NEW |