Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / shell / browser / shell_network_controller_chromeos.cc
blob4ff45c70b6227880ebe3421c5030f47937edcfac
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.
5 #include "extensions/shell/browser/shell_network_controller_chromeos.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "chromeos/network/network_connection_handler.h"
13 #include "chromeos/network/network_device_handler.h"
14 #include "chromeos/network/network_handler.h"
15 #include "chromeos/network/network_handler_callbacks.h"
16 #include "chromeos/network/network_state.h"
17 #include "chromeos/network/network_state_handler.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
20 namespace extensions {
22 namespace {
24 // Frequency at which networks should be scanned when not connected to a network
25 // or when connected to a non-preferred network.
26 const int kScanIntervalSec = 10;
28 void HandleEnableWifiError(const std::string& error_name,
29 scoped_ptr<base::DictionaryValue> error_data) {
30 LOG(WARNING) << "Unable to enable wifi: " << error_name;
33 // Returns a human-readable name for the network described by |network|.
34 std::string GetNetworkName(const chromeos::NetworkState& network) {
35 return !network.name().empty()
36 ? network.name()
37 : base::StringPrintf("[%s]", network.type().c_str());
40 // Returns true if shill is either connected or connecting to a network.
41 bool IsConnectedOrConnecting() {
42 chromeos::NetworkStateHandler* state_handler =
43 chromeos::NetworkHandler::Get()->network_state_handler();
44 return state_handler->ConnectedNetworkByType(
45 chromeos::NetworkTypePattern::Default()) ||
46 state_handler->ConnectingNetworkByType(
47 chromeos::NetworkTypePattern::Default());
50 } // namespace
52 ShellNetworkController::ShellNetworkController(
53 const std::string& preferred_network_name)
54 : state_(STATE_IDLE),
55 preferred_network_name_(preferred_network_name),
56 preferred_network_is_active_(false),
57 weak_ptr_factory_(this) {
58 chromeos::NetworkStateHandler* state_handler =
59 chromeos::NetworkHandler::Get()->network_state_handler();
60 state_handler->AddObserver(this, FROM_HERE);
61 state_handler->SetTechnologyEnabled(
62 chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi),
63 true,
64 base::Bind(&HandleEnableWifiError));
66 // If we're unconnected, trigger a connection attempt and start scanning.
67 NetworkConnectionStateChanged(NULL);
70 ShellNetworkController::~ShellNetworkController() {
71 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
72 this, FROM_HERE);
75 void ShellNetworkController::NetworkListChanged() {
76 VLOG(1) << "Network list changed";
77 ConnectIfUnconnected();
80 void ShellNetworkController::NetworkConnectionStateChanged(
81 const chromeos::NetworkState* network) {
82 if (network) {
83 VLOG(1) << "Network connection state changed:"
84 << " name=" << GetNetworkName(*network)
85 << " type=" << network->type() << " path=" << network->path()
86 << " state=" << network->connection_state();
87 } else {
88 VLOG(1) << "Network connection state changed: [none]";
91 const chromeos::NetworkState* wifi_network = GetActiveWiFiNetwork();
92 preferred_network_is_active_ =
93 wifi_network && wifi_network->name() == preferred_network_name_;
94 VLOG(2) << "Active WiFi network is "
95 << (wifi_network ? wifi_network->name() : std::string("[none]"));
97 if (preferred_network_is_active_ ||
98 (preferred_network_name_.empty() && wifi_network)) {
99 SetScanningEnabled(false);
100 } else {
101 SetScanningEnabled(true);
102 ConnectIfUnconnected();
106 void ShellNetworkController::SetCellularAllowRoaming(bool allow_roaming) {
107 chromeos::NetworkDeviceHandler* device_handler =
108 chromeos::NetworkHandler::Get()->network_device_handler();
109 device_handler->SetCellularAllowRoaming(allow_roaming);
112 const chromeos::NetworkState* ShellNetworkController::GetActiveWiFiNetwork() {
113 chromeos::NetworkStateHandler* state_handler =
114 chromeos::NetworkHandler::Get()->network_state_handler();
115 const chromeos::NetworkState* network = state_handler->FirstNetworkByType(
116 chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi));
117 return network &&
118 (network->IsConnectedState() || network->IsConnectingState())
119 ? network
120 : NULL;
123 void ShellNetworkController::SetScanningEnabled(bool enabled) {
124 const bool currently_enabled = scan_timer_.IsRunning();
125 if (enabled == currently_enabled)
126 return;
128 VLOG(1) << (enabled ? "Starting" : "Stopping") << " scanning";
129 if (enabled) {
130 RequestScan();
131 scan_timer_.Start(FROM_HERE,
132 base::TimeDelta::FromSeconds(kScanIntervalSec),
133 this,
134 &ShellNetworkController::RequestScan);
135 } else {
136 scan_timer_.Stop();
140 void ShellNetworkController::RequestScan() {
141 VLOG(1) << "Requesting scan";
142 chromeos::NetworkHandler::Get()->network_state_handler()->RequestScan();
145 void ShellNetworkController::ConnectIfUnconnected() {
146 // Don't do anything if the default network is already the preferred one or if
147 // we have a pending request to connect to it.
148 if (preferred_network_is_active_ ||
149 state_ == STATE_WAITING_FOR_PREFERRED_RESULT)
150 return;
152 const chromeos::NetworkState* best_network = NULL;
153 bool can_connect_to_preferred_network = false;
155 chromeos::NetworkHandler* handler = chromeos::NetworkHandler::Get();
156 chromeos::NetworkStateHandler::NetworkStateList network_list;
157 handler->network_state_handler()->GetVisibleNetworkListByType(
158 chromeos::NetworkTypePattern::WiFi(), &network_list);
159 for (chromeos::NetworkStateHandler::NetworkStateList::const_iterator it =
160 network_list.begin();
161 it != network_list.end();
162 ++it) {
163 const chromeos::NetworkState* network = *it;
164 if (!network->connectable())
165 continue;
167 if (!preferred_network_name_.empty() &&
168 network->name() == preferred_network_name_) {
169 best_network = network;
170 can_connect_to_preferred_network = true;
171 break;
172 } else if (!best_network) {
173 best_network = network;
177 // Don't switch networks if we're already connecting/connected and wouldn't be
178 // switching to the preferred network.
179 if ((IsConnectedOrConnecting() || state_ != STATE_IDLE) &&
180 !can_connect_to_preferred_network)
181 return;
183 if (!best_network) {
184 VLOG(1) << "Didn't find any connectable networks";
185 return;
188 VLOG(1) << "Connecting to network " << GetNetworkName(*best_network)
189 << " with path " << best_network->path() << " and strength "
190 << best_network->signal_strength();
191 state_ = can_connect_to_preferred_network
192 ? STATE_WAITING_FOR_PREFERRED_RESULT
193 : STATE_WAITING_FOR_NON_PREFERRED_RESULT;
194 handler->network_connection_handler()->ConnectToNetwork(
195 best_network->path(),
196 base::Bind(&ShellNetworkController::HandleConnectionSuccess,
197 weak_ptr_factory_.GetWeakPtr()),
198 base::Bind(&ShellNetworkController::HandleConnectionError,
199 weak_ptr_factory_.GetWeakPtr()),
200 false /* check_error_state */);
203 void ShellNetworkController::HandleConnectionSuccess() {
204 VLOG(1) << "Successfully connected to network";
205 state_ = STATE_IDLE;
208 void ShellNetworkController::HandleConnectionError(
209 const std::string& error_name,
210 scoped_ptr<base::DictionaryValue> error_data) {
211 LOG(WARNING) << "Unable to connect to network: " << error_name;
212 state_ = STATE_IDLE;
215 } // namespace extensions