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"
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
{
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()
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());
52 ShellNetworkController::ShellNetworkController(
53 const std::string
& preferred_network_name
)
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
),
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(
75 void ShellNetworkController::NetworkListChanged() {
76 VLOG(1) << "Network list changed";
77 ConnectIfUnconnected();
80 void ShellNetworkController::NetworkConnectionStateChanged(
81 const chromeos::NetworkState
* network
) {
83 VLOG(1) << "Network connection state changed:"
84 << " name=" << GetNetworkName(*network
)
85 << " type=" << network
->type() << " path=" << network
->path()
86 << " state=" << network
->connection_state();
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);
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
));
118 (network
->IsConnectedState() || network
->IsConnectingState())
123 void ShellNetworkController::SetScanningEnabled(bool enabled
) {
124 const bool currently_enabled
= scan_timer_
.IsRunning();
125 if (enabled
== currently_enabled
)
128 VLOG(1) << (enabled
? "Starting" : "Stopping") << " scanning";
131 scan_timer_
.Start(FROM_HERE
,
132 base::TimeDelta::FromSeconds(kScanIntervalSec
),
134 &ShellNetworkController::RequestScan
);
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
)
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();
163 const chromeos::NetworkState
* network
= *it
;
164 if (!network
->connectable())
167 if (!preferred_network_name_
.empty() &&
168 network
->name() == preferred_network_name_
) {
169 best_network
= network
;
170 can_connect_to_preferred_network
= true;
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
)
184 VLOG(1) << "Didn't find any connectable networks";
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";
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
;
215 } // namespace extensions