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