blob: 3501f379ffdc45ca94ada74b98c11bfc09f39fbd [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_IMPL_H_
#define SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_IMPL_H_
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/network_change_notifier.h"
#include "services/device/geolocation/position_cache.h"
#include "services/device/public/mojom/geoposition.mojom.h"
namespace base {
class TickClock;
} // namespace base
namespace device {
class PositionCacheImpl
: public PositionCache,
public net::NetworkChangeNotifier::NetworkChangeObserver {
public:
// The maximum size of the cache of positions.
static const size_t kMaximumSize;
// The maximum time an entry can reside in cache before forced eviction.
// This is to ensure the user's location cannot be tracked arbitrarily far
// back in history.
static const base::TimeDelta kMaximumLifetime;
// |clock| is used to measure time left until kMaximumLifetime.
explicit PositionCacheImpl(const base::TickClock* clock);
PositionCacheImpl(const PositionCacheImpl&) = delete;
PositionCacheImpl& operator=(const PositionCacheImpl&) = delete;
~PositionCacheImpl() override;
// PositionCache
void CachePosition(const WifiData& wifi_data,
const mojom::Geoposition& position) override;
const mojom::Geoposition* FindPosition(const WifiData& wifi_data) override;
size_t GetPositionCacheSize() const override;
const mojom::GeopositionResult* GetLastUsedNetworkPosition() const override;
void SetLastUsedNetworkPosition(
const mojom::GeopositionResult& result) override;
void FillDiagnostics(mojom::PositionCacheDiagnostics& diagnostics) override;
// net::NetworkChangeNotifier::NetworkChangeObserver
void OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) override;
private:
// In order to avoid O(N) comparisons while searching for the right WifiData,
// we hash the contents of those objects and use the hashes as cache keys.
using Hash = std::string;
class CacheEntry {
public:
CacheEntry(const Hash& hash,
mojom::GeopositionPtr position,
std::unique_ptr<base::OneShotTimer> eviction_timer);
CacheEntry(const CacheEntry&) = delete;
CacheEntry& operator=(const CacheEntry&) = delete;
CacheEntry(CacheEntry&&);
CacheEntry& operator=(CacheEntry&&);
~CacheEntry();
inline bool operator==(const Hash& hash) const { return hash_ == hash; }
const mojom::Geoposition* position() const { return position_.get(); }
private:
Hash hash_;
mojom::GeopositionPtr position_;
std::unique_ptr<base::OneShotTimer> eviction_timer_;
};
static Hash MakeKey(const WifiData& wifi_data);
void EvictEntry(const Hash& hash);
raw_ptr<const base::TickClock> clock_;
std::vector<CacheEntry> data_;
mojom::GeopositionResultPtr last_used_result_;
std::optional<base::Time> last_hit_;
std::optional<base::Time> last_miss_;
int hit_count_ = 0;
int miss_count_ = 0;
};
} // namespace device
#endif // SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_IMPL_H_