network_change_notifier_linux.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. #include "net/base/network_change_notifier_linux.h"
  5. #include <string>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/compiler_specific.h"
  9. #include "base/task/sequenced_task_runner.h"
  10. #include "base/task/task_traits.h"
  11. #include "base/task/thread_pool.h"
  12. #include "base/threading/thread.h"
  13. #include "net/base/address_tracker_linux.h"
  14. #include "net/dns/dns_config_service_posix.h"
  15. namespace net {
  16. // A collection of objects that live on blocking threads.
  17. class NetworkChangeNotifierLinux::BlockingThreadObjects {
  18. public:
  19. explicit BlockingThreadObjects(
  20. const std::unordered_set<std::string>& ignored_interfaces);
  21. BlockingThreadObjects(const BlockingThreadObjects&) = delete;
  22. BlockingThreadObjects& operator=(const BlockingThreadObjects&) = delete;
  23. // Plumbing for NetworkChangeNotifier::GetCurrentConnectionType.
  24. // Safe to call from any thread.
  25. NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() {
  26. return address_tracker_.GetCurrentConnectionType();
  27. }
  28. const internal::AddressTrackerLinux* address_tracker() const {
  29. return &address_tracker_;
  30. }
  31. // Begin watching for DNS and netlink changes.
  32. void Init();
  33. private:
  34. void OnIPAddressChanged();
  35. void OnLinkChanged();
  36. // Used to detect online/offline state and IP address changes.
  37. internal::AddressTrackerLinux address_tracker_;
  38. NetworkChangeNotifier::ConnectionType last_type_ =
  39. NetworkChangeNotifier::CONNECTION_NONE;
  40. };
  41. NetworkChangeNotifierLinux::BlockingThreadObjects::BlockingThreadObjects(
  42. const std::unordered_set<std::string>& ignored_interfaces)
  43. : address_tracker_(
  44. base::BindRepeating(&NetworkChangeNotifierLinux::
  45. BlockingThreadObjects::OnIPAddressChanged,
  46. base::Unretained(this)),
  47. base::BindRepeating(
  48. &NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged,
  49. base::Unretained(this)),
  50. base::DoNothing(),
  51. ignored_interfaces) {}
  52. void NetworkChangeNotifierLinux::BlockingThreadObjects::Init() {
  53. address_tracker_.Init();
  54. last_type_ = GetCurrentConnectionType();
  55. }
  56. void NetworkChangeNotifierLinux::BlockingThreadObjects::OnIPAddressChanged() {
  57. NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
  58. // When the IP address of a network interface is added/deleted, the
  59. // connection type may have changed.
  60. OnLinkChanged();
  61. }
  62. void NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged() {
  63. if (last_type_ != GetCurrentConnectionType()) {
  64. NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
  65. last_type_ = GetCurrentConnectionType();
  66. double max_bandwidth_mbps =
  67. NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
  68. last_type_ == CONNECTION_NONE ? SUBTYPE_NONE : SUBTYPE_UNKNOWN);
  69. NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(
  70. max_bandwidth_mbps, last_type_);
  71. }
  72. }
  73. NetworkChangeNotifierLinux::NetworkChangeNotifierLinux(
  74. const std::unordered_set<std::string>& ignored_interfaces)
  75. : NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()),
  76. blocking_thread_runner_(
  77. base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
  78. blocking_thread_objects_(
  79. new BlockingThreadObjects(ignored_interfaces),
  80. // Ensure |blocking_thread_objects_| lives on
  81. // |blocking_thread_runner_| to prevent races where
  82. // NetworkChangeNotifierLinux outlives
  83. // TaskEnvironment. https://crbug.com/938126
  84. base::OnTaskRunnerDeleter(blocking_thread_runner_)) {
  85. blocking_thread_runner_->PostTask(
  86. FROM_HERE,
  87. base::BindOnce(&NetworkChangeNotifierLinux::BlockingThreadObjects::Init,
  88. // The Unretained pointer is safe here because it's
  89. // posted before the deleter can post.
  90. base::Unretained(blocking_thread_objects_.get())));
  91. }
  92. NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
  93. ClearGlobalPointer();
  94. }
  95. // static
  96. NetworkChangeNotifier::NetworkChangeCalculatorParams
  97. NetworkChangeNotifierLinux::NetworkChangeCalculatorParamsLinux() {
  98. NetworkChangeCalculatorParams params;
  99. // Delay values arrived at by simple experimentation and adjusted so as to
  100. // produce a single signal when switching between network connections.
  101. params.ip_address_offline_delay_ = base::Milliseconds(2000);
  102. params.ip_address_online_delay_ = base::Milliseconds(2000);
  103. params.connection_type_offline_delay_ = base::Milliseconds(1500);
  104. params.connection_type_online_delay_ = base::Milliseconds(500);
  105. return params;
  106. }
  107. NetworkChangeNotifier::ConnectionType
  108. NetworkChangeNotifierLinux::GetCurrentConnectionType() const {
  109. return blocking_thread_objects_->GetCurrentConnectionType();
  110. }
  111. const internal::AddressTrackerLinux*
  112. NetworkChangeNotifierLinux::GetAddressTrackerInternal() const {
  113. return blocking_thread_objects_->address_tracker();
  114. }
  115. } // namespace net