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

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

Powered by Google App Engine
This is Rietveld 408576698