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