shell_network_controller_chromeos.cc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright 2014 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 "extensions/shell/browser/shell_network_controller_chromeos.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/location.h"
  8. #include "base/logging.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "base/time/time.h"
  11. #include "base/values.h"
  12. #include "chromeos/ash/components/network/network_configuration_handler.h"
  13. #include "chromeos/ash/components/network/network_connection_handler.h"
  14. #include "chromeos/ash/components/network/network_device_handler.h"
  15. #include "chromeos/ash/components/network/network_handler.h"
  16. #include "chromeos/ash/components/network/network_handler_callbacks.h"
  17. #include "chromeos/ash/components/network/network_state.h"
  18. #include "chromeos/ash/components/network/network_state_handler.h"
  19. #include "chromeos/ash/components/network/network_type_pattern.h"
  20. #include "third_party/cros_system_api/dbus/service_constants.h"
  21. namespace extensions {
  22. namespace {
  23. // Frequency at which networks should be scanned when not connected to a network
  24. // or when connected to a non-preferred network.
  25. const int kScanIntervalSec = 10;
  26. void HandleEnableWifiError(const std::string& error_name) {
  27. LOG(WARNING) << "Unable to enable wifi: " << error_name;
  28. }
  29. // Returns a human-readable name for the network described by |network|.
  30. std::string GetNetworkName(const ash::NetworkState& network) {
  31. return !network.name().empty()
  32. ? network.name()
  33. : base::StringPrintf("[%s]", network.type().c_str());
  34. }
  35. // Returns true if shill is either connected or connecting to a network.
  36. bool IsConnectedOrConnecting() {
  37. ash::NetworkStateHandler* state_handler =
  38. ash::NetworkHandler::Get()->network_state_handler();
  39. return state_handler->ConnectedNetworkByType(
  40. ash::NetworkTypePattern::Default()) ||
  41. state_handler->ConnectingNetworkByType(
  42. ash::NetworkTypePattern::Default());
  43. }
  44. } // namespace
  45. ShellNetworkController::ShellNetworkController(
  46. const std::string& preferred_network_name)
  47. : state_(STATE_IDLE),
  48. preferred_network_name_(preferred_network_name),
  49. preferred_network_is_active_(false) {
  50. ash::NetworkStateHandler* state_handler =
  51. ash::NetworkHandler::Get()->network_state_handler();
  52. state_handler->AddObserver(this, FROM_HERE);
  53. state_handler->SetTechnologyEnabled(
  54. ash::NetworkTypePattern::Primitive(shill::kTypeWifi), true,
  55. base::BindRepeating(&HandleEnableWifiError));
  56. // If we're unconnected, trigger a connection attempt and start scanning.
  57. NetworkConnectionStateChanged(NULL);
  58. }
  59. ShellNetworkController::~ShellNetworkController() {
  60. ash::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
  61. this, FROM_HERE);
  62. }
  63. void ShellNetworkController::NetworkListChanged() {
  64. VLOG(1) << "Network list changed";
  65. ConnectIfUnconnected();
  66. }
  67. void ShellNetworkController::NetworkConnectionStateChanged(
  68. const ash::NetworkState* network) {
  69. if (network) {
  70. VLOG(1) << "Network connection state changed:"
  71. << " name=" << GetNetworkName(*network)
  72. << " type=" << network->type() << " path=" << network->path()
  73. << " state=" << network->connection_state();
  74. } else {
  75. VLOG(1) << "Network connection state changed: [none]";
  76. }
  77. const ash::NetworkState* wifi_network = GetActiveWiFiNetwork();
  78. preferred_network_is_active_ =
  79. wifi_network && wifi_network->name() == preferred_network_name_;
  80. VLOG(2) << "Active WiFi network is "
  81. << (wifi_network ? wifi_network->name() : std::string("[none]"));
  82. if (preferred_network_is_active_ ||
  83. (preferred_network_name_.empty() && wifi_network)) {
  84. SetScanningEnabled(false);
  85. } else {
  86. SetScanningEnabled(true);
  87. ConnectIfUnconnected();
  88. }
  89. }
  90. void ShellNetworkController::SetCellularAllowRoaming(bool allow_roaming) {
  91. ash::NetworkHandler* handler = ash::NetworkHandler::Get();
  92. ash::NetworkStateHandler::NetworkStateList network_list;
  93. base::DictionaryValue properties;
  94. properties.SetKey(shill::kCellularAllowRoamingProperty,
  95. base::Value(allow_roaming));
  96. handler->network_state_handler()->GetVisibleNetworkListByType(
  97. ash::NetworkTypePattern::Cellular(), &network_list);
  98. for (const ash::NetworkState* network : network_list) {
  99. handler->network_configuration_handler()->SetShillProperties(
  100. network->path(), properties, base::DoNothing(),
  101. ash::network_handler::ErrorCallback());
  102. }
  103. }
  104. const ash::NetworkState* ShellNetworkController::GetActiveWiFiNetwork() {
  105. ash::NetworkStateHandler* state_handler =
  106. ash::NetworkHandler::Get()->network_state_handler();
  107. const ash::NetworkState* network = state_handler->FirstNetworkByType(
  108. ash::NetworkTypePattern::Primitive(shill::kTypeWifi));
  109. return network &&
  110. (network->IsConnectedState() || network->IsConnectingState())
  111. ? network
  112. : NULL;
  113. }
  114. void ShellNetworkController::SetScanningEnabled(bool enabled) {
  115. const bool currently_enabled = scan_timer_.IsRunning();
  116. if (enabled == currently_enabled)
  117. return;
  118. VLOG(1) << (enabled ? "Starting" : "Stopping") << " scanning";
  119. if (enabled) {
  120. RequestScan();
  121. scan_timer_.Start(FROM_HERE, base::Seconds(kScanIntervalSec), this,
  122. &ShellNetworkController::RequestScan);
  123. } else {
  124. scan_timer_.Stop();
  125. }
  126. }
  127. void ShellNetworkController::RequestScan() {
  128. VLOG(1) << "Requesting scan";
  129. ash::NetworkHandler::Get()->network_state_handler()->RequestScan(
  130. ash::NetworkTypePattern::Default());
  131. }
  132. void ShellNetworkController::ConnectIfUnconnected() {
  133. // Don't do anything if the default network is already the preferred one or if
  134. // we have a pending request to connect to it.
  135. if (preferred_network_is_active_ ||
  136. state_ == STATE_WAITING_FOR_PREFERRED_RESULT)
  137. return;
  138. const ash::NetworkState* best_network = NULL;
  139. bool can_connect_to_preferred_network = false;
  140. ash::NetworkHandler* handler = ash::NetworkHandler::Get();
  141. ash::NetworkStateHandler::NetworkStateList network_list;
  142. handler->network_state_handler()->GetVisibleNetworkListByType(
  143. ash::NetworkTypePattern::WiFi(), &network_list);
  144. for (ash::NetworkStateHandler::NetworkStateList::const_iterator it =
  145. network_list.begin();
  146. it != network_list.end(); ++it) {
  147. const ash::NetworkState* network = *it;
  148. if (!network->connectable())
  149. continue;
  150. if (!preferred_network_name_.empty() &&
  151. network->name() == preferred_network_name_) {
  152. best_network = network;
  153. can_connect_to_preferred_network = true;
  154. break;
  155. } else if (!best_network) {
  156. best_network = network;
  157. }
  158. }
  159. // Don't switch networks if we're already connecting/connected and wouldn't be
  160. // switching to the preferred network.
  161. if ((IsConnectedOrConnecting() || state_ != STATE_IDLE) &&
  162. !can_connect_to_preferred_network)
  163. return;
  164. if (!best_network) {
  165. VLOG(1) << "Didn't find any connectable networks";
  166. return;
  167. }
  168. VLOG(1) << "Connecting to network " << GetNetworkName(*best_network)
  169. << " with path " << best_network->path() << " and strength "
  170. << best_network->signal_strength();
  171. state_ = can_connect_to_preferred_network
  172. ? STATE_WAITING_FOR_PREFERRED_RESULT
  173. : STATE_WAITING_FOR_NON_PREFERRED_RESULT;
  174. handler->network_connection_handler()->ConnectToNetwork(
  175. best_network->path(),
  176. base::BindOnce(&ShellNetworkController::HandleConnectionSuccess,
  177. weak_ptr_factory_.GetWeakPtr()),
  178. base::BindRepeating(&ShellNetworkController::HandleConnectionError,
  179. weak_ptr_factory_.GetWeakPtr()),
  180. false /* check_error_state */, ash::ConnectCallbackMode::ON_COMPLETED);
  181. }
  182. void ShellNetworkController::HandleConnectionSuccess() {
  183. VLOG(1) << "Successfully connected to network";
  184. state_ = STATE_IDLE;
  185. }
  186. void ShellNetworkController::HandleConnectionError(
  187. const std::string& error_name) {
  188. LOG(WARNING) << "Unable to connect to network: " << error_name;
  189. state_ = STATE_IDLE;
  190. }
  191. } // namespace extensions