position_cache_impl.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/device/geolocation/position_cache_impl.h"
  5. #include <algorithm>
  6. #include "base/strings/utf_string_conversions.h"
  7. #include "services/device/geolocation/wifi_data.h"
  8. #include "services/device/public/mojom/geoposition.mojom.h"
  9. namespace device {
  10. // static
  11. const size_t PositionCacheImpl::kMaximumSize = 10;
  12. // static
  13. const base::TimeDelta PositionCacheImpl::kMaximumLifetime = base::Days(1);
  14. PositionCacheImpl::CacheEntry::CacheEntry(
  15. const Hash& hash,
  16. const mojom::Geoposition& position,
  17. std::unique_ptr<base::OneShotTimer> eviction_timer)
  18. : hash_(hash),
  19. position_(position),
  20. eviction_timer_(std::move(eviction_timer)) {}
  21. PositionCacheImpl::CacheEntry::~CacheEntry() = default;
  22. PositionCacheImpl::CacheEntry::CacheEntry(CacheEntry&&) = default;
  23. PositionCacheImpl::CacheEntry& PositionCacheImpl::CacheEntry::operator=(
  24. CacheEntry&&) = default;
  25. // static
  26. PositionCacheImpl::Hash PositionCacheImpl::MakeKey(const WifiData& wifi_data) {
  27. // Currently we use only WiFi data and base the key only on the MAC addresses.
  28. std::u16string key;
  29. const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|"
  30. key.reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress);
  31. const std::u16string separator(u"|");
  32. for (const auto& access_point_data : wifi_data.access_point_data) {
  33. key += separator;
  34. key += access_point_data.mac_address;
  35. key += separator;
  36. }
  37. return key;
  38. }
  39. PositionCacheImpl::PositionCacheImpl(const base::TickClock* clock)
  40. : clock_(clock) {
  41. net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
  42. }
  43. PositionCacheImpl::~PositionCacheImpl() {
  44. net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
  45. }
  46. void PositionCacheImpl::CachePosition(const WifiData& wifi_data,
  47. const mojom::Geoposition& position) {
  48. const Hash key = MakeKey(wifi_data);
  49. // If the cache is full, remove the oldest entry.
  50. if (data_.size() == kMaximumSize)
  51. data_.erase(data_.begin());
  52. DCHECK_LT(data_.size(), kMaximumSize);
  53. auto eviction_timer = std::make_unique<base::OneShotTimer>(clock_);
  54. // Ensure that the entry we're adding will be evicted after kMaximumLifetime.
  55. // base::Unretained safe because the timer is indirectly owned by |this|.
  56. eviction_timer->Start(FROM_HERE, kMaximumLifetime,
  57. base::BindOnce(&PositionCacheImpl::EvictEntry,
  58. base::Unretained(this), key));
  59. data_.emplace_back(key, position, std::move(eviction_timer));
  60. }
  61. const mojom::Geoposition* PositionCacheImpl::FindPosition(
  62. const WifiData& wifi_data) const {
  63. const Hash key = MakeKey(wifi_data);
  64. auto it = std::find(data_.begin(), data_.end(), key);
  65. return it == data_.end() ? nullptr : (it->position());
  66. }
  67. size_t PositionCacheImpl::GetPositionCacheSize() const {
  68. return data_.size();
  69. }
  70. const mojom::Geoposition& PositionCacheImpl::GetLastUsedNetworkPosition()
  71. const {
  72. return last_used_position_;
  73. }
  74. void PositionCacheImpl::SetLastUsedNetworkPosition(
  75. const mojom::Geoposition& position) {
  76. last_used_position_ = position;
  77. }
  78. void PositionCacheImpl::OnNetworkChanged(
  79. net::NetworkChangeNotifier::ConnectionType) {
  80. // OnNetworkChanged is called " when a change occurs to the host
  81. // computer's hardware or software that affects the route network packets
  82. // take to any network server.". This means that whatever position we had
  83. // stored for a wired connection (empty WifiData) could have become stale.
  84. EvictEntry(MakeKey(WifiData()));
  85. last_used_position_ = {};
  86. }
  87. void PositionCacheImpl::EvictEntry(const Hash& hash) {
  88. data_.erase(std::remove(data_.begin(), data_.end(), hash), data_.end());
  89. }
  90. } // namespace device