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 
5 #ifndef SERVICES_NETWORK_PUBLIC_CPP_NETWORK_QUALITY_TRACKER_H_
6 #define SERVICES_NETWORK_PUBLIC_CPP_NETWORK_QUALITY_TRACKER_H_
7 
8 #include <memory>
9 
10 #include "base/callback.h"
11 #include "base/component_export.h"
12 #include "base/macros.h"
13 #include "base/observer_list.h"
14 #include "base/sequence_checker.h"
15 #include "mojo/public/cpp/bindings/receiver.h"
16 #include "net/nqe/effective_connection_type.h"
17 #include "services/network/public/mojom/network_quality_estimator_manager.mojom.h"
18 #include "services/network/public/mojom/network_service.mojom-forward.h"
19 
20 namespace network {
21 
22 // This class subscribes to network quality change events from
23 // network::mojom::NetworkQualityEstimatorManagerClient and propagates these
24 // notifications to its list of EffectiveConnectionTypeObserver registered
25 // through AddObserver() and RemoveObserver().
COMPONENT_EXPORT(NETWORK_CPP)26 class COMPONENT_EXPORT(NETWORK_CPP) NetworkQualityTracker
27     : public network::mojom::NetworkQualityEstimatorManagerClient {
28  public:
29   class COMPONENT_EXPORT(NETWORK_CPP) EffectiveConnectionTypeObserver {
30    public:
31     // Called when there is a change in the effective connection type. The
32     // |observer| is notified of the current effective connection type on the
33     // same thread on which it was added.
34     virtual void OnEffectiveConnectionTypeChanged(
35         net::EffectiveConnectionType type) = 0;
36 
37    protected:
38     EffectiveConnectionTypeObserver() {}
39     virtual ~EffectiveConnectionTypeObserver() {}
40 
41    private:
42     DISALLOW_COPY_AND_ASSIGN(EffectiveConnectionTypeObserver);
43   };
44 
45   // Observes changes in the HTTP RTT, transport RTT or downstream throughput
46   // estimates.
47   class COMPONENT_EXPORT(NETWORK_CPP) RTTAndThroughputEstimatesObserver {
48    public:
49     // Called when there is a substantial change in either HTTP RTT, transport
50     // RTT or downstream estimate. If either of the RTT estimates are
51     // unavailable, then the value of that estimate is set to base::TimeDelta().
52     // If downstream estimate is unavailable, its value is set to INT32_MAX.
53     // The |observer| is notified of the current effective connection type on
54     // the same thread on which it was added.
55     virtual void OnRTTOrThroughputEstimatesComputed(
56         base::TimeDelta http_rtt,
57         base::TimeDelta transport_rtt,
58         int32_t downstream_throughput_kbps) = 0;
59 
60     virtual ~RTTAndThroughputEstimatesObserver() {}
61 
62    protected:
63     RTTAndThroughputEstimatesObserver() {}
64 
65    private:
66     DISALLOW_COPY_AND_ASSIGN(RTTAndThroughputEstimatesObserver);
67   };
68 
69   // Running the |callback| returns the network service in use.
70   // NetworkQualityTracker does not need to be destroyed before the network
71   // service.
72   explicit NetworkQualityTracker(
73       base::RepeatingCallback<network::mojom::NetworkService*()> callback);
74 
75   ~NetworkQualityTracker() override;
76 
77   // Returns the current estimate of the effective connection type.
78   virtual net::EffectiveConnectionType GetEffectiveConnectionType() const;
79 
80   // Returns the current HTTP RTT estimate. The RTT at the HTTP layer measures
81   // the time from when the request was sent (this happens after the connection
82   // is established) to the time when the response headers were received.
83   virtual base::TimeDelta GetHttpRTT() const;
84 
85   // Returns the current transport-layer RTT estimate. The RTT at the transport
86   // layer provides an aggregate estimate of the transport RTT as computed by
87   // various underlying TCP and QUIC connections.
88   virtual base::TimeDelta GetTransportRTT() const;
89 
90   // Returns the current downstream throughput estimate (in kilobits per
91   // second).
92   virtual int32_t GetDownstreamThroughputKbps() const;
93 
94   // Registers |observer| to receive notifications of network changes. The
95   // thread on which this is called is the thread on which |observer| will be
96   // called back with notifications. The |observer| is notified of the current
97   // effective connection type on the same thread. At the time |observer| is
98   // added, if the estimated effective connection type is unknown, then the
99   // |observer| is not notified until there is a change in the network quality
100   // estimate.
101   void AddEffectiveConnectionTypeObserver(
102       EffectiveConnectionTypeObserver* observer);
103 
104   // Unregisters |observer| from receiving notifications. This must be called
105   // on the same thread on which AddObserver() was called.
106   // All observers must be unregistered before |this| is destroyed.
107   void RemoveEffectiveConnectionTypeObserver(
108       EffectiveConnectionTypeObserver* observer);
109 
110   // Registers |observer| to receive notifications of RTT or throughput changes.
111   // This should be called on the same thread as the thread on which |this| is
112   // created. The |observer| would be called back with notifications on that
113   // same thread. The |observer| is notified of the current HTTP RTT, transport
114   // RTT and downstrean bandwidth estimates on the same thread. If either of the
115   // RTT estimate are unavailable, then the value of that estimate is set to
116   // base::TimeDelta(). If downstream estimate is unavailable, its value is set
117   // to INT32_MAX. The |observer| is notified of the current RTT and
118   // throughput estimates synchronously when this method is invoked.
119   void AddRTTAndThroughputEstimatesObserver(
120       RTTAndThroughputEstimatesObserver* observer);
121 
122   // Unregisters |observer| from receiving notifications. This must be called
123   // on the same thread on which AddObserver() was called.
124   // All observers must be unregistered before |this| is destroyed.
125   void RemoveRTTAndThroughputEstimatesObserver(
126       RTTAndThroughputEstimatesObserver* observer);
127 
128   // Changes effective connection type estimate to the provided value, and
129   // reports |effective_connection_type| to all
130   // EffectiveConnectionTypeObservers. Calling this also disables all organic
131   // notifications sent to observers.
132   void ReportEffectiveConnectionTypeForTesting(
133       net::EffectiveConnectionType effective_connection_type);
134 
135   // Changes RTT and throughput estimate to the provided estimates, and
136   // reports it to all RTTAndThroughputEstimatesObservers. Calling this also
137   // disables all organic notifications sent to observers.
138   void ReportRTTsAndThroughputForTesting(base::TimeDelta http_rtt,
139                                          int32_t downstream_throughput_kbps);
140 
141  protected:
142   // Constructor for testing purposes only without the network service instance.
143   NetworkQualityTracker();
144 
145   // NetworkQualityEstimatorManagerClient implementation. Protected for testing.
146   void OnNetworkQualityChanged(
147       net::EffectiveConnectionType effective_connection_type,
148       base::TimeDelta http_rtt,
149       base::TimeDelta transport_rtt,
150       int32_t downlink_bandwidth_kbps) override;
151 
152  private:
153   // Starts listening for network quality change notifications from
154   // network_service. Observers may be added and GetEffectiveConnectionType
155   // called, but no network information will be provided until this method is
156   // called.
157   void InitializeMojoChannel();
158 
159   void HandleNetworkServicePipeBroken();
160 
161   // Running the |get_network_service_callback_| returns the network service in
162   // use.
163   const base::RepeatingCallback<network::mojom::NetworkService*()>
164       get_network_service_callback_;
165 
166   net::EffectiveConnectionType effective_connection_type_;
167   base::TimeDelta http_rtt_;
168   base::TimeDelta transport_rtt_;
169   int32_t downlink_bandwidth_kbps_;
170 
171   // True if network quality has been overridden by tests. If set to true, it
172   // disables all organic notifications sent to observers.
173   bool network_quality_overridden_for_testing_;
174 
175   base::ObserverList<EffectiveConnectionTypeObserver>::Unchecked
176       effective_connection_type_observer_list_;
177 
178   base::ObserverList<RTTAndThroughputEstimatesObserver>::Unchecked
179       rtt_and_throughput_observer_list_;
180 
181   mojo::Receiver<network::mojom::NetworkQualityEstimatorManagerClient>
182       receiver_{this};
183 
184   SEQUENCE_CHECKER(sequence_checker_);
185 
186   DISALLOW_COPY_AND_ASSIGN(NetworkQualityTracker);
187 };
188 
189 }  // namespace network
190 
191 #endif  // SERVICES_NETWORK_PUBLIC_CPP_NETWORK_QUALITY_TRACKER_H_
192