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_handler.h"
14 #include "chromeos/network/network_handler_callbacks.h"
15 #include "chromeos/network/network_state.h"
16 #include "chromeos/network/network_state_handler.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 namespace extensions
{
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;
27 void HandleEnableWifiError(const std::string
& error_name
,
28 scoped_ptr
<base::DictionaryValue
> error_data
) {
29 LOG(WARNING
) << "Unable to enable wifi: " << error_name
;
32 // Returns a human-readable name for the network described by |network|.
33 std::string
GetNetworkName(const chromeos::NetworkState
& network
) {
34 return !network
.name().empty()
36 : base::StringPrintf("[%s]", network
.type().c_str());
39 // Returns true if shill is either connected or connecting to a network.
40 bool IsConnectedOrConnecting() {
41 chromeos::NetworkStateHandler
* state_handler
=
42 chromeos::NetworkHandler::Get()->network_state_handler();
43 return state_handler
->ConnectedNetworkByType(
44 chromeos::NetworkTypePattern::Default()) ||
45 state_handler
->ConnectingNetworkByType(
46 chromeos::NetworkTypePattern::Default());
51 ShellNetworkController::ShellNetworkController(
52 const std::string
& preferred_network_name
)
54 preferred_network_name_(preferred_network_name
),
55 preferred_network_is_active_(false),
56 weak_ptr_factory_(this) {
57 chromeos::NetworkStateHandler
* state_handler
=
58 chromeos::NetworkHandler::Get()->network_state_handler();
59 state_handler
->AddObserver(this, FROM_HERE
);
60 state_handler
->SetTechnologyEnabled(
61 chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi
),
63 base::Bind(&HandleEnableWifiError
));
65 // If we're unconnected, trigger a connection attempt and start scanning.
66 NetworkConnectionStateChanged(NULL
);
69 ShellNetworkController::~ShellNetworkController() {
70 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
74 void ShellNetworkController::NetworkListChanged() {
75 VLOG(1) << "Network list changed";
76 ConnectIfUnconnected();
79 void ShellNetworkController::NetworkConnectionStateChanged(
80 const chromeos::NetworkState
* network
) {
82 VLOG(1) << "Network connection state changed:"
83 << " name=" << GetNetworkName(*network
)
84 << " type=" << network
->type() << " path=" << network
->path()
85 << " state=" << network
->connection_state();
87 VLOG(1) << "Network connection state changed: [none]";
90 const chromeos::NetworkState
* wifi_network
= GetActiveWiFiNetwork();
91 preferred_network_is_active_
=
92 wifi_network
&& wifi_network
->name() == preferred_network_name_
;
93 VLOG(2) << "Active WiFi network is "
94 << (wifi_network
? wifi_network
->name() : std::string("[none]"));
96 if (preferred_network_is_active_
||
97 (preferred_network_name_
.empty() && wifi_network
)) {
98 SetScanningEnabled(false);
100 SetScanningEnabled(true);
101 ConnectIfUnconnected();
105 const chromeos::NetworkState
* ShellNetworkController::GetActiveWiFiNetwork() {
106 chromeos::NetworkStateHandler
* state_handler
=
107 chromeos::NetworkHandler::Get()->network_state_handler();
108 const chromeos::NetworkState
* network
= state_handler
->FirstNetworkByType(
109 chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi
));
111 (network
->IsConnectedState() || network
->IsConnectingState())
116 void ShellNetworkController::SetScanningEnabled(bool enabled
) {
117 const bool currently_enabled
= scan_timer_
.IsRunning();
118 if (enabled
== currently_enabled
)
121 VLOG(1) << (enabled
? "Starting" : "Stopping") << " scanning";
124 scan_timer_
.Start(FROM_HERE
,
125 base::TimeDelta::FromSeconds(kScanIntervalSec
),
127 &ShellNetworkController::RequestScan
);
133 void ShellNetworkController::RequestScan() {
134 VLOG(1) << "Requesting scan";
135 chromeos::NetworkHandler::Get()->network_state_handler()->RequestScan();
138 void ShellNetworkController::ConnectIfUnconnected() {
139 // Don't do anything if the default network is already the preferred one or if
140 // we have a pending request to connect to it.
141 if (preferred_network_is_active_
||
142 state_
== STATE_WAITING_FOR_PREFERRED_RESULT
)
145 const chromeos::NetworkState
* best_network
= NULL
;
146 bool can_connect_to_preferred_network
= false;
148 chromeos::NetworkHandler
* handler
= chromeos::NetworkHandler::Get();
149 chromeos::NetworkStateHandler::NetworkStateList network_list
;
150 handler
->network_state_handler()->GetVisibleNetworkListByType(
151 chromeos::NetworkTypePattern::WiFi(), &network_list
);
152 for (chromeos::NetworkStateHandler::NetworkStateList::const_iterator it
=
153 network_list
.begin();
154 it
!= network_list
.end();
156 const chromeos::NetworkState
* network
= *it
;
157 if (!network
->connectable())
160 if (!preferred_network_name_
.empty() &&
161 network
->name() == preferred_network_name_
) {
162 best_network
= network
;
163 can_connect_to_preferred_network
= true;
165 } else if (!best_network
) {
166 best_network
= network
;
170 // Don't switch networks if we're already connecting/connected and wouldn't be
171 // switching to the preferred network.
172 if ((IsConnectedOrConnecting() || state_
!= STATE_IDLE
) &&
173 !can_connect_to_preferred_network
)
177 VLOG(1) << "Didn't find any connectable networks";
181 VLOG(1) << "Connecting to network " << GetNetworkName(*best_network
)
182 << " with path " << best_network
->path() << " and strength "
183 << best_network
->signal_strength();
184 state_
= can_connect_to_preferred_network
185 ? STATE_WAITING_FOR_PREFERRED_RESULT
186 : STATE_WAITING_FOR_NON_PREFERRED_RESULT
;
187 handler
->network_connection_handler()->ConnectToNetwork(
188 best_network
->path(),
189 base::Bind(&ShellNetworkController::HandleConnectionSuccess
,
190 weak_ptr_factory_
.GetWeakPtr()),
191 base::Bind(&ShellNetworkController::HandleConnectionError
,
192 weak_ptr_factory_
.GetWeakPtr()),
193 false /* check_error_state */);
196 void ShellNetworkController::HandleConnectionSuccess() {
197 VLOG(1) << "Successfully connected to network";
201 void ShellNetworkController::HandleConnectionError(
202 const std::string
& error_name
,
203 scoped_ptr
<base::DictionaryValue
> error_data
) {
204 LOG(WARNING
) << "Unable to connect to network: " << error_name
;
208 } // namespace extensions