OLD | NEW |
| (Empty) |
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 | |
5 #include "apps/shell/browser/shell_network_controller_chromeos.h" | |
6 | |
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_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" | |
18 | |
19 namespace apps { | |
20 | |
21 namespace { | |
22 | |
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 | |
27 void HandleEnableWifiError( | |
28 const std::string& error_name, | |
29 scoped_ptr<base::DictionaryValue> error_data) { | |
30 LOG(WARNING) << "Unable to enable wifi: " << error_name; | |
31 } | |
32 | |
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() ? network.name() : | |
36 base::StringPrintf("[%s]", network.type().c_str()); | |
37 } | |
38 | |
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()); | |
47 } | |
48 | |
49 } // namespace | |
50 | |
51 ShellNetworkController::ShellNetworkController( | |
52 const std::string& preferred_network_name) | |
53 : state_(STATE_IDLE), | |
54 preferred_network_name_(preferred_network_name), | |
55 preferred_network_is_active_(false), | |
56 weak_ptr_factory_(this) { | |
57 chromeos::NetworkHandler::Initialize(); | |
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, base::Bind(&HandleEnableWifiError)); | |
64 | |
65 // If we're unconnected, trigger a connection attempt and start scanning. | |
66 NetworkConnectionStateChanged(NULL); | |
67 } | |
68 | |
69 ShellNetworkController::~ShellNetworkController() { | |
70 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( | |
71 this, FROM_HERE); | |
72 chromeos::NetworkHandler::Shutdown(); | |
73 } | |
74 | |
75 void ShellNetworkController::NetworkListChanged() { | |
76 VLOG(1) << "Network list changed"; | |
77 ConnectIfUnconnected(); | |
78 } | |
79 | |
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() | |
86 << " path=" << network->path() | |
87 << " state=" << network->connection_state(); | |
88 } else { | |
89 VLOG(1) << "Network connection state changed: [none]"; | |
90 } | |
91 | |
92 const chromeos::NetworkState* wifi_network = GetActiveWiFiNetwork(); | |
93 preferred_network_is_active_ = | |
94 wifi_network && wifi_network->name() == preferred_network_name_; | |
95 VLOG(2) << "Active WiFi network is " | |
96 << (wifi_network ? wifi_network->name() : std::string("[none]")); | |
97 | |
98 if (preferred_network_is_active_ || | |
99 (preferred_network_name_.empty() && wifi_network)) { | |
100 SetScanningEnabled(false); | |
101 } else { | |
102 SetScanningEnabled(true); | |
103 ConnectIfUnconnected(); | |
104 } | |
105 } | |
106 | |
107 const chromeos::NetworkState* | |
108 ShellNetworkController::GetActiveWiFiNetwork() { | |
109 chromeos::NetworkStateHandler* state_handler = | |
110 chromeos::NetworkHandler::Get()->network_state_handler(); | |
111 const chromeos::NetworkState* network = state_handler->FirstNetworkByType( | |
112 chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi)); | |
113 return network && | |
114 (network->IsConnectedState() || network->IsConnectingState()) ? | |
115 network : NULL; | |
116 } | |
117 | |
118 void ShellNetworkController::SetScanningEnabled(bool enabled) { | |
119 const bool currently_enabled = scan_timer_.IsRunning(); | |
120 if (enabled == currently_enabled) | |
121 return; | |
122 | |
123 VLOG(1) << (enabled ? "Starting" : "Stopping") << " scanning"; | |
124 if (enabled) { | |
125 RequestScan(); | |
126 scan_timer_.Start(FROM_HERE, | |
127 base::TimeDelta::FromSeconds(kScanIntervalSec), | |
128 this, &ShellNetworkController::RequestScan); | |
129 } else { | |
130 scan_timer_.Stop(); | |
131 } | |
132 } | |
133 | |
134 void ShellNetworkController::RequestScan() { | |
135 VLOG(1) << "Requesting scan"; | |
136 chromeos::NetworkHandler::Get()->network_state_handler()->RequestScan(); | |
137 } | |
138 | |
139 void ShellNetworkController::ConnectIfUnconnected() { | |
140 // Don't do anything if the default network is already the preferred one or if | |
141 // we have a pending request to connect to it. | |
142 if (preferred_network_is_active_ || | |
143 state_ == STATE_WAITING_FOR_PREFERRED_RESULT) | |
144 return; | |
145 | |
146 const chromeos::NetworkState* best_network = NULL; | |
147 bool can_connect_to_preferred_network = false; | |
148 | |
149 chromeos::NetworkHandler* handler = chromeos::NetworkHandler::Get(); | |
150 chromeos::NetworkStateHandler::NetworkStateList network_list; | |
151 handler->network_state_handler()->GetVisibleNetworkListByType( | |
152 chromeos::NetworkTypePattern::WiFi(), &network_list); | |
153 for (chromeos::NetworkStateHandler::NetworkStateList::const_iterator it = | |
154 network_list.begin(); it != network_list.end(); ++it) { | |
155 const chromeos::NetworkState* network = *it; | |
156 if (!network->connectable()) | |
157 continue; | |
158 | |
159 if (!preferred_network_name_.empty() && | |
160 network->name() == preferred_network_name_) { | |
161 best_network = network; | |
162 can_connect_to_preferred_network = true; | |
163 break; | |
164 } else if (!best_network) { | |
165 best_network = network; | |
166 } | |
167 } | |
168 | |
169 // Don't switch networks if we're already connecting/connected and wouldn't be | |
170 // switching to the preferred network. | |
171 if ((IsConnectedOrConnecting() || state_ != STATE_IDLE) && | |
172 !can_connect_to_preferred_network) | |
173 return; | |
174 | |
175 if (!best_network) { | |
176 VLOG(1) << "Didn't find any connectable networks"; | |
177 return; | |
178 } | |
179 | |
180 VLOG(1) << "Connecting to network " << GetNetworkName(*best_network) | |
181 << " with path " << best_network->path() << " and strength " | |
182 << best_network->signal_strength(); | |
183 state_ = can_connect_to_preferred_network ? | |
184 STATE_WAITING_FOR_PREFERRED_RESULT : | |
185 STATE_WAITING_FOR_NON_PREFERRED_RESULT; | |
186 handler->network_connection_handler()->ConnectToNetwork( | |
187 best_network->path(), | |
188 base::Bind(&ShellNetworkController::HandleConnectionSuccess, | |
189 weak_ptr_factory_.GetWeakPtr()), | |
190 base::Bind(&ShellNetworkController::HandleConnectionError, | |
191 weak_ptr_factory_.GetWeakPtr()), | |
192 false /* check_error_state */); | |
193 } | |
194 | |
195 void ShellNetworkController::HandleConnectionSuccess() { | |
196 VLOG(1) << "Successfully connected to network"; | |
197 state_ = STATE_IDLE; | |
198 } | |
199 | |
200 void ShellNetworkController::HandleConnectionError( | |
201 const std::string& error_name, | |
202 scoped_ptr<base::DictionaryValue> error_data) { | |
203 LOG(WARNING) << "Unable to connect to network: " << error_name; | |
204 state_ = STATE_IDLE; | |
205 } | |
206 | |
207 } // namespace apps | |
OLD | NEW |