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