1 // Copyright (c) 2013 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.
5 #include "chromeos/network/network_profile_handler.h"
10 #include "base/strings/string_util.h"
11 #include "base/values.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/shill_manager_client.h"
14 #include "chromeos/dbus/shill_profile_client.h"
15 #include "chromeos/network/network_profile_observer.h"
16 #include "dbus/object_path.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
23 bool ConvertListValueToStringVector(const base::ListValue
& string_list
,
24 std::vector
<std::string
>* result
) {
25 for (size_t i
= 0; i
< string_list
.GetSize(); ++i
) {
27 if (!string_list
.GetString(i
, &str
))
29 result
->push_back(str
);
34 void LogProfileRequestError(const std::string
& profile_path
,
35 const std::string
& error_name
,
36 const std::string
& error_message
) {
37 LOG(ERROR
) << "Error when requesting properties for profile "
38 << profile_path
<< ": " << error_message
;
41 class ProfilePathEquals
{
43 explicit ProfilePathEquals(const std::string
& path
)
47 bool operator()(const NetworkProfile
& profile
) {
48 return profile
.path
== path_
;
58 std::string
NetworkProfileHandler::GetSharedProfilePath() {
59 return ShillProfileClient::GetSharedProfilePath();
62 void NetworkProfileHandler::AddObserver(NetworkProfileObserver
* observer
) {
63 observers_
.AddObserver(observer
);
66 void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver
* observer
) {
67 observers_
.RemoveObserver(observer
);
70 void NetworkProfileHandler::GetManagerPropertiesCallback(
71 DBusMethodCallStatus call_status
,
72 const base::DictionaryValue
& properties
) {
73 if (DBUS_METHOD_CALL_FAILURE
) {
74 LOG(ERROR
) << "Error when requesting manager properties.";
78 const base::Value
* profiles
= NULL
;
79 properties
.GetWithoutPathExpansion(shill::kProfilesProperty
, &profiles
);
81 LOG(ERROR
) << "Manager properties returned from Shill don't contain "
82 << "the field " << shill::kProfilesProperty
;
85 OnPropertyChanged(shill::kProfilesProperty
, *profiles
);
88 void NetworkProfileHandler::OnPropertyChanged(const std::string
& name
,
89 const base::Value
& value
) {
90 if (name
!= shill::kProfilesProperty
)
93 const base::ListValue
* profiles_value
= NULL
;
94 value
.GetAsList(&profiles_value
);
95 DCHECK(profiles_value
);
97 std::vector
<std::string
> new_profile_paths
;
98 bool result
= ConvertListValueToStringVector(*profiles_value
,
102 VLOG(2) << "Profiles: " << profiles_
.size();
103 // Search for removed profiles.
104 std::vector
<std::string
> removed_profile_paths
;
105 for (ProfileList::const_iterator it
= profiles_
.begin();
106 it
!= profiles_
.end(); ++it
) {
107 if (std::find(new_profile_paths
.begin(),
108 new_profile_paths
.end(),
109 it
->path
) == new_profile_paths
.end()) {
110 removed_profile_paths
.push_back(it
->path
);
114 for (const std::string
& profile_path
: removed_profile_paths
) {
115 RemoveProfile(profile_path
);
116 // Also stop pending creations of this profile.
117 pending_profile_creations_
.erase(profile_path
);
120 for (std::vector
<std::string
>::const_iterator it
= new_profile_paths
.begin();
121 it
!= new_profile_paths
.end(); ++it
) {
122 // Skip known profiles. The associated userhash should never change.
123 if (GetProfileForPath(*it
) || pending_profile_creations_
.count(*it
) > 0)
125 pending_profile_creations_
.insert(*it
);
127 VLOG(2) << "Requesting properties of profile path " << *it
<< ".";
128 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
129 dbus::ObjectPath(*it
),
130 base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback
,
131 weak_ptr_factory_
.GetWeakPtr(),
133 base::Bind(&LogProfileRequestError
, *it
));
137 void NetworkProfileHandler::GetProfilePropertiesCallback(
138 const std::string
& profile_path
,
139 const base::DictionaryValue
& properties
) {
140 if (pending_profile_creations_
.erase(profile_path
) == 0) {
141 VLOG(1) << "Ignore received properties, profile was removed.";
144 if (GetProfileForPath(profile_path
)) {
145 VLOG(1) << "Ignore received properties, profile is already created.";
148 std::string userhash
;
149 properties
.GetStringWithoutPathExpansion(shill::kUserHashProperty
, &userhash
);
151 AddProfile(NetworkProfile(profile_path
, userhash
));
154 void NetworkProfileHandler::AddProfile(const NetworkProfile
& profile
) {
155 VLOG(2) << "Adding profile " << profile
.ToDebugString() << ".";
156 profiles_
.push_back(profile
);
157 FOR_EACH_OBSERVER(NetworkProfileObserver
, observers_
,
158 OnProfileAdded(profiles_
.back()));
161 void NetworkProfileHandler::RemoveProfile(const std::string
& profile_path
) {
162 VLOG(2) << "Removing profile for path " << profile_path
<< ".";
163 ProfileList::iterator found
= std::find_if(profiles_
.begin(), profiles_
.end(),
164 ProfilePathEquals(profile_path
));
165 if (found
== profiles_
.end())
167 NetworkProfile profile
= *found
;
168 profiles_
.erase(found
);
169 FOR_EACH_OBSERVER(NetworkProfileObserver
, observers_
,
170 OnProfileRemoved(profile
));
173 const NetworkProfile
* NetworkProfileHandler::GetProfileForPath(
174 const std::string
& profile_path
) const {
175 ProfileList::const_iterator found
=
176 std::find_if(profiles_
.begin(), profiles_
.end(),
177 ProfilePathEquals(profile_path
));
179 if (found
== profiles_
.end())
184 const NetworkProfile
* NetworkProfileHandler::GetProfileForUserhash(
185 const std::string
& userhash
) const {
186 for (NetworkProfileHandler::ProfileList::const_iterator it
=
188 it
!= profiles_
.end(); ++it
) {
189 if (it
->userhash
== userhash
)
195 const NetworkProfile
* NetworkProfileHandler::GetDefaultUserProfile() const {
196 for (NetworkProfileHandler::ProfileList::const_iterator it
=
198 it
!= profiles_
.end(); ++it
) {
199 if (!it
->userhash
.empty())
205 NetworkProfileHandler::NetworkProfileHandler()
206 : weak_ptr_factory_(this) {
209 void NetworkProfileHandler::Init() {
210 DBusThreadManager::Get()->GetShillManagerClient()->
211 AddPropertyChangedObserver(this);
213 // Request the initial profile list.
214 DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
215 base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback
,
216 weak_ptr_factory_
.GetWeakPtr()));
219 NetworkProfileHandler::~NetworkProfileHandler() {
220 DBusThreadManager::Get()->GetShillManagerClient()->
221 RemovePropertyChangedObserver(this);
224 } // namespace chromeos