12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/shill_profile_client_stub.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind_helpers.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/dbus/shill_manager_client.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/shill_property_changed_observer.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/shill_service_client.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/bus.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/message.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/object_path.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/values_util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)struct ShillProfileClientStub::ProfileProperties {
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::DictionaryValue entries;
26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::DictionaryValue properties;
27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)};
28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PassDictionary(
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ShillProfileClient::DictionaryValueCallbackWithoutStatus& callback,
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* dictionary) {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(*dictionary);
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// static
403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochconst char ShillProfileClientStub::kSharedProfilePath[] = "/profile/default";
413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ShillProfileClientStub::ShillProfileClientStub() {
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  AddProfile(kSharedProfilePath, std::string());
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ShillProfileClientStub::~ShillProfileClientStub() {
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  STLDeleteValues(&profiles_);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShillProfileClientStub::AddPropertyChangedObserver(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& profile_path,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShillPropertyChangedObserver* observer) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShillProfileClientStub::RemovePropertyChangedObserver(
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& profile_path,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShillPropertyChangedObserver* observer) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShillProfileClientStub::GetProperties(
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& profile_path,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DictionaryValueCallbackWithoutStatus& callback,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProfileProperties* profile = GetProfile(profile_path, error_callback);
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> properties(profile->properties.DeepCopy());
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue* entry_paths = new base::ListValue;
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  properties->SetWithoutPathExpansion(flimflam::kEntriesProperty, entry_paths);
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (base::DictionaryValue::Iterator it(profile->entries); !it.IsAtEnd();
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       it.Advance()) {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entry_paths->AppendString(it.key());
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&PassDictionary, callback, base::Owned(properties.release())));
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShillProfileClientStub::GetEntry(
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& profile_path,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& entry_path,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DictionaryValueCallbackWithoutStatus& callback,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProfileProperties* profile = GetProfile(profile_path, error_callback);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue* entry = NULL;
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  profile->entries.GetDictionaryWithoutPathExpansion(entry_path, &entry);
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!entry) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_callback.Run("Error.InvalidProfileEntry", "Invalid profile entry");
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&PassDictionary, callback, base::Owned(entry->DeepCopy())));
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShillProfileClientStub::DeleteEntry(const dbus::ObjectPath& profile_path,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const std::string& entry_path,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const base::Closure& callback,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const ErrorCallback& error_callback) {
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProfileProperties* profile = GetProfile(profile_path, error_callback);
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!profile->entries.RemoveWithoutPathExpansion(entry_path, NULL)) {
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    error_callback.Run("Error.InvalidProfileEntry", entry_path);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::StringValue profile_path_value("");
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SetServiceProperty(entry_path,
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         flimflam::kProfileProperty,
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         profile_path_value);
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ShillProfileClient::TestInterface* ShillProfileClientStub::GetTestInterface() {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return this;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ShillProfileClientStub::AddProfile(const std::string& profile_path,
129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        const std::string& userhash) {
130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (GetProfile(dbus::ObjectPath(profile_path), ErrorCallback()))
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProfileProperties* profile = new ProfileProperties;
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  profile->properties.SetStringWithoutPathExpansion(shill::kUserHashProperty,
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                    userhash);
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  profiles_[profile_path] = profile;
137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      AddProfile(profile_path);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ShillProfileClientStub::AddEntry(const std::string& profile_path,
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const std::string& entry_path,
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::DictionaryValue& properties) {
144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          ErrorCallback());
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(profile);
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  profile->entries.SetWithoutPathExpansion(entry_path,
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                           properties.DeepCopy());
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      AddManagerService(entry_path, false /* visible */, false /* watch */);
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ShillProfileClientStub::AddService(const std::string& profile_path,
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                        const std::string& service_path) {
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                          ErrorCallback());
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!profile) {
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "No matching profile: " << profile_path;
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ShillServiceClient::TestInterface* service_test =
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const base::DictionaryValue* service_properties =
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      service_test->GetServiceProperties(service_path);
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!service_properties) {
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "No matching service: " << service_path;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string service_profile_path;
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  service_properties->GetStringWithoutPathExpansion(flimflam::kProfileProperty,
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                    &service_profile_path);
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!service_profile_path.empty() && service_profile_path != profile_path) {
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Service has non matching profile path: "
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch               << service_profile_path;
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::StringValue profile_path_value(profile_path);
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  service_test->SetServiceProperty(service_path,
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   flimflam::kProfileProperty,
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   profile_path_value);
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  profile->entries.SetWithoutPathExpansion(service_path,
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           service_properties->DeepCopy());
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ShillProfileClientStub::GetProfilePaths(
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::vector<std::string>* profiles) {
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (ProfileMap::iterator iter = profiles_.begin();
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       iter != profiles_.end(); ++iter) {
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    profiles->push_back(iter->first);
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ShillProfileClientStub::ProfileProperties* ShillProfileClientStub::GetProfile(
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const dbus::ObjectPath& profile_path,
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProfileMap::const_iterator found = profiles_.find(profile_path.value());
200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (found == profiles_.end()) {
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!error_callback.is_null())
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      error_callback.Run("Error.InvalidProfile", "Invalid profile");
203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return NULL;
204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return found->second;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
210