Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: net/base/network_change_notifier.cc

Issue 11360108: Start calculating new combined NetworkChangeNotifier signal (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use a default constructor Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/network_change_notifier.h ('k') | net/base/network_change_notifier_linux.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.h" 5 #include "net/base/network_change_notifier.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "base/synchronization/lock.h" 8 #include "base/synchronization/lock.h"
9 #include "build/build_config.h" 9 #include "build/build_config.h"
10 #include "googleurl/src/gurl.h" 10 #include "googleurl/src/gurl.h"
(...skipping 28 matching lines...) Expand all
39 return CONNECTION_UNKNOWN; 39 return CONNECTION_UNKNOWN;
40 } 40 }
41 }; 41 };
42 42
43 } // namespace 43 } // namespace
44 44
45 // The main observer class that records UMAs for network events. 45 // The main observer class that records UMAs for network events.
46 class HistogramWatcher 46 class HistogramWatcher
47 : public NetworkChangeNotifier::ConnectionTypeObserver, 47 : public NetworkChangeNotifier::ConnectionTypeObserver,
48 public NetworkChangeNotifier::IPAddressObserver, 48 public NetworkChangeNotifier::IPAddressObserver,
49 public NetworkChangeNotifier::DNSObserver { 49 public NetworkChangeNotifier::DNSObserver,
50 public NetworkChangeNotifier::NetworkChangeObserver {
50 public: 51 public:
51 HistogramWatcher() 52 HistogramWatcher()
52 : last_ip_address_change_(base::TimeTicks::Now()), 53 : last_ip_address_change_(base::TimeTicks::Now()),
53 last_connection_change_(base::TimeTicks::Now()), 54 last_connection_change_(base::TimeTicks::Now()),
54 last_dns_change_(base::TimeTicks::Now()), 55 last_dns_change_(base::TimeTicks::Now()),
56 last_network_change_(base::TimeTicks::Now()),
55 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), 57 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
56 offline_packets_received_(0) {} 58 offline_packets_received_(0) {}
57 59
58 // Registers our three Observer implementations. This is called from the 60 // Registers our three Observer implementations. This is called from the
59 // network thread so that our Observer implementations are also called 61 // network thread so that our Observer implementations are also called
60 // from the network thread. This avoids multi-threaded race conditions 62 // from the network thread. This avoids multi-threaded race conditions
61 // because the only other interface, |NotifyDataReceived| is also 63 // because the only other interface, |NotifyDataReceived| is also
62 // only called from the network thread. 64 // only called from the network thread.
63 void Init() { 65 void Init() {
64 NetworkChangeNotifier::AddConnectionTypeObserver(this); 66 NetworkChangeNotifier::AddConnectionTypeObserver(this);
65 NetworkChangeNotifier::AddIPAddressObserver(this); 67 NetworkChangeNotifier::AddIPAddressObserver(this);
66 NetworkChangeNotifier::AddDNSObserver(this); 68 NetworkChangeNotifier::AddDNSObserver(this);
69 NetworkChangeNotifier::AddNetworkChangeObserver(this);
67 } 70 }
68 71
69 virtual ~HistogramWatcher() {} 72 virtual ~HistogramWatcher() {}
70 73
71 // NetworkChangeNotifier::IPAddressObserver implementation. 74 // NetworkChangeNotifier::IPAddressObserver implementation.
72 virtual void OnIPAddressChanged() OVERRIDE { 75 virtual void OnIPAddressChanged() OVERRIDE {
73 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange", 76 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
74 SinceLast(&last_ip_address_change_)); 77 SinceLast(&last_ip_address_change_));
78 UMA_HISTOGRAM_MEDIUM_TIMES(
79 "NCN.ConnectionTypeChangeToIPAddressChange",
80 last_ip_address_change_ - last_connection_change_);
75 } 81 }
76 82
77 // NetworkChangeNotifier::ConnectionTypeObserver implementation. 83 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
78 virtual void OnConnectionTypeChanged( 84 virtual void OnConnectionTypeChanged(
79 NetworkChangeNotifier::ConnectionType type) OVERRIDE { 85 NetworkChangeNotifier::ConnectionType type) OVERRIDE {
80 if (type != NetworkChangeNotifier::CONNECTION_NONE) { 86 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
81 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", 87 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange",
82 SinceLast(&last_connection_change_)); 88 SinceLast(&last_connection_change_));
83 89
84 if (offline_packets_received_) { 90 if (offline_packets_received_) {
85 if ((last_connection_change_ - last_offline_packet_received_) < 91 if ((last_connection_change_ - last_offline_packet_received_) <
86 base::TimeDelta::FromSeconds(5)) { 92 base::TimeDelta::FromSeconds(5)) {
87 // We can compare this sum with the sum of NCN.OfflineDataRecv. 93 // We can compare this sum with the sum of NCN.OfflineDataRecv.
88 UMA_HISTOGRAM_COUNTS_10000( 94 UMA_HISTOGRAM_COUNTS_10000(
89 "NCN.OfflineDataRecvAny5sBeforeOnline", 95 "NCN.OfflineDataRecvAny5sBeforeOnline",
90 offline_packets_received_); 96 offline_packets_received_);
91 } 97 }
92 98
93 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline", 99 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline",
94 last_connection_change_ - 100 last_connection_change_ -
95 last_offline_packet_received_); 101 last_offline_packet_received_);
96 } 102 }
97 } else { 103 } else {
98 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", 104 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange",
99 SinceLast(&last_connection_change_)); 105 SinceLast(&last_connection_change_));
100 } 106 }
107 UMA_HISTOGRAM_MEDIUM_TIMES(
108 "NCN.IPAddressChangeToConnectionTypeChange",
109 last_connection_change_ - last_ip_address_change_);
101 110
102 offline_packets_received_ = 0; 111 offline_packets_received_ = 0;
103 last_connection_type_ = type; 112 last_connection_type_ = type;
104 polling_interval_ = base::TimeDelta::FromSeconds(1); 113 polling_interval_ = base::TimeDelta::FromSeconds(1);
105 } 114 }
106 115
107 // NetworkChangeNotifier::DNSObserver implementation. 116 // NetworkChangeNotifier::DNSObserver implementation.
108 virtual void OnDNSChanged() OVERRIDE { 117 virtual void OnDNSChanged() OVERRIDE {
109 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange", 118 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
110 SinceLast(&last_dns_change_)); 119 SinceLast(&last_dns_change_));
111 } 120 }
112 121
122 // NetworkChangeNotifier::NetworkChangeObserver implementation.
123 virtual void OnNetworkChanged(
124 NetworkChangeNotifier::ConnectionType type) OVERRIDE {
125 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
126 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
127 SinceLast(&last_network_change_));
128 } else {
129 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
130 SinceLast(&last_network_change_));
131 }
132 }
133
113 // Record histogram data whenever we receive a packet but think we're 134 // Record histogram data whenever we receive a packet but think we're
114 // offline. Should only be called from the network thread. 135 // offline. Should only be called from the network thread.
115 void NotifyDataReceived(const GURL& source) { 136 void NotifyDataReceived(const GURL& source) {
116 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE || 137 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE ||
117 IsLocalhost(source.host()) || 138 IsLocalhost(source.host()) ||
118 !(source.SchemeIs("http") || source.SchemeIs("https"))) { 139 !(source.SchemeIs("http") || source.SchemeIs("https"))) {
119 return; 140 return;
120 } 141 }
121 142
122 base::TimeTicks current_time = base::TimeTicks::Now(); 143 base::TimeTicks current_time = base::TimeTicks::Now();
(...skipping 23 matching lines...) Expand all
146 static base::TimeDelta SinceLast(base::TimeTicks *last_time) { 167 static base::TimeDelta SinceLast(base::TimeTicks *last_time) {
147 base::TimeTicks current_time = base::TimeTicks::Now(); 168 base::TimeTicks current_time = base::TimeTicks::Now();
148 base::TimeDelta delta = current_time - *last_time; 169 base::TimeDelta delta = current_time - *last_time;
149 *last_time = current_time; 170 *last_time = current_time;
150 return delta; 171 return delta;
151 } 172 }
152 173
153 base::TimeTicks last_ip_address_change_; 174 base::TimeTicks last_ip_address_change_;
154 base::TimeTicks last_connection_change_; 175 base::TimeTicks last_connection_change_;
155 base::TimeTicks last_dns_change_; 176 base::TimeTicks last_dns_change_;
177 base::TimeTicks last_network_change_;
156 base::TimeTicks last_offline_packet_received_; 178 base::TimeTicks last_offline_packet_received_;
157 base::TimeTicks last_polled_connection_; 179 base::TimeTicks last_polled_connection_;
158 // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our 180 // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
159 // first transition to offline and on subsequent transitions. Once offline, 181 // first transition to offline and on subsequent transitions. Once offline,
160 // |polling_interval_| doubles as offline data is received and we poll 182 // |polling_interval_| doubles as offline data is received and we poll
161 // with |NetworkChangeNotifier::GetConnectionType| to verify the connection 183 // with |NetworkChangeNotifier::GetConnectionType| to verify the connection
162 // state. 184 // state.
163 base::TimeDelta polling_interval_; 185 base::TimeDelta polling_interval_;
164 // |last_connection_type_| is the last value passed to 186 // |last_connection_type_| is the last value passed to
165 // |OnConnectionTypeChanged|. 187 // |OnConnectionTypeChanged|.
(...skipping 20 matching lines...) Expand all
186 void SetDnsConfig(const DnsConfig& dns_config) { 208 void SetDnsConfig(const DnsConfig& dns_config) {
187 base::AutoLock lock(lock_); 209 base::AutoLock lock(lock_);
188 dns_config_ = dns_config; 210 dns_config_ = dns_config;
189 } 211 }
190 212
191 private: 213 private:
192 mutable base::Lock lock_; 214 mutable base::Lock lock_;
193 DnsConfig dns_config_; 215 DnsConfig dns_config_;
194 }; 216 };
195 217
218 NetworkChangeNotifier::NetworkChangeCalculatorParams::
219 NetworkChangeCalculatorParams() {
220 }
221
222 // Calculates NetworkChange signal from IPAddress and ConnectionType signals.
223 class NetworkChangeNotifier::NetworkChangeCalculator
224 : public ConnectionTypeObserver,
225 public IPAddressObserver {
226 public:
227 NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
228 : params_(params),
229 have_announced_(false),
230 last_announced_connection_type_(CONNECTION_NONE),
231 pending_connection_type_(CONNECTION_NONE) {}
232
233 void Init() {
234 AddConnectionTypeObserver(this);
235 AddIPAddressObserver(this);
236 }
237
238 virtual ~NetworkChangeCalculator() {
239 RemoveConnectionTypeObserver(this);
240 RemoveIPAddressObserver(this);
241 }
242
243 // NetworkChangeNotifier::IPAddressObserver implementation.
244 virtual void OnIPAddressChanged() OVERRIDE {
245 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
246 ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
247 // Cancels any previous timer.
248 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
249 }
250
251 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
252 virtual void OnConnectionTypeChanged(ConnectionType type) OVERRIDE {
253 pending_connection_type_ = type;
254 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
255 ? params_.connection_type_offline_delay_
256 : params_.connection_type_online_delay_;
257 // Cancels any previous timer.
258 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
259 }
260
261 private:
262 void Notify() {
263 // Don't bother signaling about dead connections.
264 if (have_announced_ &&
265 (last_announced_connection_type_ == CONNECTION_NONE) &&
266 (pending_connection_type_ == CONNECTION_NONE)) {
267 return;
268 }
269 have_announced_ = true;
270 last_announced_connection_type_ = pending_connection_type_;
271 // Immediately before sending out an online signal, send out an offline
272 // signal to perform any destructive actions before constructive actions.
273 if (pending_connection_type_ != CONNECTION_NONE)
274 NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
275 NetworkChangeNotifier::NotifyObserversOfNetworkChange(
276 pending_connection_type_);
277 }
278
279 const NetworkChangeCalculatorParams params_;
280
281 // Indicates if NotifyObserversOfNetworkChange has been called yet.
282 bool have_announced_;
283 // Last value passed to NotifyObserversOfNetworkChange.
284 ConnectionType last_announced_connection_type_;
285 // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
286 ConnectionType pending_connection_type_;
287 // Used to delay notifications so duplicates can be combined.
288 base::OneShotTimer<NetworkChangeCalculator> timer_;
289 };
290
196 NetworkChangeNotifier::~NetworkChangeNotifier() { 291 NetworkChangeNotifier::~NetworkChangeNotifier() {
197 DCHECK_EQ(this, g_network_change_notifier); 292 DCHECK_EQ(this, g_network_change_notifier);
198 g_network_change_notifier = NULL; 293 g_network_change_notifier = NULL;
199 } 294 }
200 295
201 // static 296 // static
202 void NetworkChangeNotifier::SetFactory( 297 void NetworkChangeNotifier::SetFactory(
203 NetworkChangeNotifierFactory* factory) { 298 NetworkChangeNotifierFactory* factory) {
204 CHECK(!g_network_change_notifier_factory); 299 CHECK(!g_network_change_notifier_factory);
205 g_network_change_notifier_factory = factory; 300 g_network_change_notifier_factory = factory;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } 434 }
340 } 435 }
341 436
342 void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) { 437 void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
343 if (g_network_change_notifier) { 438 if (g_network_change_notifier) {
344 g_network_change_notifier->resolver_state_observer_list_->AddObserver( 439 g_network_change_notifier->resolver_state_observer_list_->AddObserver(
345 observer); 440 observer);
346 } 441 }
347 } 442 }
348 443
444 void NetworkChangeNotifier::AddNetworkChangeObserver(
445 NetworkChangeObserver* observer) {
446 if (g_network_change_notifier) {
447 g_network_change_notifier->network_change_observer_list_->AddObserver(
448 observer);
449 }
450 }
451
349 void NetworkChangeNotifier::RemoveIPAddressObserver( 452 void NetworkChangeNotifier::RemoveIPAddressObserver(
350 IPAddressObserver* observer) { 453 IPAddressObserver* observer) {
351 if (g_network_change_notifier) { 454 if (g_network_change_notifier) {
352 g_network_change_notifier->ip_address_observer_list_->RemoveObserver( 455 g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
353 observer); 456 observer);
354 } 457 }
355 } 458 }
356 459
357 void NetworkChangeNotifier::RemoveConnectionTypeObserver( 460 void NetworkChangeNotifier::RemoveConnectionTypeObserver(
358 ConnectionTypeObserver* observer) { 461 ConnectionTypeObserver* observer) {
359 if (g_network_change_notifier) { 462 if (g_network_change_notifier) {
360 g_network_change_notifier->connection_type_observer_list_->RemoveObserver( 463 g_network_change_notifier->connection_type_observer_list_->RemoveObserver(
361 observer); 464 observer);
362 } 465 }
363 } 466 }
364 467
365 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) { 468 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
366 if (g_network_change_notifier) { 469 if (g_network_change_notifier) {
367 g_network_change_notifier->resolver_state_observer_list_->RemoveObserver( 470 g_network_change_notifier->resolver_state_observer_list_->RemoveObserver(
368 observer); 471 observer);
369 } 472 }
370 } 473 }
371 474
372 NetworkChangeNotifier::NetworkChangeNotifier() 475 void NetworkChangeNotifier::RemoveNetworkChangeObserver(
373 : ip_address_observer_list_( 476 NetworkChangeObserver* observer) {
374 new ObserverListThreadSafe<IPAddressObserver>( 477 if (g_network_change_notifier) {
375 ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), 478 g_network_change_notifier->network_change_observer_list_->RemoveObserver(
376 connection_type_observer_list_( 479 observer);
377 new ObserverListThreadSafe<ConnectionTypeObserver>( 480 }
378 ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)), 481 }
379 resolver_state_observer_list_( 482
380 new ObserverListThreadSafe<DNSObserver>( 483 NetworkChangeNotifier::NetworkChangeNotifier() {
381 ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)), 484 CommonConstructor(NetworkChangeCalculatorParams());
382 network_state_(new NetworkState()), 485 }
383 histogram_watcher_(new HistogramWatcher()) { 486
487 NetworkChangeNotifier::NetworkChangeNotifier(
488 const NetworkChangeCalculatorParams& params) {
489 CommonConstructor(params);
490 }
491
492 void NetworkChangeNotifier::CommonConstructor(
493 const NetworkChangeCalculatorParams& params) {
494 ip_address_observer_list_ = new ObserverListThreadSafe<IPAddressObserver>(
495 ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY);
szym 2012/12/07 17:56:24 I wish there was a better way. Where's C++11 when
496 connection_type_observer_list_ =
497 new ObserverListThreadSafe<ConnectionTypeObserver>(
498 ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY);
499 resolver_state_observer_list_ = new ObserverListThreadSafe<DNSObserver>(
500 ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY);
501 network_change_observer_list_ =
502 new ObserverListThreadSafe<NetworkChangeObserver>(
503 ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY);
504 network_state_.reset(new NetworkState());
505 histogram_watcher_.reset(new HistogramWatcher());
506 network_change_calculator_.reset(new NetworkChangeCalculator(params));
507
384 DCHECK(!g_network_change_notifier); 508 DCHECK(!g_network_change_notifier);
385 g_network_change_notifier = this; 509 g_network_change_notifier = this;
510 network_change_calculator_->Init();
386 } 511 }
387 512
388 #if defined(OS_LINUX) 513 #if defined(OS_LINUX)
389 const internal::AddressTrackerLinux* 514 const internal::AddressTrackerLinux*
390 NetworkChangeNotifier::GetAddressTrackerInternal() const { 515 NetworkChangeNotifier::GetAddressTrackerInternal() const {
391 return NULL; 516 return NULL;
392 } 517 }
393 #endif 518 #endif
394 519
395 // static 520 // static
(...skipping 21 matching lines...) Expand all
417 } 542 }
418 543
419 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { 544 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
420 if (g_network_change_notifier) { 545 if (g_network_change_notifier) {
421 g_network_change_notifier->connection_type_observer_list_->Notify( 546 g_network_change_notifier->connection_type_observer_list_->Notify(
422 &ConnectionTypeObserver::OnConnectionTypeChanged, 547 &ConnectionTypeObserver::OnConnectionTypeChanged,
423 GetConnectionType()); 548 GetConnectionType());
424 } 549 }
425 } 550 }
426 551
552 void NetworkChangeNotifier::NotifyObserversOfNetworkChange(
553 ConnectionType type) {
554 if (g_network_change_notifier) {
555 g_network_change_notifier->network_change_observer_list_->Notify(
556 &NetworkChangeObserver::OnNetworkChanged,
557 type);
558 }
559 }
560
427 NetworkChangeNotifier::DisableForTest::DisableForTest() 561 NetworkChangeNotifier::DisableForTest::DisableForTest()
428 : network_change_notifier_(g_network_change_notifier) { 562 : network_change_notifier_(g_network_change_notifier) {
429 DCHECK(g_network_change_notifier); 563 DCHECK(g_network_change_notifier);
430 g_network_change_notifier = NULL; 564 g_network_change_notifier = NULL;
431 } 565 }
432 566
433 NetworkChangeNotifier::DisableForTest::~DisableForTest() { 567 NetworkChangeNotifier::DisableForTest::~DisableForTest() {
434 DCHECK(!g_network_change_notifier); 568 DCHECK(!g_network_change_notifier);
435 g_network_change_notifier = network_change_notifier_; 569 g_network_change_notifier = network_change_notifier_;
436 } 570 }
437 571
438 } // namespace net 572 } // namespace net
OLDNEW
« no previous file with comments | « net/base/network_change_notifier.h ('k') | net/base/network_change_notifier_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698