| // Copyright 2017 The Chromium 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 "chromeos/components/tether/persistent_host_scan_cache_impl.h" |
| |
| #include <memory> |
| #include <unordered_set> |
| |
| #include "base/logging.h" |
| #include "chromeos/components/tether/pref_names.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service.h" |
| |
| namespace chromeos { |
| |
| namespace tether { |
| |
| namespace { |
| |
| constexpr char kTetherNetworkGuidKey[] = "tether_network_guid"; |
| constexpr char kDeviceNameKey[] = "device_name"; |
| constexpr char kCarrierKey[] = "carrier"; |
| constexpr char kBatteryPercentageKey[] = "battery_percentage"; |
| constexpr char kSignalStrengthKey[] = "signal_strength"; |
| constexpr char kSetupRequiredKey[] = "setup_required"; |
| |
| std::unique_ptr<base::DictionaryValue> HostScanCacheEntryToDictionary( |
| const HostScanCacheEntry& entry) { |
| std::unique_ptr<base::DictionaryValue> dictionary = |
| std::make_unique<base::DictionaryValue>(); |
| |
| dictionary->SetString(kTetherNetworkGuidKey, entry.tether_network_guid); |
| dictionary->SetString(kDeviceNameKey, entry.device_name); |
| dictionary->SetString(kCarrierKey, entry.carrier); |
| dictionary->SetInteger(kBatteryPercentageKey, entry.battery_percentage); |
| dictionary->SetInteger(kSignalStrengthKey, entry.signal_strength); |
| dictionary->SetBoolean(kSetupRequiredKey, entry.setup_required); |
| |
| return dictionary; |
| } |
| |
| std::unique_ptr<HostScanCacheEntry> DictionaryToHostScanCacheEntry( |
| const base::DictionaryValue& dictionary) { |
| HostScanCacheEntry::Builder builder; |
| |
| std::string tether_network_guid; |
| if (!dictionary.GetString(kTetherNetworkGuidKey, &tether_network_guid) || |
| tether_network_guid.empty()) { |
| return nullptr; |
| } |
| builder.SetTetherNetworkGuid(tether_network_guid); |
| |
| std::string device_name; |
| if (!dictionary.GetString(kDeviceNameKey, &device_name)) { |
| return nullptr; |
| } |
| builder.SetDeviceName(device_name); |
| |
| std::string carrier; |
| if (!dictionary.GetString(kCarrierKey, &carrier)) { |
| return nullptr; |
| } |
| builder.SetCarrier(carrier); |
| |
| int battery_percentage; |
| if (!dictionary.GetInteger(kBatteryPercentageKey, &battery_percentage) || |
| battery_percentage < 0 || battery_percentage > 100) { |
| return nullptr; |
| } |
| builder.SetBatteryPercentage(battery_percentage); |
| |
| int signal_strength; |
| if (!dictionary.GetInteger(kSignalStrengthKey, &signal_strength) || |
| signal_strength < 0 || signal_strength > 100) { |
| return nullptr; |
| } |
| builder.SetSignalStrength(signal_strength); |
| |
| bool setup_required; |
| if (!dictionary.GetBoolean(kSetupRequiredKey, &setup_required)) { |
| return nullptr; |
| } |
| builder.SetSetupRequired(setup_required); |
| |
| return builder.Build(); |
| } |
| |
| } // namespace |
| |
| // static |
| void PersistentHostScanCacheImpl::RegisterPrefs(PrefRegistrySimple* registry) { |
| registry->RegisterListPref(prefs::kHostScanCache); |
| } |
| |
| PersistentHostScanCacheImpl::PersistentHostScanCacheImpl( |
| PrefService* pref_service) |
| : pref_service_(pref_service) {} |
| |
| PersistentHostScanCacheImpl::~PersistentHostScanCacheImpl() = default; |
| |
| std::unordered_map<std::string, HostScanCacheEntry> |
| PersistentHostScanCacheImpl::GetStoredCacheEntries() { |
| const base::ListValue* cache_entry_list = |
| pref_service_->GetList(prefs::kHostScanCache); |
| DCHECK(cache_entry_list); |
| |
| std::unordered_map<std::string, HostScanCacheEntry> entries; |
| std::unordered_set<std::string> ids_processed_so_far; |
| for (auto& cache_entry_value : cache_entry_list->GetList()) { |
| const base::DictionaryValue* cache_entry_dict; |
| |
| if (!cache_entry_value.GetAsDictionary(&cache_entry_dict)) { |
| // All prefs stored in the ListValue should be valid DictionaryValues. |
| NOTREACHED(); |
| } |
| |
| std::unique_ptr<HostScanCacheEntry> entry = |
| DictionaryToHostScanCacheEntry(*cache_entry_dict); |
| DCHECK(entry); |
| |
| std::string tether_network_guid = entry->tether_network_guid; |
| DCHECK(!tether_network_guid.empty()); |
| |
| // There should never be duplicate entries stored for one Tether network |
| // GUID. |
| DCHECK(ids_processed_so_far.find(tether_network_guid) == |
| ids_processed_so_far.end()); |
| ids_processed_so_far.insert(tether_network_guid); |
| |
| entries.emplace(tether_network_guid, *entry); |
| } |
| |
| return entries; |
| } |
| |
| void PersistentHostScanCacheImpl::SetHostScanResult( |
| const HostScanCacheEntry& entry) { |
| std::unordered_map<std::string, HostScanCacheEntry> entries = |
| GetStoredCacheEntries(); |
| |
| // Erase any existing scan result for this GUID (if none currently exists, |
| // this is a no-op). |
| entries.erase(entry.tether_network_guid); |
| |
| // Add the entry supplied. |
| entries.emplace(entry.tether_network_guid, entry); |
| |
| StoreCacheEntriesToPrefs(entries); |
| } |
| |
| bool PersistentHostScanCacheImpl::RemoveHostScanResultImpl( |
| const std::string& tether_network_guid) { |
| std::unordered_map<std::string, HostScanCacheEntry> entries = |
| GetStoredCacheEntries(); |
| |
| bool result_was_removed = entries.erase(tether_network_guid); |
| |
| // Only store the updated entries if a scan result was actually removed. |
| // Otherwise, nothing has changed and there is no reason to re-write the same |
| // data. |
| if (result_was_removed) |
| StoreCacheEntriesToPrefs(entries); |
| |
| return result_was_removed; |
| } |
| |
| bool PersistentHostScanCacheImpl::ExistsInCache( |
| const std::string& tether_network_guid) { |
| std::unordered_map<std::string, HostScanCacheEntry> entries = |
| GetStoredCacheEntries(); |
| return entries.find(tether_network_guid) != entries.end(); |
| } |
| |
| std::unordered_set<std::string> |
| PersistentHostScanCacheImpl::GetTetherGuidsInCache() { |
| std::unordered_set<std::string> tether_guids; |
| for (const auto& entry : GetStoredCacheEntries()) |
| tether_guids.insert(entry.first); |
| return tether_guids; |
| } |
| |
| bool PersistentHostScanCacheImpl::DoesHostRequireSetup( |
| const std::string& tether_network_guid) { |
| std::unordered_map<std::string, HostScanCacheEntry> entries = |
| GetStoredCacheEntries(); |
| |
| auto it = entries.find(tether_network_guid); |
| DCHECK(it != entries.end()); |
| |
| return it->second.setup_required; |
| } |
| |
| void PersistentHostScanCacheImpl::StoreCacheEntriesToPrefs( |
| const std::unordered_map<std::string, HostScanCacheEntry>& entries) { |
| base::ListValue entries_list; |
| |
| for (const auto& it : entries) { |
| std::unique_ptr<base::DictionaryValue> entry_dict = |
| HostScanCacheEntryToDictionary(it.second); |
| DCHECK(entry_dict); |
| entries_list.Append(std::move(entry_dict)); |
| } |
| |
| pref_service_->Set(prefs::kHostScanCache, entries_list); |
| } |
| |
| } // namespace tether |
| |
| } // namespace chromeos |