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

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 wifi->SetString(onc::wifi::kPassphrase, password);
33
34 return properties.Pass();
35 }
36
37 } // namespace
38
39 class WifiManagerNonChromeos::NetworkListWatcherImpl
40 : public NetworkListWatcher {
41 public:
42 NetworkListWatcherImpl(const WifiManager::SSIDListCallback& callback,
43 base::WeakPtr<WifiManagerNonChromeos> wifi_manager);
44 virtual ~NetworkListWatcherImpl();
45
46 virtual void Start() OVERRIDE;
47
48 void OnNetworkListChanged(const std::vector<NetworkProperties>& ssid_list);
stevenjb 2014/05/23 16:42:40 I think this class would be better named NetworkLi
Noam Samuel 2014/05/24 00:15:39 Obsolete, see above.
49
50 private:
51 WifiManager::SSIDListCallback callback_;
52 bool started_;
53 base::WeakPtr<WifiManagerNonChromeos> wifi_manager_;
54
55 DISALLOW_COPY_AND_ASSIGN(NetworkListWatcherImpl);
56 };
57
58 class WifiManagerNonChromeos::WifiServiceWrapper {
59 public:
60 WifiServiceWrapper(
61 const base::Callback<void(const base::Closure&)>& post_callback,
62 const WifiManager::SSIDListCallback& network_list_update);
63
64 ~WifiServiceWrapper();
65
66 void Start();
67
68 void GetSSIDList(const WifiManager::SSIDListCallback& callback);
69
70 void ConfigureAndConnectPskNetwork(
71 const std::string& ssid,
72 const std::string& password,
73 const WifiManager::SuccessCallback& callback);
74
75 base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper> AsWeakPtr();
76
77 void RequestScan();
78
79 void ConnectToNetworkByID(const std::string& network_guid,
80 const WifiManager::SuccessCallback& callback);
81
82 void RequestNetworkCredentials(
83 const std::string& network_guid,
84 const WifiManager::CredentialsCallback& callback);
85
86 private:
87 void GetSSIDListInternal(std::vector<NetworkProperties>* ssid_list);
88
89 void OnNetworkListChangedEvent(const std::vector<std::string>& network_guids);
90
91 void OnNetworksChangedEvent(const std::vector<std::string>& network_guids);
92
93 std::string GetConnectedGUID();
94
95 bool IsConnected(const std::string& network_guid);
96
97 void OnConnectToNetworkTimeout();
98
99 scoped_ptr<WiFiService> wifi_service_;
100
101 base::Callback<void(const base::Closure&)> post_callback_;
102 WifiManager::SSIDListCallback network_list_update_;
103
104 WifiManager::SuccessCallback connect_success_callback_;
105 base::CancelableClosure connect_failure_callback_;
106 std::string connected_network_guid_; // SSID of previously connected network.
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 // SSID of network we are connecting to. std::stri
Noam Samuel 2014/05/24 00:15:39 Done.
107 std::string
108 connecting_network_guid_; // SSID of network we are connecting to.
109
110 base::WeakPtrFactory<WifiServiceWrapper> weak_factory_;
111
112 DISALLOW_COPY_AND_ASSIGN(WifiServiceWrapper);
113 };
114
stevenjb 2014/05/23 16:42:40 Either move the implementations just below each cl
Noam Samuel 2014/05/24 00:15:39 Obsolete, see above.
115 WifiManagerNonChromeos::NetworkListWatcherImpl::NetworkListWatcherImpl(
116 const WifiManager::SSIDListCallback& callback,
117 base::WeakPtr<WifiManagerNonChromeos> wifi_manager)
118 : callback_(callback), started_(false), wifi_manager_(wifi_manager) {
119 }
120
121 WifiManagerNonChromeos::NetworkListWatcherImpl::~NetworkListWatcherImpl() {
122 if (started_ && wifi_manager_)
123 wifi_manager_->RemoveObserver(this);
124 }
125
126 void WifiManagerNonChromeos::NetworkListWatcherImpl::Start() {
127 DCHECK(!started_);
128
129 if (wifi_manager_)
130 wifi_manager_->AddObserver(this);
131 }
132
133 void WifiManagerNonChromeos::NetworkListWatcherImpl::OnNetworkListChanged(
134 const std::vector<NetworkProperties>& ssid_list) {
135 callback_.Run(ssid_list);
136 }
137
138 WifiManagerNonChromeos::WifiServiceWrapper::WifiServiceWrapper(
139 const base::Callback<void(const base::Closure&)>& post_callback,
140 const WifiManager::SSIDListCallback& network_list_update)
141 : post_callback_(post_callback),
142 network_list_update_(network_list_update),
143 weak_factory_(this) {
144 }
145
146 WifiManagerNonChromeos::WifiServiceWrapper::~WifiServiceWrapper() {
147 }
148
149 void WifiManagerNonChromeos::WifiServiceWrapper::Start() {
150 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
151 wifi_service_.reset(WiFiService::Create());
152
153 wifi_service_->Initialize(base::MessageLoopProxy::current());
154
155 wifi_service_->SetEventObservers(
156 base::MessageLoopProxy::current(),
157 base::Bind(&WifiServiceWrapper::OnNetworksChangedEvent,
158 base::Unretained(this)),
159 base::Bind(&WifiServiceWrapper::OnNetworkListChangedEvent,
160 base::Unretained(this)));
161 }
162
163 void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDList(
164 const WifiManager::SSIDListCallback& callback) {
165 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
166
167 std::vector<NetworkProperties> network_property_list;
168
169 GetSSIDListInternal(&network_property_list);
170
171 content::BrowserThread::PostTask(
172 content::BrowserThread::UI,
173 FROM_HERE,
174 base::Bind(post_callback_, base::Bind(callback, network_property_list)));
stevenjb 2014/05/23 16:42:40 This requires copying the entire vector in the bin
Noam Samuel 2014/05/24 00:15:39 I assume you mean scoped_ptr<std::vector>, and not
175 }
176
177 void WifiManagerNonChromeos::WifiServiceWrapper::ConfigureAndConnectPskNetwork(
178 const std::string& ssid,
179 const std::string& password,
180 const WifiManager::SuccessCallback& callback) {
181 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
182 scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password);
mef 2014/05/23 18:22:50 You also need a to pass in wifi security type: htt
Noam Samuel 2014/05/24 00:15:39 Done-ish. For now this'll work since this method i
183
184 std::string network_guid;
185 std::string error_string;
186 wifi_service_->CreateNetwork(
187 false, properties.Pass(), &network_guid, &error_string);
stevenjb 2014/05/23 16:42:40 Is this a no-op if a matching network is already c
mef 2014/05/23 18:22:50 CreateNetwork will return an error if matching net
Noam Samuel 2014/05/24 00:15:39 Added comment
188
189 // If we cannot create the network, attempt to configure and connect to an
190 // existing network.
191 bool error = false;
192 if (!error_string.empty()) {
193 error_string.clear();
194 std::vector<NetworkProperties> network_property_list;
195 GetSSIDListInternal(&network_property_list);
196
197 network_guid.clear();
198 for (std::vector<NetworkProperties>::iterator it =
199 network_property_list.begin();
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 with indexes it's just one line for statement
Noam Samuel 2014/05/24 00:15:39 Done.
200 it != network_property_list.end();
201 ++it) {
202 if (it->ssid == ssid) {
stevenjb 2014/05/23 16:42:40 On Chrome OS it is possible to have more than one
mef 2014/05/23 18:22:50 WiFiService currently doesn't support multiple sec
Noam Samuel 2014/05/24 00:15:39 Added TODO
203 network_guid = it->internal_id;
204 break;
205 }
206 }
207
208 if (network_guid.empty()) {
209 error = true; // Could not create the network but it is not configured.
stevenjb 2014/05/23 16:42:40 nit: s/but/and
Noam Samuel 2014/05/24 00:15:39 Done.
210 } else {
211 properties = MakeProperties(ssid, password);
212 wifi_service_->SetProperties(
213 network_guid, properties.Pass(), &error_string);
214
215 if (!error_string.empty()) {
216 LOG(ERROR) << "Could not set properties on network: " << error_string;
217 error = true;
218 }
219 }
220 }
221
222 if (!error) {
223 ConnectToNetworkByID(network_guid, callback);
224 } else {
225 content::BrowserThread::PostTask(
226 content::BrowserThread::UI,
227 FROM_HERE,
228 base::Bind(post_callback_, base::Bind(callback, !error)));
stevenjb 2014/05/23 16:42:40 nit: s/!error/false /* success *//
Noam Samuel 2014/05/24 00:15:39 Done.
229 }
230 }
231
232 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkListChangedEvent(
233 const std::vector<std::string>& network_guids) {
234 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
235 std::vector<NetworkProperties> ssid_list;
236 GetSSIDListInternal(&ssid_list);
237 content::BrowserThread::PostTask(content::BrowserThread::UI,
238 FROM_HERE,
239 base::Bind(network_list_update_, ssid_list));
240 }
241
242 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworksChangedEvent(
243 const std::vector<std::string>& network_guids) {
244 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
245 if (connecting_network_guid_.empty() ||
246 !IsConnected(connecting_network_guid_)) {
247 return;
248 }
249
250 connecting_network_guid_.clear();
251 connect_failure_callback_.Cancel();
252
253 content::BrowserThread::PostTask(
254 content::BrowserThread::UI,
255 FROM_HERE,
256 base::Bind(post_callback_, base::Bind(connect_success_callback_, true)));
257
258 connect_success_callback_.Reset();
259 }
260
261 base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper>
262 WifiManagerNonChromeos::WifiServiceWrapper::AsWeakPtr() {
263 return weak_factory_.GetWeakPtr();
264 }
265
266 void WifiManagerNonChromeos::WifiServiceWrapper::RequestScan() {
267 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
268 wifi_service_->RequestNetworkScan();
269 }
270
271 void WifiManagerNonChromeos::WifiServiceWrapper::ConnectToNetworkByID(
272 const std::string& network_guid,
273 const WifiManager::SuccessCallback& callback) {
274 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
275
276 std::string connected_network_id = GetConnectedGUID();
277 std::string error_string;
278 wifi_service_->StartConnect(network_guid, &error_string);
279
280 bool error = false;
281 if (!error_string.empty()) {
282 LOG(ERROR) << "Could not connect to network by ID: " << error_string;
283 error = true;
284 wifi_service_->StartConnect(connected_network_id, &error_string);
285 }
286
287 bool connected = IsConnected(network_guid);
288
289 if (error || connected) {
290 content::BrowserThread::PostTask(
291 content::BrowserThread::UI,
292 FROM_HERE,
293 base::Bind(post_callback_, base::Bind(callback, !error && connected)));
stevenjb 2014/05/23 16:42:40 nit: s/!error && connected/!error/
Noam Samuel 2014/05/24 00:15:39 Done.
294 return;
295 }
296
297 connect_success_callback_ = callback;
298 connecting_network_guid_ = network_guid;
299 connected_network_guid_ = connected_network_id;
300
301 connect_failure_callback_.Reset(base::Bind(
302 &WifiServiceWrapper::OnConnectToNetworkTimeout, base::Unretained(this)));
303
304 base::MessageLoop::current()->PostDelayedTask(
305 FROM_HERE,
306 connect_failure_callback_.callback(),
307 base::TimeDelta::FromSeconds(kConnectionTimeoutSeconds));
308 }
309
310 void WifiManagerNonChromeos::WifiServiceWrapper::OnConnectToNetworkTimeout() {
311 bool connected = IsConnected(connecting_network_guid_);
312 std::string error_string;
313
314 if (!connected)
315 wifi_service_->StartConnect(connected_network_guid_, &error_string);
316
317 connecting_network_guid_.clear();
318
319 content::BrowserThread::PostTask(
320 content::BrowserThread::UI,
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 Extract following into method. content::BrowserThr
Noam Samuel 2014/05/24 00:15:39 Done.
321 FROM_HERE,
322 base::Bind(post_callback_,
323 base::Bind(connect_success_callback_, connected)));
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 maybe save some callback_runner_ in constructor in
Noam Samuel 2014/05/24 00:15:39 Done.
324
325 connect_success_callback_.Reset();
326 }
327
328 void WifiManagerNonChromeos::WifiServiceWrapper::RequestNetworkCredentials(
329 const std::string& network_guid,
330 const WifiManager::CredentialsCallback& callback) {
331 #if defined(OS_WIN)
332 NOTIMPLEMENTED();
333
334 content::BrowserThread::PostTask(
335 content::BrowserThread::UI,
336 FROM_HERE,
337 base::Bind(post_callback_,
338 base::Bind(callback, false, std::string(), std::string())));
stevenjb 2014/05/23 16:42:40 nit: maybe declare error, ssid, and key above the
Noam Samuel 2014/05/24 00:15:39 Done.
339 #else
340 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 move outside DCHECK FILE?
Noam Samuel 2014/05/24 00:15:39 Done.
341 base::DictionaryValue properties;
342 std::string error_string;
343 wifi_service_->GetProperties(network_guid, &properties, &error_string);
344
345 bool error = false;
346 if (!error_string.empty()) {
347 LOG(ERROR) << "Could not get network properties: " << error_string;
348 error = true;
349 }
350
351 std::string ssid;
352 if (!properties.GetString(onc::network_config::kName, &ssid)) {
353 LOG(ERROR) << "Could not get network SSID";
354 error = true;
355 }
356
357 std::string key;
358 if (!error) {
359 wifi_service_->GetKeyFromSystem(network_guid, &key, &error_string);
360
361 if (!error_string.empty()) {
362 LOG(ERROR) << "Could not get key from system: " << error_string;
363 error = true;
364 }
365 }
366
367 content::BrowserThread::PostTask(
368 content::BrowserThread::UI,
369 FROM_HERE,
370 base::Bind(post_callback_, base::Bind(callback, !error, ssid, key)));
371 #endif // OS_WIN
372 }
373
374 void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDListInternal(
375 std::vector<NetworkProperties>* ssid_list) {
376 base::ListValue visible_networks;
377
378 wifi_service_->GetVisibleNetworks(onc::network_type::kWiFi,
379 &visible_networks);
380
381 for (size_t i = 0; i < visible_networks.GetSize(); i++) {
382 const base::DictionaryValue* network_value = NULL;
383 NetworkProperties network_properties;
384 std::string connection_status;
385
386 if (!visible_networks.GetDictionary(i, &network_value) ||
387 !network_value->GetString(onc::network_config::kName,
388 &network_properties.ssid) ||
389 !network_value->GetString(onc::network_config::kGUID,
390 &network_properties.internal_id) ||
391 !network_value->GetString(onc::network_config::kConnectionState,
392 &connection_status)) {
393 NOTREACHED();
394 continue;
395 }
396
397 network_properties.connected =
398 (connection_status == onc::connection_state::kConnected);
399
400 ssid_list->push_back(network_properties);
401 }
402 }
403
404 std::string WifiManagerNonChromeos::WifiServiceWrapper::GetConnectedGUID() {
405 std::vector<NetworkProperties> ssid_list;
406 GetSSIDListInternal(&ssid_list);
407
408 for (std::vector<NetworkProperties>::const_iterator it = ssid_list.begin();
409 it != ssid_list.end();
410 ++it) {
411 if (it->connected) {
412 return it->internal_id;
413 }
stevenjb 2014/05/23 16:42:40 nit: {} unnecessary.
Noam Samuel 2014/05/24 00:15:39 Done.
414 }
415
416 return "";
417 }
418
419 bool WifiManagerNonChromeos::WifiServiceWrapper::IsConnected(
420 const std::string& network_guid) {
421 std::vector<NetworkProperties> ssid_list;
422 GetSSIDListInternal(&ssid_list);
423
424 for (std::vector<NetworkProperties>::const_iterator it = ssid_list.begin();
425 it != ssid_list.end();
426 ++it) {
427 if (it->connected && it->internal_id == network_guid) {
428 return true;
429 }
stevenjb 2014/05/23 16:42:40 nit: {} unnecessary.
Noam Samuel 2014/05/24 00:15:39 Done.
430 }
431
432 return false;
433 }
434
435 scoped_ptr<WifiManager> WifiManager::Create() {
436 return scoped_ptr<WifiManager>(new WifiManagerNonChromeos());
437 }
438
439 WifiManagerNonChromeos::WifiManagerNonChromeos()
440 : wifi_wrapper_(NULL), weak_factory_(this) {
441 }
442
443 WifiManagerNonChromeos::~WifiManagerNonChromeos() {
444 if (wifi_wrapper_) {
445 content::BrowserThread::DeleteSoon(
446 content::BrowserThread::FILE, FROM_HERE, wifi_wrapper_);
447 }
448 }
449
450 void WifiManagerNonChromeos::Start() {
451 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
452 task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
453 content::BrowserThread::FILE);
454
455 // Allocated on UI thread, but all initialization is done on file
456 // thread. Destroyed on file thread, which should be safe since all of the
457 // thread-unsafe members are created on the file thread.
458 wifi_wrapper_ = new WifiServiceWrapper(
459 base::Bind(&WifiManagerNonChromeos::PostClosure,
460 weak_factory_.GetWeakPtr()),
461 base::Bind(&WifiManagerNonChromeos::OnNetworkListChanged,
462 weak_factory_.GetWeakPtr()));
463
464 task_runner_->PostTask(
465 FROM_HERE,
466 base::Bind(&WifiServiceWrapper::Start, wifi_wrapper_->AsWeakPtr()));
467 }
468
469 void WifiManagerNonChromeos::GetSSIDList(const SSIDListCallback& callback) {
470 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
471 task_runner_->PostTask(FROM_HERE,
472 base::Bind(&WifiServiceWrapper::GetSSIDList,
473 wifi_wrapper_->AsWeakPtr(),
474 callback));
475 }
476
477 void WifiManagerNonChromeos::RequestScan() {
478 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
479 task_runner_->PostTask(
480 FROM_HERE,
481 base::Bind(&WifiServiceWrapper::RequestScan, wifi_wrapper_->AsWeakPtr()));
482 }
483
484 void WifiManagerNonChromeos::OnNetworkListChanged(
485 const std::vector<NetworkProperties>& ssid_list) {
486 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
487 FOR_EACH_OBSERVER(NetworkListWatcherImpl,
488 network_list_observers_,
489 OnNetworkListChanged(ssid_list));
490 }
491
492 void WifiManagerNonChromeos::PostClosure(const base::Closure& callback) {
493 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
494 callback.Run();
495 }
496
497 void WifiManagerNonChromeos::ConfigureAndConnectNetwork(
498 const std::string& ssid,
499 const WifiCredentials& credentials,
500 const SuccessCallback& callback) {
501 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
502 task_runner_->PostTask(
503 FROM_HERE,
504 base::Bind(&WifiServiceWrapper::ConfigureAndConnectPskNetwork,
505 wifi_wrapper_->AsWeakPtr(),
506 ssid,
507 credentials.psk,
508 callback));
509 }
510
511 void WifiManagerNonChromeos::ConnectToNetworkByID(
512 const std::string& internal_id,
513 const SuccessCallback& callback) {
514 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
515 task_runner_->PostTask(FROM_HERE,
516 base::Bind(&WifiServiceWrapper::ConnectToNetworkByID,
517 wifi_wrapper_->AsWeakPtr(),
518 internal_id,
519 callback));
520 }
521
522 void WifiManagerNonChromeos::RequestNetworkCredentials(
523 const std::string& internal_id,
524 const CredentialsCallback& callback) {
525 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
526 task_runner_->PostTask(
527 FROM_HERE,
528 base::Bind(&WifiServiceWrapper::RequestNetworkCredentials,
529 wifi_wrapper_->AsWeakPtr(),
530 internal_id,
531 callback));
532 }
533
534 scoped_ptr<NetworkListWatcher> WifiManagerNonChromeos::CreateNetworkListWatcher(
535 const SSIDListCallback& callback) {
536 return scoped_ptr<NetworkListWatcher>(
537 new NetworkListWatcherImpl(callback, weak_factory_.GetWeakPtr()));
538 }
539
540 void WifiManagerNonChromeos::AddObserver(NetworkListWatcherImpl* observer) {
541 network_list_observers_.AddObserver(observer);
542 }
543
544 void WifiManagerNonChromeos::RemoveObserver(NetworkListWatcherImpl* observer) {
545 network_list_observers_.RemoveObserver(observer);
546 }
547
548 } // namespace wifi
549
550 } // namespace local_discovery
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698