1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 163003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/prefs.h" 183003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 19d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo#include <algorithm> 20d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo 2106c76a49bfd29c8abdb8abd5b646a6583783191aBen Chan#include <base/files/file_util.h> 22362757765e7697dd93e8de05fa0a59f29242eb89Darin Petkov#include <base/logging.h> 2375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_number_conversions.h> 2475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h> 25362757765e7697dd93e8de05fa0a59f29242eb89Darin Petkov 2639910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 273003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 283003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkovusing std::string; 293003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 303003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkovnamespace chromeos_update_engine { 313003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 32a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::GetString(const string& key, string* value) const { 33a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return storage_->GetKey(key, value); 343003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 353003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 36a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::SetString(const string& key, const string& value) { 37a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(storage_->SetKey(key, value)); 38d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo const auto observers_for_key = observers_.find(key); 39d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo if (observers_for_key != observers_.end()) { 40d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo std::vector<ObserverInterface*> copy_observers(observers_for_key->second); 41d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo for (ObserverInterface* observer : copy_observers) 42d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo observer->OnPrefSet(key); 43d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo } 443003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov return true; 453003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 463003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 47a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::GetInt64(const string& key, int64_t* value) const { 483003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov string str_value; 4908fce04e5341c99f308ee7462b1f351f5232eacdJay Srinivasan if (!GetString(key, &str_value)) 5008fce04e5341c99f308ee7462b1f351f5232eacdJay Srinivasan return false; 51736fcb57ca2dcf09710a797e4c23a64f6cd64e16Ben Chan base::TrimWhitespaceASCII(str_value, base::TRIM_ALL, &str_value); 52790e62e2d8114647b0785574bea361cf931c482bChris Masone TEST_AND_RETURN_FALSE(base::StringToInt64(str_value, value)); 533003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov return true; 543003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 553003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 56a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::SetInt64(const string& key, const int64_t value) { 57790e62e2d8114647b0785574bea361cf931c482bChris Masone return SetString(key, base::Int64ToString(value)); 583003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 593003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 60a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::GetBoolean(const string& key, bool* value) const { 61efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo string str_value; 62efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo if (!GetString(key, &str_value)) 63efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo return false; 64736fcb57ca2dcf09710a797e4c23a64f6cd64e16Ben Chan base::TrimWhitespaceASCII(str_value, base::TRIM_ALL, &str_value); 65efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo if (str_value == "false") { 66efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo *value = false; 67efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo return true; 68efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo } 69efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo if (str_value == "true") { 70efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo *value = true; 71efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo return true; 72efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo } 73efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo return false; 74efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo} 75efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo 76a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::SetBoolean(const string& key, const bool value) { 77efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo return SetString(key, value ? "true" : "false"); 78efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo} 79efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo 80a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::Exists(const string& key) const { 81a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return storage_->KeyExists(key); 82480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan} 83480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan 84a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool PrefsBase::Delete(const string& key) { 85a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(storage_->DeleteKey(key)); 86d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo const auto observers_for_key = observers_.find(key); 87d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo if (observers_for_key != observers_.end()) { 88d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo std::vector<ObserverInterface*> copy_observers(observers_for_key->second); 89d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo for (ObserverInterface* observer : copy_observers) 90d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo observer->OnPrefDeleted(key); 91d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo } 92d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo return true; 93d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo} 94d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo 95a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymovoid PrefsBase::AddObserver(const string& key, ObserverInterface* observer) { 96d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo observers_[key].push_back(observer); 97d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo} 98d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo 99a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymovoid PrefsBase::RemoveObserver(const string& key, ObserverInterface* observer) { 100d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo std::vector<ObserverInterface*>& observers_for_key = observers_[key]; 101d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo auto observer_it = 102d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo std::find(observers_for_key.begin(), observers_for_key.end(), observer); 103d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo if (observer_it != observers_for_key.end()) 104d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo observers_for_key.erase(observer_it); 105480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan} 106480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan 107a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo// Prefs 108a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 109a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::Init(const base::FilePath& prefs_dir) { 110a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return file_storage_.Init(prefs_dir); 111a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 112a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 113a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) { 114a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo prefs_dir_ = prefs_dir; 115a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 116a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 117a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 118a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::FileStorage::GetKey(const string& key, string* value) const { 119a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo base::FilePath filename; 120a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 121a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo if (!base::ReadFileToString(filename, value)) { 122a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo LOG(INFO) << key << " not present in " << prefs_dir_.value(); 123a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return false; 124a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo } 125a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 126a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 127a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 128a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::FileStorage::SetKey(const string& key, const string& value) { 129a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo base::FilePath filename; 130a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 131a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo if (!base::DirectoryExists(filename.DirName())) { 132a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo // Only attempt to create the directory if it doesn't exist to avoid calls 133a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo // to parent directories where we might not have permission to write to. 134a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName())); 135a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo } 136a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) == 137a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo static_cast<int>(value.size())); 138a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 139a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 140a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 141a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::FileStorage::KeyExists(const string& key) const { 142a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo base::FilePath filename; 143a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 144a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return base::PathExists(filename); 145a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 146a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 147a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::FileStorage::DeleteKey(const string& key) { 148a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo base::FilePath filename; 149a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 150a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false)); 151a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 152a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 153a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 154a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool Prefs::FileStorage::GetFileNameForKey(const string& key, 155a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo base::FilePath* filename) const { 1563003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov // Allows only non-empty keys containing [A-Za-z0-9_-]. 1573003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov TEST_AND_RETURN_FALSE(!key.empty()); 1583003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov for (size_t i = 0; i < key.size(); ++i) { 1593003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov char c = key.at(i); 1600103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko TEST_AND_RETURN_FALSE(base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || 1613003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov c == '_' || c == '-'); 1623003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov } 1633003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov *filename = prefs_dir_.Append(key); 1643003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov return true; 1653003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 1663003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 167a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo// MemoryPrefs 168a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 169a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool MemoryPrefs::MemoryStorage::GetKey(const string& key, 170a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo string* value) const { 171a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo auto it = values_.find(key); 172a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo if (it == values_.end()) 173a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return false; 174a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo *value = it->second; 175a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 176a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 177a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 178a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool MemoryPrefs::MemoryStorage::SetKey(const string& key, 179a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo const string& value) { 180a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo values_[key] = value; 181a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 182a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 183a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 184a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool MemoryPrefs::MemoryStorage::KeyExists(const string& key) const { 185a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return values_.find(key) != values_.end(); 186a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 187a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 188a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymobool MemoryPrefs::MemoryStorage::DeleteKey(const string& key) { 189a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo auto it = values_.find(key); 190a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo if (it == values_.end()) 191a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return false; 192a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo values_.erase(it); 193a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo return true; 194a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo} 195a0284ace424d1653f36208da24b5ce878d393c7eAlex Deymo 1963003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} // namespace chromeos_update_engine 197