Home | History | Annotate | Download | only in dbus
      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