1 // Copyright (c) 2012 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 "chromeos/network/shill_property_handler.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <sstream>
11
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/format_macros.h"
15 #include "base/macros.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h"
18 #include "base/values.h"
19 #include "chromeos/dbus/shill/shill_device_client.h"
20 #include "chromeos/dbus/shill/shill_ipconfig_client.h"
21 #include "chromeos/dbus/shill/shill_manager_client.h"
22 #include "chromeos/dbus/shill/shill_profile_client.h"
23 #include "chromeos/dbus/shill/shill_service_client.h"
24 #include "chromeos/network/network_event_log.h"
25 #include "chromeos/network/network_state.h"
26 #include "dbus/object_path.h"
27 #include "third_party/cros_system_api/dbus/service_constants.h"
28
29 namespace {
30
31 // Limit the number of services or devices we observe. Since they are listed in
32 // priority order, it should be reasonable to ignore services past this.
33 const size_t kMaxObserved = 100;
34
GetListValue(const std::string & key,const base::Value & value)35 const base::ListValue* GetListValue(const std::string& key,
36 const base::Value& value) {
37 const base::ListValue* vlist = nullptr;
38 if (!value.GetAsList(&vlist)) {
39 NET_LOG(ERROR) << "Error parsing key as list: " << key;
40 return nullptr;
41 }
42 return vlist;
43 }
44
45 } // namespace
46
47 namespace chromeos {
48 namespace internal {
49
50 // Class to manage Shill service property changed observers. Observers are
51 // added on construction and removed on destruction. Runs the handler when
52 // OnPropertyChanged is called.
53 class ShillPropertyObserver : public ShillPropertyChangedObserver {
54 public:
55 using Handler = base::RepeatingCallback<void(ManagedState::ManagedType type,
56 const std::string& service,
57 const std::string& name,
58 const base::Value& value)>;
59
ShillPropertyObserver(ManagedState::ManagedType type,const std::string & path,const Handler & handler)60 ShillPropertyObserver(ManagedState::ManagedType type,
61 const std::string& path,
62 const Handler& handler)
63 : type_(type), path_(path), handler_(handler) {
64 switch (type_) {
65 case ManagedState::MANAGED_TYPE_NETWORK:
66 DVLOG(2) << "ShillPropertyObserver: Network: " << path;
67 ShillServiceClient::Get()->AddPropertyChangedObserver(
68 dbus::ObjectPath(path_), this);
69 break;
70 case ManagedState::MANAGED_TYPE_DEVICE:
71 DVLOG(2) << "ShillPropertyObserver: Device: " << path;
72 ShillDeviceClient::Get()->AddPropertyChangedObserver(
73 dbus::ObjectPath(path_), this);
74 break;
75 }
76 }
77
~ShillPropertyObserver()78 ~ShillPropertyObserver() override {
79 switch (type_) {
80 case ManagedState::MANAGED_TYPE_NETWORK:
81 ShillServiceClient::Get()->RemovePropertyChangedObserver(
82 dbus::ObjectPath(path_), this);
83 break;
84 case ManagedState::MANAGED_TYPE_DEVICE:
85 ShillDeviceClient::Get()->RemovePropertyChangedObserver(
86 dbus::ObjectPath(path_), this);
87 break;
88 }
89 }
90
91 // ShillPropertyChangedObserver overrides.
OnPropertyChanged(const std::string & key,const base::Value & value)92 void OnPropertyChanged(const std::string& key,
93 const base::Value& value) override {
94 handler_.Run(type_, path_, key, value);
95 }
96
97 private:
98 ManagedState::ManagedType type_;
99 std::string path_;
100 Handler handler_;
101
102 DISALLOW_COPY_AND_ASSIGN(ShillPropertyObserver);
103 };
104
105 //------------------------------------------------------------------------------
106 // ShillPropertyHandler
107
ShillPropertyHandler(Listener * listener)108 ShillPropertyHandler::ShillPropertyHandler(Listener* listener)
109 : listener_(listener), shill_manager_(ShillManagerClient::Get()) {}
110
~ShillPropertyHandler()111 ShillPropertyHandler::~ShillPropertyHandler() {
112 // Delete network service observers.
113 CHECK(shill_manager_ == ShillManagerClient::Get());
114 shill_manager_->RemovePropertyChangedObserver(this);
115 }
116
Init()117 void ShillPropertyHandler::Init() {
118 UpdateManagerProperties();
119 shill_manager_->AddPropertyChangedObserver(this);
120 }
121
UpdateManagerProperties()122 void ShillPropertyHandler::UpdateManagerProperties() {
123 NET_LOG(EVENT) << "UpdateManagerProperties";
124 shill_manager_->GetProperties(base::BindOnce(
125 &ShillPropertyHandler::ManagerPropertiesCallback, AsWeakPtr()));
126 }
127
IsTechnologyAvailable(const std::string & technology) const128 bool ShillPropertyHandler::IsTechnologyAvailable(
129 const std::string& technology) const {
130 return available_technologies_.count(technology) != 0;
131 }
132
IsTechnologyEnabled(const std::string & technology) const133 bool ShillPropertyHandler::IsTechnologyEnabled(
134 const std::string& technology) const {
135 return enabled_technologies_.count(technology) != 0;
136 }
137
IsTechnologyEnabling(const std::string & technology) const138 bool ShillPropertyHandler::IsTechnologyEnabling(
139 const std::string& technology) const {
140 return enabling_technologies_.count(technology) != 0;
141 }
142
IsTechnologyDisabling(const std::string & technology) const143 bool ShillPropertyHandler::IsTechnologyDisabling(
144 const std::string& technology) const {
145 return disabling_technologies_.count(technology) != 0;
146 }
147
IsTechnologyProhibited(const std::string & technology) const148 bool ShillPropertyHandler::IsTechnologyProhibited(
149 const std::string& technology) const {
150 return prohibited_technologies_.count(technology) != 0;
151 }
152
IsTechnologyUninitialized(const std::string & technology) const153 bool ShillPropertyHandler::IsTechnologyUninitialized(
154 const std::string& technology) const {
155 return uninitialized_technologies_.count(technology) != 0;
156 }
157
SetTechnologyEnabled(const std::string & technology,bool enabled,network_handler::ErrorCallback error_callback)158 void ShillPropertyHandler::SetTechnologyEnabled(
159 const std::string& technology,
160 bool enabled,
161 network_handler::ErrorCallback error_callback) {
162 if (enabled) {
163 if (prohibited_technologies_.find(technology) !=
164 prohibited_technologies_.end()) {
165 chromeos::network_handler::RunErrorCallback(
166 std::move(error_callback), "", "prohibited_technologies",
167 "Ignored: Attempt to enable prohibited network technology " +
168 technology);
169 return;
170 }
171 enabling_technologies_.insert(technology);
172 disabling_technologies_.erase(technology);
173 shill_manager_->EnableTechnology(
174 technology, base::DoNothing(),
175 base::BindOnce(&ShillPropertyHandler::EnableTechnologyFailed,
176 AsWeakPtr(), technology, std::move(error_callback)));
177 } else {
178 // Clear locally from enabling lists and add to the disabling list.
179 enabling_technologies_.erase(technology);
180 disabling_technologies_.insert(technology);
181 shill_manager_->DisableTechnology(
182 technology, base::DoNothing(),
183 base::BindOnce(&ShillPropertyHandler::DisableTechnologyFailed,
184 AsWeakPtr(), technology, std::move(error_callback)));
185 }
186 }
187
SetProhibitedTechnologies(const std::vector<std::string> & prohibited_technologies)188 void ShillPropertyHandler::SetProhibitedTechnologies(
189 const std::vector<std::string>& prohibited_technologies) {
190 prohibited_technologies_.clear();
191 prohibited_technologies_.insert(prohibited_technologies.begin(),
192 prohibited_technologies.end());
193
194 // Remove technologies from the other lists.
195 // And manually disable them.
196 for (const auto& technology : prohibited_technologies) {
197 enabling_technologies_.erase(technology);
198 enabled_technologies_.erase(technology);
199 shill_manager_->DisableTechnology(
200 technology, base::DoNothing(),
201 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
202 "DisableTechnology Failed", technology,
203 network_handler::ErrorCallback()));
204 }
205
206 // Send updated prohibited technology list to shill.
207 const std::string prohibited_list =
208 base::JoinString(prohibited_technologies, ",");
209 base::Value value(prohibited_list);
210 shill_manager_->SetProperty(
211 "ProhibitedTechnologies", value, base::DoNothing(),
212 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
213 "SetTechnologiesProhibited Failed", prohibited_list,
214 network_handler::ErrorCallback()));
215 }
216
SetCheckPortalList(const std::string & check_portal_list)217 void ShillPropertyHandler::SetCheckPortalList(
218 const std::string& check_portal_list) {
219 base::Value value(check_portal_list);
220 shill_manager_->SetProperty(
221 shill::kCheckPortalListProperty, value, base::DoNothing(),
222 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
223 "SetCheckPortalList Failed", "Manager",
224 network_handler::ErrorCallback()));
225 }
226
SetWakeOnLanEnabled(bool enabled)227 void ShillPropertyHandler::SetWakeOnLanEnabled(bool enabled) {
228 base::Value value(enabled);
229 shill_manager_->SetProperty(
230 shill::kWakeOnLanEnabledProperty, value, base::DoNothing(),
231 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
232 "SetWakeOnLanEnabled Failed", "Manager",
233 network_handler::ErrorCallback()));
234 }
235
SetHostname(const std::string & hostname)236 void ShillPropertyHandler::SetHostname(const std::string& hostname) {
237 base::Value value(hostname);
238 shill_manager_->SetProperty(
239 shill::kDhcpPropertyHostnameProperty, value, base::DoNothing(),
240 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
241 "SetHostname Failed", "Manager",
242 network_handler::ErrorCallback()));
243 }
244
SetNetworkThrottlingStatus(bool throttling_enabled,uint32_t upload_rate_kbits,uint32_t download_rate_kbits)245 void ShillPropertyHandler::SetNetworkThrottlingStatus(
246 bool throttling_enabled,
247 uint32_t upload_rate_kbits,
248 uint32_t download_rate_kbits) {
249 shill_manager_->SetNetworkThrottlingStatus(
250 ShillManagerClient::NetworkThrottlingStatus{
251 throttling_enabled,
252 upload_rate_kbits,
253 download_rate_kbits,
254 },
255 base::DoNothing(),
256 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
257 "SetNetworkThrottlingStatus failed", "Manager",
258 network_handler::ErrorCallback()));
259 }
260
SetFastTransitionStatus(bool enabled)261 void ShillPropertyHandler::SetFastTransitionStatus(bool enabled) {
262 base::Value value(enabled);
263 shill_manager_->SetProperty(
264 shill::kWifiGlobalFTEnabledProperty, value, base::DoNothing(),
265 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
266 "SetFastTransitionStatus failed", "Manager",
267 network_handler::ErrorCallback()));
268 }
269
RequestScanByType(const std::string & type) const270 void ShillPropertyHandler::RequestScanByType(const std::string& type) const {
271 shill_manager_->RequestScan(
272 type, base::DoNothing(),
273 base::BindOnce(&network_handler::ShillErrorCallbackFunction,
274 "RequestScan Failed", type,
275 network_handler::ErrorCallback()));
276 }
277
RequestProperties(ManagedState::ManagedType type,const std::string & path)278 void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type,
279 const std::string& path) {
280 if (pending_updates_[type].find(path) != pending_updates_[type].end())
281 return; // Update already requested.
282
283 NET_LOG(DEBUG) << "Request Properties for: " << NetworkPathId(path);
284 pending_updates_[type].insert(path);
285 switch (type) {
286 case ManagedState::MANAGED_TYPE_NETWORK:
287 ShillServiceClient::Get()->GetProperties(
288 dbus::ObjectPath(path),
289 base::BindOnce(&ShillPropertyHandler::GetPropertiesCallback,
290 AsWeakPtr(), type, path));
291 return;
292 case ManagedState::MANAGED_TYPE_DEVICE:
293 ShillDeviceClient::Get()->GetProperties(
294 dbus::ObjectPath(path),
295 base::BindOnce(&ShillPropertyHandler::GetPropertiesCallback,
296 AsWeakPtr(), type, path));
297 return;
298 }
299 NOTREACHED();
300 }
301
OnPropertyChanged(const std::string & key,const base::Value & value)302 void ShillPropertyHandler::OnPropertyChanged(const std::string& key,
303 const base::Value& value) {
304 ManagerPropertyChanged(key, value);
305 CheckPendingStateListUpdates(key);
306 }
307
308 //------------------------------------------------------------------------------
309 // Private methods
310
ManagerPropertiesCallback(base::Optional<base::Value> properties)311 void ShillPropertyHandler::ManagerPropertiesCallback(
312 base::Optional<base::Value> properties) {
313 if (!properties) {
314 NET_LOG(ERROR) << "ManagerPropertiesCallback Failed";
315 return;
316 }
317 NET_LOG(EVENT) << "ManagerPropertiesCallback: Success";
318 for (const auto& item : properties->DictItems()) {
319 ManagerPropertyChanged(item.first, item.second);
320 }
321
322 CheckPendingStateListUpdates("");
323 }
324
CheckPendingStateListUpdates(const std::string & key)325 void ShillPropertyHandler::CheckPendingStateListUpdates(
326 const std::string& key) {
327 // Once there are no pending updates, signal the state list changed
328 // callbacks.
329 if ((key.empty() || key == shill::kServiceCompleteListProperty) &&
330 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0) {
331 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_NETWORK);
332 }
333 if ((key.empty() || key == shill::kDevicesProperty) &&
334 pending_updates_[ManagedState::MANAGED_TYPE_DEVICE].size() == 0) {
335 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_DEVICE);
336 }
337 }
338
ManagerPropertyChanged(const std::string & key,const base::Value & value)339 void ShillPropertyHandler::ManagerPropertyChanged(const std::string& key,
340 const base::Value& value) {
341 if (key == shill::kDefaultServiceProperty) {
342 std::string service_path;
343 value.GetAsString(&service_path);
344 NET_LOG(EVENT) << "Manager.DefaultService = "
345 << NetworkPathId(service_path);
346 listener_->DefaultNetworkServiceChanged(service_path);
347 return;
348 }
349 NET_LOG(DEBUG) << "ManagerPropertyChanged: " << key << " = " << value;
350 if (key == shill::kServiceCompleteListProperty) {
351 const base::ListValue* vlist = GetListValue(key, value);
352 if (vlist) {
353 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist);
354 UpdateProperties(ManagedState::MANAGED_TYPE_NETWORK, *vlist);
355 UpdateObserved(ManagedState::MANAGED_TYPE_NETWORK, *vlist);
356 }
357 } else if (key == shill::kDevicesProperty) {
358 const base::ListValue* vlist = GetListValue(key, value);
359 if (vlist) {
360 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist);
361 UpdateProperties(ManagedState::MANAGED_TYPE_DEVICE, *vlist);
362 UpdateObserved(ManagedState::MANAGED_TYPE_DEVICE, *vlist);
363 }
364 } else if (key == shill::kAvailableTechnologiesProperty) {
365 const base::ListValue* vlist = GetListValue(key, value);
366 if (vlist)
367 UpdateAvailableTechnologies(*vlist);
368 } else if (key == shill::kEnabledTechnologiesProperty) {
369 const base::ListValue* vlist = GetListValue(key, value);
370 if (vlist)
371 UpdateEnabledTechnologies(*vlist);
372 } else if (key == shill::kUninitializedTechnologiesProperty) {
373 const base::ListValue* vlist = GetListValue(key, value);
374 if (vlist)
375 UpdateUninitializedTechnologies(*vlist);
376 } else if (key == shill::kProhibitedTechnologiesProperty) {
377 std::string prohibited_technologies;
378 if (value.GetAsString(&prohibited_technologies))
379 UpdateProhibitedTechnologies(prohibited_technologies);
380 } else if (key == shill::kProfilesProperty) {
381 listener_->ProfileListChanged();
382 } else if (key == shill::kCheckPortalListProperty) {
383 std::string check_portal_list;
384 if (value.GetAsString(&check_portal_list))
385 listener_->CheckPortalListChanged(check_portal_list);
386 } else if (key == shill::kDhcpPropertyHostnameProperty) {
387 std::string hostname;
388 if (value.GetAsString(&hostname))
389 listener_->HostnameChanged(hostname);
390 } else {
391 VLOG(2) << "Ignored Manager Property: " << key;
392 }
393 }
394
UpdateProperties(ManagedState::ManagedType type,const base::ListValue & entries)395 void ShillPropertyHandler::UpdateProperties(ManagedState::ManagedType type,
396 const base::ListValue& entries) {
397 std::set<std::string>& requested_updates = requested_updates_[type];
398 std::set<std::string> new_requested_updates;
399 NET_LOG(DEBUG) << "UpdateProperties: " << ManagedState::TypeToString(type)
400 << ": " << entries.GetSize();
401 for (base::ListValue::const_iterator iter = entries.begin();
402 iter != entries.end(); ++iter) {
403 std::string path;
404 iter->GetAsString(&path);
405 if (path.empty())
406 continue;
407
408 // We add a special case for devices here to work around an issue in shill
409 // that prevents it from sending property changed signals for cellular
410 // devices (see crbug.com/321854).
411 if (type == ManagedState::MANAGED_TYPE_DEVICE ||
412 requested_updates.find(path) == requested_updates.end()) {
413 RequestProperties(type, path);
414 }
415 new_requested_updates.insert(path);
416 }
417 requested_updates.swap(new_requested_updates);
418 }
419
UpdateObserved(ManagedState::ManagedType type,const base::ListValue & entries)420 void ShillPropertyHandler::UpdateObserved(ManagedState::ManagedType type,
421 const base::ListValue& entries) {
422 ShillPropertyObserverMap& observer_map =
423 (type == ManagedState::MANAGED_TYPE_NETWORK) ? observed_networks_
424 : observed_devices_;
425 ShillPropertyObserverMap new_observed;
426 for (const auto& entry : entries) {
427 std::string path;
428 entry.GetAsString(&path);
429 if (path.empty())
430 continue;
431 auto iter = observer_map.find(path);
432 std::unique_ptr<ShillPropertyObserver> observer;
433 if (iter != observer_map.end()) {
434 observer = std::move(iter->second);
435 } else {
436 // Create an observer for future updates.
437 observer = std::make_unique<ShillPropertyObserver>(
438 type, path,
439 base::BindRepeating(&ShillPropertyHandler::PropertyChangedCallback,
440 AsWeakPtr()));
441 }
442 auto result =
443 new_observed.insert(std::make_pair(path, std::move(observer)));
444 if (!result.second) {
445 NET_LOG(ERROR) << path << " is duplicated in the list.";
446 }
447 observer_map.erase(path);
448 // Limit the number of observed services.
449 if (new_observed.size() >= kMaxObserved)
450 break;
451 }
452 observer_map.swap(new_observed);
453 }
454
UpdateAvailableTechnologies(const base::ListValue & technologies)455 void ShillPropertyHandler::UpdateAvailableTechnologies(
456 const base::ListValue& technologies) {
457 NET_LOG(EVENT) << "AvailableTechnologies:" << technologies;
458 std::set<std::string> new_available_technologies;
459 for (const base::Value& technology : technologies.GetList())
460 new_available_technologies.insert(technology.GetString());
461 if (new_available_technologies == available_technologies_)
462 return;
463 available_technologies_.swap(new_available_technologies);
464 // If any entries in |enabling_technologies_| are no longer available,
465 // remove them from the enabling list.
466 for (auto iter = enabling_technologies_.begin();
467 iter != enabling_technologies_.end();) {
468 if (!available_technologies_.count(*iter))
469 iter = enabling_technologies_.erase(iter);
470 else
471 ++iter;
472 }
473 listener_->TechnologyListChanged();
474 }
475
UpdateEnabledTechnologies(const base::ListValue & technologies)476 void ShillPropertyHandler::UpdateEnabledTechnologies(
477 const base::ListValue& technologies) {
478 NET_LOG(EVENT) << "EnabledTechnologies:" << technologies;
479 std::set<std::string> new_enabled_technologies;
480 for (const base::Value& technology : technologies.GetList())
481 new_enabled_technologies.insert(technology.GetString());
482 if (new_enabled_technologies == enabled_technologies_)
483 return;
484 enabled_technologies_.swap(new_enabled_technologies);
485
486 // If any entries in |disabling_technologies_| are disabled, remove them
487 // from the disabling list.
488 for (auto it = disabling_technologies_.begin();
489 it != disabling_technologies_.end();) {
490 base::Value technology_value(*it);
491 if (!base::Contains(technologies.GetList(), technology_value))
492 it = disabling_technologies_.erase(it);
493 else
494 ++it;
495 }
496
497 // If any entries in |enabling_technologies_| are enabled, remove them from
498 // the enabling list.
499 for (auto iter = enabling_technologies_.begin();
500 iter != enabling_technologies_.end();) {
501 if (enabled_technologies_.count(*iter))
502 iter = enabling_technologies_.erase(iter);
503 else
504 ++iter;
505 }
506 listener_->TechnologyListChanged();
507 }
508
UpdateUninitializedTechnologies(const base::ListValue & technologies)509 void ShillPropertyHandler::UpdateUninitializedTechnologies(
510 const base::ListValue& technologies) {
511 NET_LOG(EVENT) << "UninitializedTechnologies:" << technologies;
512 std::set<std::string> new_uninitialized_technologies;
513 for (const base::Value& technology : technologies.GetList())
514 new_uninitialized_technologies.insert(technology.GetString());
515 if (new_uninitialized_technologies == uninitialized_technologies_)
516 return;
517 uninitialized_technologies_.swap(new_uninitialized_technologies);
518 listener_->TechnologyListChanged();
519 }
520
UpdateProhibitedTechnologies(const std::string & technologies)521 void ShillPropertyHandler::UpdateProhibitedTechnologies(
522 const std::string& technologies) {
523 std::vector<std::string> prohibited_list = base::SplitString(
524 technologies, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
525 std::set<std::string> new_prohibited_technologies(prohibited_list.begin(),
526 prohibited_list.end());
527 if (new_prohibited_technologies == prohibited_technologies_)
528 return;
529 prohibited_technologies_.swap(new_prohibited_technologies);
530 listener_->TechnologyListChanged();
531 }
532
EnableTechnologyFailed(const std::string & technology,network_handler::ErrorCallback error_callback,const std::string & dbus_error_name,const std::string & dbus_error_message)533 void ShillPropertyHandler::EnableTechnologyFailed(
534 const std::string& technology,
535 network_handler::ErrorCallback error_callback,
536 const std::string& dbus_error_name,
537 const std::string& dbus_error_message) {
538 enabling_technologies_.erase(technology);
539 network_handler::ShillErrorCallbackFunction(
540 "EnableTechnology Failed", technology, std::move(error_callback),
541 dbus_error_name, dbus_error_message);
542 listener_->TechnologyListChanged();
543 }
544
DisableTechnologyFailed(const std::string & technology,network_handler::ErrorCallback error_callback,const std::string & dbus_error_name,const std::string & dbus_error_message)545 void ShillPropertyHandler::DisableTechnologyFailed(
546 const std::string& technology,
547 network_handler::ErrorCallback error_callback,
548 const std::string& dbus_error_name,
549 const std::string& dbus_error_message) {
550 disabling_technologies_.erase(technology);
551 network_handler::ShillErrorCallbackFunction(
552 "DisableTechnology Failed", technology, std::move(error_callback),
553 dbus_error_name, dbus_error_message);
554 listener_->TechnologyListChanged();
555 }
556
GetPropertiesCallback(ManagedState::ManagedType type,const std::string & path,base::Optional<base::Value> properties)557 void ShillPropertyHandler::GetPropertiesCallback(
558 ManagedState::ManagedType type,
559 const std::string& path,
560 base::Optional<base::Value> properties) {
561 pending_updates_[type].erase(path);
562 if (!properties) {
563 // The shill service no longer exists. This can happen when a network
564 // has been removed.
565 return;
566 }
567 NET_LOG(DEBUG) << "GetProperties received for " << NetworkPathId(path);
568 listener_->UpdateManagedStateProperties(type, path, *properties);
569
570 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
571 // Request IPConfig properties.
572 const base::Value* value = properties->FindKey(shill::kIPConfigProperty);
573 if (value)
574 RequestIPConfig(type, path, *value);
575 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
576 // Clear and request IPConfig properties for each entry in IPConfigs.
577 const base::Value* value = properties->FindKey(shill::kIPConfigsProperty);
578 if (value)
579 RequestIPConfigsList(type, path, *value);
580 }
581
582 // Notify the listener only when all updates for that type have completed.
583 if (pending_updates_[type].size() == 0)
584 listener_->ManagedStateListChanged(type);
585 }
586
PropertyChangedCallback(ManagedState::ManagedType type,const std::string & path,const std::string & key,const base::Value & value)587 void ShillPropertyHandler::PropertyChangedCallback(
588 ManagedState::ManagedType type,
589 const std::string& path,
590 const std::string& key,
591 const base::Value& value) {
592 if (type == ManagedState::MANAGED_TYPE_NETWORK &&
593 key == shill::kIPConfigProperty) {
594 RequestIPConfig(type, path, value);
595 } else if (type == ManagedState::MANAGED_TYPE_DEVICE &&
596 key == shill::kIPConfigsProperty) {
597 RequestIPConfigsList(type, path, value);
598 }
599
600 switch (type) {
601 case ManagedState::MANAGED_TYPE_NETWORK:
602 listener_->UpdateNetworkServiceProperty(path, key, value);
603 return;
604 case ManagedState::MANAGED_TYPE_DEVICE:
605 listener_->UpdateDeviceProperty(path, key, value);
606 return;
607 }
608 NOTREACHED();
609 }
610
RequestIPConfig(ManagedState::ManagedType type,const std::string & path,const base::Value & ip_config_path_value)611 void ShillPropertyHandler::RequestIPConfig(
612 ManagedState::ManagedType type,
613 const std::string& path,
614 const base::Value& ip_config_path_value) {
615 std::string ip_config_path;
616 if (!ip_config_path_value.GetAsString(&ip_config_path) ||
617 ip_config_path.empty()) {
618 NET_LOG(ERROR) << "Invalid IPConfig: " << path;
619 return;
620 }
621 ShillIPConfigClient::Get()->GetProperties(
622 dbus::ObjectPath(ip_config_path),
623 base::BindOnce(&ShillPropertyHandler::GetIPConfigCallback, AsWeakPtr(),
624 type, path, ip_config_path));
625 }
626
RequestIPConfigsList(ManagedState::ManagedType type,const std::string & path,const base::Value & ip_config_list_value)627 void ShillPropertyHandler::RequestIPConfigsList(
628 ManagedState::ManagedType type,
629 const std::string& path,
630 const base::Value& ip_config_list_value) {
631 const base::ListValue* ip_configs;
632 if (!ip_config_list_value.GetAsList(&ip_configs))
633 return;
634 for (base::ListValue::const_iterator iter = ip_configs->begin();
635 iter != ip_configs->end(); ++iter) {
636 RequestIPConfig(type, path, *iter);
637 }
638 }
639
GetIPConfigCallback(ManagedState::ManagedType type,const std::string & path,const std::string & ip_config_path,base::Optional<base::Value> properties)640 void ShillPropertyHandler::GetIPConfigCallback(
641 ManagedState::ManagedType type,
642 const std::string& path,
643 const std::string& ip_config_path,
644 base::Optional<base::Value> properties) {
645 if (!properties) {
646 // IP Config properties not available. Shill will emit a property change
647 // when they are.
648 NET_LOG(EVENT) << "Failed to get IP Config properties: " << ip_config_path
649 << ", For: " << NetworkPathId(path);
650 return;
651 }
652 NET_LOG(EVENT) << "IP Config properties received: " << NetworkPathId(path);
653 listener_->UpdateIPConfigProperties(type, path, ip_config_path, *properties);
654 }
655
656 } // namespace internal
657 } // namespace chromeos
658