| Alex Deymo | aea4c1c | 2015-08-19 20:24:43 -0700 | [diff] [blame] | 1 | // | 
 | 2 | // Copyright (C) 2012 The Android Open Source Project | 
 | 3 | // | 
 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 | // you may not use this file except in compliance with the License. | 
 | 6 | // You may obtain a copy of the License at | 
 | 7 | // | 
 | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 | // | 
 | 10 | // Unless required by applicable law or agreed to in writing, software | 
 | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 | // See the License for the specific language governing permissions and | 
 | 14 | // limitations under the License. | 
 | 15 | // | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 16 |  | 
| Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 17 | #include "update_engine/common/prefs.h" | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 18 |  | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 19 | #include <algorithm> | 
 | 20 |  | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 21 | #include <base/files/file_enumerator.h> | 
| Ben Chan | 06c76a4 | 2014-09-05 08:21:06 -0700 | [diff] [blame] | 22 | #include <base/files/file_util.h> | 
| Darin Petkov | 3627577 | 2010-10-01 11:40:57 -0700 | [diff] [blame] | 23 | #include <base/logging.h> | 
| Alex Vakulenko | 75039d7 | 2014-03-25 12:36:28 -0700 | [diff] [blame] | 24 | #include <base/strings/string_number_conversions.h> | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 25 | #include <base/strings/string_split.h> | 
| Alex Vakulenko | 75039d7 | 2014-03-25 12:36:28 -0700 | [diff] [blame] | 26 | #include <base/strings/string_util.h> | 
| Darin Petkov | 3627577 | 2010-10-01 11:40:57 -0700 | [diff] [blame] | 27 |  | 
| Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 28 | #include "update_engine/common/utils.h" | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 29 |  | 
 | 30 | using std::string; | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 31 | using std::vector; | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 32 |  | 
 | 33 | namespace chromeos_update_engine { | 
 | 34 |  | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 35 | namespace { | 
 | 36 |  | 
 | 37 | void DeleteEmptyDirectories(const base::FilePath& path) { | 
 | 38 |   base::FileEnumerator path_enum( | 
 | 39 |       path, false /* recursive */, base::FileEnumerator::DIRECTORIES); | 
 | 40 |   for (base::FilePath dir_path = path_enum.Next(); !dir_path.empty(); | 
 | 41 |        dir_path = path_enum.Next()) { | 
 | 42 |     DeleteEmptyDirectories(dir_path); | 
 | 43 |     if (base::IsDirectoryEmpty(dir_path)) | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 44 | #if BASE_VER < 800000 | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 45 |       base::DeleteFile(dir_path, false); | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 46 | #else | 
 | 47 |       base::DeleteFile(dir_path); | 
 | 48 | #endif | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 49 |   } | 
 | 50 | } | 
 | 51 |  | 
 | 52 | }  // namespace | 
 | 53 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 54 | bool PrefsBase::GetString(const std::string_view key, string* value) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 55 |   return storage_->GetKey(key, value); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 56 | } | 
 | 57 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 58 | bool PrefsBase::SetString(std::string_view key, std::string_view value) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 59 |   TEST_AND_RETURN_FALSE(storage_->SetKey(key, value)); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 60 |   const auto observers_for_key = observers_.find(key); | 
 | 61 |   if (observers_for_key != observers_.end()) { | 
 | 62 |     std::vector<ObserverInterface*> copy_observers(observers_for_key->second); | 
 | 63 |     for (ObserverInterface* observer : copy_observers) | 
 | 64 |       observer->OnPrefSet(key); | 
 | 65 |   } | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 66 |   return true; | 
 | 67 | } | 
 | 68 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 69 | bool PrefsBase::GetInt64(const std::string_view key, int64_t* value) const { | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 70 |   string str_value; | 
| Jay Srinivasan | 08fce04 | 2012-06-07 16:31:01 -0700 | [diff] [blame] | 71 |   if (!GetString(key, &str_value)) | 
 | 72 |     return false; | 
| Ben Chan | 736fcb5 | 2014-05-21 18:28:22 -0700 | [diff] [blame] | 73 |   base::TrimWhitespaceASCII(str_value, base::TRIM_ALL, &str_value); | 
| Chris Masone | 790e62e | 2010-08-12 10:41:18 -0700 | [diff] [blame] | 74 |   TEST_AND_RETURN_FALSE(base::StringToInt64(str_value, value)); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 75 |   return true; | 
 | 76 | } | 
 | 77 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 78 | bool PrefsBase::SetInt64(std::string_view key, const int64_t value) { | 
| hscham | 00b6aa2 | 2020-02-20 12:32:06 +0900 | [diff] [blame] | 79 |   return SetString(key, base::NumberToString(value)); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 80 | } | 
 | 81 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 82 | bool PrefsBase::GetBoolean(std::string_view key, bool* value) const { | 
| Alex Deymo | efb7c4c | 2013-07-09 14:34:00 -0700 | [diff] [blame] | 83 |   string str_value; | 
 | 84 |   if (!GetString(key, &str_value)) | 
 | 85 |     return false; | 
| Ben Chan | 736fcb5 | 2014-05-21 18:28:22 -0700 | [diff] [blame] | 86 |   base::TrimWhitespaceASCII(str_value, base::TRIM_ALL, &str_value); | 
| Alex Deymo | efb7c4c | 2013-07-09 14:34:00 -0700 | [diff] [blame] | 87 |   if (str_value == "false") { | 
 | 88 |     *value = false; | 
 | 89 |     return true; | 
 | 90 |   } | 
 | 91 |   if (str_value == "true") { | 
 | 92 |     *value = true; | 
 | 93 |     return true; | 
 | 94 |   } | 
 | 95 |   return false; | 
 | 96 | } | 
 | 97 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 98 | bool PrefsBase::SetBoolean(std::string_view key, const bool value) { | 
| Alex Deymo | efb7c4c | 2013-07-09 14:34:00 -0700 | [diff] [blame] | 99 |   return SetString(key, value ? "true" : "false"); | 
 | 100 | } | 
 | 101 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 102 | bool PrefsBase::Exists(std::string_view key) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 103 |   return storage_->KeyExists(key); | 
