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