Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/network_change_notifier_win.h" | 5 #include "net/base/network_change_notifier_win.h" |
| 6 | 6 |
| 7 #include <iphlpapi.h> | 7 #include <iphlpapi.h> |
| 8 #include <winsock2.h> | 8 #include <winsock2.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 dns_config_service_thread_(new DnsConfigServiceThread()), | 58 dns_config_service_thread_(new DnsConfigServiceThread()), |
| 59 last_computed_connection_type_(RecomputeCurrentConnectionType()), | 59 last_computed_connection_type_(RecomputeCurrentConnectionType()), |
| 60 last_announced_offline_(last_computed_connection_type_ == | 60 last_announced_offline_(last_computed_connection_type_ == |
| 61 CONNECTION_NONE), | 61 CONNECTION_NONE), |
| 62 weak_factory_(this) { | 62 weak_factory_(this) { |
| 63 memset(&addr_overlapped_, 0, sizeof addr_overlapped_); | 63 memset(&addr_overlapped_, 0, sizeof addr_overlapped_); |
| 64 addr_overlapped_.hEvent = WSACreateEvent(); | 64 addr_overlapped_.hEvent = WSACreateEvent(); |
| 65 } | 65 } |
| 66 | 66 |
| 67 NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { | 67 NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { |
| 68 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 68 if (is_watching_) { | 69 if (is_watching_) { |
| 69 CancelIPChangeNotify(&addr_overlapped_); | 70 CancelIPChangeNotify(&addr_overlapped_); |
|
Ryan Sleevi
2017/05/26 11:54:50
This is why I'm not sure
| |
| 70 addr_watcher_.StopWatching(); | 71 addr_watcher_.StopWatching(); |
| 71 } | 72 } |
| 72 WSACloseEvent(addr_overlapped_.hEvent); | 73 WSACloseEvent(addr_overlapped_.hEvent); |
| 73 } | 74 } |
| 74 | 75 |
| 75 // static | 76 // static |
| 76 NetworkChangeNotifier::NetworkChangeCalculatorParams | 77 NetworkChangeNotifier::NetworkChangeCalculatorParams |
| 77 NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() { | 78 NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() { |
| 78 NetworkChangeCalculatorParams params; | 79 NetworkChangeCalculatorParams params; |
| 79 // Delay values arrived at by simple experimentation and adjusted so as to | 80 // Delay values arrived at by simple experimentation and adjusted so as to |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 // * Approach (2) took an average of 3.25 milliseconds to enumerate the | 130 // * Approach (2) took an average of 3.25 milliseconds to enumerate the |
| 130 // adapters. | 131 // adapters. |
| 131 // * Approach (3) took an average of 0.8 ms to enumerate the providers. | 132 // * Approach (3) took an average of 0.8 ms to enumerate the providers. |
| 132 // | 133 // |
| 133 // In terms of correctness, all three approaches were comparable for the simple | 134 // In terms of correctness, all three approaches were comparable for the simple |
| 134 // experiments I ran... However none of them correctly returned "offline" when | 135 // experiments I ran... However none of them correctly returned "offline" when |
| 135 // executing 'ipconfig /release'. | 136 // executing 'ipconfig /release'. |
| 136 // | 137 // |
| 137 NetworkChangeNotifier::ConnectionType | 138 NetworkChangeNotifier::ConnectionType |
| 138 NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const { | 139 NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const { |
| 139 DCHECK(CalledOnValidThread()); | 140 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 140 | 141 |
| 141 EnsureWinsockInit(); | 142 EnsureWinsockInit(); |
| 142 | 143 |
| 143 // The following code was adapted from: | 144 // The following code was adapted from: |
| 144 // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/net/notifier/ base/win/async_network_alive_win32.cc?view=markup&pathrev=47343 | 145 // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/net/notifier/ base/win/async_network_alive_win32.cc?view=markup&pathrev=47343 |
| 145 // The main difference is we only call WSALookupServiceNext once, whereas | 146 // The main difference is we only call WSALookupServiceNext once, whereas |
| 146 // the earlier code would traverse the entire list and pass LUP_FLUSHPREVIOUS | 147 // the earlier code would traverse the entire list and pass LUP_FLUSHPREVIOUS |
| 147 // to skip past the large results. | 148 // to skip past the large results. |
| 148 | 149 |
| 149 HANDLE ws_handle; | 150 HANDLE ws_handle; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 return last_computed_connection_type_; | 212 return last_computed_connection_type_; |
| 212 } | 213 } |
| 213 | 214 |
| 214 void NetworkChangeNotifierWin::SetCurrentConnectionType( | 215 void NetworkChangeNotifierWin::SetCurrentConnectionType( |
| 215 ConnectionType connection_type) { | 216 ConnectionType connection_type) { |
| 216 base::AutoLock auto_lock(last_computed_connection_type_lock_); | 217 base::AutoLock auto_lock(last_computed_connection_type_lock_); |
| 217 last_computed_connection_type_ = connection_type; | 218 last_computed_connection_type_ = connection_type; |
| 218 } | 219 } |
| 219 | 220 |
| 220 void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { | 221 void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { |
| 221 DCHECK(CalledOnValidThread()); | 222 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 222 DCHECK(is_watching_); | 223 DCHECK(is_watching_); |
| 223 is_watching_ = false; | 224 is_watching_ = false; |
| 224 | 225 |
| 225 // Start watching for the next address change. | 226 // Start watching for the next address change. |
| 226 WatchForAddressChange(); | 227 WatchForAddressChange(); |
| 227 | 228 |
| 228 NotifyObservers(); | 229 NotifyObservers(); |
| 229 } | 230 } |
| 230 | 231 |
| 231 void NetworkChangeNotifierWin::NotifyObservers() { | 232 void NetworkChangeNotifierWin::NotifyObservers() { |
| 232 DCHECK(CalledOnValidThread()); | 233 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 233 SetCurrentConnectionType(RecomputeCurrentConnectionType()); | 234 SetCurrentConnectionType(RecomputeCurrentConnectionType()); |
| 234 NotifyObserversOfIPAddressChange(); | 235 NotifyObserversOfIPAddressChange(); |
| 235 | 236 |
| 236 // Calling GetConnectionType() at this very moment is likely to give | 237 // Calling GetConnectionType() at this very moment is likely to give |
| 237 // the wrong result, so we delay that until a little bit later. | 238 // the wrong result, so we delay that until a little bit later. |
| 238 // | 239 // |
| 239 // The one second delay chosen here was determined experimentally | 240 // The one second delay chosen here was determined experimentally |
| 240 // by adamk on Windows 7. | 241 // by adamk on Windows 7. |
| 241 // If after one second we determine we are still offline, we will | 242 // If after one second we determine we are still offline, we will |
| 242 // delay again. | 243 // delay again. |
| 243 offline_polls_ = 0; | 244 offline_polls_ = 0; |
| 244 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this, | 245 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this, |
| 245 &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange); | 246 &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange); |
| 246 } | 247 } |
| 247 | 248 |
| 248 void NetworkChangeNotifierWin::WatchForAddressChange() { | 249 void NetworkChangeNotifierWin::WatchForAddressChange() { |
| 249 DCHECK(CalledOnValidThread()); | 250 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 250 DCHECK(!is_watching_); | 251 DCHECK(!is_watching_); |
| 251 | 252 |
| 252 // NotifyAddrChange occasionally fails with ERROR_OPEN_FAILED for unknown | 253 // NotifyAddrChange occasionally fails with ERROR_OPEN_FAILED for unknown |
| 253 // reasons. More rarely, it's also been observed failing with | 254 // reasons. More rarely, it's also been observed failing with |
| 254 // ERROR_NO_SYSTEM_RESOURCES. When either of these happens, we retry later. | 255 // ERROR_NO_SYSTEM_RESOURCES. When either of these happens, we retry later. |
| 255 if (!WatchForAddressChangeInternal()) { | 256 if (!WatchForAddressChangeInternal()) { |
| 256 ++sequential_failures_; | 257 ++sequential_failures_; |
| 257 | 258 |
| 258 // TODO(mmenke): If the UMA histograms indicate that this fixes | 259 // TODO(mmenke): If the UMA histograms indicate that this fixes |
| 259 // http://crbug.com/69198, remove this histogram and consider reducing the | 260 // http://crbug.com/69198, remove this histogram and consider reducing the |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 280 if (sequential_failures_ < 2000) { | 281 if (sequential_failures_ < 2000) { |
| 281 UMA_HISTOGRAM_COUNTS_10000("Net.NotifyAddrChangeFailures", | 282 UMA_HISTOGRAM_COUNTS_10000("Net.NotifyAddrChangeFailures", |
| 282 sequential_failures_); | 283 sequential_failures_); |
| 283 } | 284 } |
| 284 | 285 |
| 285 is_watching_ = true; | 286 is_watching_ = true; |
| 286 sequential_failures_ = 0; | 287 sequential_failures_ = 0; |
| 287 } | 288 } |
| 288 | 289 |
| 289 bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() { | 290 bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() { |
| 290 DCHECK(CalledOnValidThread()); | 291 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 291 | 292 |
| 292 if (!dns_config_service_thread_->IsRunning()) { | 293 if (!dns_config_service_thread_->IsRunning()) { |
| 293 dns_config_service_thread_->StartWithOptions( | 294 dns_config_service_thread_->StartWithOptions( |
| 294 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 295 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
| 295 } | 296 } |
| 296 | 297 |
| 297 ResetEventIfSignaled(addr_overlapped_.hEvent); | 298 ResetEventIfSignaled(addr_overlapped_.hEvent); |
| 298 HANDLE handle = NULL; | 299 HANDLE handle = NULL; |
| 299 DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_); | 300 DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_); |
| 300 if (ret != ERROR_IO_PENDING) | 301 if (ret != ERROR_IO_PENDING) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 323 | 324 |
| 324 NotifyObserversOfConnectionTypeChange(); | 325 NotifyObserversOfConnectionTypeChange(); |
| 325 double max_bandwidth_mbps = 0.0; | 326 double max_bandwidth_mbps = 0.0; |
| 326 ConnectionType connection_type = CONNECTION_NONE; | 327 ConnectionType connection_type = CONNECTION_NONE; |
| 327 GetCurrentMaxBandwidthAndConnectionType(&max_bandwidth_mbps, | 328 GetCurrentMaxBandwidthAndConnectionType(&max_bandwidth_mbps, |
| 328 &connection_type); | 329 &connection_type); |
| 329 NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, connection_type); | 330 NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, connection_type); |
| 330 } | 331 } |
| 331 | 332 |
| 332 } // namespace net | 333 } // namespace net |
| OLD | NEW |