Fix race condition in WebstoreInstallHelper.
[chromium-blink-merge.git] / chromeos / network / network_profile_handler.cc
blob002421ae44e4b87f622e14767462da540e4ee21d
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"
7 #include <algorithm>
9 #include "base/bind.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"
19 namespace chromeos {
21 namespace {
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) {
26 std::string str;
27 if (!string_list.GetString(i, &str))
28 return false;
29 result->push_back(str);
31 return true;
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 {
42 public:
43 explicit ProfilePathEquals(const std::string& path)
44 : path_(path) {
47 bool operator()(const NetworkProfile& profile) {
48 return profile.path == path_;
51 private:
52 std::string path_;
55 } // namespace
57 // static
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.";
75 return;
78 const base::Value* profiles = NULL;
79 properties.GetWithoutPathExpansion(shill::kProfilesProperty, &profiles);
80 if (!profiles) {
81 LOG(ERROR) << "Manager properties returned from Shill don't contain "
82 << "the field " << shill::kProfilesProperty;
83 return;
85 OnPropertyChanged(shill::kProfilesProperty, *profiles);
88 void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
89 const base::Value& value) {
90 if (name != shill::kProfilesProperty)
91 return;
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,
99 &new_profile_paths);
100 DCHECK(result);
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)
124 continue;
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(),
132 *it),
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.";
142 return;
144 if (GetProfileForPath(profile_path)) {
145 VLOG(1) << "Ignore received properties, profile is already created.";
146 return;
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())
166 return;
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())
180 return NULL;
181 return &*found;
184 const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
185 const std::string& userhash) const {
186 for (NetworkProfileHandler::ProfileList::const_iterator it =
187 profiles_.begin();
188 it != profiles_.end(); ++it) {
189 if (it->userhash == userhash)
190 return &*it;
192 return NULL;
195 const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
196 for (NetworkProfileHandler::ProfileList::const_iterator it =
197 profiles_.begin();
198 it != profiles_.end(); ++it) {
199 if (!it->userhash.empty())
200 return &*it;
202 return NULL;
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