OLD | NEW |
| (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/extensions/api/networking_private/networking_private_li
nux.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/callback.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/strings/string16.h" | |
12 #include "base/strings/string_split.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "base/threading/sequenced_worker_pool.h" | |
15 #include "chrome/browser/extensions/api/networking_private/network_config_dbus_c
onstants_linux.h" | |
16 #include "chrome/browser/extensions/api/networking_private/networking_private_ap
i.h" | |
17 #include "chrome/browser/extensions/api/networking_private/networking_private_de
legate_observer.h" | |
18 #include "components/onc/onc_constants.h" | |
19 #include "content/public/browser/browser_context.h" | |
20 #include "content/public/browser/browser_thread.h" | |
21 #include "dbus/bus.h" | |
22 #include "dbus/message.h" | |
23 #include "dbus/object_path.h" | |
24 #include "dbus/object_proxy.h" | |
25 | |
26 //////////////////////////////////////////////////////////////////////////////// | |
27 | |
28 namespace extensions { | |
29 | |
30 namespace { | |
31 // Access Point info strings. | |
32 const char kAccessPointInfoName[] = "Name"; | |
33 const char kAccessPointInfoGuid[] = "GUID"; | |
34 const char kAccessPointInfoConnectable[] = "Connectable"; | |
35 const char kAccessPointInfoConnectionState[] = "ConnectionState"; | |
36 const char kAccessPointInfoType[] = "Type"; | |
37 const char kAccessPointInfoTypeWifi[] = "WiFi"; | |
38 const char kAccessPointInfoWifiSignalStrengthDotted[] = "WiFi.SignalStrength"; | |
39 const char kAccessPointInfoWifiSecurityDotted[] = "WiFi.Security"; | |
40 | |
41 // Access point security type strings. | |
42 const char kAccessPointSecurityNone[] = "None"; | |
43 const char kAccessPointSecurityUnknown[] = "Unknown"; | |
44 const char kAccessPointSecurityWpaPsk[] = "WPA-PSK"; | |
45 const char kAccessPointSecurity9021X[] = "WEP-8021X"; | |
46 | |
47 // Parses the GUID which contains 3 pieces of relevant information. The | |
48 // object path to the network device, the object path of the access point, | |
49 // and the ssid. | |
50 bool ParseNetworkGuid(const std::string& guid, | |
51 std::string* device_path, | |
52 std::string* access_point_path, | |
53 std::string* ssid) { | |
54 std::vector<std::string> guid_parts; | |
55 | |
56 base::SplitString(guid, '|', &guid_parts); | |
57 | |
58 if (guid_parts.size() != 3) { | |
59 return false; | |
60 } | |
61 | |
62 *device_path = guid_parts[0]; | |
63 *access_point_path = guid_parts[1]; | |
64 *ssid = guid_parts[2]; | |
65 | |
66 if (device_path->empty() || access_point_path->empty() || ssid->empty()) { | |
67 return false; | |
68 } | |
69 | |
70 return true; | |
71 } | |
72 | |
73 // Simplified helper to parse the SSID from the GUID. | |
74 bool GuidToSsid(const std::string& guid, std::string* ssid) { | |
75 std::string unused_1; | |
76 std::string unused_2; | |
77 return ParseNetworkGuid(guid, &unused_1, &unused_2, ssid); | |
78 } | |
79 | |
80 // Iterates over the map cloning the contained networks to a | |
81 // list then returns the list. | |
82 scoped_ptr<base::ListValue> CopyNetworkMapToList( | |
83 const NetworkingPrivateLinux::NetworkMap& network_map) { | |
84 scoped_ptr<base::ListValue> network_list(new base::ListValue); | |
85 | |
86 for (const auto& network : network_map) { | |
87 network_list->Append(network.second->DeepCopy()); | |
88 } | |
89 | |
90 return network_list.Pass(); | |
91 } | |
92 | |
93 // Constructs a network guid from its constituent parts. | |
94 std::string ConstructNetworkGuid(const dbus::ObjectPath& device_path, | |
95 const dbus::ObjectPath& access_point_path, | |
96 const std::string& ssid) { | |
97 return device_path.value() + "|" + access_point_path.value() + "|" + ssid; | |
98 } | |
99 | |
100 // Logs that the method is not implemented and reports |kErrorNotSupported| | |
101 // to the failure callback. | |
102 void ReportNotSupported( | |
103 const std::string& method_name, | |
104 const NetworkingPrivateDelegate::FailureCallback& failure_callback) { | |
105 LOG(WARNING) << method_name << " is not supported"; | |
106 failure_callback.Run(extensions::networking_private::kErrorNotSupported); | |
107 } | |
108 | |
109 // Fires the appropriate callback when the network connect operation succeeds | |
110 // or fails. | |
111 void OnNetworkConnectOperationCompleted( | |
112 scoped_ptr<std::string> error, | |
113 const NetworkingPrivateDelegate::VoidCallback& success_callback, | |
114 const NetworkingPrivateDelegate::FailureCallback& failure_callback) { | |
115 if (!error->empty()) { | |
116 failure_callback.Run(*error); | |
117 return; | |
118 } | |
119 success_callback.Run(); | |
120 } | |
121 | |
122 // Fires the appropriate callback when the network properties are returned | |
123 // from the |dbus_thread_|. | |
124 void GetCachedNetworkPropertiesCallback( | |
125 scoped_ptr<std::string> error, | |
126 scoped_ptr<base::DictionaryValue> properties, | |
127 const NetworkingPrivateDelegate::DictionaryCallback& success_callback, | |
128 const NetworkingPrivateDelegate::FailureCallback& failure_callback) { | |
129 if (!error->empty()) { | |
130 failure_callback.Run(*error); | |
131 return; | |
132 } | |
133 success_callback.Run(properties.Pass()); | |
134 } | |
135 | |
136 } // namespace | |
137 | |
138 NetworkingPrivateLinux::NetworkingPrivateLinux( | |
139 content::BrowserContext* browser_context, | |
140 scoped_ptr<VerifyDelegate> verify_delegate) | |
141 : NetworkingPrivateDelegate(verify_delegate.Pass()), | |
142 browser_context_(browser_context), | |
143 dbus_thread_("Networking Private DBus"), | |
144 network_manager_proxy_(NULL) { | |
145 base::Thread::Options thread_options(base::MessageLoop::Type::TYPE_IO, 0); | |
146 | |
147 dbus_thread_.StartWithOptions(thread_options); | |
148 dbus_thread_.task_runner()->PostTask( | |
149 FROM_HERE, | |
150 base::Bind(&NetworkingPrivateLinux::Initialize, base::Unretained(this))); | |
151 } | |
152 | |
153 NetworkingPrivateLinux::~NetworkingPrivateLinux() { | |
154 dbus_thread_.Stop(); | |
155 } | |
156 | |
157 void NetworkingPrivateLinux::AssertOnDBusThread() { | |
158 DCHECK(dbus_task_runner_->RunsTasksOnCurrentThread()); | |
159 } | |
160 | |
161 void NetworkingPrivateLinux::Initialize() { | |
162 dbus_task_runner_ = dbus_thread_.task_runner(); | |
163 // This has to be called after the task runner is initialized. | |
164 AssertOnDBusThread(); | |
165 | |
166 dbus::Bus::Options dbus_options; | |
167 dbus_options.bus_type = dbus::Bus::SYSTEM; | |
168 dbus_options.connection_type = dbus::Bus::PRIVATE; | |
169 dbus_options.dbus_task_runner = dbus_task_runner_; | |
170 | |
171 dbus_ = new dbus::Bus(dbus_options); | |
172 network_manager_proxy_ = dbus_->GetObjectProxy( | |
173 networking_private::kNetworkManagerNamespace, | |
174 dbus::ObjectPath(networking_private::kNetworkManagerPath)); | |
175 | |
176 if (!network_manager_proxy_) { | |
177 LOG(ERROR) << "Platform does not support NetworkManager over DBUS"; | |
178 } | |
179 | |
180 network_map_.reset(new NetworkMap()); | |
181 } | |
182 | |
183 bool NetworkingPrivateLinux::CheckNetworkManagerSupported( | |
184 const FailureCallback& failure_callback) { | |
185 if (!network_manager_proxy_) { | |
186 ReportNotSupported("NetworkManager over DBus", failure_callback); | |
187 return false; | |
188 } | |
189 | |
190 return true; | |
191 } | |
192 | |
193 void NetworkingPrivateLinux::GetProperties( | |
194 const std::string& guid, | |
195 const DictionaryCallback& success_callback, | |
196 const FailureCallback& failure_callback) { | |
197 GetState(guid, success_callback, failure_callback); | |
198 } | |
199 | |
200 void NetworkingPrivateLinux::GetManagedProperties( | |
201 const std::string& guid, | |
202 const DictionaryCallback& success_callback, | |
203 const FailureCallback& failure_callback) { | |
204 ReportNotSupported("GetManagedProperties", failure_callback); | |
205 } | |
206 | |
207 void NetworkingPrivateLinux::GetState( | |
208 const std::string& guid, | |
209 const DictionaryCallback& success_callback, | |
210 const FailureCallback& failure_callback) { | |
211 if (!CheckNetworkManagerSupported(failure_callback)) | |
212 return; | |
213 | |
214 scoped_ptr<std::string> error(new std::string); | |
215 scoped_ptr<base::DictionaryValue> network_properties( | |
216 new base::DictionaryValue); | |
217 | |
218 // Runs GetCachedNetworkProperties on |dbus_thread|. | |
219 dbus_thread_.task_runner()->PostTaskAndReply( | |
220 FROM_HERE, base::Bind(&NetworkingPrivateLinux::GetCachedNetworkProperties, | |
221 base::Unretained(this), guid, | |
222 base::Unretained(network_properties.get()), | |
223 base::Unretained(error.get())), | |
224 base::Bind(&GetCachedNetworkPropertiesCallback, base::Passed(&error), | |
225 base::Passed(&network_properties), success_callback, | |
226 failure_callback)); | |
227 } | |
228 | |
229 void NetworkingPrivateLinux::GetCachedNetworkProperties( | |
230 const std::string& guid, | |
231 base::DictionaryValue* properties, | |
232 std::string* error) { | |
233 AssertOnDBusThread(); | |
234 std::string ssid; | |
235 | |
236 if (!GuidToSsid(guid, &ssid)) { | |
237 *error = "Invalid Network GUID format"; | |
238 return; | |
239 } | |
240 | |
241 NetworkMap::const_iterator network_iter = | |
242 network_map_->find(base::UTF8ToUTF16(ssid)); | |
243 if (network_iter == network_map_->end()) { | |
244 *error = "Unknown network GUID"; | |
245 return; | |
246 } | |
247 | |
248 // Make a copy of the properties out of the cached map. | |
249 scoped_ptr<base::DictionaryValue> temp_properties( | |
250 network_iter->second->DeepCopy()); | |
251 | |
252 // Swap the new copy into the dictionary that is shared with the reply. | |
253 properties->Swap(temp_properties.get()); | |
254 } | |
255 | |
256 void NetworkingPrivateLinux::SetProperties( | |
257 const std::string& guid, | |
258 scoped_ptr<base::DictionaryValue> properties, | |
259 const VoidCallback& success_callback, | |
260 const FailureCallback& failure_callback) { | |
261 ReportNotSupported("SetProperties", failure_callback); | |
262 } | |
263 | |
264 void NetworkingPrivateLinux::CreateNetwork( | |
265 bool shared, | |
266 scoped_ptr<base::DictionaryValue> properties, | |
267 const StringCallback& success_callback, | |
268 const FailureCallback& failure_callback) { | |
269 ReportNotSupported("CreateNetwork", failure_callback); | |
270 } | |
271 | |
272 void NetworkingPrivateLinux::GetNetworks( | |
273 const std::string& network_type, | |
274 bool configured_only, | |
275 bool visible_only, | |
276 int limit, | |
277 const NetworkListCallback& success_callback, | |
278 const FailureCallback& failure_callback) { | |
279 if (!CheckNetworkManagerSupported(failure_callback)) { | |
280 return; | |
281 } | |
282 | |
283 scoped_ptr<NetworkMap> network_map(new NetworkMap); | |
284 | |
285 if (!(network_type == ::onc::network_type::kWiFi || | |
286 network_type == ::onc::network_type::kWireless || | |
287 network_type == ::onc::network_type::kAllTypes)) { | |
288 // Only enumerating WiFi networks is supported on linux. | |
289 ReportNotSupported("GetNetworks with network_type=" + network_type, | |
290 failure_callback); | |
291 return; | |
292 } | |
293 | |
294 // Runs GetAllWiFiAccessPoints on the dbus_thread and returns the | |
295 // results back to OnAccessPointsFound where the callback is fired. | |
296 dbus_thread_.task_runner()->PostTaskAndReply( | |
297 FROM_HERE, | |
298 base::Bind(&NetworkingPrivateLinux::GetAllWiFiAccessPoints, | |
299 base::Unretained(this), configured_only, visible_only, limit, | |
300 base::Unretained(network_map.get())), | |
301 base::Bind(&NetworkingPrivateLinux::OnAccessPointsFound, | |
302 base::Unretained(this), base::Passed(&network_map), | |
303 success_callback, failure_callback)); | |
304 } | |
305 | |
306 bool NetworkingPrivateLinux::GetNetworksForScanRequest() { | |
307 if (!network_manager_proxy_) { | |
308 return false; | |
309 } | |
310 | |
311 scoped_ptr<NetworkMap> network_map(new NetworkMap); | |
312 | |
313 // Runs GetAllWiFiAccessPoints on the dbus_thread and returns the | |
314 // results back to SendNetworkListChangedEvent to fire the event. No | |
315 // callbacks are used in this case. | |
316 dbus_thread_.task_runner()->PostTaskAndReply( | |
317 FROM_HERE, base::Bind(&NetworkingPrivateLinux::GetAllWiFiAccessPoints, | |
318 base::Unretained(this), false /* configured_only */, | |
319 false /* visible_only */, 0 /* limit */, | |
320 base::Unretained(network_map.get())), | |
321 base::Bind(&NetworkingPrivateLinux::OnAccessPointsFoundViaScan, | |
322 base::Unretained(this), base::Passed(&network_map))); | |
323 | |
324 return true; | |
325 } | |
326 | |
327 // Constructs the network configuration message and connects to the network. | |
328 // The message is of the form: | |
329 // { | |
330 // '802-11-wireless': { | |
331 // 'ssid': 'FooNetwork' | |
332 // } | |
333 // } | |
334 void NetworkingPrivateLinux::ConnectToNetwork(const std::string& guid, | |
335 std::string* error) { | |
336 AssertOnDBusThread(); | |
337 std::string device_path_str; | |
338 std::string access_point_path_str; | |
339 std::string ssid; | |
340 DVLOG(1) << "Connecting to network GUID " << guid; | |
341 | |
342 if (!ParseNetworkGuid(guid, &device_path_str, &access_point_path_str, | |
343 &ssid)) { | |
344 *error = "Invalid Network GUID format"; | |
345 return; | |
346 } | |
347 | |
348 // Set the connection state to connecting in the map. | |
349 if (!SetConnectionStateAndPostEvent(guid, ssid, | |
350 ::onc::connection_state::kConnecting)) { | |
351 *error = "Unknown network GUID"; | |
352 return; | |
353 } | |
354 | |
355 dbus::ObjectPath device_path(device_path_str); | |
356 dbus::ObjectPath access_point_path(access_point_path_str); | |
357 | |
358 dbus::MethodCall method_call( | |
359 networking_private::kNetworkManagerNamespace, | |
360 networking_private::kNetworkManagerAddAndActivateConnectionMethod); | |
361 dbus::MessageWriter builder(&method_call); | |
362 | |
363 // Build up the settings nested dictionary. | |
364 dbus::MessageWriter array_writer(&method_call); | |
365 builder.OpenArray("{sa{sv}}", &array_writer); | |
366 | |
367 dbus::MessageWriter dict_writer(&method_call); | |
368 array_writer.OpenDictEntry(&dict_writer); | |
369 // TODO(zentaro): Support other network types. Currently only WiFi is | |
370 // supported. | |
371 dict_writer.AppendString( | |
372 networking_private::kNetworkManagerConnectionConfig80211Wireless); | |
373 | |
374 dbus::MessageWriter wifi_array(&method_call); | |
375 dict_writer.OpenArray("{sv}", &wifi_array); | |
376 | |
377 dbus::MessageWriter wifi_dict_writer(&method_call); | |
378 wifi_array.OpenDictEntry(&wifi_dict_writer); | |
379 wifi_dict_writer.AppendString( | |
380 networking_private::kNetworkManagerConnectionConfigSsid); | |
381 | |
382 dbus::MessageWriter variant_writer(&method_call); | |
383 wifi_dict_writer.OpenVariant("ay", &variant_writer); | |
384 variant_writer.AppendArrayOfBytes( | |
385 reinterpret_cast<const uint8*>(ssid.c_str()), ssid.size()); | |
386 | |
387 // Close all the arrays and dicts. | |
388 wifi_dict_writer.CloseContainer(&variant_writer); | |
389 wifi_array.CloseContainer(&wifi_dict_writer); | |
390 dict_writer.CloseContainer(&wifi_array); | |
391 array_writer.CloseContainer(&dict_writer); | |
392 builder.CloseContainer(&array_writer); | |
393 | |
394 builder.AppendObjectPath(device_path); | |
395 builder.AppendObjectPath(access_point_path); | |
396 | |
397 scoped_ptr<dbus::Response> response( | |
398 network_manager_proxy_->CallMethodAndBlock( | |
399 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
400 if (!response) { | |
401 LOG(ERROR) << "Failed to add a new connection"; | |
402 *error = "Failed to connect."; | |
403 | |
404 // Set the connection state to NotConnected in the map. | |
405 SetConnectionStateAndPostEvent(guid, ssid, | |
406 ::onc::connection_state::kNotConnected); | |
407 return; | |
408 } | |
409 | |
410 dbus::MessageReader reader(response.get()); | |
411 dbus::ObjectPath connection_settings_path; | |
412 dbus::ObjectPath active_connection_path; | |
413 | |
414 if (!reader.PopObjectPath(&connection_settings_path)) { | |
415 LOG(ERROR) << "Unexpected response for add connection path " | |
416 << ": " << response->ToString(); | |
417 *error = "Failed to connect."; | |
418 | |
419 // Set the connection state to NotConnected in the map. | |
420 SetConnectionStateAndPostEvent(guid, ssid, | |
421 ::onc::connection_state::kNotConnected); | |
422 return; | |
423 } | |
424 | |
425 if (!reader.PopObjectPath(&active_connection_path)) { | |
426 LOG(ERROR) << "Unexpected response for connection path " | |
427 << ": " << response->ToString(); | |
428 *error = "Failed to connect."; | |
429 | |
430 // Set the connection state to NotConnected in the map. | |
431 SetConnectionStateAndPostEvent(guid, ssid, | |
432 ::onc::connection_state::kNotConnected); | |
433 return; | |
434 } | |
435 | |
436 // Set the connection state to Connected in the map. | |
437 SetConnectionStateAndPostEvent(guid, ssid, | |
438 ::onc::connection_state::kConnected); | |
439 return; | |
440 } | |
441 | |
442 void NetworkingPrivateLinux::DisconnectFromNetwork(const std::string& guid, | |
443 std::string* error) { | |
444 AssertOnDBusThread(); | |
445 std::string device_path_str; | |
446 std::string access_point_path_str; | |
447 std::string ssid; | |
448 DVLOG(1) << "Disconnecting from network GUID " << guid; | |
449 | |
450 if (!ParseNetworkGuid(guid, &device_path_str, &access_point_path_str, | |
451 &ssid)) { | |
452 *error = "Invalid Network GUID format"; | |
453 return; | |
454 } | |
455 | |
456 scoped_ptr<NetworkMap> network_map(new NetworkMap); | |
457 GetAllWiFiAccessPoints(false /* configured_only */, false /* visible_only */, | |
458 0 /* limit */, network_map.get()); | |
459 | |
460 NetworkMap::const_iterator network_iter = | |
461 network_map->find(base::UTF8ToUTF16(ssid)); | |
462 if (network_iter == network_map->end()) { | |
463 // This network doesn't exist so there's nothing to do. | |
464 return; | |
465 } | |
466 | |
467 std::string connection_state; | |
468 network_iter->second->GetString(kAccessPointInfoConnectionState, | |
469 &connection_state); | |
470 if (connection_state == ::onc::connection_state::kNotConnected) { | |
471 // Already disconnected so nothing to do. | |
472 return; | |
473 } | |
474 | |
475 // It's not disconnected so disconnect it. | |
476 dbus::ObjectProxy* device_proxy = | |
477 dbus_->GetObjectProxy(networking_private::kNetworkManagerNamespace, | |
478 dbus::ObjectPath(device_path_str)); | |
479 dbus::MethodCall method_call( | |
480 networking_private::kNetworkManagerDeviceNamespace, | |
481 networking_private::kNetworkManagerDisconnectMethod); | |
482 scoped_ptr<dbus::Response> response(device_proxy->CallMethodAndBlock( | |
483 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
484 | |
485 if (!response) { | |
486 LOG(WARNING) << "Failed to disconnect network on device " | |
487 << device_path_str; | |
488 *error = "Failed to disconnect network"; | |
489 } | |
490 } | |
491 | |
492 void NetworkingPrivateLinux::StartConnect( | |
493 const std::string& guid, | |
494 const VoidCallback& success_callback, | |
495 const FailureCallback& failure_callback) { | |
496 if (!CheckNetworkManagerSupported(failure_callback)) | |
497 return; | |
498 | |
499 scoped_ptr<std::string> error(new std::string); | |
500 | |
501 // Runs ConnectToNetwork on |dbus_thread|. | |
502 dbus_thread_.task_runner()->PostTaskAndReply( | |
503 FROM_HERE, | |
504 base::Bind(&NetworkingPrivateLinux::ConnectToNetwork, | |
505 base::Unretained(this), guid, base::Unretained(error.get())), | |
506 base::Bind(&OnNetworkConnectOperationCompleted, base::Passed(&error), | |
507 success_callback, failure_callback)); | |
508 } | |
509 | |
510 void NetworkingPrivateLinux::StartDisconnect( | |
511 const std::string& guid, | |
512 const VoidCallback& success_callback, | |
513 const FailureCallback& failure_callback) { | |
514 if (!CheckNetworkManagerSupported(failure_callback)) | |
515 return; | |
516 | |
517 scoped_ptr<std::string> error(new std::string); | |
518 | |
519 // Runs DisconnectFromNetwork on |dbus_thread|. | |
520 dbus_thread_.task_runner()->PostTaskAndReply( | |
521 FROM_HERE, | |
522 base::Bind(&NetworkingPrivateLinux::DisconnectFromNetwork, | |
523 base::Unretained(this), guid, base::Unretained(error.get())), | |
524 base::Bind(&OnNetworkConnectOperationCompleted, base::Passed(&error), | |
525 success_callback, failure_callback)); | |
526 } | |
527 | |
528 void NetworkingPrivateLinux::SetWifiTDLSEnabledState( | |
529 const std::string& ip_or_mac_address, | |
530 bool enabled, | |
531 const StringCallback& success_callback, | |
532 const FailureCallback& failure_callback) { | |
533 ReportNotSupported("SetWifiTDLSEnabledState", failure_callback); | |
534 } | |
535 | |
536 void NetworkingPrivateLinux::GetWifiTDLSStatus( | |
537 const std::string& ip_or_mac_address, | |
538 const StringCallback& success_callback, | |
539 const FailureCallback& failure_callback) { | |
540 ReportNotSupported("GetWifiTDLSStatus", failure_callback); | |
541 } | |
542 | |
543 void NetworkingPrivateLinux::GetCaptivePortalStatus( | |
544 const std::string& guid, | |
545 const StringCallback& success_callback, | |
546 const FailureCallback& failure_callback) { | |
547 ReportNotSupported("GetCaptivePortalStatus", failure_callback); | |
548 } | |
549 | |
550 scoped_ptr<base::ListValue> NetworkingPrivateLinux::GetEnabledNetworkTypes() { | |
551 scoped_ptr<base::ListValue> network_list(new base::ListValue); | |
552 return network_list.Pass(); | |
553 } | |
554 | |
555 bool NetworkingPrivateLinux::EnableNetworkType(const std::string& type) { | |
556 return false; | |
557 } | |
558 | |
559 bool NetworkingPrivateLinux::DisableNetworkType(const std::string& type) { | |
560 return false; | |
561 } | |
562 | |
563 bool NetworkingPrivateLinux::RequestScan() { | |
564 return GetNetworksForScanRequest(); | |
565 } | |
566 | |
567 void NetworkingPrivateLinux::AddObserver( | |
568 NetworkingPrivateDelegateObserver* observer) { | |
569 network_events_observers_.AddObserver(observer); | |
570 } | |
571 | |
572 void NetworkingPrivateLinux::RemoveObserver( | |
573 NetworkingPrivateDelegateObserver* observer) { | |
574 network_events_observers_.RemoveObserver(observer); | |
575 } | |
576 | |
577 void NetworkingPrivateLinux::OnAccessPointsFound( | |
578 scoped_ptr<NetworkMap> network_map, | |
579 const NetworkListCallback& success_callback, | |
580 const FailureCallback& failure_callback) { | |
581 scoped_ptr<base::ListValue> network_list = CopyNetworkMapToList(*network_map); | |
582 // Give ownership to the member variable. | |
583 network_map_.swap(network_map); | |
584 SendNetworkListChangedEvent(*network_list); | |
585 success_callback.Run(network_list.Pass()); | |
586 } | |
587 | |
588 void NetworkingPrivateLinux::OnAccessPointsFoundViaScan( | |
589 scoped_ptr<NetworkMap> network_map) { | |
590 scoped_ptr<base::ListValue> network_list = CopyNetworkMapToList(*network_map); | |
591 // Give ownership to the member variable. | |
592 network_map_.swap(network_map); | |
593 SendNetworkListChangedEvent(*network_list); | |
594 } | |
595 | |
596 void NetworkingPrivateLinux::SendNetworkListChangedEvent( | |
597 const base::ListValue& network_list) { | |
598 GuidList guidsForEventCallback; | |
599 | |
600 for (const auto& network : network_list) { | |
601 std::string guid; | |
602 base::DictionaryValue* dict; | |
603 if (network->GetAsDictionary(&dict)) { | |
604 if (dict->GetString(kAccessPointInfoGuid, &guid)) { | |
605 guidsForEventCallback.push_back(guid); | |
606 } | |
607 } | |
608 } | |
609 | |
610 OnNetworkListChangedEventOnUIThread(guidsForEventCallback); | |
611 } | |
612 | |
613 bool NetworkingPrivateLinux::GetNetworkDevices( | |
614 std::vector<dbus::ObjectPath>* device_paths) { | |
615 AssertOnDBusThread(); | |
616 dbus::MethodCall method_call( | |
617 networking_private::kNetworkManagerNamespace, | |
618 networking_private::kNetworkManagerGetDevicesMethod); | |
619 | |
620 scoped_ptr<dbus::Response> device_response( | |
621 network_manager_proxy_->CallMethodAndBlock( | |
622 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
623 | |
624 if (!device_response) { | |
625 return false; | |
626 } | |
627 | |
628 dbus::MessageReader reader(device_response.get()); | |
629 if (!reader.PopArrayOfObjectPaths(device_paths)) { | |
630 LOG(WARNING) << "Unexpected response: " << device_response->ToString(); | |
631 return false; | |
632 } | |
633 | |
634 return true; | |
635 } | |
636 | |
637 NetworkingPrivateLinux::DeviceType NetworkingPrivateLinux::GetDeviceType( | |
638 const dbus::ObjectPath& device_path) { | |
639 AssertOnDBusThread(); | |
640 dbus::ObjectProxy* device_proxy = dbus_->GetObjectProxy( | |
641 networking_private::kNetworkManagerNamespace, device_path); | |
642 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
643 networking_private::kNetworkManagerGetMethod); | |
644 dbus::MessageWriter builder(&method_call); | |
645 builder.AppendString(networking_private::kNetworkManagerDeviceNamespace); | |
646 builder.AppendString(networking_private::kNetworkManagerDeviceType); | |
647 | |
648 scoped_ptr<dbus::Response> response(device_proxy->CallMethodAndBlock( | |
649 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
650 | |
651 if (!response) { | |
652 LOG(ERROR) << "Failed to get the device type for device " | |
653 << device_path.value(); | |
654 return NetworkingPrivateLinux::NM_DEVICE_TYPE_UNKNOWN; | |
655 } | |
656 | |
657 dbus::MessageReader reader(response.get()); | |
658 uint32 device_type = 0; | |
659 if (!reader.PopVariantOfUint32(&device_type)) { | |
660 LOG(ERROR) << "Unexpected response for device " << device_type << ": " | |
661 << response->ToString(); | |
662 return NM_DEVICE_TYPE_UNKNOWN; | |
663 } | |
664 | |
665 return static_cast<NetworkingPrivateLinux::DeviceType>(device_type); | |
666 } | |
667 | |
668 void NetworkingPrivateLinux::GetAllWiFiAccessPoints(bool configured_only, | |
669 bool visible_only, | |
670 int limit, | |
671 NetworkMap* network_map) { | |
672 AssertOnDBusThread(); | |
673 // TODO(zentaro): The filters are not implemented and are ignored. | |
674 std::vector<dbus::ObjectPath> device_paths; | |
675 if (!GetNetworkDevices(&device_paths)) { | |
676 LOG(ERROR) << "Failed to enumerate network devices"; | |
677 return; | |
678 } | |
679 | |
680 for (const auto& device_path : device_paths) { | |
681 NetworkingPrivateLinux::DeviceType device_type = GetDeviceType(device_path); | |
682 | |
683 // Get the access points for each WiFi adapter. Other network types are | |
684 // ignored. | |
685 if (device_type != NetworkingPrivateLinux::NM_DEVICE_TYPE_WIFI) | |
686 continue; | |
687 | |
688 // Found a wlan adapter | |
689 if (!AddAccessPointsFromDevice(device_path, network_map)) { | |
690 // Ignore devices we can't enumerate. | |
691 LOG(WARNING) << "Failed to add access points from device " | |
692 << device_path.value(); | |
693 } | |
694 } | |
695 } | |
696 | |
697 scoped_ptr<dbus::Response> NetworkingPrivateLinux::GetAccessPointProperty( | |
698 dbus::ObjectProxy* access_point_proxy, | |
699 const std::string& property_name) { | |
700 AssertOnDBusThread(); | |
701 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
702 networking_private::kNetworkManagerGetMethod); | |
703 dbus::MessageWriter builder(&method_call); | |
704 builder.AppendString(networking_private::kNetworkManagerAccessPointNamespace); | |
705 builder.AppendString(property_name); | |
706 scoped_ptr<dbus::Response> response = access_point_proxy->CallMethodAndBlock( | |
707 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); | |
708 if (!response) { | |
709 LOG(ERROR) << "Failed to get property for " << property_name; | |
710 } | |
711 return response.Pass(); | |
712 } | |
713 | |
714 bool NetworkingPrivateLinux::GetAccessPointInfo( | |
715 const dbus::ObjectPath& access_point_path, | |
716 const scoped_ptr<base::DictionaryValue>& access_point_info) { | |
717 AssertOnDBusThread(); | |
718 dbus::ObjectProxy* access_point_proxy = dbus_->GetObjectProxy( | |
719 networking_private::kNetworkManagerNamespace, access_point_path); | |
720 | |
721 // Read the SSID. The GUID is derived from the Ssid. | |
722 { | |
723 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
724 access_point_proxy, networking_private::kNetworkManagerSsidProperty)); | |
725 | |
726 if (!response) { | |
727 return false; | |
728 } | |
729 | |
730 // The response should contain a variant that contains an array of bytes. | |
731 dbus::MessageReader reader(response.get()); | |
732 dbus::MessageReader variant_reader(response.get()); | |
733 if (!reader.PopVariant(&variant_reader)) { | |
734 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
735 << ": " << response->ToString(); | |
736 return false; | |
737 } | |
738 | |
739 const uint8* ssid_bytes = NULL; | |
740 size_t ssid_length = 0; | |
741 if (!variant_reader.PopArrayOfBytes(&ssid_bytes, &ssid_length)) { | |
742 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
743 << ": " << response->ToString(); | |
744 return false; | |
745 } | |
746 | |
747 std::string ssidUTF8(ssid_bytes, ssid_bytes + ssid_length); | |
748 base::string16 ssid = base::UTF8ToUTF16(ssidUTF8); | |
749 | |
750 access_point_info->SetString(kAccessPointInfoName, ssid); | |
751 } | |
752 | |
753 // Read signal strength. | |
754 { | |
755 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
756 access_point_proxy, | |
757 networking_private::kNetworkManagerStrengthProperty)); | |
758 if (!response) { | |
759 return false; | |
760 } | |
761 | |
762 dbus::MessageReader reader(response.get()); | |
763 uint8 strength = 0; | |
764 if (!reader.PopVariantOfByte(&strength)) { | |
765 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
766 << ": " << response->ToString(); | |
767 return false; | |
768 } | |
769 | |
770 access_point_info->SetInteger(kAccessPointInfoWifiSignalStrengthDotted, | |
771 strength); | |
772 } | |
773 | |
774 // Read the security type. This is from the WpaFlags and RsnFlags property | |
775 // which are of the same type and can be OR'd together to find all supported | |
776 // security modes. | |
777 | |
778 uint32 wpa_security_flags = 0; | |
779 { | |
780 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
781 access_point_proxy, | |
782 networking_private::kNetworkManagerWpaFlagsProperty)); | |
783 if (!response) { | |
784 return false; | |
785 } | |
786 | |
787 dbus::MessageReader reader(response.get()); | |
788 | |
789 if (!reader.PopVariantOfUint32(&wpa_security_flags)) { | |
790 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
791 << ": " << response->ToString(); | |
792 return false; | |
793 } | |
794 } | |
795 | |
796 uint32 rsn_security_flags = 0; | |
797 { | |
798 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
799 access_point_proxy, | |
800 networking_private::kNetworkManagerRsnFlagsProperty)); | |
801 if (!response) { | |
802 return false; | |
803 } | |
804 | |
805 dbus::MessageReader reader(response.get()); | |
806 | |
807 if (!reader.PopVariantOfUint32(&rsn_security_flags)) { | |
808 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
809 << ": " << response->ToString(); | |
810 return false; | |
811 } | |
812 } | |
813 | |
814 std::string security; | |
815 MapSecurityFlagsToString(rsn_security_flags | wpa_security_flags, &security); | |
816 access_point_info->SetString(kAccessPointInfoWifiSecurityDotted, security); | |
817 access_point_info->SetString(kAccessPointInfoType, kAccessPointInfoTypeWifi); | |
818 access_point_info->SetBoolean(kAccessPointInfoConnectable, true); | |
819 return true; | |
820 } | |
821 | |
822 bool NetworkingPrivateLinux::AddAccessPointsFromDevice( | |
823 const dbus::ObjectPath& device_path, | |
824 NetworkMap* network_map) { | |
825 AssertOnDBusThread(); | |
826 dbus::ObjectPath connected_access_point; | |
827 if (!GetConnectedAccessPoint(device_path, &connected_access_point)) { | |
828 return false; | |
829 } | |
830 | |
831 dbus::ObjectProxy* device_proxy = dbus_->GetObjectProxy( | |
832 networking_private::kNetworkManagerNamespace, device_path); | |
833 dbus::MethodCall method_call( | |
834 networking_private::kNetworkManagerWirelessDeviceNamespace, | |
835 networking_private::kNetworkManagerGetAccessPointsMethod); | |
836 scoped_ptr<dbus::Response> response(device_proxy->CallMethodAndBlock( | |
837 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
838 | |
839 if (!response) { | |
840 LOG(WARNING) << "Failed to get access points data for " | |
841 << device_path.value(); | |
842 return false; | |
843 } | |
844 | |
845 dbus::MessageReader reader(response.get()); | |
846 std::vector<dbus::ObjectPath> access_point_paths; | |
847 if (!reader.PopArrayOfObjectPaths(&access_point_paths)) { | |
848 LOG(ERROR) << "Unexpected response for " << device_path.value() << ": " | |
849 << response->ToString(); | |
850 return false; | |
851 } | |
852 | |
853 for (const auto& access_point_path : access_point_paths) { | |
854 scoped_ptr<base::DictionaryValue> access_point(new base::DictionaryValue); | |
855 | |
856 if (GetAccessPointInfo(access_point_path, access_point)) { | |
857 std::string connection_state = | |
858 (access_point_path == connected_access_point) | |
859 ? ::onc::connection_state::kConnected | |
860 : ::onc::connection_state::kNotConnected; | |
861 | |
862 access_point->SetString(kAccessPointInfoConnectionState, | |
863 connection_state); | |
864 std::string ssid; | |
865 access_point->GetString(kAccessPointInfoName, &ssid); | |
866 | |
867 std::string network_guid = | |
868 ConstructNetworkGuid(device_path, access_point_path, ssid); | |
869 | |
870 // Adds the network to the map. Since each SSID can actually have multiple | |
871 // access point paths, this consolidates them. If it is already | |
872 // in the map it updates the signal strength and GUID paths if this | |
873 // network is stronger or the one that is connected. | |
874 AddOrUpdateAccessPoint(network_map, network_guid, access_point); | |
875 } | |
876 } | |
877 | |
878 return true; | |
879 } | |
880 | |
881 void NetworkingPrivateLinux::AddOrUpdateAccessPoint( | |
882 NetworkMap* network_map, | |
883 const std::string& network_guid, | |
884 scoped_ptr<base::DictionaryValue>& access_point) { | |
885 base::string16 ssid; | |
886 std::string connection_state; | |
887 int signal_strength; | |
888 | |
889 access_point->GetString(kAccessPointInfoConnectionState, &connection_state); | |
890 access_point->GetInteger(kAccessPointInfoWifiSignalStrengthDotted, | |
891 &signal_strength); | |
892 access_point->GetString(kAccessPointInfoName, &ssid); | |
893 access_point->SetString(kAccessPointInfoGuid, network_guid); | |
894 | |
895 NetworkMap::iterator existing_access_point_iter = network_map->find(ssid); | |
896 | |
897 if (existing_access_point_iter == network_map->end()) { | |
898 // Unseen access point. Add it to the map. | |
899 network_map->insert(NetworkMap::value_type( | |
900 ssid, linked_ptr<base::DictionaryValue>(access_point.release()))); | |
901 } else { | |
902 // Already seen access point. Update the record if this is the connected | |
903 // record or if the signal strength is higher. But don't override a weaker | |
904 // access point if that is the one that is connected. | |
905 int existing_signal_strength; | |
906 linked_ptr<base::DictionaryValue>& existing_access_point = | |
907 existing_access_point_iter->second; | |
908 existing_access_point->GetInteger(kAccessPointInfoWifiSignalStrengthDotted, | |
909 &existing_signal_strength); | |
910 | |
911 std::string existing_connection_state; | |
912 existing_access_point->GetString(kAccessPointInfoConnectionState, | |
913 &existing_connection_state); | |
914 | |
915 if ((connection_state == ::onc::connection_state::kConnected) || | |
916 (!(existing_connection_state == ::onc::connection_state::kConnected) && | |
917 signal_strength > existing_signal_strength)) { | |
918 existing_access_point->SetString(kAccessPointInfoConnectionState, | |
919 connection_state); | |
920 existing_access_point->SetInteger( | |
921 kAccessPointInfoWifiSignalStrengthDotted, signal_strength); | |
922 existing_access_point->SetString(kAccessPointInfoGuid, network_guid); | |
923 } | |
924 } | |
925 } | |
926 | |
927 void NetworkingPrivateLinux::MapSecurityFlagsToString(uint32 security_flags, | |
928 std::string* security) { | |
929 // Valid values are None, WEP-PSK, WEP-8021X, WPA-PSK, WPA-EAP | |
930 if (security_flags == NetworkingPrivateLinux::NM_802_11_AP_SEC_NONE) { | |
931 *security = kAccessPointSecurityNone; | |
932 } else if (security_flags & | |
933 NetworkingPrivateLinux::NM_802_11_AP_SEC_KEY_MGMT_PSK) { | |
934 *security = kAccessPointSecurityWpaPsk; | |
935 } else if (security_flags & | |
936 NetworkingPrivateLinux::NM_802_11_AP_SEC_KEY_MGMT_802_1X) { | |
937 *security = kAccessPointSecurity9021X; | |
938 } else { | |
939 DVLOG(1) << "Security flag mapping is missing. Found " << security_flags; | |
940 *security = kAccessPointSecurityUnknown; | |
941 } | |
942 | |
943 DVLOG(1) << "Network security setting " << *security; | |
944 } | |
945 | |
946 bool NetworkingPrivateLinux::GetConnectedAccessPoint( | |
947 dbus::ObjectPath device_path, | |
948 dbus::ObjectPath* access_point_path) { | |
949 AssertOnDBusThread(); | |
950 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
951 networking_private::kNetworkManagerGetMethod); | |
952 dbus::MessageWriter builder(&method_call); | |
953 builder.AppendString(networking_private::kNetworkManagerNamespace); | |
954 builder.AppendString(networking_private::kNetworkManagerActiveConnections); | |
955 | |
956 scoped_ptr<dbus::Response> response( | |
957 network_manager_proxy_->CallMethodAndBlock( | |
958 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
959 | |
960 if (!response) { | |
961 LOG(WARNING) << "Failed to get a list of active connections"; | |
962 return false; | |
963 } | |
964 | |
965 dbus::MessageReader reader(response.get()); | |
966 dbus::MessageReader variant_reader(response.get()); | |
967 if (!reader.PopVariant(&variant_reader)) { | |
968 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
969 return false; | |
970 } | |
971 | |
972 std::vector<dbus::ObjectPath> connection_paths; | |
973 if (!variant_reader.PopArrayOfObjectPaths(&connection_paths)) { | |
974 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
975 return false; | |
976 } | |
977 | |
978 for (const auto& connection_path : connection_paths) { | |
979 dbus::ObjectPath connections_device_path; | |
980 if (!GetDeviceOfConnection(connection_path, &connections_device_path)) { | |
981 return false; | |
982 } | |
983 | |
984 if (connections_device_path == device_path) { | |
985 if (!GetAccessPointForConnection(connection_path, access_point_path)) { | |
986 return false; | |
987 } | |
988 | |
989 break; | |
990 } | |
991 } | |
992 | |
993 return true; | |
994 } | |
995 | |
996 bool NetworkingPrivateLinux::GetDeviceOfConnection( | |
997 dbus::ObjectPath connection_path, | |
998 dbus::ObjectPath* device_path) { | |
999 AssertOnDBusThread(); | |
1000 dbus::ObjectProxy* connection_proxy = dbus_->GetObjectProxy( | |
1001 networking_private::kNetworkManagerNamespace, connection_path); | |
1002 | |
1003 if (!connection_proxy) { | |
1004 return false; | |
1005 } | |
1006 | |
1007 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
1008 networking_private::kNetworkManagerGetMethod); | |
1009 dbus::MessageWriter builder(&method_call); | |
1010 builder.AppendString( | |
1011 networking_private::kNetworkManagerActiveConnectionNamespace); | |
1012 builder.AppendString("Devices"); | |
1013 | |
1014 scoped_ptr<dbus::Response> response(connection_proxy->CallMethodAndBlock( | |
1015 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
1016 | |
1017 if (!response) { | |
1018 LOG(ERROR) << "Failed to get devices"; | |
1019 return false; | |
1020 } | |
1021 | |
1022 dbus::MessageReader reader(response.get()); | |
1023 dbus::MessageReader variant_reader(response.get()); | |
1024 if (!reader.PopVariant(&variant_reader)) { | |
1025 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
1026 return false; | |
1027 } | |
1028 | |
1029 std::vector<dbus::ObjectPath> device_paths; | |
1030 if (!variant_reader.PopArrayOfObjectPaths(&device_paths)) { | |
1031 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
1032 return false; | |
1033 } | |
1034 | |
1035 if (device_paths.size() == 1) { | |
1036 *device_path = device_paths[0]; | |
1037 | |
1038 return true; | |
1039 } | |
1040 | |
1041 return false; | |
1042 } | |
1043 | |
1044 bool NetworkingPrivateLinux::GetAccessPointForConnection( | |
1045 dbus::ObjectPath connection_path, | |
1046 dbus::ObjectPath* access_point_path) { | |
1047 AssertOnDBusThread(); | |
1048 dbus::ObjectProxy* connection_proxy = dbus_->GetObjectProxy( | |
1049 networking_private::kNetworkManagerNamespace, connection_path); | |
1050 | |
1051 if (!connection_proxy) { | |
1052 return false; | |
1053 } | |
1054 | |
1055 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
1056 networking_private::kNetworkManagerGetMethod); | |
1057 dbus::MessageWriter builder(&method_call); | |
1058 builder.AppendString( | |
1059 networking_private::kNetworkManagerActiveConnectionNamespace); | |
1060 builder.AppendString(networking_private::kNetworkManagerSpecificObject); | |
1061 | |
1062 scoped_ptr<dbus::Response> response(connection_proxy->CallMethodAndBlock( | |
1063 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
1064 | |
1065 if (!response) { | |
1066 LOG(WARNING) << "Failed to get access point from active connection"; | |
1067 return false; | |
1068 } | |
1069 | |
1070 dbus::MessageReader reader(response.get()); | |
1071 dbus::MessageReader variant_reader(response.get()); | |
1072 if (!reader.PopVariant(&variant_reader)) { | |
1073 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
1074 return false; | |
1075 } | |
1076 | |
1077 if (!variant_reader.PopObjectPath(access_point_path)) { | |
1078 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
1079 return false; | |
1080 } | |
1081 | |
1082 return true; | |
1083 } | |
1084 | |
1085 bool NetworkingPrivateLinux::SetConnectionStateAndPostEvent( | |
1086 const std::string& guid, | |
1087 const std::string& ssid, | |
1088 const std::string& connection_state) { | |
1089 AssertOnDBusThread(); | |
1090 | |
1091 NetworkMap::iterator network_iter = | |
1092 network_map_->find(base::UTF8ToUTF16(ssid)); | |
1093 if (network_iter == network_map_->end()) { | |
1094 return false; | |
1095 } | |
1096 | |
1097 DVLOG(1) << "Setting connection state of " << ssid << " to " | |
1098 << connection_state; | |
1099 | |
1100 // If setting this network to connected, find the previously connected network | |
1101 // and disconnect that one. Also retain the guid of that network to fire a | |
1102 // changed event. | |
1103 std::string connected_network_guid; | |
1104 if (connection_state == ::onc::connection_state::kConnected) { | |
1105 for (auto& network : *network_map_) { | |
1106 std::string other_connection_state; | |
1107 if (network.second->GetString(kAccessPointInfoConnectionState, | |
1108 &other_connection_state)) { | |
1109 if (other_connection_state == ::onc::connection_state::kConnected) { | |
1110 network.second->GetString(kAccessPointInfoGuid, | |
1111 &connected_network_guid); | |
1112 network.second->SetString(kAccessPointInfoConnectionState, | |
1113 ::onc::connection_state::kNotConnected); | |
1114 } | |
1115 } | |
1116 } | |
1117 } | |
1118 | |
1119 // Set the status. | |
1120 network_iter->second->SetString(kAccessPointInfoConnectionState, | |
1121 connection_state); | |
1122 | |
1123 scoped_ptr<GuidList> changed_networks(new GuidList()); | |
1124 changed_networks->push_back(guid); | |
1125 | |
1126 // Only add a second network if it exists and it is not the same as the | |
1127 // network already being added to the list. | |
1128 if (!connected_network_guid.empty() && connected_network_guid != guid) { | |
1129 changed_networks->push_back(connected_network_guid); | |
1130 } | |
1131 | |
1132 PostOnNetworksChangedToUIThread(changed_networks.Pass()); | |
1133 return true; | |
1134 } | |
1135 | |
1136 void NetworkingPrivateLinux::OnNetworksChangedEventOnUIThread( | |
1137 const GuidList& network_guids) { | |
1138 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
1139 FOR_EACH_OBSERVER(NetworkingPrivateDelegateObserver, | |
1140 network_events_observers_, | |
1141 OnNetworksChangedEvent(network_guids)); | |
1142 } | |
1143 | |
1144 void NetworkingPrivateLinux::OnNetworkListChangedEventOnUIThread( | |
1145 const GuidList& network_guids) { | |
1146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
1147 FOR_EACH_OBSERVER(NetworkingPrivateDelegateObserver, | |
1148 network_events_observers_, | |
1149 OnNetworkListChangedEvent(network_guids)); | |
1150 } | |
1151 | |
1152 void NetworkingPrivateLinux::PostOnNetworksChangedToUIThread( | |
1153 scoped_ptr<GuidList> guid_list) { | |
1154 AssertOnDBusThread(); | |
1155 | |
1156 content::BrowserThread::PostTask( | |
1157 content::BrowserThread::UI, FROM_HERE, | |
1158 base::Bind(&NetworkingPrivateLinux::OnNetworksChangedEventTask, | |
1159 base::Unretained(this), base::Passed(&guid_list))); | |
1160 } | |
1161 | |
1162 void NetworkingPrivateLinux::OnNetworksChangedEventTask( | |
1163 scoped_ptr<GuidList> guid_list) { | |
1164 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
1165 OnNetworksChangedEventOnUIThread(*guid_list); | |
1166 } | |
1167 | |
1168 } // namespace extensions | |
OLD | NEW |