• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 NET_BASE_NETWORK_CHANGE_NOTIFIER_WIN_H_
6 #define NET_BASE_NETWORK_CHANGE_NOTIFIER_WIN_H_
7 
8 #include <windows.h>
9 
10 #include <atomic>
11 
12 #include "base/compiler_specific.h"
13 #include "base/functional/callback.h"
14 #include "base/memory/scoped_refptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/sequence_checker.h"
17 #include "base/thread_annotations.h"
18 #include "base/threading/sequence_bound.h"
19 #include "base/timer/timer.h"
20 #include "base/win/object_watcher.h"
21 #include "net/base/net_export.h"
22 #include "net/base/network_change_notifier.h"
23 
24 namespace base {
25 class SequencedTaskRunner;
26 }  // namespace base
27 
28 namespace net {
29 
30 class NetworkCostChangeNotifierWin;
31 
32 // NetworkChangeNotifierWin uses a SequenceChecker, as all its internal
33 // notification code must be called on the sequence it is created and destroyed
34 // on.  All the NetworkChangeNotifier methods it implements are threadsafe.
35 class NET_EXPORT_PRIVATE NetworkChangeNotifierWin
36     : public NetworkChangeNotifier,
37       public base::win::ObjectWatcher::Delegate {
38  public:
39   NetworkChangeNotifierWin();
40   NetworkChangeNotifierWin(const NetworkChangeNotifierWin&) = delete;
41   NetworkChangeNotifierWin& operator=(const NetworkChangeNotifierWin&) = delete;
42   ~NetworkChangeNotifierWin() override;
43 
44   // Begins listening for a single subsequent address change.  If it fails to
45   // start watching, it retries on a timer.  Must be called only once, on the
46   // sequence |this| was created on.  This cannot be called in the constructor,
47   // as WatchForAddressChangeInternal is mocked out in unit tests.
48   // TODO(mmenke): Consider making this function a part of the
49   //               NetworkChangeNotifier interface, so other subclasses can be
50   //               unit tested in similar fashion, as needed.
51   void WatchForAddressChange();
52 
53  protected:
54   // For unit tests only.
is_watching()55   bool is_watching() const { return is_watching_; }
set_is_watching(bool is_watching)56   void set_is_watching(bool is_watching) { is_watching_ = is_watching; }
sequential_failures()57   int sequential_failures() const { return sequential_failures_; }
58 
59  private:
60   friend class NetworkChangeNotifierWinTest;
61   friend class TestNetworkChangeNotifierWin;
62 
63   // NetworkChangeNotifier methods:
64   ConnectionCost GetCurrentConnectionCost() override;
65 
66   ConnectionType GetCurrentConnectionType() const override;
67 
68   // ObjectWatcher::Delegate methods:
69   // Must only be called on the sequence |this| was created on.
70   void OnObjectSignaled(HANDLE object) override;
71 
72   // Recompute the current connection type on newer versions of Windows (Win10
73   // Build 19041 and above).
74   static ConnectionType RecomputeCurrentConnectionTypeModern();
75 
76   // Does the actual work to determine the current connection type. This will
77   // call into RecomputeCurrentConnectionTypeModern on modern OS. It is not
78   // thread safe, see crbug.com/324913.
79   static ConnectionType RecomputeCurrentConnectionType();
80 
81   // Calls RecomputeCurrentConnectionTypeImpl on the DNS sequence and runs
82   // |reply_callback| with the type on the calling sequence.
83   virtual void RecomputeCurrentConnectionTypeOnBlockingSequence(
84       base::OnceCallback<void(ConnectionType)> reply_callback) const;
85 
86   void SetCurrentConnectionType(ConnectionType connection_type);
87 
88   // Notifies IP address change observers of a change immediately, and notifies
89   // network state change observers on a delay.  Must only be called on the
90   // sequence |this| was created on.
91   void NotifyObservers(ConnectionType connection_type);
92 
93   // Forwards connection type notifications to parent class.
94   void NotifyParentOfConnectionTypeChange();
95   void NotifyParentOfConnectionTypeChangeImpl(ConnectionType connection_type);
96 
97   // Tries to start listening for a single subsequent address change.  Returns
98   // false on failure.  The caller is responsible for updating |is_watching_|.
99   // Virtual for unit tests.  Must only be called on the sequence |this| was
100   // created on.
101   virtual bool WatchForAddressChangeInternal();
102 
103   static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsWin();
104 
105   void OnCostChanged(NetworkChangeNotifier::ConnectionCost new_cost);
106 
107   // All member variables may only be accessed on the sequence |this| was
108   // created on.
109 
110   // False when not currently watching for network change events.  This only
111   // happens on initialization and when WatchForAddressChangeInternal fails and
112   // there is a pending task to try again.  Needed for safe cleanup.
113   bool is_watching_ = false;
114 
115   base::win::ObjectWatcher addr_watcher_;
116   OVERLAPPED addr_overlapped_;
117 
118   base::OneShotTimer timer_;
119 
120   // Number of times WatchForAddressChange has failed in a row.
121   int sequential_failures_ = 0;
122 
123   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
124 
125   mutable base::Lock last_computed_connection_type_lock_;
126   ConnectionType last_computed_connection_type_;
127 
128   std::atomic<NetworkChangeNotifier::ConnectionCost>
129       last_computed_connection_cost_ =
130           NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN;
131 
132   // Provides the cost of the current connection.  Uses the Windows OS APIs to
133   // monitor and determine cost.
134   base::SequenceBound<NetworkCostChangeNotifierWin> cost_change_notifier_;
135 
136   // Result of IsOffline() when NotifyObserversOfConnectionTypeChange()
137   // was last called.
138   bool last_announced_offline_;
139   // Number of times polled to check if still offline.
140   int offline_polls_;
141 
142   // Used to ensure that all registration actions are properly sequenced on the
143   // same thread regardless of which thread was used to call into the
144   // NetworkChangeNotifier API.
145   scoped_refptr<base::SequencedTaskRunner> sequence_runner_for_registration_;
146 
147   SEQUENCE_CHECKER(sequence_checker_);
148 
149   // Used for calling WatchForAddressChange again on failure.
150   base::WeakPtrFactory<NetworkChangeNotifierWin> weak_factory_{this};
151 };
152 
153 }  // namespace net
154 
155 #endif  // NET_BASE_NETWORK_CHANGE_NOTIFIER_WIN_H_
156