[go: nahoru, domu]

blob: ff91a342a5a1c0254ccf4bd3670c4d331fe1515d [file] [log] [blame]
Avi Drissman3a215d1e2022-09-07 19:43:091// Copyright 2021 The Chromium Authors
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef ASH_SYSTEM_GEOLOCATION_GEOLOCATION_CONTROLLER_H_
6#define ASH_SYSTEM_GEOLOCATION_GEOLOCATION_CONTROLLER_H_
7
8#include <memory>
9#include <string>
10
11#include "ash/ash_export.h"
Eric Sumf97e7b892023-04-17 22:41:4412#include "ash/public/cpp/session/session_observer.h"
13#include "base/memory/raw_ptr.h"
Hans Wennborg9a23f412022-02-11 19:36:1814#include "base/observer_list.h"
15#include "base/observer_list_types.h"
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5116#include "base/time/time.h"
17#include "base/timer/timer.h"
Henrique Ferreiro129f0b72022-09-01 20:57:0518#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
Henrique Ferreiro1eaedc42022-10-05 15:33:4719#include "chromeos/ash/components/settings/timezone_settings.h"
Cattalyya Nuengsigkapian0a5b3092022-05-11 04:50:5120#include "chromeos/dbus/power/power_manager_client.h"
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5121#include "services/network/public/cpp/shared_url_loader_factory.h"
22
Eric Sumf97e7b892023-04-17 22:41:4423class PrefRegistrySimple;
24class PrefService;
25
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5126namespace base {
27class Clock;
28} // namespace base
29
30namespace ash {
31
32// Represents a geolocation position fix. It's "simple" because it doesn't
33// expose all the parameters of the position interface as defined by the
34// Geolocation API Specification:
35// https://dev.w3.org/geo/api/spec-source.html#position_interface
36// The GeolocationController is only interested in valid latitude and
37// longitude. It also doesn't require any specific accuracy. The more accurate
38// the positions, the more accurate sunset and sunrise times calculations.
39// However, an IP-based geoposition is considered good enough.
40struct SimpleGeoposition {
41 bool operator==(const SimpleGeoposition& other) const {
42 return latitude == other.latitude && longitude == other.longitude;
43 }
44 double latitude;
45 double longitude;
46};
47
48// Periodically requests the IP-based geolocation and provides it to the
49// observers, `GeolocationController::Observer`. This class also observes
50// timezone changes to request a new geoposition.
51// TODO(crbug.com/1272178): `GeolocationController` should observe the sleep
52// and update next request time.
53class ASH_EXPORT GeolocationController
Henrique Ferreiro1eaedc42022-10-05 15:33:4754 : public system::TimezoneSettings::Observer,
zauri0e1264752023-04-04 16:52:3655 public chromeos::PowerManagerClient::Observer,
Eric Sumf97e7b892023-04-17 22:41:4456 public SessionObserver,
zauri0e1264752023-04-04 16:52:3657 public SimpleGeolocationProvider::Delegate {
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5158 public:
59 class Observer : public base::CheckedObserver {
60 public:
Cattalyya Nuengsigkapian98d81312021-12-22 15:51:0561 // Emitted when the Geoposition is updated with
62 // |possible_change_in_timezone| to indicate whether timezone might have
63 // changed as a result of the geoposition change.
64 virtual void OnGeopositionChanged(bool possible_change_in_timezone) {}
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5165
66 protected:
67 ~Observer() override = default;
68 };
69
70 explicit GeolocationController(
71 scoped_refptr<network::SharedURLLoaderFactory> factory);
72 GeolocationController(const GeolocationController&) = delete;
73 GeolocationController& operator=(const GeolocationController&) = delete;
74 ~GeolocationController() override;
75
Cattalyya Nuengsigkapian98d81312021-12-22 15:51:0576 static GeolocationController* Get();
Eric Sumf97e7b892023-04-17 22:41:4477 static void RegisterProfilePrefs(PrefRegistrySimple* registry);
Cattalyya Nuengsigkapian98d81312021-12-22 15:51:0578
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5179 const base::OneShotTimer& timer() const { return *timer_; }
80
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5181 const std::u16string& current_timezone_id() const {
82 return current_timezone_id_;
83 }
84
85 void AddObserver(Observer* observer);
86 void RemoveObserver(Observer* observer);
87
Henrique Ferreiro1eaedc42022-10-05 15:33:4788 // system::TimezoneSettings::Observer:
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:5189 void TimezoneChanged(const icu::TimeZone& timezone) override;
90
Cattalyya Nuengsigkapian0a5b3092022-05-11 04:50:5191 // chromeos::PowerManagerClient::Observer:
92 void SuspendDone(base::TimeDelta sleep_duration) override;
93
zauri0e1264752023-04-04 16:52:3694 // SimpleGeolocationProvider::Delegate:
95 bool IsPreciseGeolocationAllowed() const override;
96
Eric Sumf97e7b892023-04-17 22:41:4497 // SessionObserver:
98 void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
99
100 // Returns sunset and sunrise time calculated from the most recently observed
101 // geoposition. If a geoposition has not been observed, defaults to sunset
102 // 6 PM and sunrise 6 AM.
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51103 base::Time GetSunsetTime() const { return GetSunRiseSet(/*sunrise=*/false); }
104 base::Time GetSunriseTime() const { return GetSunRiseSet(/*sunrise=*/true); }
105
106 static base::TimeDelta GetNextRequestDelayAfterSuccessForTesting();
107
Cattalyya Nuengsigkapian2e703a82022-03-26 00:29:59108 network::SharedURLLoaderFactory* GetFactoryForTesting() { return factory_; }
109
Cattalyya Nuengsigkapian860e05d2022-04-26 19:12:00110 base::OneShotTimer* GetTimerForTesting() { return timer_.get(); }
111
112 bool HasObserverForTesting(const Observer* obs) const {
113 return observers_.HasObserver(obs);
114 }
115
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51116 void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer);
117
118 void SetClockForTesting(base::Clock* clock);
119
120 void SetCurrentTimezoneIdForTesting(const std::u16string& timezone_id);
121
122 protected:
123 // The callback of geolocation request via `provider_`. Once receiving a
124 // new position, it `NotifyWithCurrentGeoposition()` to broadcast the position
125 // to observers and `ScheduleNextRequest()` on the next day. If the retrieval
126 // fails, it `ScheduleNextRequest()` after a `backoff_delay_`, which is
127 // doubled for each failure.
128 void OnGeoposition(const Geoposition& position,
129 bool server_error,
130 const base::TimeDelta elapsed);
131
Cattalyya Nuengsigkapianbba6f472022-02-07 22:56:59132 // Virtual so that it can be overridden by a fake implementation in unit tests
133 // that doesn't request actual geopositions.
134 virtual void RequestGeoposition();
135
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51136 private:
137 // Gets now time from the `clock_` or `base::Time::Now()` if `clock_` does
138 // not exist.
139 base::Time GetNow() const;
140
141 // Calls `RequestGeoposition()` after `delay`.
142 void ScheduleNextRequest(base::TimeDelta delay);
143
Cattalyya Nuengsigkapian98d81312021-12-22 15:51:05144 // Broadcasts the change in geoposition to all observers with
145 // |possible_change_in_timezone| to indicate whether timezone might have
146 // changed as a result of the geoposition change.
147 void NotifyGeopositionChange(bool possible_change_in_timezone);
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51148
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51149 // Note that the below computation is intentionally performed every time
150 // GetSunsetTime() or GetSunriseTime() is called rather than once whenever we
151 // receive a geoposition (which happens at least once a day). This reduces
152 // the chances of getting inaccurate values, especially around DST changes.
153 base::Time GetSunRiseSet(bool sunrise) const;
154
Eric Sumf97e7b892023-04-17 22:41:44155 // Called only when the active user changes in order to see if we need to use
156 // a previously cached geoposition value from the active user's prefs.
157 void LoadCachedGeopositionIfNeeded();
158
159 // Called whenever we receive a new geoposition update to cache it in all
160 // logged-in users' prefs so that it can be used later in the event of not
161 // being able to retrieve a valid geoposition.
162 void StoreCachedGeoposition() const;
163
Arthur Sonzogni834e018f2023-04-22 10:20:02164 const raw_ptr<network::SharedURLLoaderFactory, ExperimentalAsh> factory_;
Cattalyya Nuengsigkapian2e703a82022-03-26 00:29:59165
Eric Sumf97e7b892023-04-17 22:41:44166 // May be null if a user has not logged in yet.
167 base::raw_ptr<PrefService> active_user_pref_service_ = nullptr;
168
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51169 // The IP-based geolocation provider.
170 SimpleGeolocationProvider provider_;
171
172 // Delay after which a new request is retried after a failed one.
173 base::TimeDelta backoff_delay_;
174
175 std::unique_ptr<base::OneShotTimer> timer_;
176
177 // Optional Used in tests to override the time of "Now".
Arthur Sonzogni834e018f2023-04-22 10:20:02178 raw_ptr<base::Clock, ExperimentalAsh> clock_ = nullptr; // Not owned.
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51179
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51180 // The ID of the current timezone in the format similar to "America/Chicago".
181 std::u16string current_timezone_id_;
182
183 base::ObserverList<Observer> observers_;
184
Eric Sumf97e7b892023-04-17 22:41:44185 // True if the current `geoposition_` is from a previously cached value in the
186 // user prefs of any of the users in the current session. It is reset to false
187 // once we receive a newly-updated geoposition. This is used to treat the
188 // current geoposition as temporary until we receive a valid geoposition
189 // update, and also not to let a cached geoposition value to leak to another
190 // user for privacy reasons.
191 bool is_current_geoposition_from_cache_ = false;
192
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51193 std::unique_ptr<SimpleGeoposition> geoposition_;
Eric Sumf97e7b892023-04-17 22:41:44194
195 ScopedSessionObserver scoped_session_observer_;
Cattalyya Nuengsigkapian2ef94332021-11-20 05:42:51196};
197
198} // namespace ash
199
200#endif // ASH_SYSTEM_GEOLOCATION_GEOLOCATION_CONTROLLER_H_