| Jay Srinivasan | 480ddfa | 2012-06-01 19:15:26 -0700 | [diff] [blame] | 104 | } | 
 | 105 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 106 | bool PrefsBase::Delete(std::string_view key) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 107 |   TEST_AND_RETURN_FALSE(storage_->DeleteKey(key)); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 108 |   const auto observers_for_key = observers_.find(key); | 
 | 109 |   if (observers_for_key != observers_.end()) { | 
 | 110 |     std::vector<ObserverInterface*> copy_observers(observers_for_key->second); | 
 | 111 |     for (ObserverInterface* observer : copy_observers) | 
 | 112 |       observer->OnPrefDeleted(key); | 
 | 113 |   } | 
 | 114 |   return true; | 
 | 115 | } | 
 | 116 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 117 | bool PrefsBase::Delete(std::string_view pref_key, const vector<string>& nss) { | 
| Vyshu Khota | 4c5413d | 2020-11-04 16:17:25 -0800 | [diff] [blame] | 118 |   // Delete pref key for platform. | 
 | 119 |   bool success = Delete(pref_key); | 
 | 120 |   // Delete pref key in each namespace. | 
 | 121 |   for (const auto& ns : nss) { | 
 | 122 |     vector<string> namespace_keys; | 
 | 123 |     success = GetSubKeys(ns, &namespace_keys) && success; | 
 | 124 |     for (const auto& key : namespace_keys) { | 
 | 125 |       auto last_key_seperator = key.find_last_of(kKeySeparator); | 
 | 126 |       if (last_key_seperator != string::npos && | 
 | 127 |           pref_key == key.substr(last_key_seperator + 1)) { | 
 | 128 |         success = Delete(key) && success; | 
 | 129 |       } | 
 | 130 |     } | 
 | 131 |   } | 
 | 132 |   return success; | 
 | 133 | } | 
 | 134 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 135 | bool PrefsBase::GetSubKeys(std::string_view ns, vector<string>* keys) const { | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 136 |   return storage_->GetSubKeys(ns, keys); | 
 | 137 | } | 
 | 138 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 139 | void PrefsBase::AddObserver(std::string_view key, ObserverInterface* observer) { | 
 | 140 |   observers_[std::string{key}].push_back(observer); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 141 | } | 
 | 142 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 143 | void PrefsBase::RemoveObserver(std::string_view key, | 
 | 144 |                                ObserverInterface* observer) { | 
 | 145 |   std::vector<ObserverInterface*>& observers_for_key = | 
 | 146 |       observers_[std::string{key}]; | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 147 |   auto observer_it = | 
 | 148 |       std::find(observers_for_key.begin(), observers_for_key.end(), observer); | 
 | 149 |   if (observer_it != observers_for_key.end()) | 
 | 150 |     observers_for_key.erase(observer_it); | 
| Jay Srinivasan | 480ddfa | 2012-06-01 19:15:26 -0700 | [diff] [blame] | 151 | } | 
 | 152 |  | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 153 | string PrefsInterface::CreateSubKey(const vector<string>& ns_and_key) { | 
 | 154 |   return base::JoinString(ns_and_key, string(1, kKeySeparator)); | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 155 | } | 
 | 156 |  | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 157 | // Prefs | 
 | 158 |  | 
 | 159 | bool Prefs::Init(const base::FilePath& prefs_dir) { | 
 | 160 |   return file_storage_.Init(prefs_dir); | 
 | 161 | } | 
 | 162 |  | 
 | 163 | bool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) { | 
 | 164 |   prefs_dir_ = prefs_dir; | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 165 |   // Delete empty directories. Ignore errors when deleting empty directories. | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 166 |   DeleteEmptyDirectories(prefs_dir_); | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 167 |   return true; | 
 | 168 | } | 
 | 169 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 170 | bool Prefs::FileStorage::GetKey(std::string_view key, string* value) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 171 |   base::FilePath filename; | 
 | 172 |   TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
 | 173 |   if (!base::ReadFileToString(filename, value)) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 174 |     return false; | 
 | 175 |   } | 
 | 176 |   return true; | 
 | 177 | } | 
 | 178 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 179 | bool Prefs::FileStorage::GetSubKeys(std::string_view ns, | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 180 |                                     vector<string>* keys) const { | 
 | 181 |   base::FilePath filename; | 
 | 182 |   TEST_AND_RETURN_FALSE(GetFileNameForKey(ns, &filename)); | 
 | 183 |   base::FileEnumerator namespace_enum( | 
 | 184 |       prefs_dir_, true, base::FileEnumerator::FILES); | 
 | 185 |   for (base::FilePath f = namespace_enum.Next(); !f.empty(); | 
 | 186 |        f = namespace_enum.Next()) { | 
 | 187 |     auto filename_str = filename.value(); | 
 | 188 |     if (f.value().compare(0, filename_str.length(), filename_str) == 0) { | 
 | 189 |       // Only return the key portion excluding the |prefs_dir_| with slash. | 
 | 190 |       keys->push_back(f.value().substr( | 
 | 191 |           prefs_dir_.AsEndingWithSeparator().value().length())); | 
 | 192 |     } | 
 | 193 |   } | 
 | 194 |   return true; | 
 | 195 | } | 
 | 196 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 197 | bool Prefs::FileStorage::SetKey(std::string_view key, std::string_view value) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 198 |   base::FilePath filename; | 
 | 199 |   TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
 | 200 |   if (!base::DirectoryExists(filename.DirName())) { | 
 | 201 |     // Only attempt to create the directory if it doesn't exist to avoid calls | 
 | 202 |     // to parent directories where we might not have permission to write to. | 
 | 203 |     TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName())); | 
 | 204 |   } | 
 | 205 |   TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) == | 
 | 206 |                         static_cast<int>(value.size())); | 
 | 207 |   return true; | 
 | 208 | } | 
 | 209 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 210 | bool Prefs::FileStorage::KeyExists(std::string_view key) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 211 |   base::FilePath filename; | 
 | 212 |   TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
 | 213 |   return base::PathExists(filename); | 
 | 214 | } | 
 | 215 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 216 | bool Prefs::FileStorage::DeleteKey(std::string_view key) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 217 |   base::FilePath filename; | 
 | 218 |   TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 219 | #if BASE_VER < 800000 | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 220 |   TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false)); | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 221 | #else | 
 | 222 |   TEST_AND_RETURN_FALSE(base::DeleteFile(filename)); | 
 | 223 | #endif | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 224 |   return true; | 
 | 225 | } | 
 | 226 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 227 | bool Prefs::FileStorage::GetFileNameForKey(std::string_view key, | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 228 |                                            base::FilePath* filename) const { | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 229 |   // Allows only non-empty keys containing [A-Za-z0-9_-/]. | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 230 |   TEST_AND_RETURN_FALSE(!key.empty()); | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 231 |   for (char c : key) | 
| Alex Vakulenko | 0103c36 | 2016-01-20 07:56:15 -0800 | [diff] [blame] | 232 |     TEST_AND_RETURN_FALSE(base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 233 |                           c == '_' || c == '-' || c == kKeySeparator); | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 234 |   *filename = prefs_dir_.Append( | 
 | 235 |       base::FilePath::StringPieceType(key.data(), key.size())); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 236 |   return true; | 
 | 237 | } | 
 | 238 |  | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 239 | // MemoryPrefs | 
 | 240 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 241 | bool MemoryPrefs::MemoryStorage::GetKey(std::string_view key, | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 242 |                                         string* value) const { | 
 | 243 |   auto it = values_.find(key); | 
 | 244 |   if (it == values_.end()) | 
 | 245 |     return false; | 
 | 246 |   *value = it->second; | 
 | 247 |   return true; | 
 | 248 | } | 
 | 249 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 250 | bool MemoryPrefs::MemoryStorage::GetSubKeys(std::string_view ns, | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 251 |                                             vector<string>* keys) const { | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 252 |   auto lower_comp = [](const auto& pr, const auto& ns) { | 
 | 253 |     return std::string_view{pr.first.data(), ns.length()} < ns; | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 254 |   }; | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 255 |   auto upper_comp = [](const auto& ns, const auto& pr) { | 
 | 256 |     return ns < std::string_view{pr.first.data(), ns.length()}; | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 257 |   }; | 
 | 258 |   auto lower_it = | 
 | 259 |       std::lower_bound(begin(values_), end(values_), ns, lower_comp); | 
 | 260 |   auto upper_it = std::upper_bound(lower_it, end(values_), ns, upper_comp); | 
 | 261 |   while (lower_it != upper_it) | 
 | 262 |     keys->push_back((lower_it++)->first); | 
 | 263 |   return true; | 
 | 264 | } | 
 | 265 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 266 | bool MemoryPrefs::MemoryStorage::SetKey(std::string_view key, | 
| Kelvin Zhang | cf4600e | 2020-10-27 15:50:33 -0400 | [diff] [blame] | 267 |                                         std::string_view value) { | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 268 |   values_[std::string{key}] = value; | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 269 |   return true; | 
 | 270 | } | 
 | 271 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 272 | bool MemoryPrefs::MemoryStorage::KeyExists(std::string_view key) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 273 |   return values_.find(key) != values_.end(); | 
 | 274 | } | 
 | 275 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 276 | bool MemoryPrefs::MemoryStorage::DeleteKey(std::string_view key) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 277 |   auto it = values_.find(key); | 
| Andrew | 914f554 | 2020-04-21 10:56:33 -0700 | [diff] [blame] | 278 |   if (it != values_.end()) | 
 | 279 |     values_.erase(it); | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 280 |   return true; | 
 | 281 | } | 
 | 282 |  | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 283 | }  // namespace chromeos_update_engine |