Home | History | Annotate | Download | only in network
      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 
     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 
     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:
     43   explicit ProfilePathEquals(const std::string& path)
     44       : path_(path) {
     45   }
     46 
     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
     58 std::string NetworkProfileHandler::GetSharedProfilePath() {
     59   return ShillProfileClient::GetSharedProfilePath();
     60 }
     61 
     62 void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
     63   observers_.AddObserver(observer);
     64 }
     65 
     66 void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
     67   observers_.RemoveObserver(observer);
     68 }
     69 
     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 
     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 
    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 
    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 
    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 
    164 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 
    175 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 
    186 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 
    196 NetworkProfileHandler::NetworkProfileHandler()
    197     : weak_ptr_factory_(this) {
    198 }
    199 
    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 
    210 NetworkProfileHandler::~NetworkProfileHandler() {
    211   DBusThreadManager::Get()->GetShillManagerClient()->
    212       RemovePropertyChangedObserver(this);
    213 }
    214 
    215 }  // namespace chromeos
    216