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 32e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool PrefsBase::GetString(const string& key, string* value) const { 33e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return storage_->GetKey(key, value); 343003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 353003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 36e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool PrefsBase::SetString(const string& key, const string& value) { 37e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex 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 47e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex 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 56e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool PrefsBase::SetInt64(const string& key, const int64_t value) { 57790e62e2d8114647b0785574bea361cf931c482bChris Masone return SetString(key, base::Int64ToString(value)); 583003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} 593003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov 60e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex 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 76e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool PrefsBase::SetBoolean(const string& key, const bool value) { 77efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo return SetString(key, value ? "true" : "false"); 78efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo} 79efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo 80e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool PrefsBase::Exists(const string& key) const { 81e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return storage_->KeyExists(key); 82480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan} 83480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan 84e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool PrefsBase::Delete(const string& key) { 85e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex 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 95e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymovoid PrefsBase::AddObserver(const string& key, ObserverInterface* observer) { 96d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo observers_[key].push_back(observer); 97d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo} 98d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo 99e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex 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 107e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo// Prefs 108e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 109e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::Init(const base::FilePath& prefs_dir) { 110e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return file_storage_.Init(prefs_dir); 111e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 112e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 113e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) { 114e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo prefs_dir_ = prefs_dir; 115e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 116e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 117e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 118e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::FileStorage::GetKey(const string& key, string* value) const { 119e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo base::FilePath filename; 120e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 121e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo if (!base::ReadFileToString(filename, value)) { 122e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo LOG(INFO) << key << " not present in " << prefs_dir_.value(); 123e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return false; 124e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo } 125e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 126e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 127e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 128e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::FileStorage::SetKey(const string& key, const string& value) { 129e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo base::FilePath filename; 130e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 131e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo if (!base::DirectoryExists(filename.DirName())) { 132e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo // Only attempt to create the directory if it doesn't exist to avoid calls 133e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo // to parent directories where we might not have permission to write to. 134e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName())); 135e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo } 136e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) == 137e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo static_cast<int>(value.size())); 138e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 139e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 140e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 141e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::FileStorage::KeyExists(const string& key) const { 142e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo base::FilePath filename; 143e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 144e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return base::PathExists(filename); 145e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 146e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 147e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::FileStorage::DeleteKey(const string& key) { 148e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo base::FilePath filename; 149e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); 150e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false)); 151e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 152e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 153e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 154e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool Prefs::FileStorage::GetFileNameForKey(const string& key, 155e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex 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); 160a3cf75a1d01aeb03d2341600ebff3db0a8316200Alex 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 167e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo// MemoryPrefs 168e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 169e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool MemoryPrefs::MemoryStorage::GetKey(const string& key, 170e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo string* value) const { 171e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo auto it = values_.find(key); 172e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo if (it == values_.end()) 173e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return false; 174e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo *value = it->second; 175e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 176e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 177e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 178e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool MemoryPrefs::MemoryStorage::SetKey(const string& key, 179e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo const string& value) { 180e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo values_[key] = value; 181e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 182e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 183e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 184e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool MemoryPrefs::MemoryStorage::KeyExists(const string& key) const { 185e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return values_.find(key) != values_.end(); 186e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 187e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 188e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymobool MemoryPrefs::MemoryStorage::DeleteKey(const string& key) { 189e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo auto it = values_.find(key); 190e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo if (it == values_.end()) 191e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return false; 192e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo values_.erase(it); 193e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo return true; 194e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo} 195e6eef83c63a50f043b2c4a85175030b6d8b6b91dAlex Deymo 1963003059032a7ac8a49f1bdd9fda2d58becec8374Darin Petkov} // namespace chromeos_update_engine 197