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

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 "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"
mef 2014/05/28 16:28:30 nit: shouldn't this be a first include?
Noam Samuel 2014/05/28 23:04:36 Done.
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
99 // SSID of previously connected network.
100 std::string connected_network_guid_;
101
102 // SSID of network we are connecting to.
103 std::string connecting_network_guid_;
104
105 scoped_refptr<base::MessageLoopProxy> callback_runner_;
106
107 base::WeakPtrFactory<WifiServiceWrapper> weak_factory_;
108
109 DISALLOW_COPY_AND_ASSIGN(WifiServiceWrapper);
110 };
111
112 WifiManagerNonChromeos::WifiServiceWrapper::WifiServiceWrapper(
113 base::WeakPtr<WifiManagerNonChromeos> wifi_manager)
114 : wifi_manager_(wifi_manager),
115 callback_runner_(base::MessageLoopProxy::current()),
116 weak_factory_(this) {
117 }
118
119 WifiManagerNonChromeos::WifiServiceWrapper::~WifiServiceWrapper() {
120 }
121
122 void WifiManagerNonChromeos::WifiServiceWrapper::Start() {
123 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
124 wifi_service_.reset(WiFiService::Create());
125
126 wifi_service_->Initialize(base::MessageLoopProxy::current());
127
128 wifi_service_->SetEventObservers(
129 base::MessageLoopProxy::current(),
130 base::Bind(&WifiServiceWrapper::OnNetworksChangedEvent,
131 base::Unretained(this)),
132 base::Bind(&WifiServiceWrapper::OnNetworkListChangedEvent,
133 base::Unretained(this)));
134 }
135
136 void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDList(
137 const WifiManager::SSIDListCallback& callback) {
138 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
139
140 scoped_ptr<NetworkPropertiesList> ssid_list(new NetworkPropertiesList);
141 GetSSIDListInternal(ssid_list.get());
142
143 callback_runner_->PostTask(
144 FROM_HERE,
145 base::Bind(&WifiManagerNonChromeos::PostSSIDListCallback,
146 wifi_manager_,
147 callback,
148 base::Passed(&ssid_list)));
149 }
150
151 void WifiManagerNonChromeos::WifiServiceWrapper::ConfigureAndConnectPskNetwork(
152 const std::string& ssid,
153 const std::string& password,
154 const WifiManager::SuccessCallback& callback) {
155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
156 scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password);
157
158 std::string network_guid;
159 std::string error_string;
160 // Will fail without changing system state if network already exists.
161 wifi_service_->CreateNetwork(
162 false, properties.Pass(), &network_guid, &error_string);
163
164 if (error_string.empty()) {
165 ConnectToNetworkByID(network_guid, callback);
166 return;
167 }
168
169 // If we cannot create the network, attempt to configure and connect to an
170 // existing network.
171 if (FindAndConfigureNetwork(ssid, password, &network_guid)) {
172 ConnectToNetworkByID(network_guid, callback);
173 } else {
174 PostClosure(base::Bind(callback, false /* success */));
175 }
176 }
177
178 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkListChangedEvent(
179 const std::vector<std::string>& network_guids) {
180 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
181 scoped_ptr<NetworkPropertiesList> ssid_list(new NetworkPropertiesList);
182 GetSSIDListInternal(ssid_list.get());
183 callback_runner_->PostTask(
184 FROM_HERE,
185 base::Bind(&WifiManagerNonChromeos::OnNetworkListChanged,
186 wifi_manager_,
187 base::Passed(&ssid_list)));
188 }
189
190 void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworksChangedEvent(
191 const std::vector<std::string>& network_guids) {
192 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
193 if (connecting_network_guid_.empty() ||
194 !IsConnected(connecting_network_guid_)) {
195 return;
196 }
197
198 connecting_network_guid_.clear();
199 connect_failure_callback_.Cancel();
200
201 PostClosure(base::Bind(connect_success_callback_, true));
202
203 connect_success_callback_.Reset();
204 }
205
206 base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper>
207 WifiManagerNonChromeos::WifiServiceWrapper::AsWeakPtr() {
208 return weak_factory_.GetWeakPtr();
209 }
210
211 void WifiManagerNonChromeos::WifiServiceWrapper::RequestScan() {
212 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
213 wifi_service_->RequestNetworkScan();
214 }
215
216 void WifiManagerNonChromeos::WifiServiceWrapper::ConnectToNetworkByID(
217 const std::string& network_guid,
218 const WifiManager::SuccessCallback& callback) {
219 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
220
221 std::string connected_network_id = GetConnectedGUID();
222 std::string error_string;
223 wifi_service_->StartConnect(network_guid, &error_string);
224
225 if (!error_string.empty()) {
226 LOG(ERROR) << "Could not connect to network by ID: " << error_string;
227 PostClosure(base::Bind(callback, false /* success */));
228 wifi_service_->StartConnect(connected_network_id, &error_string);
229 return;
230 }
231
232 if (IsConnected(network_guid)) {
233 PostClosure(base::Bind(callback, true /* success */));
234 return;
235 }
236
237 connect_success_callback_ = callback;
238 connecting_network_guid_ = network_guid;
239 connected_network_guid_ = connected_network_id;
240
241 connect_failure_callback_.Reset(base::Bind(
242 &WifiServiceWrapper::OnConnectToNetworkTimeout, base::Unretained(this)));
243
244 base::MessageLoop::current()->PostDelayedTask(
245 FROM_HERE,
246 connect_failure_callback_.callback(),
247 base::TimeDelta::FromSeconds(kConnectionTimeoutSeconds));
248 }
249
250 void WifiManagerNonChromeos::WifiServiceWrapper::OnConnectToNetworkTimeout() {
251 bool connected = IsConnected(connecting_network_guid_);
252 std::string error_string;
253
254 // If we did not connect, return to the network the user was originally
255 // connected to.
256 if (!connected)
257 wifi_service_->StartConnect(connected_network_guid_, &error_string);
258
259 connecting_network_guid_.clear();
260
261 PostClosure(base::Bind(connect_success_callback_, connected /* success */));
262
263 connect_success_callback_.Reset();
264 }
265
266 void WifiManagerNonChromeos::WifiServiceWrapper::RequestNetworkCredentials(
267 const std::string& network_guid,
268 const WifiManager::CredentialsCallback& callback) {
269 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
270
271 bool success = true;
272 std::string ssid;
273 std::string key;
274
275 #if defined(OS_WIN)
276 NOTIMPLEMENTED();
277 success = false;
278 #else
279 base::DictionaryValue properties;
280 std::string error_string;
281 wifi_service_->GetProperties(network_guid, &properties, &error_string);
282
283 if (!error_string.empty()) {
284 LOG(ERROR) << "Could not get network properties: " << error_string;
285 success = false;
286 }
287
288 if (!properties.GetString(onc::network_config::kName, &ssid)) {
289 LOG(ERROR) << "Could not get network SSID";
290 success = false;
291 }
292
293 if (success) {
294 wifi_service_->GetKeyFromSystem(network_guid, &key, &error_string);
295
296 if (!error_string.empty()) {
297 LOG(ERROR) << "Could not get key from system: " << error_string;
298 success = false;
299 }
300 }
301 #endif // OS_WIN
302 PostClosure(base::Bind(callback, success, ssid, key));
303 }
304
305 void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDListInternal(
306 NetworkPropertiesList* ssid_list) {
307 base::ListValue visible_networks;
308
309 wifi_service_->GetVisibleNetworks(onc::network_type::kWiFi,
310 &visible_networks);
311
312 for (size_t i = 0; i < visible_networks.GetSize(); i++) {
313 const base::DictionaryValue* network_value = NULL;
314 NetworkProperties network_properties;
315 std::string connection_status;
316
317 if (!visible_networks.GetDictionary(i, &network_value) ||
318 !network_value->GetString(onc::network_config::kName,
319 &network_properties.ssid) ||
320 !network_value->GetString(onc::network_config::kGUID,
321 &network_properties.internal_id) ||
322 !network_value->GetString(onc::network_config::kConnectionState,
323 &connection_status)) {
324 NOTREACHED();
325 }
326
327 network_properties.connected =
328 (connection_status == onc::connection_state::kConnected);
329
330 ssid_list->push_back(network_properties);
331 }
332 }
333
334 std::string WifiManagerNonChromeos::WifiServiceWrapper::GetConnectedGUID() {
335 NetworkPropertiesList ssid_list;
336 GetSSIDListInternal(&ssid_list);
337
338 for (NetworkPropertiesList::const_iterator it = ssid_list.begin();
339 it != ssid_list.end();
340 ++it) {
341 if (it->connected)
342 return it->internal_id;
343 }
344
345 return "";
346 }
347
348 bool WifiManagerNonChromeos::WifiServiceWrapper::IsConnected(
349 const std::string& network_guid) {
350 NetworkPropertiesList ssid_list;
351 GetSSIDListInternal(&ssid_list);
352
353 for (NetworkPropertiesList::const_iterator it = ssid_list.begin();
354 it != ssid_list.end();
355 ++it) {
356 if (it->connected && it->internal_id == network_guid)
357 return true;
358 }
359
360 return false;
361 }
362
363 bool WifiManagerNonChromeos::WifiServiceWrapper::FindAndConfigureNetwork(
364 const std::string& ssid,
365 const std::string& password,
366 std::string* network_guid) {
367 std::string provisional_network_guid;
368 NetworkPropertiesList network_property_list;
369 GetSSIDListInternal(&network_property_list);
370
371 for (size_t i = 0; i < network_property_list.size(); i++) {
372 // TODO(noamsml): Handle case where there are multiple networks with the
373 // same SSID but different security.
374 if (network_property_list[i].ssid == ssid) {
375 provisional_network_guid = network_property_list[i].internal_id;
376 break;
377 }
378 }
379
380 if (provisional_network_guid.empty())
381 return false;
382
383 scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password);
384
385 std::string error_string;
386 wifi_service_->SetProperties(
387 provisional_network_guid, properties.Pass(), &error_string);
388
389 if (!error_string.empty()) {
390 LOG(ERROR) << "Could not set properties on network: " << error_string;
391 return false;
392 }
393
394 *network_guid = provisional_network_guid;
395 return true;
396 }
397
398 void WifiManagerNonChromeos::WifiServiceWrapper::PostClosure(
399 const base::Closure& closure) {
400 callback_runner_->PostTask(
401 FROM_HERE,
402 base::Bind(&WifiManagerNonChromeos::PostClosure, wifi_manager_, closure));
403 }
404
405 scoped_ptr<WifiManager> WifiManager::Create() {
406 return scoped_ptr<WifiManager>(new WifiManagerNonChromeos());
407 }
408
409 WifiManagerNonChromeos::WifiManagerNonChromeos()
410 : wifi_wrapper_(NULL), weak_factory_(this) {
411 }
412
413 WifiManagerNonChromeos::~WifiManagerNonChromeos() {
414 if (wifi_wrapper_) {
415 content::BrowserThread::DeleteSoon(
416 content::BrowserThread::FILE, FROM_HERE, wifi_wrapper_);
417 }
418 }
419
420 void WifiManagerNonChromeos::Start() {
421 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
422 task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
423 content::BrowserThread::FILE);
424
425 // Allocated on UI thread, but all initialization is done on file
426 // thread. Destroyed on file thread, which should be safe since all of the
427 // thread-unsafe members are created on the file thread.
428 wifi_wrapper_ = new WifiServiceWrapper(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<NetworkPropertiesList> 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<NetworkPropertiesList> 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