1 // Copyright 2017 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 
5 #ifndef SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_LOCATION_NOTIFIER_H_
6 #define SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_LOCATION_NOTIFIER_H_
7 
8 #include <memory>
9 
10 #include "base/callback.h"
11 #include "base/callback_list.h"
12 #include "base/cancelable_callback.h"
13 #include "base/macros.h"
14 #include "base/optional.h"
15 #include "base/time/time.h"
16 #include "net/traffic_annotation/network_traffic_annotation.h"
17 #include "services/device/geolocation/geolocation_provider.h"
18 #include "services/device/geolocation/network_location_request.h"
19 #include "services/device/public/mojom/geoposition.mojom.h"
20 #include "services/network/public/cpp/network_connection_tracker.h"
21 
22 namespace device {
23 
24 class NetworkLocationRequest;
25 struct WifiData;
26 
27 // Provides subscribers with updates of the device's approximate geographic
28 // location inferred from its publicly-visible IP address.
29 // Sequencing:
30 // * Must be created, used, and destroyed on the same sequence.
31 class PublicIpAddressLocationNotifier
32     : public network::NetworkConnectionTracker::NetworkConnectionObserver {
33  public:
34   // Creates a notifier that uses the specified Google |api_key| and
35   // |url_loader_factory| for network location requests.
36   PublicIpAddressLocationNotifier(
37       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
38       network::NetworkConnectionTracker* network_connection_tracker,
39       const std::string& api_key);
40   ~PublicIpAddressLocationNotifier() override;
41 
42   using QueryNextPositionCallback =
43       base::OnceCallback<void(const mojom::Geoposition&)>;
44 
45   // Requests a callback with the next Geoposition obtained later than
46   // |time_of_prev_position|.
47   // Specifically:
48   // * If a position has been obtained subsequent to |time_of_prev_position|,
49   // returns it.
50   // * Otherwise, returns an updated position once a network change has
51   // occurred.
52   // * Note that it is possible for |callback| to never be called if no network
53   // change ever occurs after |time_of_prev_position|.
54   void QueryNextPosition(base::Time time_of_prev_position,
55                          const net::PartialNetworkTrafficAnnotationTag& tag,
56                          QueryNextPositionCallback callback);
57 
58  private:
59   // Sequence checker for all methods.
60   SEQUENCE_CHECKER(sequence_checker_);
61 
62   // NetworkConnectionTracker::NetworkConnectionObserver:
63   // Network change notifications tend to come in a cluster in a short time, so
64   // this just sets a task to run ReactToNetworkChange after a short time.
65   void OnConnectionChanged(network::mojom::ConnectionType type) override;
66 
67   // Actually react to a network change, starting a network geolocation request
68   // if any clients are waiting.
69   void ReactToNetworkChange();
70 
71   // Creates |network_location_request_| and starts the network request, which
72   // will invoke OnNetworkLocationResponse when done.
73   void MakeNetworkLocationRequest();
74 
75   // Completion callback for network_location_request_.
76   void OnNetworkLocationResponse(const mojom::Geoposition& position,
77                                  bool server_error,
78                                  const WifiData& wifi_data);
79 
80   // Cancelable closure to absorb overlapping delayed calls to
81   // ReactToNetworkChange.
82   base::CancelableOnceClosure react_to_network_change_closure_;
83 
84   // Whether we have been notified of a network change since the last network
85   // location request was sent.
86   bool network_changed_since_last_request_;
87 
88   // The geoposition as of the latest network change, if it has been obtained.
89   base::Optional<mojom::Geoposition> latest_geoposition_;
90 
91   // Google API key for network geolocation requests.
92   const std::string api_key_;
93 
94   // SharedURLLoaderFactory for network geolocation requests.
95   const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
96 
97   // Used to listen to network connection changes.
98   // Must outlive this object.
99   network::NetworkConnectionTracker* network_connection_tracker_;
100 
101   // Used to make calls to the Maps geolocate API.
102   // Empty unless a call is currently in progress.
103   std::unique_ptr<NetworkLocationRequest> network_location_request_;
104 
105   // Clients waiting for an updated geoposition.
106   std::vector<QueryNextPositionCallback> callbacks_;
107 
108   // The most recent PartialNetworkTrafficAnnotationTag provided by a client.
109   std::unique_ptr<const net::PartialNetworkTrafficAnnotationTag>
110       network_traffic_annotation_tag_;
111 
112   // Weak references to |this| for posted tasks.
113   base::WeakPtrFactory<PublicIpAddressLocationNotifier> weak_ptr_factory_{this};
114 
115   DISALLOW_COPY_AND_ASSIGN(PublicIpAddressLocationNotifier);
116 };
117 
118 }  // namespace device
119 
120 #endif  // SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_LOCATION_NOTIFIER_H_
121