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/dbus/shill_profile_client_stub.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/stl_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_property_changed_observer.h" 15 #include "chromeos/dbus/shill_service_client.h" 16 #include "dbus/bus.h" 17 #include "dbus/message.h" 18 #include "dbus/object_path.h" 19 #include "dbus/values_util.h" 20 #include "third_party/cros_system_api/dbus/service_constants.h" 21 22 namespace chromeos { 23 24 struct ShillProfileClientStub::ProfileProperties { 25 base::DictionaryValue entries; 26 base::DictionaryValue properties; 27 }; 28 29 namespace { 30 31 void PassDictionary( 32 const ShillProfileClient::DictionaryValueCallbackWithoutStatus& callback, 33 const base::DictionaryValue* dictionary) { 34 callback.Run(*dictionary); 35 } 36 37 } // namespace 38 39 // static 40 const char ShillProfileClientStub::kSharedProfilePath[] = "/profile/default"; 41 42 ShillProfileClientStub::ShillProfileClientStub() { 43 AddProfile(kSharedProfilePath, std::string()); 44 } 45 46 ShillProfileClientStub::~ShillProfileClientStub() { 47 STLDeleteValues(&profiles_); 48 } 49 50 void ShillProfileClientStub::AddPropertyChangedObserver( 51 const dbus::ObjectPath& profile_path, 52 ShillPropertyChangedObserver* observer) { 53 } 54 55 void ShillProfileClientStub::RemovePropertyChangedObserver( 56 const dbus::ObjectPath& profile_path, 57 ShillPropertyChangedObserver* observer) { 58 } 59 60 void ShillProfileClientStub::GetProperties( 61 const dbus::ObjectPath& profile_path, 62 const DictionaryValueCallbackWithoutStatus& callback, 63 const ErrorCallback& error_callback) { 64 ProfileProperties* profile = GetProfile(profile_path, error_callback); 65 if (!profile) 66 return; 67 68 scoped_ptr<base::DictionaryValue> properties(profile->properties.DeepCopy()); 69 base::ListValue* entry_paths = new base::ListValue; 70 properties->SetWithoutPathExpansion(flimflam::kEntriesProperty, entry_paths); 71 for (base::DictionaryValue::Iterator it(profile->entries); !it.IsAtEnd(); 72 it.Advance()) { 73 entry_paths->AppendString(it.key()); 74 } 75 76 base::MessageLoop::current()->PostTask( 77 FROM_HERE, 78 base::Bind(&PassDictionary, callback, base::Owned(properties.release()))); 79 } 80 81 void ShillProfileClientStub::GetEntry( 82 const dbus::ObjectPath& profile_path, 83 const std::string& entry_path, 84 const DictionaryValueCallbackWithoutStatus& callback, 85 const ErrorCallback& error_callback) { 86 ProfileProperties* profile = GetProfile(profile_path, error_callback); 87 if (!profile) 88 return; 89 90 base::DictionaryValue* entry = NULL; 91 profile->entries.GetDictionaryWithoutPathExpansion(entry_path, &entry); 92 if (!entry) { 93 error_callback.Run("Error.InvalidProfileEntry", "Invalid profile entry"); 94 return; 95 } 96 97 base::MessageLoop::current()->PostTask( 98 FROM_HERE, 99 base::Bind(&PassDictionary, callback, base::Owned(entry->DeepCopy()))); 100 } 101 102 void ShillProfileClientStub::DeleteEntry(const dbus::ObjectPath& profile_path, 103 const std::string& entry_path, 104 const base::Closure& callback, 105 const ErrorCallback& error_callback) { 106 ProfileProperties* profile = GetProfile(profile_path, error_callback); 107 if (!profile) 108 return; 109 110 if (!profile->entries.RemoveWithoutPathExpansion(entry_path, NULL)) { 111 error_callback.Run("Error.InvalidProfileEntry", entry_path); 112 return; 113 } 114 115 base::StringValue profile_path_value(""); 116 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()-> 117 SetServiceProperty(entry_path, 118 flimflam::kProfileProperty, 119 profile_path_value); 120 121 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 122 } 123 124 ShillProfileClient::TestInterface* ShillProfileClientStub::GetTestInterface() { 125 return this; 126 } 127 128 void ShillProfileClientStub::AddProfile(const std::string& profile_path, 129 const std::string& userhash) { 130 if (GetProfile(dbus::ObjectPath(profile_path), ErrorCallback())) 131 return; 132 133 ProfileProperties* profile = new ProfileProperties; 134 profile->properties.SetStringWithoutPathExpansion(shill::kUserHashProperty, 135 userhash); 136 profiles_[profile_path] = profile; 137 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()-> 138 AddProfile(profile_path); 139 } 140 141 void ShillProfileClientStub::AddEntry(const std::string& profile_path, 142 const std::string& entry_path, 143 const base::DictionaryValue& properties) { 144 ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path), 145 ErrorCallback()); 146 DCHECK(profile); 147 profile->entries.SetWithoutPathExpansion(entry_path, 148 properties.DeepCopy()); 149 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()-> 150 AddManagerService(entry_path, false /* visible */, false /* watch */); 151 } 152 153 bool ShillProfileClientStub::AddService(const std::string& profile_path, 154 const std::string& service_path) { 155 ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path), 156 ErrorCallback()); 157 if (!profile) { 158 LOG(ERROR) << "No matching profile: " << profile_path; 159 return false; 160 } 161 162 ShillServiceClient::TestInterface* service_test = 163 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 164 const base::DictionaryValue* service_properties = 165 service_test->GetServiceProperties(service_path); 166 if (!service_properties) { 167 LOG(ERROR) << "No matching service: " << service_path; 168 return false; 169 } 170 std::string service_profile_path; 171 service_properties->GetStringWithoutPathExpansion(flimflam::kProfileProperty, 172 &service_profile_path); 173 if (!service_profile_path.empty() && service_profile_path != profile_path) { 174 LOG(ERROR) << "Service has non matching profile path: " 175 << service_profile_path; 176 return false; 177 } 178 179 base::StringValue profile_path_value(profile_path); 180 service_test->SetServiceProperty(service_path, 181 flimflam::kProfileProperty, 182 profile_path_value); 183 profile->entries.SetWithoutPathExpansion(service_path, 184 service_properties->DeepCopy()); 185 return true; 186 } 187 188 void ShillProfileClientStub::GetProfilePaths( 189 std::vector<std::string>* profiles) { 190 for (ProfileMap::iterator iter = profiles_.begin(); 191 iter != profiles_.end(); ++iter) { 192 profiles->push_back(iter->first); 193 } 194 } 195 196 ShillProfileClientStub::ProfileProperties* ShillProfileClientStub::GetProfile( 197 const dbus::ObjectPath& profile_path, 198 const ErrorCallback& error_callback) { 199 ProfileMap::const_iterator found = profiles_.find(profile_path.value()); 200 if (found == profiles_.end()) { 201 if (!error_callback.is_null()) 202 error_callback.Run("Error.InvalidProfile", "Invalid profile"); 203 return NULL; 204 } 205 206 return found->second; 207 } 208 209 } // namespace chromeos 210