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 "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(flimflam::kProfilesProperty, &profiles);
     79   if (!profiles) {
     80     LOG(ERROR) << "Manager properties returned from Shill don't contain "
     81                << "the field " << flimflam::kProfilesProperty;
     82     return;
     83   }
     84   OnPropertyChanged(flimflam::kProfilesProperty, *profiles);
     85 }
     86 
     87 void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
     88                                               const base::Value& value) {
     89   if (name != flimflam::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,
    145                                            &userhash);
    146 
    147   AddProfile(NetworkProfile(profile_path, userhash));
    148 }
    149 
    150 void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
    151   VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
    152   profiles_.push_back(profile);
    153   FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
    154                     OnProfileAdded(profiles_.back()));
    155 }
    156 
    157 void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
    158   VLOG(2) << "Removing profile for path " << profile_path << ".";
    159   ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
    160                                              ProfilePathEquals(profile_path));
    161   if (found == profiles_.end())
    162     return;
    163   NetworkProfile profile = *found;
    164   profiles_.erase(found);
    165   FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
    166                     OnProfileRemoved(profile));
    167 }
    168 
    169 const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
    170     const std::string& profile_path) const {
    171   ProfileList::const_iterator found =
    172       std::find_if(profiles_.begin(), profiles_.end(),
    173                    ProfilePathEquals(profile_path));
    174 
    175   if (found == profiles_.end())
    176     return NULL;
    177   return &*found;
    178 }
    179 
    180 const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
    181     const std::string& userhash) const {
    182   for (NetworkProfileHandler::ProfileList::const_iterator it =
    183            profiles_.begin();
    184        it != profiles_.end(); ++it) {
    185     if (it->userhash == userhash)
    186       return &*it;
    187   }
    188   return NULL;
    189 }
    190 
    191 const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
    192   for (NetworkProfileHandler::ProfileList::const_iterator it =
    193            profiles_.begin();
    194        it != profiles_.end(); ++it) {
    195     if (!it->userhash.empty())
    196       return &*it;
    197   }
    198   return NULL;
    199 }
    200 
    201 NetworkProfileHandler::NetworkProfileHandler()
    202     : network_state_handler_(NULL),
    203       weak_ptr_factory_(this) {
    204 }
    205 
    206 void NetworkProfileHandler::Init(NetworkStateHandler* network_state_handler) {
    207   network_state_handler_ = network_state_handler;
    208 
    209   DBusThreadManager::Get()->GetShillManagerClient()->
    210       AddPropertyChangedObserver(this);
    211 
    212   // Request the initial profile list.
    213   DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
    214       base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
    215                  weak_ptr_factory_.GetWeakPtr()));
    216 }
    217 
    218 NetworkProfileHandler::~NetworkProfileHandler() {
    219   DBusThreadManager::Get()->GetShillManagerClient()->
    220       RemovePropertyChangedObserver(this);
    221 }
    222 
    223 }  // namespace chromeos
    224