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