blob: cb75f1fbc1619536723af6b64ada09d3834b051d [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "login_manager/pref_store.h"
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/file_path.h>
#include <base/file_util.h>
#include <base/logging.h>
#include <base/values.h>
#include "login_manager/system_utils.h"
namespace login_manager {
// static
const char PrefStore::kWhitelistPrefix[] = "whitelist";
// static
const char PrefStore::kPropertiesPrefix[] = "properties";
// static
const char PrefStore::kValueField[] = ".value";
// static
const char PrefStore::kSignatureField[] = ".signature";
// static
const char PrefStore::kDefaultPath[] = "/var/lib/whitelist/preferences";
PrefStore::PrefStore(const FilePath& prefs_path)
: prefs_(NULL),
prefs_path_(prefs_path) {
}
PrefStore::~PrefStore() {}
bool PrefStore::LoadOrCreate() {
// These will all get blown away if we get a valid dictionary.
prefs_.reset(new DictionaryValue);
whitelist_ = new DictionaryValue;
properties_ = new DictionaryValue;
// prefs_ takes ownership of whitelist_ and properties_ here.
prefs_->Set(kWhitelistPrefix, whitelist_);
prefs_->Set(kPropertiesPrefix, properties_);
if (!file_util::PathExists(prefs_path_)) {
return true;
}
std::string json;
if (!file_util::ReadFileToString(prefs_path_, &json)) {
PLOG(ERROR) << "Could not read prefs off disk: ";
return false;
}
int error_code = 0;
std::string error;
// I take ownership of |new_dict|.
scoped_ptr<Value> new_val(base::JSONReader::ReadAndReturnError(json,
false,
&error_code,
&error));
if (!new_val.get()) {
LOG(ERROR) << "Could not parse prefs off disk: " << error;
return false;
}
if (!new_val->IsType(Value::TYPE_DICTIONARY)) {
LOG(ERROR) << "Prefs file wasn't a dictionary!";
return false;
}
DictionaryValue* new_dict = static_cast<DictionaryValue*>(new_val.get());
if (!new_dict->GetDictionary(kWhitelistPrefix, &whitelist_)) {
LOG(ERROR) << "Prefs file had no whitelist sub-dictionary.";
return false;
}
if (!new_dict->GetDictionary(kPropertiesPrefix, &properties_)) {
LOG(ERROR) << "Prefs file had no properties sub-dictionary.";
return false;
}
prefs_.reset(static_cast<DictionaryValue*>(new_val.release()));
return true;
}
bool PrefStore::Persist() {
std::string json;
base::JSONWriter::Write(prefs_.get(),
true /* pretty print, for now */,
&json);
SystemUtils utils;
return utils.AtomicFileWrite(prefs_path_, json.c_str(), json.length());
}
void PrefStore::Whitelist(const std::string& name,
const std::string& signature) {
StringValue* signature_value = new StringValue(signature);
whitelist_->SetWithoutPathExpansion(name, signature_value);
}
void PrefStore::Unwhitelist(const std::string& name) {
// Passing NULL causes the value to get nuked.
whitelist_->RemoveWithoutPathExpansion(name, NULL);
}
bool PrefStore::GetFromWhitelist(const std::string& name,
std::string* signature_out) {
CHECK(signature_out);
return whitelist_->GetStringWithoutPathExpansion(name, signature_out);
}
void PrefStore::EnumerateWhitelisted(std::vector<std::string>* list_out) {
CHECK(list_out) << "OUT_list cannot be NULL";
for (DictionaryValue::key_iterator key(whitelist_->begin_keys());
key != whitelist_->end_keys(); ++key) {
list_out->push_back(*key);
}
}
void PrefStore::Set(const std::string& name,
const std::string& value,
const std::string& signature) {
std::string value_key = name + kValueField;
std::string signature_key = name + kSignatureField;
properties_->SetString(value_key, value);
properties_->SetString(signature_key, signature);
}
bool PrefStore::Get(const std::string& name,
std::string* value_out,
std::string* signature_out) {
CHECK(value_out);
CHECK(signature_out);
std::string value_key = name + kValueField;
std::string signature_key = name + kSignatureField;
bool rv = properties_->GetString(value_key, value_out);
return rv && properties_->GetString(signature_key, signature_out);
}
bool PrefStore::Remove(const std::string& name,
std::string* value_out,
std::string* signature_out) {
CHECK(value_out);
CHECK(signature_out);
std::string value_key = name + kValueField;
std::string signature_key = name + kSignatureField;
bool rv = RemoveOneString(value_key, value_out);
return rv && RemoveOneString(signature_key, signature_out);
}
void PrefStore::Delete(const std::string& name) {
std::string value_key = name + kValueField;
std::string signature_key = name + kSignatureField;
properties_->Remove(value_key, NULL);
properties_->Remove(signature_key, NULL);
}
bool PrefStore::RemoveOneString(const std::string& key, std::string* out) {
CHECK(out);
Value* tmp;
if (!properties_->Remove(key, &tmp))
return false;
// now, I own the removed object.
bool rv = tmp->GetAsString(out);
delete tmp;
return rv;
}
} // namespace login_manager