| Index: chromeos/network/network_profile_handler.cc
|
| diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..30c8fde78eb00274c715305bae8d8b3596263eae
|
| --- /dev/null
|
| +++ b/chromeos/network/network_profile_handler.cc
|
| @@ -0,0 +1,233 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chromeos/network/network_profile_handler.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/string_util.h"
|
| +#include "base/values.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| +#include "chromeos/dbus/shill_manager_client.h"
|
| +#include "chromeos/dbus/shill_profile_client.h"
|
| +#include "chromeos/network/network_profile_observer.h"
|
| +#include "dbus/object_path.h"
|
| +#include "third_party/cros_system_api/dbus/service_constants.h"
|
| +
|
| +namespace chromeos {
|
| +
|
| +static NetworkProfileHandler* g_profile_handler_instance = NULL;
|
| +
|
| +namespace {
|
| +
|
| +bool ConvertListValueToStringVector(const base::ListValue& string_list,
|
| + std::vector<std::string>* result) {
|
| + for (size_t i = 0; i < string_list.GetSize(); ++i) {
|
| + std::string str;
|
| + if (!string_list.GetString(i, &str))
|
| + return false;
|
| + result->push_back(str);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void LogProfileRequestError(const std::string& profile_path,
|
| + const std::string& error_name,
|
| + const std::string& error_message) {
|
| + LOG(ERROR) << "Error when requesting properties for profile "
|
| + << profile_path << ": " << error_message;
|
| +}
|
| +
|
| +class ProfilePathEquals {
|
| + public:
|
| + explicit ProfilePathEquals(const std::string& path)
|
| + : path_(path) {
|
| + }
|
| +
|
| + bool operator()(const NetworkProfile& profile) {
|
| + return profile.path == path_;
|
| + }
|
| +
|
| + private:
|
| + std::string path_;
|
| +};
|
| +
|
| +class NetworkProfileHandlerImpl : public NetworkProfileHandler {
|
| + public:
|
| + NetworkProfileHandlerImpl() {
|
| + DBusThreadManager::Get()->GetShillManagerClient()->
|
| + AddPropertyChangedObserver(this);
|
| +
|
| + // Request the initial profile list.
|
| + DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
|
| + base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| + }
|
| +
|
| + virtual ~NetworkProfileHandlerImpl() {
|
| + DBusThreadManager::Get()->GetShillManagerClient()->
|
| + RemovePropertyChangedObserver(this);
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +NetworkProfileHandler* NetworkProfileHandler::Initialize() {
|
| + CHECK(!g_profile_handler_instance);
|
| + g_profile_handler_instance = new NetworkProfileHandlerImpl();
|
| + return g_profile_handler_instance;
|
| +}
|
| +
|
| +// static
|
| +bool NetworkProfileHandler::IsInitialized() {
|
| + return g_profile_handler_instance;
|
| +}
|
| +
|
| +// static
|
| +void NetworkProfileHandler::Shutdown() {
|
| + CHECK(g_profile_handler_instance);
|
| + delete g_profile_handler_instance;
|
| + g_profile_handler_instance = NULL;
|
| +}
|
| +
|
| +// static
|
| +NetworkProfileHandler* NetworkProfileHandler::Get() {
|
| + CHECK(g_profile_handler_instance);
|
| + return g_profile_handler_instance;
|
| +}
|
| +
|
| +void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
|
| + observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
|
| + observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +void NetworkProfileHandler::GetManagerPropertiesCallback(
|
| + DBusMethodCallStatus call_status,
|
| + const base::DictionaryValue& properties) {
|
| + if (DBUS_METHOD_CALL_FAILURE) {
|
| + LOG(ERROR) << "Error when requesting manager properties.";
|
| + return;
|
| + }
|
| +
|
| + const base::Value* profiles = NULL;
|
| + properties.GetWithoutPathExpansion(flimflam::kProfilesProperty, &profiles);
|
| + if (!profiles) {
|
| + LOG(ERROR) << "Manager properties returned from Shill don't contain "
|
| + << "the field " << flimflam::kProfilesProperty;
|
| + return;
|
| + }
|
| + OnPropertyChanged(flimflam::kProfilesProperty, *profiles);
|
| +}
|
| +
|
| +void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
|
| + const base::Value& value) {
|
| + if (name != flimflam::kProfilesProperty)
|
| + return;
|
| +
|
| + const base::ListValue* profiles_value = NULL;
|
| + value.GetAsList(&profiles_value);
|
| + DCHECK(profiles_value);
|
| +
|
| + std::vector<std::string> new_profile_paths;
|
| + bool result = ConvertListValueToStringVector(*profiles_value,
|
| + &new_profile_paths);
|
| + DCHECK(result);
|
| +
|
| + // Search for removed profiles.
|
| + std::vector<std::string> removed_profile_paths;
|
| + for (ProfileList::const_iterator it = profiles_.begin();
|
| + it != profiles_.end(); ++it) {
|
| + if (std::find(new_profile_paths.begin(),
|
| + new_profile_paths.end(),
|
| + it->path) == new_profile_paths.end()) {
|
| + removed_profile_paths.push_back(it->path);
|
| + }
|
| + }
|
| +
|
| + for (std::vector<std::string>::const_iterator it =
|
| + removed_profile_paths.begin();
|
| + it != removed_profile_paths.end(); ++it) {
|
| + RemoveProfile(*it);
|
| + }
|
| +
|
| + for (std::vector<std::string>::const_iterator it = new_profile_paths.begin();
|
| + it != new_profile_paths.end(); ++it) {
|
| + // Skip known profiles. The associated userhash should never change.
|
| + if (GetProfileForPath(*it))
|
| + continue;
|
| +
|
| + VLOG(2) << "Requesting properties of profile path " << *it << ".";
|
| + DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
|
| + dbus::ObjectPath(*it),
|
| + base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + *it),
|
| + base::Bind(&LogProfileRequestError, *it));
|
| + }
|
| +}
|
| +
|
| +void NetworkProfileHandler::GetProfilePropertiesCallback(
|
| + const std::string& profile_path,
|
| + const base::DictionaryValue& properties) {
|
| + std::string userhash;
|
| + properties.GetStringWithoutPathExpansion(shill::kUserHashProperty,
|
| + &userhash);
|
| +
|
| + AddProfile(NetworkProfile(profile_path, userhash));
|
| +}
|
| +
|
| +void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
|
| + VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
|
| + profiles_.push_back(profile);
|
| + FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
|
| + OnProfileAdded(profiles_.back()));
|
| +}
|
| +
|
| +void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
|
| + VLOG(2) << "Removing profile for path " << profile_path << ".";
|
| + ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
|
| + ProfilePathEquals(profile_path));
|
| + if (found == profiles_.end())
|
| + return;
|
| + NetworkProfile profile = *found;
|
| + profiles_.erase(found);
|
| + FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
|
| + OnProfileRemoved(profile));
|
| +}
|
| +
|
| +const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
|
| + const std::string& profile_path) const {
|
| + ProfileList::const_iterator found =
|
| + std::find_if(profiles_.begin(), profiles_.end(),
|
| + ProfilePathEquals(profile_path));
|
| +
|
| + if (found == profiles_.end())
|
| + return NULL;
|
| + return &*found;
|
| +}
|
| +
|
| +const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
|
| + const std::string& userhash) const {
|
| + for (NetworkProfileHandler::ProfileList::const_iterator it =
|
| + profiles_.begin();
|
| + it != profiles_.end(); ++it) {
|
| + if (it->userhash == userhash)
|
| + return &*it;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +NetworkProfileHandler::NetworkProfileHandler()
|
| + : weak_ptr_factory_(this) {
|
| +}
|
| +
|
| +NetworkProfileHandler::~NetworkProfileHandler() {
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|