• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chromeos/network/network_profile_handler.h"
6 
7 #include <algorithm>
8 
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"
18 
19 namespace chromeos {
20 
21 namespace {
22 
ConvertListValueToStringVector(const base::ListValue & string_list,std::vector<std::string> * result)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);
30   }
31   return true;
32 }
33 
LogProfileRequestError(const std::string & profile_path,const std::string & error_name,const std::string & error_message)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;
39 }
40 
41 class ProfilePathEquals {
42  public:
ProfilePathEquals(const std::string & path)43   explicit ProfilePathEquals(const std::string& path)
44       : path_(path) {
45   }
46 
operator ()(const NetworkProfile & profile)47   bool operator()(const NetworkProfile& profile) {
48     return profile.path == path_;
49   }
50 
51  private:
52   std::string path_;
53 };
54 
55 }  // namespace
56 
57 // static
GetSharedProfilePath()58 std::string NetworkProfileHandler::GetSharedProfilePath() {
59   return ShillProfileClient::GetSharedProfilePath();
60 }
61 
AddObserver(NetworkProfileObserver * observer)62 void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
63   observers_.AddObserver(observer);
64 }
65 
RemoveObserver(NetworkProfileObserver * observer)66 void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
67   observers_.RemoveObserver(observer);
68 }
69 
GetManagerPropertiesCallback(DBusMethodCallStatus call_status,const base::DictionaryValue & properties)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;
76   }
77 
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;
84   }
85   OnPropertyChanged(shill::kProfilesProperty, *profiles);
86 }
87 
OnPropertyChanged(const std::string & name,const base::Value & value)88 void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
89                                               const base::Value& value) {
90   if (name != shill::kProfilesProperty)
91     return;
92 
93   const base::ListValue* profiles_value = NULL;
94   value.GetAsList(&profiles_value);
95   DCHECK(profiles_value);
96 
97   std::vector<std::string> new_profile_paths;
98   bool result = ConvertListValueToStringVector(*profiles_value,
99                                                &new_profile_paths);
100   DCHECK(result);
101 
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);
111     }
112   }
113 
114   for (std::vector<std::string>::const_iterator it =
115            removed_profile_paths.begin();
116        it != removed_profile_paths.end(); ++it) {
117     RemoveProfile(*it);
118   }
119 
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))
124       continue;
125 
126     VLOG(2) << "Requesting properties of profile path " << *it << ".";
127     DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
128         dbus::ObjectPath(*it),
129         base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback,
130                    weak_ptr_factory_.GetWeakPtr(),
131                    *it),
132         base::Bind(&LogProfileRequestError, *it));
133   }
134 }
135 
GetProfilePropertiesCallback(const std::string & profile_path,const base::DictionaryValue & properties)136 void NetworkProfileHandler::GetProfilePropertiesCallback(
137     const std::string& profile_path,
138     const base::DictionaryValue& properties) {
139   std::string userhash;
140   properties.GetStringWithoutPathExpansion(shill::kUserHashProperty, &userhash);
141 
142   AddProfile(NetworkProfile(profile_path, userhash));
143 }
144 
AddProfile(const NetworkProfile & profile)145 void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
146   VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
147   profiles_.push_back(profile);
148   FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
149                     OnProfileAdded(profiles_.back()));
150 }
151 
RemoveProfile(const std::string & profile_path)152 void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
153   VLOG(2) << "Removing profile for path " << profile_path << ".";
154   ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
155                                              ProfilePathEquals(profile_path));
156   if (found == profiles_.end())
157     return;
158   NetworkProfile profile = *found;
159   profiles_.erase(found);
160   FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
161                     OnProfileRemoved(profile));
162 }
163 
GetProfileForPath(const std::string & profile_path) const164 const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
165     const std::string& profile_path) const {
166   ProfileList::const_iterator found =
167       std::find_if(profiles_.begin(), profiles_.end(),
168                    ProfilePathEquals(profile_path));
169 
170   if (found == profiles_.end())
171     return NULL;
172   return &*found;
173 }
174 
GetProfileForUserhash(const std::string & userhash) const175 const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
176     const std::string& userhash) const {
177   for (NetworkProfileHandler::ProfileList::const_iterator it =
178            profiles_.begin();
179        it != profiles_.end(); ++it) {
180     if (it->userhash == userhash)
181       return &*it;
182   }
183   return NULL;
184 }
185 
GetDefaultUserProfile() const186 const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
187   for (NetworkProfileHandler::ProfileList::const_iterator it =
188            profiles_.begin();
189        it != profiles_.end(); ++it) {
190     if (!it->userhash.empty())
191       return &*it;
192   }
193   return NULL;
194 }
195 
NetworkProfileHandler()196 NetworkProfileHandler::NetworkProfileHandler()
197     : weak_ptr_factory_(this) {
198 }
199 
Init()200 void NetworkProfileHandler::Init() {
201   DBusThreadManager::Get()->GetShillManagerClient()->
202       AddPropertyChangedObserver(this);
203 
204   // Request the initial profile list.
205   DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
206       base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
207                  weak_ptr_factory_.GetWeakPtr()));
208 }
209 
~NetworkProfileHandler()210 NetworkProfileHandler::~NetworkProfileHandler() {
211   DBusThreadManager::Get()->GetShillManagerClient()->
212       RemovePropertyChangedObserver(this);
213 }
214 
215 }  // namespace chromeos
216