Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc

Issue 226883002: WiFi client for GCD bootstrapping (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.h"
6
7 #include "base/cancelable_callback.h"
8 #include "base/threading/sequenced_worker_pool.h"
9 #include "base/threading/thread.h"
10 #include "components/onc/onc_constants.h"
11 #include "components/wifi/wifi_service.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "net/base/network_change_notifier.h"
14
15 using ::wifi::WiFiService;
16
17 namespace local_discovery {
18
19 namespace wifi {
20
21 namespace {
22
23 const int kConnectionTimeoutSeconds = 10;
24
25 scoped_ptr<base::DictionaryValue> MakeProperties(const std::string& ssid,
26 const std::string& password) {
27 scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue);
28
29 properties->SetString(onc::network_config::kType, onc::network_type::kWiFi);
30 base::DictionaryValue* wifi = new base::DictionaryValue;
31 properties->Set(onc::network_config::kWiFi, wifi);
32
33 wifi->SetString(onc::wifi::kSSID, ssid);
34 if (!password.empty()) {
35 wifi->SetString(onc::wifi::kPassphrase, password);
36 // TODO(noamsml): Allow choosing security mechanism in a more fine-grained
37 // manner.
38 wifi->SetString(onc::wifi::kSecurity, onc::wifi::kWPA2_PSK);
39 } else {
40 wifi->SetString(onc::wifi::kSecurity, onc::wifi::kNone);
41 }
42
43 return properties.Pass();
44 }
45
46 } // namespace
47
48 class WifiManagerNonChromeos::WifiServiceWrapper
49 : public net::NetworkChangeNotifier::NetworkChangeObserver {
50 public:
51 explicit WifiServiceWrapper(
52 base::WeakPtr<WifiManagerNonChromeos> wifi_manager);
53
54 virtual ~WifiServiceWrapper();
55
56 void Start();
57
58 void GetSSIDList(const WifiManager::SSIDListCallback& callback);
59
60 void ConfigureAndConnectPskNetwork(
61 const std::string& ssid,
62 const std::string& password,
63 const WifiManager::SuccessCallback& callback);
64
65 base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper> AsWeakPtr();
66
67 void RequestScan();
68
69 void ConnectToNetworkByID(const std::string& network_guid,
70 const WifiManager::SuccessCallback& callback);
71
72 void RequestNetworkCredentials(
73 const std::string& network_guid,
74 const WifiManager::CredentialsCallback& callback);
75
76 private:
77 // net::NetworkChangeNotifier::NetworkChangeObserver implementation.
78 virtual void OnNetworkChanged(
79 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
80
81 void GetSSIDListInternal(NetworkPropertiesList* ssid_list);
82
83 void OnNetworkListChangedEvent(const std::vector<std::string>& network_guids);
84
85 void OnNetworksChangedEvent(const std::vector<std::string>& network_guids);
86
87 std::string GetConnectedGUID();
88
89 bool IsConnected(const std::string& network_guid);
90
91 void OnConnectToNetworkTimeout();
92
93 void PostClosure(const base::Closure& closure);
94
95 bool FindAndConfigureNetwork(const std::string& ssid,
96 const std::string& password,
97 std::string* network_guid);
98
99 scoped_ptr<WiFiService> wifi_service_;
100
101 base::WeakPtr<WifiManagerNonChromeos> wifi_manager_;
102
103 WifiManager::SuccessCallback connect_success_callback_;
104 base::CancelableClosure connect_failure_callback_;
105
106 // SSID of previously connected network.
107 std::string connected_network_guid_;
108
109 // SSID of network we are connecting to.
110 std::string connecting_network_guid_;
111
112 scoped_refptr<base::MessageLoopProxy> callback_runner_;
113
114 base::WeakPtrFactory<WifiServiceWrapper> weak_factory_;
115
116 DISALLOW_COPY_AND_ASSIGN(WifiServiceWrapper);
117 };
118
119 WifiManagerNonChromeos::WifiServiceWrapper::WifiServiceWrapper(
120 base::WeakPtr<WifiManagerNonChromeos> wifi_manager)
121 : wifi_manager_(wifi_manager),
122 callback_runner_(base::MessageLoopProxy::current()),
123 weak_factory_(this) {
124 }
125
126 WifiManagerNonChromeos::WifiServiceWrapper::~WifiServiceWrapper() {
127 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
128 }
129
130 void WifiManagerNonChromeos::WifiServiceWrapper::Start() {
131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
132 wifi_service_.reset(WiFiService::Create());
133
134 wifi_service_->Initialize(base::MessageLoopProxy::current());
135
136 wifi_service_->SetEventObservers(
137 base::MessageLoopProxy::current(),
138 base::Bind(&WifiServiceWrapper::OnNetworksChangedEvent,
139 base::Unretained(this)),
140 base::Bind(&WifiServiceWrapper::OnNetworkListChangedEvent,
141 base::Unretained(this)));
142
143 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
144 }
145
146 void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDList(
147 const WifiManager::SSIDListCallback& callback) {
148 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
149
150 scoped_ptr<NetworkPropertiesList> ssid_list(new NetworkPropertiesList);
151 GetSSIDListInternal(ssid_list.get());
152
153 callback_runner_->PostTask(
154 FROM_HERE,
155 base::Bind(&WifiManagerNonChromeos::PostSSIDListCallback,
156 wifi_manager_,
157 callback,
158 base::Passed(&ssid_list)));
159 }
160
161 void WifiManagerNonChromeos::WifiServiceWrapper::ConfigureAndConnectPskNetwork(
162 const std::string& ssid,
163 const std::string& password,
164 const WifiManager::SuccessCallback& callback) {
165 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
166 scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password);
167
168 std::string network_guid;
169 std::string error_string;
170 // Will fail without changing system state if network already exists.
171 wifi_service_->CreateNetwork(
172 false, properties.Pass(), &network_guid, &error_string);
173
174 if (error_string.empty()) {
175 ConnectToNetworkByID(network_guid, callback);
176 return;
177 }
178
179 // If we cannot create the network, attempt to configure and connect to an
180 // existing network.
181 if (FindAndConfigureNetwork(ssid, password, &network_guid)) {
182 ConnectToNetworkByID(network_guid, callback);
183 } else {
184 PostClosure(base::Bind(callback, false /* success */));
185 }
186 }
187
188 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkListChangedEvent(
189 const std::vector<std::string>& network_guids) {
190 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
191 scoped_ptr<NetworkPropertiesList> ssid_list(new NetworkPropertiesList);
192 GetSSIDListInternal(ssid_list.get());
193 callback_runner_->PostTask(
194 FROM_HERE,
195 base::Bind(&WifiManagerNonChromeos::OnNetworkListChanged,
196 wifi_manager_,
197 base::Passed(&ssid_list)));
198 }
199
200 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworksChangedEvent(
201 const std::vector<std::string>& network_guids) {
202 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
203 if (connecting_network_guid_.empty() ||
204 !IsConnected(connecting_network_guid_)) {
205 return;
206 }
207
208 connecting_network_guid_.clear();
209 connect_failure_callback_.Cancel();
210
211 PostClosure(base::Bind(connect_success_callback_, true));
212
213 connect_success_callback_.Reset();
214 }
215
216 base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper>
217 WifiManagerNonChromeos::WifiServiceWrapper::AsWeakPtr() {
218 return weak_factory_.GetWeakPtr();
219 }
220
221 void WifiManagerNonChromeos::WifiServiceWrapper::RequestScan() {
222 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
223 wifi_service_->RequestNetworkScan();
224 }
225
226 void WifiManagerNonChromeos::WifiServiceWrapper::ConnectToNetworkByID(
227 const std::string& network_guid,
228 const WifiManager::SuccessCallback& callback) {
229 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
230
231 std::string connected_network_id = GetConnectedGUID();
232 std::string error_string;
233 wifi_service_->StartConnect(network_guid, &error_string);
234
235 if (!error_string.empty()) {
236 LOG(ERROR) << "Could not connect to network by ID: " << error_string;
237 PostClosure(base::Bind(callback, false /* success */));
238 wifi_service_->StartConnect(connected_network_id, &error_string);
239 return;
240 }
241
242 if (IsConnected(network_guid)) {
243 PostClosure(base::Bind(callback, true /* success */));
244 return;
245 }
246
247 connect_success_callback_ = callback;
248 connecting_network_guid_ = network_guid;
249 connected_network_guid_ = connected_network_id;
250
251 connect_failure_callback_.Reset(base::Bind(
252 &WifiServiceWrapper::OnConnectToNetworkTimeout, base::Unretained(this)));
253
254 base::MessageLoop::current()->PostDelayedTask(
255 FROM_HERE,
256 connect_failure_callback_.callback(),
257 base::TimeDelta::FromSeconds(kConnectionTimeoutSeconds));
258 }
259
260 void WifiManagerNonChromeos::WifiServiceWrapper::OnConnectToNetworkTimeout() {
261 bool connected = IsConnected(connecting_network_guid_);
262 std::string error_string;
263
264 WifiManager::SuccessCallback connect_success_callback =
265 connect_success_callback_;
266
267 connect_success_callback_.Reset();
268
269 connecting_network_guid_.clear();
270
271 // If we did not connect, return to the network the user was originally
272 // connected to.
273 if (!connected)
274 wifi_service_->StartConnect(connected_network_guid_, &error_string);
275
276 PostClosure(base::Bind(connect_success_callback, connected /* success */));
277 }
278
279 void WifiManagerNonChromeos::WifiServiceWrapper::RequestNetworkCredentials(
280 const std::string& network_guid,
281 const WifiManager::CredentialsCallback& callback) {
282 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
283
284 bool success = true;
285 std::string ssid;
286 std::string key;
287
288 #if defined(OS_WIN)
289 NOTIMPLEMENTED();
290 success = false;
291 #else
292 base::DictionaryValue properties;
293 std::string error_string;
294 wifi_service_->GetProperties(network_guid, &properties, &error_string);
295
296 if (!error_string.empty()) {
297 LOG(ERROR) << "Could not get network properties: " << error_string;
298 success = false;
299 }
300
301 if (!properties.GetString(onc::network_config::kName, &ssid)) {
302 LOG(ERROR) << "Could not get network SSID";
303 success = false;
304 }
305
306 if (success) {
307 wifi_service_->GetKeyFromSystem(network_guid, &key, &error_string);
308
309 if (!error_string.empty()) {
310 LOG(ERROR) << "Could not get key from system: " << error_string;
311 success = false;
312 }
313 }
314 #endif // OS_WIN
315 PostClosure(base::Bind(callback, success, ssid, key));
316 }
317
318 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkChanged(
319 net::NetworkChangeNotifier::ConnectionType type) {
320 wifi_service_->RequestConnectedNetworkUpdate();
321 }
322
323 void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDListInternal(
324 NetworkPropertiesList* ssid_list) {
325 base::ListValue visible_networks;
326
327 wifi_service_->GetVisibleNetworks(
328 onc::network_type::kWiFi, &visible_networks, true);
329
330 for (size_t i = 0; i < visible_networks.GetSize(); i++) {
331 const base::DictionaryValue* network_value = NULL;
332 NetworkProperties network_properties;
333
334 if (!visible_networks.GetDictionary(i, &network_value)) {
335 NOTREACHED();
336 }
337
338 network_properties.UpdateFromValue(*network_value);
339
340 ssid_list->push_back(network_properties);
341 }
342 }
343
344 std::string WifiManagerNonChromeos::WifiServiceWrapper::GetConnectedGUID() {
345 NetworkPropertiesList ssid_list;
346 GetSSIDListInternal(&ssid_list);
347
348 for (NetworkPropertiesList::const_iterator it = ssid_list.begin();
349 it != ssid_list.end();
350 ++it) {
351 if (it->connection_state == onc::connection_state::kConnected)
352 return it->guid;
353 }
354
355 return "";
356 }
357
358 bool WifiManagerNonChromeos::WifiServiceWrapper::IsConnected(
359 const std::string& network_guid) {
360 NetworkPropertiesList ssid_list;
361 GetSSIDListInternal(&ssid_list);
362
363 for (NetworkPropertiesList::const_iterator it = ssid_list.begin();
364 it != ssid_list.end();
365 ++it) {
366 if (it->connection_state == onc::connection_state::kConnected &&
367 it->guid == network_guid)
368 return true;
369 }
370
371 return false;
372 }
373
374 bool WifiManagerNonChromeos::WifiServiceWrapper::FindAndConfigureNetwork(
375 const std::string& ssid,
376 const std::string& password,
377 std::string* network_guid) {
378 std::string provisional_network_guid;
379 NetworkPropertiesList network_property_list;
380 GetSSIDListInternal(&network_property_list);
381
382 for (size_t i = 0; i < network_property_list.size(); i++) {
383 // TODO(noamsml): Handle case where there are multiple networks with the
384 // same SSID but different security.
385 if (network_property_list[i].ssid == ssid) {
386 provisional_network_guid = network_property_list[i].guid;
387 break;
388 }
389 }
390
391 if (provisional_network_guid.empty())
392 return false;
393
394 scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password);
395
396 std::string error_string;
397 wifi_service_->SetProperties(
398 provisional_network_guid, properties.Pass(), &error_string);
399
400 if (!error_string.empty()) {
401 LOG(ERROR) << "Could not set properties on network: " << error_string;
402 return false;
403 }
404
405 *network_guid = provisional_network_guid;
406 return true;
407 }
408
409 void WifiManagerNonChromeos::WifiServiceWrapper::PostClosure(
410 const base::Closure& closure) {
411 callback_runner_->PostTask(
412 FROM_HERE,
413 base::Bind(&WifiManagerNonChromeos::PostClosure, wifi_manager_, closure));
414 }
415
416 scoped_ptr<WifiManager> WifiManager::Create() {
417 return scoped_ptr<WifiManager>(new WifiManagerNonChromeos());
418 }
419
420 WifiManagerNonChromeos::WifiManagerNonChromeos()
421 : wifi_wrapper_(NULL), weak_factory_(this) {
422 }
423
424 WifiManagerNonChromeos::~WifiManagerNonChromeos() {
425 if (wifi_wrapper_) {
426 content::BrowserThread::DeleteSoon(
427 content::BrowserThread::FILE, FROM_HERE, wifi_wrapper_);
428 }
429 }
430
431 void WifiManagerNonChromeos::Start() {
432 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
433 task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
434 content::BrowserThread::FILE);
435
436 // Allocated on UI thread, but all initialization is done on file
437 // thread. Destroyed on file thread, which should be safe since all of the
438 // thread-unsafe members are created on the file thread.
439 wifi_wrapper_ = new WifiServiceWrapper(weak_factory_.GetWeakPtr());
440
441 task_runner_->PostTask(
442 FROM_HERE,
443 base::Bind(&WifiServiceWrapper::Start, wifi_wrapper_->AsWeakPtr()));
444 }
445
446 void WifiManagerNonChromeos::GetSSIDList(const SSIDListCallback& callback) {
447 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
448 task_runner_->PostTask(FROM_HERE,
449 base::Bind(&WifiServiceWrapper::GetSSIDList,
450 wifi_wrapper_->AsWeakPtr(),
451 callback));
452 }
453
454 void WifiManagerNonChromeos::RequestScan() {
455 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
456 task_runner_->PostTask(
457 FROM_HERE,
458 base::Bind(&WifiServiceWrapper::RequestScan, wifi_wrapper_->AsWeakPtr()));
459 }
460
461 void WifiManagerNonChromeos::OnNetworkListChanged(
462 scoped_ptr<NetworkPropertiesList> ssid_list) {
463 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
464 FOR_EACH_OBSERVER(NetworkListObserver,
465 network_list_observers_,
466 OnNetworkListChanged(*ssid_list));
467 }
468
469 void WifiManagerNonChromeos::PostClosure(const base::Closure& callback) {
470 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
471 callback.Run();
472 }
473
474 void WifiManagerNonChromeos::PostSSIDListCallback(
475 const SSIDListCallback& callback,
476 scoped_ptr<NetworkPropertiesList> ssid_list) {
477 callback.Run(*ssid_list);
478 }
479
480 void WifiManagerNonChromeos::ConfigureAndConnectNetwork(
481 const std::string& ssid,
482 const WifiCredentials& credentials,
483 const SuccessCallback& callback) {
484 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
485 task_runner_->PostTask(
486 FROM_HERE,
487 base::Bind(&WifiServiceWrapper::ConfigureAndConnectPskNetwork,
488 wifi_wrapper_->AsWeakPtr(),
489 ssid,
490 credentials.psk,
491 callback));
492 }
493
494 void WifiManagerNonChromeos::ConnectToNetworkByID(
495 const std::string& internal_id,
496 const SuccessCallback& callback) {
497 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
498 task_runner_->PostTask(FROM_HERE,
499 base::Bind(&WifiServiceWrapper::ConnectToNetworkByID,
500 wifi_wrapper_->AsWeakPtr(),
501 internal_id,
502 callback));
503 }
504
505 void WifiManagerNonChromeos::RequestNetworkCredentials(
506 const std::string& internal_id,
507 const CredentialsCallback& callback) {
508 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
509 task_runner_->PostTask(
510 FROM_HERE,
511 base::Bind(&WifiServiceWrapper::RequestNetworkCredentials,
512 wifi_wrapper_->AsWeakPtr(),
513 internal_id,
514 callback));
515 }
516
517 void WifiManagerNonChromeos::AddNetworkListObserver(
518 NetworkListObserver* observer) {
519 network_list_observers_.AddObserver(observer);
520 }
521
522 void WifiManagerNonChromeos::RemoveNetworkListObserver(
523 NetworkListObserver* observer) {
524 network_list_observers_.RemoveObserver(observer);
525 }
526
527 } // namespace wifi
528
529 } // namespace local_discovery
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698