GaiaOAuthClient::Core::GetUserInfo() does not need to send or receive cookies.
[chromium-blink-merge.git] / rlz / chromeos / lib / rlz_value_store_chromeos.cc
blob06e4a54dbc9e95110243770f24b8e3ff6845ea21
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
3 // found in the LICENSE file.
5 #include "rlz/chromeos/lib/rlz_value_store_chromeos.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"
11 #include "base/logging.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/values.h"
15 #include "rlz/lib/lib_values.h"
16 #include "rlz/lib/recursive_cross_process_lock_posix.h"
17 #include "rlz/lib/rlz_lib.h"
19 namespace rlz_lib {
21 namespace {
23 // Key names.
24 const char kPingTimeKey[] = "ping_time";
25 const char kAccessPointKey[] = "access_points";
26 const char kProductEventKey[] = "product_events";
27 const char kStatefulEventKey[] = "stateful_events";
29 // Brand name used when there is no supplementary brand name.
30 const char kNoSupplementaryBrand[] = "_";
32 // RLZ store filename.
33 const base::FilePath::CharType kRLZDataFileName[] =
34 FILE_PATH_LITERAL("RLZ Data");
36 // RLZ store lock filename
37 const base::FilePath::CharType kRLZLockFileName[] =
38 FILE_PATH_LITERAL("RLZ Data.lock");
40 // RLZ store path for testing.
41 base::FilePath g_testing_rlz_store_path_;
43 // Returns file path of the RLZ storage.
44 base::FilePath GetRlzStorePath() {
45 return g_testing_rlz_store_path_.empty() ?
46 base::GetHomeDir().Append(kRLZDataFileName) :
47 g_testing_rlz_store_path_.Append(kRLZDataFileName);
50 // Returns file path of the RLZ storage lock file.
51 base::FilePath GetRlzStoreLockPath() {
52 return g_testing_rlz_store_path_.empty() ?
53 base::GetHomeDir().Append(kRLZLockFileName) :
54 g_testing_rlz_store_path_.Append(kRLZLockFileName);
57 // Returns the dictionary key for storing access point-related prefs.
58 std::string GetKeyName(std::string key, AccessPoint access_point) {
59 std::string brand = SupplementaryBranding::GetBrand();
60 if (brand.empty())
61 brand = kNoSupplementaryBrand;
62 return key + "." + GetAccessPointName(access_point) + "." + brand;
65 // Returns the dictionary key for storing product-related prefs.
66 std::string GetKeyName(std::string key, Product product) {
67 std::string brand = SupplementaryBranding::GetBrand();
68 if (brand.empty())
69 brand = kNoSupplementaryBrand;
70 return key + "." + GetProductName(product) + "." + brand;
73 } // namespace
75 RlzValueStoreChromeOS::RlzValueStoreChromeOS(const base::FilePath& store_path)
76 : rlz_store_(new base::DictionaryValue),
77 store_path_(store_path),
78 read_only_(true) {
79 ReadStore();
82 RlzValueStoreChromeOS::~RlzValueStoreChromeOS() {
83 WriteStore();
86 bool RlzValueStoreChromeOS::HasAccess(AccessType type) {
87 DCHECK(CalledOnValidThread());
88 return type == kReadAccess || !read_only_;
91 bool RlzValueStoreChromeOS::WritePingTime(Product product, int64 time) {
92 DCHECK(CalledOnValidThread());
93 rlz_store_->SetString(GetKeyName(kPingTimeKey, product),
94 base::Int64ToString(time));
95 return true;
98 bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64* time) {
99 DCHECK(CalledOnValidThread());
100 std::string ping_time;
101 return rlz_store_->GetString(GetKeyName(kPingTimeKey, product), &ping_time) &&
102 base::StringToInt64(ping_time, time);
105 bool RlzValueStoreChromeOS::ClearPingTime(Product product) {
106 DCHECK(CalledOnValidThread());
107 rlz_store_->Remove(GetKeyName(kPingTimeKey, product), NULL);
108 return true;
111 bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point,
112 const char* new_rlz) {
113 DCHECK(CalledOnValidThread());
114 rlz_store_->SetString(
115 GetKeyName(kAccessPointKey, access_point), new_rlz);
116 return true;
119 bool RlzValueStoreChromeOS::ReadAccessPointRlz(AccessPoint access_point,
120 char* rlz,
121 size_t rlz_size) {
122 DCHECK(CalledOnValidThread());
123 std::string rlz_value;
124 rlz_store_->GetString(GetKeyName(kAccessPointKey, access_point), &rlz_value);
125 if (rlz_value.size() < rlz_size) {
126 strncpy(rlz, rlz_value.c_str(), rlz_size);
127 return true;
129 if (rlz_size > 0)
130 *rlz = '\0';
131 return false;
134 bool RlzValueStoreChromeOS::ClearAccessPointRlz(AccessPoint access_point) {
135 DCHECK(CalledOnValidThread());
136 rlz_store_->Remove(GetKeyName(kAccessPointKey, access_point), NULL);
137 return true;
140 bool RlzValueStoreChromeOS::AddProductEvent(Product product,
141 const char* event_rlz) {
142 DCHECK(CalledOnValidThread());
143 return AddValueToList(GetKeyName(kProductEventKey, product),
144 base::Value::CreateStringValue(event_rlz));
147 bool RlzValueStoreChromeOS::ReadProductEvents(
148 Product product,
149 std::vector<std::string>* events) {
150 DCHECK(CalledOnValidThread());
151 base::ListValue* events_list = NULL; ;
152 if (!rlz_store_->GetList(GetKeyName(kProductEventKey, product), &events_list))
153 return false;
154 events->clear();
155 for (size_t i = 0; i < events_list->GetSize(); ++i) {
156 std::string event;
157 if (events_list->GetString(i, &event))
158 events->push_back(event);
160 return true;
163 bool RlzValueStoreChromeOS::ClearProductEvent(Product product,
164 const char* event_rlz) {
165 DCHECK(CalledOnValidThread());
166 base::StringValue event_value(event_rlz);
167 return RemoveValueFromList(GetKeyName(kProductEventKey, product),
168 event_value);
171 bool RlzValueStoreChromeOS::ClearAllProductEvents(Product product) {
172 DCHECK(CalledOnValidThread());
173 rlz_store_->Remove(GetKeyName(kProductEventKey, product), NULL);
174 return true;
177 bool RlzValueStoreChromeOS::AddStatefulEvent(Product product,
178 const char* event_rlz) {
179 DCHECK(CalledOnValidThread());
180 return AddValueToList(GetKeyName(kStatefulEventKey, product),
181 base::Value::CreateStringValue(event_rlz));
184 bool RlzValueStoreChromeOS::IsStatefulEvent(Product product,
185 const char* event_rlz) {
186 DCHECK(CalledOnValidThread());
187 base::StringValue event_value(event_rlz);
188 base::ListValue* events_list = NULL;
189 return rlz_store_->GetList(GetKeyName(kStatefulEventKey, product),
190 &events_list) &&
191 events_list->Find(event_value) != events_list->end();
194 bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) {
195 DCHECK(CalledOnValidThread());
196 rlz_store_->Remove(GetKeyName(kStatefulEventKey, product), NULL);
197 return true;
200 void RlzValueStoreChromeOS::CollectGarbage() {
201 DCHECK(CalledOnValidThread());
202 NOTIMPLEMENTED();
205 void RlzValueStoreChromeOS::ReadStore() {
206 int error_code = 0;
207 std::string error_msg;
208 JSONFileValueSerializer serializer(store_path_);
209 scoped_ptr<base::Value> value(
210 serializer.Deserialize(&error_code, &error_msg));
211 switch (error_code) {
212 case JSONFileValueSerializer::JSON_NO_SUCH_FILE:
213 read_only_ = false;
214 break;
215 case JSONFileValueSerializer::JSON_NO_ERROR:
216 read_only_ = false;
217 rlz_store_.reset(static_cast<base::DictionaryValue*>(value.release()));
218 break;
219 default:
220 LOG(ERROR) << "Error reading RLZ store: " << error_msg;
224 void RlzValueStoreChromeOS::WriteStore() {
225 std::string json_data;
226 JSONStringValueSerializer serializer(&json_data);
227 serializer.set_pretty_print(true);
228 scoped_ptr<DictionaryValue> copy(rlz_store_->DeepCopyWithoutEmptyChildren());
229 if (!serializer.Serialize(*copy.get())) {
230 LOG(ERROR) << "Failed to serialize RLZ data";
231 NOTREACHED();
232 return;
234 if (!base::ImportantFileWriter::WriteFileAtomically(store_path_, json_data))
235 LOG(ERROR) << "Error writing RLZ store";
238 bool RlzValueStoreChromeOS::AddValueToList(std::string list_name,
239 base::Value* value) {
240 base::ListValue* list_value = NULL;
241 if (!rlz_store_->GetList(list_name, &list_value)) {
242 list_value = new base::ListValue;
243 rlz_store_->Set(list_name, list_value);
245 list_value->AppendIfNotPresent(value);
246 return true;
249 bool RlzValueStoreChromeOS::RemoveValueFromList(std::string list_name,
250 const base::Value& value) {
251 base::ListValue* list_value = NULL;
252 if (!rlz_store_->GetList(list_name, &list_value))
253 return false;
254 size_t index;
255 list_value->Remove(value, &index);
256 return true;
259 namespace {
261 // RlzValueStoreChromeOS keeps its data in memory and only writes it to disk
262 // when ScopedRlzValueStoreLock goes out of scope. Hence, if several
263 // ScopedRlzValueStoreLocks are nested, they all need to use the same store
264 // object.
266 RecursiveCrossProcessLock g_recursive_lock =
267 RECURSIVE_CROSS_PROCESS_LOCK_INITIALIZER;
269 // This counts the nesting depth of |ScopedRlzValueStoreLock|.
270 int g_lock_depth = 0;
272 // This is the shared store object. Non-|NULL| only when |g_lock_depth > 0|.
273 RlzValueStoreChromeOS* g_store = NULL;
275 } // namespace
277 ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() {
278 bool got_cross_process_lock =
279 g_recursive_lock.TryGetCrossProcessLock(GetRlzStoreLockPath());
280 // At this point, we hold the in-process lock, no matter the value of
281 // |got_cross_process_lock|.
283 ++g_lock_depth;
284 if (!got_cross_process_lock) {
285 // Acquiring cross-process lock failed, so simply return here.
286 // In-process lock will be released in dtor.
287 DCHECK(!g_store);
288 return;
291 if (g_lock_depth > 1) {
292 // Reuse the already existing store object.
293 DCHECK(g_store);
294 store_.reset(g_store);
295 return;
298 // This is the topmost lock, create a new store object.
299 DCHECK(!g_store);
300 g_store = new RlzValueStoreChromeOS(GetRlzStorePath());
301 store_.reset(g_store);
304 ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() {
305 --g_lock_depth;
306 DCHECK(g_lock_depth >= 0);
308 if (g_lock_depth > 0) {
309 // Other locks are still using store_, so don't free it yet.
310 ignore_result(store_.release());
311 return;
314 g_store = NULL;
316 g_recursive_lock.ReleaseLock();
319 RlzValueStore* ScopedRlzValueStoreLock::GetStore() {
320 return store_.get();
323 namespace testing {
325 void SetRlzStoreDirectory(const base::FilePath& directory) {
326 g_testing_rlz_store_path_ = directory;
329 std::string RlzStoreFilenameStr() {
330 return GetRlzStorePath().value();
333 } // namespace testing
335 } // namespace rlz_lib