- add sources.
[platform/framework/web/crosswalk.git] / src / chromeos / network / network_profile_handler.cc
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 "chromeos/network/network_state_handler.h"
17 #include "dbus/object_path.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19
20 namespace chromeos {
21
22 namespace {
23
24 bool ConvertListValueToStringVector(const base::ListValue& string_list,
25                                     std::vector<std::string>* result) {
26   for (size_t i = 0; i < string_list.GetSize(); ++i) {
27     std::string str;
28     if (!string_list.GetString(i, &str))
29       return false;
30     result->push_back(str);
31   }
32   return true;
33 }
34
35 void LogProfileRequestError(const std::string& profile_path,
36                             const std::string& error_name,
37                             const std::string& error_message) {
38   LOG(ERROR) << "Error when requesting properties for profile "
39              << profile_path << ": " << error_message;
40 }
41
42 class ProfilePathEquals {
43  public:
44   explicit ProfilePathEquals(const std::string& path)
45       : path_(path) {
46   }
47
48   bool operator()(const NetworkProfile& profile) {
49     return profile.path == path_;
50   }
51
52  private:
53   std::string path_;
54 };
55
56 }  // namespace
57
58 // static
59 const char NetworkProfileHandler::kSharedProfilePath[] = "/profile/default";
60
61 void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
62   observers_.AddObserver(observer);
63 }
64
65 void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
66   observers_.RemoveObserver(observer);
67 }
68
69 void NetworkProfileHandler::GetManagerPropertiesCallback(
70     DBusMethodCallStatus call_status,
71     const base::DictionaryValue& properties) {
72   if (DBUS_METHOD_CALL_FAILURE) {
73     LOG(ERROR) << "Error when requesting manager properties.";
74     return;
75   }
76
77   const base::Value* profiles = NULL;
78   properties.GetWithoutPathExpansion(shill::kProfilesProperty, &profiles);
79   if (!profiles) {
80     LOG(ERROR) << "Manager properties returned from Shill don't contain "
81                << "the field " << shill::kProfilesProperty;
82     return;
83   }
84   OnPropertyChanged(shill::kProfilesProperty, *profiles);
85 }
86
87 void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
88                                               const base::Value& value) {
89   if (name != shill::kProfilesProperty)
90     return;
91
92   const base::ListValue* profiles_value = NULL;
93   value.GetAsList(&profiles_value);
94   DCHECK(profiles_value);
95
96   std::vector<std::string> new_profile_paths;
97   bool result = ConvertListValueToStringVector(*profiles_value,
98                                                &new_profile_paths);
99   DCHECK(result);
100
101   VLOG(2) << "Profiles: " << profiles_.size();
102   // Search for removed profiles.
103   std::vector<std::string> removed_profile_paths;
104   for (ProfileList::const_iterator it = profiles_.begin();
105        it != profiles_.end(); ++it) {
106     if (std::find(new_profile_paths.begin(),
107                   new_profile_paths.end(),
108                   it->path) == new_profile_paths.end()) {
109       removed_profile_paths.push_back(it->path);
110     }
111   }
112
113   for (std::vector<std::string>::const_iterator it =
114            removed_profile_paths.begin();
115        it != removed_profile_paths.end(); ++it) {
116     RemoveProfile(*it);
117   }
118
119   for (std::vector<std::string>::const_iterator it = new_profile_paths.begin();
120        it != new_profile_paths.end(); ++it) {
121     // Skip known profiles. The associated userhash should never change.
122     if (GetProfileForPath(*it))
123       continue;
124
125     VLOG(2) << "Requesting properties of profile path " << *it << ".";
126     DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
127         dbus::ObjectPath(*it),
128         base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback,
129                    weak_ptr_factory_.GetWeakPtr(),
130                    *it),
131         base::Bind(&LogProfileRequestError, *it));
132   }
133
134   // When the profile list changes, ServiceCompleteList may also change, so
135   // trigger a Manager update to request the updated list.
136   if (network_state_handler_)
137     network_state_handler_->UpdateManagerProperties();
138 }
139
140 void NetworkProfileHandler::GetProfilePropertiesCallback(
141     const std::string& profile_path,
142     const base::DictionaryValue& properties) {
143   std::string userhash;
144   properties.GetStringWithoutPathExpansion(shill::kUserHashProperty, &userhash);
145
146   AddProfile(NetworkProfile(profile_path, userhash));
147 }
148
149 void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
150   VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
151   profiles_.push_back(profile);
152   FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
153                     OnProfileAdded(profiles_.back()));
154 }
155
156 void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
157   VLOG(2) << "Removing profile for path " << profile_path << ".";
158   ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
159                                              ProfilePathEquals(profile_path));
160   if (found == profiles_.end())
161     return;
162   NetworkProfile profile = *found;
163   profiles_.erase(found);
164   FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
165                     OnProfileRemoved(profile));
166 }
167
168 const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
169     const std::string& profile_path) const {
170   ProfileList::const_iterator found =
171       std::find_if(profiles_.begin(), profiles_.end(),
172                    ProfilePathEquals(profile_path));
173
174   if (found == profiles_.end())
175     return NULL;
176   return &*found;
177 }
178
179 const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
180     const std::string& userhash) const {
181   for (NetworkProfileHandler::ProfileList::const_iterator it =
182            profiles_.begin();
183        it != profiles_.end(); ++it) {
184     if (it->userhash == userhash)
185       return &*it;
186   }
187   return NULL;
188 }
189
190 const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
191   for (NetworkProfileHandler::ProfileList::const_iterator it =
192            profiles_.begin();
193        it != profiles_.end(); ++it) {
194     if (!it->userhash.empty())
195       return &*it;
196   }
197   return NULL;
198 }
199
200 NetworkProfileHandler::NetworkProfileHandler()
201     : network_state_handler_(NULL),
202       weak_ptr_factory_(this) {
203 }
204
205 void NetworkProfileHandler::Init(NetworkStateHandler* network_state_handler) {
206   network_state_handler_ = network_state_handler;
207
208   DBusThreadManager::Get()->GetShillManagerClient()->
209       AddPropertyChangedObserver(this);
210
211   // Request the initial profile list.
212   DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
213       base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
214                  weak_ptr_factory_.GetWeakPtr()));
215 }
216
217 NetworkProfileHandler::~NetworkProfileHandler() {
218   DBusThreadManager::Get()->GetShillManagerClient()->
219       RemovePropertyChangedObserver(this);
220 }
221
222 }  // namespace chromeos