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 <netlistmgr.h> 9 #include <ocidl.h> 10 #include <windows.h> 11 #include <wrl.h> 12 #include <wrl/client.h> 13 14 #include <memory> 15 16 #include "base/compiler_specific.h" 17 #include "base/functional/callback.h" 18 #include "base/memory/scoped_refptr.h" 19 #include "base/memory/weak_ptr.h" 20 #include "base/sequence_checker.h" 21 #include "base/thread_annotations.h" 22 #include "base/timer/timer.h" 23 #include "base/win/object_watcher.h" 24 #include "net/base/net_export.h" 25 #include "net/base/network_change_notifier.h" 26 27 namespace base { 28 class SequencedTaskRunner; 29 } // namespace base 30 31 namespace net { 32 33 class NetworkCostManagerEventSink; 34 35 // NetworkChangeNotifierWin uses a SequenceChecker, as all its internal 36 // notification code must be called on the sequence it is created and destroyed 37 // on. All the NetworkChangeNotifier methods it implements are threadsafe. 38 class NET_EXPORT_PRIVATE NetworkChangeNotifierWin 39 : public NetworkChangeNotifier, 40 public base::win::ObjectWatcher::Delegate { 41 public: 42 NetworkChangeNotifierWin(); 43 NetworkChangeNotifierWin(const NetworkChangeNotifierWin&) = delete; 44 NetworkChangeNotifierWin& operator=(const NetworkChangeNotifierWin&) = delete; 45 ~NetworkChangeNotifierWin() override; 46 47 // Begins listening for a single subsequent address change. If it fails to 48 // start watching, it retries on a timer. Must be called only once, on the 49 // sequence |this| was created on. This cannot be called in the constructor, 50 // as WatchForAddressChangeInternal is mocked out in unit tests. 51 // TODO(mmenke): Consider making this function a part of the 52 // NetworkChangeNotifier interface, so other subclasses can be 53 // unit tested in similar fashion, as needed. 54 void WatchForAddressChange(); 55 56 protected: 57 // For unit tests only. is_watching()58 bool is_watching() const { return is_watching_; } set_is_watching(bool is_watching)59 void set_is_watching(bool is_watching) { is_watching_ = is_watching; } sequential_failures()60 int sequential_failures() const { return sequential_failures_; } 61 62 private: 63 friend class NetworkChangeNotifierWinTest; 64 friend class TestNetworkChangeNotifierWin; 65 66 // NetworkChangeNotifier methods: 67 ConnectionCost GetCurrentConnectionCost() override; 68 69 ConnectionType GetCurrentConnectionType() const override; 70 71 // ObjectWatcher::Delegate methods: 72 // Must only be called on the sequence |this| was created on. 73 void OnObjectSignaled(HANDLE object) override; 74 75 // Does the actual work to determine the current connection type. 76 // It is not thread safe, see crbug.com/324913. 77 static ConnectionType RecomputeCurrentConnectionType(); 78 79 // Calls RecomputeCurrentConnectionTypeImpl on the DNS sequence and runs 80 // |reply_callback| with the type on the calling sequence. 81 virtual void RecomputeCurrentConnectionTypeOnBlockingSequence( 82 base::OnceCallback<void(ConnectionType)> reply_callback) const; 83 84 void SetCurrentConnectionType(ConnectionType connection_type); 85 86 // Notifies IP address change observers of a change immediately, and notifies 87 // network state change observers on a delay. Must only be called on the 88 // sequence |this| was created on. 89 void NotifyObservers(ConnectionType connection_type); 90 91 // Forwards connection type notifications to parent class. 92 void NotifyParentOfConnectionTypeChange(); 93 void NotifyParentOfConnectionTypeChangeImpl(ConnectionType connection_type); 94 95 // Tries to start listening for a single subsequent address change. Returns 96 // false on failure. The caller is responsible for updating |is_watching_|. 97 // Virtual for unit tests. Must only be called on the sequence |this| was 98 // created on. 99 virtual bool WatchForAddressChangeInternal(); 100 101 static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsWin(); 102 103 // Gets the current network connection cost (if possible) and caches it. 104 void InitializeConnectionCost(); 105 // Does the work of initializing for thread safety. 106 bool InitializeConnectionCostOnce(); 107 // Retrieves the current network connection cost from the OS's Cost Manager. 108 HRESULT UpdateConnectionCostFromCostManager(); 109 // Converts the OS enum values to the enum values used in our code. 110 static ConnectionCost ConnectionCostFromNlmCost(NLM_CONNECTION_COST cost); 111 // Sets the cached network connection cost value. 112 void SetCurrentConnectionCost(ConnectionCost connection_cost); 113 // Callback method for the notification event sink. 114 void OnCostChanged(); 115 // Tells this class that an observer was added and therefore this class needs 116 // to register for notifications. 117 void ConnectionCostObserverAdded() override; 118 // Since ConnectionCostObserverAdded() can be called on any thread and we 119 // don't want to do a bunch of work on an arbitrary thread, this method used 120 // to post task to do the work. 121 void OnConnectionCostObserverAdded(); 122 123 // All member variables may only be accessed on the sequence |this| was 124 // created on. 125 126 // False when not currently watching for network change events. This only 127 // happens on initialization and when WatchForAddressChangeInternal fails and 128 // there is a pending task to try again. Needed for safe cleanup. 129 bool is_watching_ = false; 130 131 base::win::ObjectWatcher addr_watcher_; 132 OVERLAPPED addr_overlapped_; 133 134 base::OneShotTimer timer_; 135 136 // Number of times WatchForAddressChange has failed in a row. 137 int sequential_failures_ = 0; 138 139 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; 140 141 mutable base::Lock last_computed_connection_type_lock_; 142 ConnectionType last_computed_connection_type_; 143 144 std::atomic<ConnectionCost> last_computed_connection_cost_ = 145 ConnectionCost::CONNECTION_COST_UNKNOWN; 146 147 // Result of IsOffline() when NotifyObserversOfConnectionTypeChange() 148 // was last called. 149 bool last_announced_offline_; 150 // Number of times polled to check if still offline. 151 int offline_polls_; 152 153 Microsoft::WRL::ComPtr<INetworkCostManager> network_cost_manager_; 154 Microsoft::WRL::ComPtr<NetworkCostManagerEventSink> 155 network_cost_manager_event_sink_; 156 157 // Used to ensure that all registration actions are properly sequenced on the 158 // same thread regardless of which thread was used to call into the 159 // NetworkChangeNotifier API. 160 scoped_refptr<base::SequencedTaskRunner> sequence_runner_for_registration_; 161 162 SEQUENCE_CHECKER(sequence_checker_); 163 164 // Used for calling WatchForAddressChange again on failure. 165 base::WeakPtrFactory<NetworkChangeNotifierWin> weak_factory_{this}; 166 }; 167 168 } // namespace net 169 170 #endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_WIN_H_ 171