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

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

Powered by Google App Engine
This is Rietveld 408576698