15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/chromeos/lib/rlz_value_store_chromeos.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/base_paths.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/important_file_writer.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_file_value_serializer.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_string_value_serializer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/path_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sequenced_task_runner.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/lib_values.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "rlz/lib/recursive_cross_process_lock_posix.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/rlz_lib.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace rlz_lib {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Key names.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPingTimeKey[] = "ping_time";
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAccessPointKey[] = "access_points";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kProductEventKey[] = "product_events";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kStatefulEventKey[] = "stateful_events";
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Brand name used when there is no supplementary brand name.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoSupplementaryBrand[] = "_";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RLZ store filename.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kRLZDataFileName[] =
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FILE_PATH_LITERAL("RLZ Data");
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RLZ store lock filename
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kRLZLockFileName[] =
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FILE_PATH_LITERAL("RLZ Data.lock");
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RLZ store path for testing.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath g_testing_rlz_store_path_;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns file path of the RLZ storage.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetRlzStorePath() {
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath homedir;
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PathService::Get(base::DIR_HOME, &homedir);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_testing_rlz_store_path_.empty() ?
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      homedir.Append(kRLZDataFileName) :
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_testing_rlz_store_path_.Append(kRLZDataFileName);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns file path of the RLZ storage lock file.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetRlzStoreLockPath() {
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath homedir;
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PathService::Get(base::DIR_HOME, &homedir);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_testing_rlz_store_path_.empty() ?
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      homedir.Append(kRLZLockFileName) :
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      g_testing_rlz_store_path_.Append(kRLZLockFileName);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the dictionary key for storing access point-related prefs.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetKeyName(std::string key, AccessPoint access_point) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string brand = SupplementaryBranding::GetBrand();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (brand.empty())
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    brand = kNoSupplementaryBrand;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return key + "." + GetAccessPointName(access_point) + "." + brand;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the dictionary key for storing product-related prefs.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetKeyName(std::string key, Product product) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string brand = SupplementaryBranding::GetBrand();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (brand.empty())
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    brand = kNoSupplementaryBrand;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return key + "." + GetProductName(product) + "." + brand;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RlzValueStoreChromeOS::RlzValueStoreChromeOS(const base::FilePath& store_path)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : rlz_store_(new base::DictionaryValue),
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      store_path_(store_path),
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_only_(true) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadStore();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RlzValueStoreChromeOS::~RlzValueStoreChromeOS() {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WriteStore();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::HasAccess(AccessType type) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return type == kReadAccess || !read_only_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::WritePingTime(Product product, int64 time) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->SetString(GetKeyName(kPingTimeKey, product),
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        base::Int64ToString(time));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64* time) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string ping_time;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rlz_store_->GetString(GetKeyName(kPingTimeKey, product), &ping_time) &&
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringToInt64(ping_time, time);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ClearPingTime(Product product) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->Remove(GetKeyName(kPingTimeKey, product), NULL);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const char* new_rlz) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->SetString(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetKeyName(kAccessPointKey, access_point), new_rlz);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ReadAccessPointRlz(AccessPoint access_point,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               char* rlz,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               size_t rlz_size) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string rlz_value;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->GetString(GetKeyName(kAccessPointKey, access_point), &rlz_value);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rlz_value.size() < rlz_size) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    strncpy(rlz, rlz_value.c_str(), rlz_size);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rlz_size > 0)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *rlz = '\0';
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ClearAccessPointRlz(AccessPoint access_point) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->Remove(GetKeyName(kAccessPointKey, access_point), NULL);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::AddProductEvent(Product product,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const char* event_rlz) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddValueToList(GetKeyName(kProductEventKey, product),
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        new base::StringValue(event_rlz));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ReadProductEvents(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Product product,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* events) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* events_list = NULL; ;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!rlz_store_->GetList(GetKeyName(kProductEventKey, product), &events_list))
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  events->clear();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < events_list->GetSize(); ++i) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string event;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (events_list->GetString(i, &event))
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      events->push_back(event);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ClearProductEvent(Product product,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const char* event_rlz) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue event_value(event_rlz);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RemoveValueFromList(GetKeyName(kProductEventKey, product),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             event_value);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ClearAllProductEvents(Product product) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->Remove(GetKeyName(kProductEventKey, product), NULL);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::AddStatefulEvent(Product product,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const char* event_rlz) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddValueToList(GetKeyName(kStatefulEventKey, product),
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        new base::StringValue(event_rlz));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::IsStatefulEvent(Product product,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const char* event_rlz) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue event_value(event_rlz);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* events_list = NULL;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rlz_store_->GetList(GetKeyName(kStatefulEventKey, product),
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             &events_list) &&
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      events_list->Find(event_value) != events_list->end();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rlz_store_->Remove(GetKeyName(kStatefulEventKey, product), NULL);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RlzValueStoreChromeOS::CollectGarbage() {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RlzValueStoreChromeOS::ReadStore() {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_code = 0;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error_msg;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JSONFileValueSerializer serializer(store_path_);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value(
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      serializer.Deserialize(&error_code, &error_msg));
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (error_code) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case JSONFileValueSerializer::JSON_NO_SUCH_FILE:
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_only_ = false;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case JSONFileValueSerializer::JSON_NO_ERROR:
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_only_ = false;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rlz_store_.reset(static_cast<base::DictionaryValue*>(value.release()));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error reading RLZ store: " << error_msg;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RlzValueStoreChromeOS::WriteStore() {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json_data;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JSONStringValueSerializer serializer(&json_data);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  serializer.set_pretty_print(true);
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> copy(
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      rlz_store_->DeepCopyWithoutEmptyChildren());
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!serializer.Serialize(*copy.get())) {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Failed to serialize RLZ data";
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!base::ImportantFileWriter::WriteFileAtomically(store_path_, json_data))
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Error writing RLZ store";
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::AddValueToList(std::string list_name,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Value* value) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* list_value = NULL;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!rlz_store_->GetList(list_name, &list_value)) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    list_value = new base::ListValue;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rlz_store_->Set(list_name, list_value);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  list_value->AppendIfNotPresent(value);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RlzValueStoreChromeOS::RemoveValueFromList(std::string list_name,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const base::Value& value) {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* list_value = NULL;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!rlz_store_->GetList(list_name, &list_value))
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  list_value->Remove(value, &index);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RlzValueStoreChromeOS keeps its data in memory and only writes it to disk
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// when ScopedRlzValueStoreLock goes out of scope. Hence, if several
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ScopedRlzValueStoreLocks are nested, they all need to use the same store
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// object.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RecursiveCrossProcessLock g_recursive_lock =
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RECURSIVE_CROSS_PROCESS_LOCK_INITIALIZER;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This counts the nesting depth of |ScopedRlzValueStoreLock|.
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int g_lock_depth = 0;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is the shared store object. Non-|NULL| only when |g_lock_depth > 0|.
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RlzValueStoreChromeOS* g_store = NULL;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() {
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool got_cross_process_lock =
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      g_recursive_lock.TryGetCrossProcessLock(GetRlzStoreLockPath());
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At this point, we hold the in-process lock, no matter the value of
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |got_cross_process_lock|.
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++g_lock_depth;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!got_cross_process_lock) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Acquiring cross-process lock failed, so simply return here.
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // In-process lock will be released in dtor.
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!g_store);
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_lock_depth > 1) {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Reuse the already existing store object.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(g_store);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    store_.reset(g_store);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is the topmost lock, create a new store object.
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!g_store);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_store = new RlzValueStoreChromeOS(GetRlzStorePath());
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  store_.reset(g_store);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  --g_lock_depth;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(g_lock_depth >= 0);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_lock_depth > 0) {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Other locks are still using store_, so don't free it yet.
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ignore_result(store_.release());
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_store = NULL;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_recursive_lock.ReleaseLock();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RlzValueStore* ScopedRlzValueStoreLock::GetStore() {
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return store_.get();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace testing {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetRlzStoreDirectory(const base::FilePath& directory) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_testing_rlz_store_path_ = directory;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string RlzStoreFilenameStr() {
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetRlzStorePath().value();
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace testing
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace rlz_lib
343