network_profile_handler.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/network_profile_handler.h"
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <algorithm>
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/bind.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/string_util.h"
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/values.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/dbus/shill_manager_client.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/dbus/shill_profile_client.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chromeos/network/network_profile_observer.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "dbus/object_path.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace chromeos {
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ConvertListValueToStringVector(const base::ListValue& string_list,
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    std::vector<std::string>* result) {
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < string_list.GetSize(); ++i) {
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string str;
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!string_list.GetString(i, &str))
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    result->push_back(str);
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void LogProfileRequestError(const std::string& profile_path,
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            const std::string& error_name,
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            const std::string& error_message) {
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LOG(ERROR) << "Error when requesting properties for profile "
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             << profile_path << ": " << error_message;
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class ProfilePathEquals {
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  explicit ProfilePathEquals(const std::string& path)
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : path_(path) {
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool operator()(const NetworkProfile& profile) {
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return profile.path == path_;
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string path_;
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  observers_.AddObserver(observer);
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  observers_.RemoveObserver(observer);
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NetworkProfileHandler::GetManagerPropertiesCallback(
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DBusMethodCallStatus call_status,
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::DictionaryValue& properties) {
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (DBUS_METHOD_CALL_FAILURE) {
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "Error when requesting manager properties.";
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const base::Value* profiles = NULL;
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  properties.GetWithoutPathExpansion(flimflam::kProfilesProperty, &profiles);
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!profiles) {
76    LOG(ERROR) << "Manager properties returned from Shill don't contain "
77               << "the field " << flimflam::kProfilesProperty;
78    return;
79  }
80  OnPropertyChanged(flimflam::kProfilesProperty, *profiles);
81}
82
83void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
84                                              const base::Value& value) {
85  if (name != flimflam::kProfilesProperty)
86    return;
87
88  const base::ListValue* profiles_value = NULL;
89  value.GetAsList(&profiles_value);
90  DCHECK(profiles_value);
91
92  std::vector<std::string> new_profile_paths;
93  bool result = ConvertListValueToStringVector(*profiles_value,
94                                               &new_profile_paths);
95  DCHECK(result);
96
97  VLOG(2) << "Profiles: " << profiles_.size();
98  // Search for removed profiles.
99  std::vector<std::string> removed_profile_paths;
100  for (ProfileList::const_iterator it = profiles_.begin();
101       it != profiles_.end(); ++it) {
102    if (std::find(new_profile_paths.begin(),
103                  new_profile_paths.end(),
104                  it->path) == new_profile_paths.end()) {
105      removed_profile_paths.push_back(it->path);
106    }
107  }
108
109  for (std::vector<std::string>::const_iterator it =
110           removed_profile_paths.begin();
111       it != removed_profile_paths.end(); ++it) {
112    RemoveProfile(*it);
113  }
114
115  for (std::vector<std::string>::const_iterator it = new_profile_paths.begin();
116       it != new_profile_paths.end(); ++it) {
117    // Skip known profiles. The associated userhash should never change.
118    if (GetProfileForPath(*it))
119      continue;
120
121    VLOG(2) << "Requesting properties of profile path " << *it << ".";
122    DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
123        dbus::ObjectPath(*it),
124        base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback,
125                   weak_ptr_factory_.GetWeakPtr(),
126                   *it),
127        base::Bind(&LogProfileRequestError, *it));
128  }
129}
130
131void NetworkProfileHandler::GetProfilePropertiesCallback(
132    const std::string& profile_path,
133    const base::DictionaryValue& properties) {
134  std::string userhash;
135  properties.GetStringWithoutPathExpansion(shill::kUserHashProperty,
136                                           &userhash);
137
138  AddProfile(NetworkProfile(profile_path, userhash));
139}
140
141void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
142  VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
143  profiles_.push_back(profile);
144  FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
145                    OnProfileAdded(profiles_.back()));
146}
147
148void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
149  VLOG(2) << "Removing profile for path " << profile_path << ".";
150  ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
151                                             ProfilePathEquals(profile_path));
152  if (found == profiles_.end())
153    return;
154  NetworkProfile profile = *found;
155  profiles_.erase(found);
156  FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
157                    OnProfileRemoved(profile));
158}
159
160const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
161    const std::string& profile_path) const {
162  ProfileList::const_iterator found =
163      std::find_if(profiles_.begin(), profiles_.end(),
164                   ProfilePathEquals(profile_path));
165
166  if (found == profiles_.end())
167    return NULL;
168  return &*found;
169}
170
171const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
172    const std::string& userhash) const {
173  for (NetworkProfileHandler::ProfileList::const_iterator it =
174           profiles_.begin();
175       it != profiles_.end(); ++it) {
176    if (it->userhash == userhash)
177      return &*it;
178  }
179  return NULL;
180}
181
182NetworkProfileHandler::NetworkProfileHandler()
183    : weak_ptr_factory_(this) {
184  DBusThreadManager::Get()->GetShillManagerClient()->
185      AddPropertyChangedObserver(this);
186
187  // Request the initial profile list.
188  DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
189      base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
190                 weak_ptr_factory_.GetWeakPtr()));
191}
192
193NetworkProfileHandler::~NetworkProfileHandler() {
194  DBusThreadManager::Get()->GetShillManagerClient()->
195      RemovePropertyChangedObserver(this);
196}
197
198}  // namespace chromeos
199