Chromium Code Reviews| Index: chromeos/dbus/privet_daemon_manager_client.cc |
| diff --git a/chromeos/dbus/privet_daemon_manager_client.cc b/chromeos/dbus/privet_daemon_manager_client.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c656270aef9e933f9e0828e4c4c934f8c8c826ff |
| --- /dev/null |
| +++ b/chromeos/dbus/privet_daemon_manager_client.cc |
| @@ -0,0 +1,306 @@ |
| +// Copyright 2015 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/dbus/privet_daemon_manager_client.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/logging.h" |
| +#include "base/memory/weak_ptr.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "base/observer_list.h" |
| +#include "dbus/bus.h" |
| +#include "dbus/message.h" |
| +#include "dbus/object_manager.h" |
| +#include "dbus/object_proxy.h" |
| +#include "dbus/values_util.h" |
|
hashimoto
2015/03/20 06:41:48
nit: Looks unused.
dtapuska
2015/03/20 13:47:55
Done.
|
| + |
| +namespace chromeos { |
| + |
| +namespace { |
| + |
| +// TODO(benchan): Move these constants to system_api. |
| +const char kManagerInterfaceName[] = "org.chromium.privetd.Manager"; |
| +const char kPrivetdManagerPath[] = "/org/chromium/privetd/Manager"; |
| +const char kPrivetdServiceName[] = "org.chromium.privetd"; |
| +const char kPrivetdServicePath[] = "/org/chromium/privetd"; |
| +const char kSetDescriptionMethod[] = "SetDescription"; |
| + |
| +const char kDescriptionProperty[] = "Description"; |
| +const char kGCDBootstrapStateProperty[] = "GCDBootstrapState"; |
| +const char kNameProperty[] = "Name"; |
| +const char kPairingInfoCodeProperty[] = "code"; |
| +const char kPairingInfoModeProperty[] = "mode"; |
| +const char kPairingInfoProperty[] = "PairingInfo"; |
| +const char kPairingInfoSessionIdProperty[] = "sessionId"; |
| +const char kWiFiBootstrapStateProperty[] = "WiFiBootstrapState"; |
| + |
| +// The PrivetDaemonManagerClient implementation used in production. |
| +class PrivetDaemonManagerClientImpl : public PrivetDaemonManagerClient, |
| + public dbus::ObjectManager::Interface { |
| + public: |
| + PrivetDaemonManagerClientImpl(); |
| + ~PrivetDaemonManagerClientImpl() override; |
| + |
| + // PrivetDaemonManagerClient overrides. |
| + void AddObserver(Observer* observer) override; |
| + void RemoveObserver(Observer* observer) override; |
| + void SetDescription(const std::string& description, |
| + const VoidDBusMethodCallback& callback) override; |
| + const Properties* GetProperties() override; |
| + |
| + // DBusClient overrides. |
| + void Init(dbus::Bus* bus) override; |
| + |
| + // dbus::ObjectManager::Interface overrides. |
| + dbus::PropertySet* CreateProperties( |
| + dbus::ObjectProxy* object_proxy, |
| + const dbus::ObjectPath& object_path, |
| + const std::string& interface_name) override; |
| + void ObjectAdded(const dbus::ObjectPath& object_path, |
| + const std::string& interface_name) override; |
| + void ObjectRemoved(const dbus::ObjectPath& object_path, |
| + const std::string& interface_name) override; |
| + |
| + private: |
| + // Called by dbus::PropertySet when a property value is changed, |
| + // either by result of a signal or response to a GetAll() or Get() |
| + // call. Informs observers. |
| + void OnManagerPropertyChanged(const std::string& property_name); |
| + void OnVoidDBusMethod(const VoidDBusMethodCallback& callback, |
| + dbus::Response* response); |
| + |
| + // List of observers interested in event notifications from us. |
| + ObserverList<Observer> observers_; |
| + dbus::ObjectManager* object_manager_; |
| + base::WeakPtrFactory<PrivetDaemonManagerClientImpl> weak_ptr_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PrivetDaemonManagerClientImpl); |
| +}; |
| + |
| +PrivetDaemonManagerClientImpl::PrivetDaemonManagerClientImpl() |
| + : object_manager_(nullptr), weak_ptr_factory_(this) { |
| +} |
| + |
| +PrivetDaemonManagerClientImpl::~PrivetDaemonManagerClientImpl() { |
| + if (object_manager_) { |
| + object_manager_->UnregisterInterface(kManagerInterfaceName); |
| + } |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::AddObserver(Observer* observer) { |
| + DCHECK(observer); |
| + observers_.AddObserver(observer); |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::RemoveObserver(Observer* observer) { |
| + DCHECK(observer); |
| + observers_.RemoveObserver(observer); |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::SetDescription( |
| + const std::string& description, |
| + const VoidDBusMethodCallback& callback) { |
| + dbus::ObjectProxy* object_proxy = |
| + object_manager_->GetObjectProxy(dbus::ObjectPath(kPrivetdManagerPath)); |
| + if (!object_proxy) { |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&PrivetDaemonManagerClientImpl::OnVoidDBusMethod, |
| + weak_ptr_factory_.GetWeakPtr(), callback, nullptr)); |
| + return; |
| + } |
| + |
| + dbus::MethodCall method_call(kManagerInterfaceName, kSetDescriptionMethod); |
| + dbus::MessageWriter writer(&method_call); |
| + writer.AppendString(description); |
| + object_proxy->CallMethod( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| + base::Bind(&PrivetDaemonManagerClientImpl::OnVoidDBusMethod, |
| + weak_ptr_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +const PrivetDaemonManagerClient::Properties* |
| +PrivetDaemonManagerClientImpl::GetProperties() { |
| + return static_cast<Properties*>(object_manager_->GetProperties( |
| + dbus::ObjectPath(kPrivetdManagerPath), kManagerInterfaceName)); |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::Init(dbus::Bus* bus) { |
| + object_manager_ = bus->GetObjectManager( |
| + kPrivetdServiceName, dbus::ObjectPath(kPrivetdServicePath)); |
| + object_manager_->RegisterInterface(kManagerInterfaceName, this); |
| +} |
| + |
| +dbus::PropertySet* PrivetDaemonManagerClientImpl::CreateProperties( |
| + dbus::ObjectProxy* object_proxy, |
| + const dbus::ObjectPath& object_path, |
| + const std::string& interface_name) { |
| + dbus::PropertySet* properties = nullptr; |
| + if (interface_name == kManagerInterfaceName) { |
| + properties = new Properties( |
| + object_proxy, interface_name, |
| + base::Bind(&PrivetDaemonManagerClientImpl::OnManagerPropertyChanged, |
| + weak_ptr_factory_.GetWeakPtr())); |
| + } else { |
| + NOTREACHED() << "Unhandled interface name " << interface_name; |
| + } |
| + return properties; |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::ObjectAdded( |
| + const dbus::ObjectPath& object_path, |
| + const std::string& interface_name) { |
| + if (interface_name == kManagerInterfaceName) { |
| + FOR_EACH_OBSERVER(Observer, observers_, ManagerAdded()); |
| + } else { |
| + NOTREACHED() << "Unhandled interface name " << interface_name; |
| + } |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::ObjectRemoved( |
| + const dbus::ObjectPath& object_path, |
| + const std::string& interface_name) { |
| + if (interface_name == kManagerInterfaceName) { |
| + FOR_EACH_OBSERVER(Observer, observers_, ManagerRemoved()); |
| + } else { |
| + NOTREACHED() << "Unhandled interface name " << interface_name; |
| + } |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::OnManagerPropertyChanged( |
| + const std::string& property_name) { |
| + FOR_EACH_OBSERVER(Observer, observers_, |
| + ManagerPropertyChanged(property_name)); |
| +} |
| + |
| +void PrivetDaemonManagerClientImpl::OnVoidDBusMethod( |
| + const VoidDBusMethodCallback& callback, |
| + dbus::Response* response) { |
| + callback.Run(response ? DBUS_METHOD_CALL_SUCCESS : DBUS_METHOD_CALL_FAILURE); |
| +} |
| + |
| +} // namespace |
| + |
| +void PrivetDaemonManagerClient::PairingInfo::Clear() { |
| + code_.clear(); |
| + mode_.clear(); |
| + session_id_.clear(); |
| +} |
| + |
| +bool PrivetDaemonManagerClient::PairingInfoProperty::PopValueFromReader( |
| + dbus::MessageReader* reader) { |
| + dbus::MessageReader variant_reader(NULL); |
| + dbus::MessageReader array_reader(NULL); |
| + if (!reader->PopVariant(&variant_reader) || |
| + !variant_reader.PopArray(&array_reader)) { |
| + return false; |
| + } |
| + value_.Clear(); |
| + while (array_reader.HasMoreData()) { |
| + dbus::MessageReader dict_entry_reader(NULL); |
| + if (!array_reader.PopDictEntry(&dict_entry_reader)) |
| + return false; |
| + std::string key; |
| + if (!dict_entry_reader.PopString(&key)) |
| + return false; |
| + |
| + dbus::MessageReader field_reader(NULL); |
| + if (!dict_entry_reader.PopVariant(&field_reader)) |
| + return false; |
| + |
| + if (field_reader.GetDataSignature() == "s") { |
| + std::string string_value; |
| + if (!field_reader.PopString(&string_value)) |
| + return false; |
| + if (key == kPairingInfoSessionIdProperty) { |
| + value_.set_session_id(string_value); |
| + } else if (key == kPairingInfoModeProperty) { |
| + value_.set_mode(string_value); |
| + } |
| + } else if (field_reader.GetDataSignature() == "ay") { |
| + const uint8* bytes = NULL; |
| + size_t length = 0; |
| + if (!field_reader.PopArrayOfBytes(&bytes, &length)) |
| + return false; |
| + if (key == kPairingInfoCodeProperty) |
| + value_.set_code(bytes, length); |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +void PrivetDaemonManagerClient::PairingInfoProperty::AppendSetValueToWriter( |
| + dbus::MessageWriter* writer) { |
| + dbus::MessageWriter variant_writer(NULL); |
| + dbus::MessageWriter dict_writer(NULL); |
| + writer->OpenVariant("a{sv}", &variant_writer); |
| + variant_writer.OpenArray("{sv}", &dict_writer); |
| + dbus::MessageWriter entry_writer(NULL); |
| + if (!set_value_.code().empty()) { |
| + dict_writer.OpenDictEntry(&entry_writer); |
| + entry_writer.AppendString(kPairingInfoCodeProperty); |
| + dbus::MessageWriter array_writer(NULL); |
| + entry_writer.OpenVariant("ay", &array_writer); |
| + array_writer.AppendArrayOfBytes(set_value_.code().data(), |
| + set_value_.code().size()); |
| + entry_writer.CloseContainer(&array_writer); |
| + dict_writer.CloseContainer(&entry_writer); |
| + } |
| + if (!set_value_.mode().empty()) { |
| + dict_writer.OpenDictEntry(&entry_writer); |
| + entry_writer.AppendString(kPairingInfoModeProperty); |
| + entry_writer.AppendVariantOfString(set_value_.mode()); |
| + dict_writer.CloseContainer(&entry_writer); |
| + } |
| + if (!set_value_.session_id().empty()) { |
| + dict_writer.OpenDictEntry(&entry_writer); |
| + entry_writer.AppendString(kPairingInfoSessionIdProperty); |
| + entry_writer.AppendVariantOfString(set_value_.session_id()); |
| + dict_writer.CloseContainer(&entry_writer); |
| + } |
| + variant_writer.CloseContainer(&dict_writer); |
| + writer->CloseContainer(&variant_writer); |
| +} |
| + |
| +void PrivetDaemonManagerClient::PairingInfoProperty:: |
| + ReplaceValueWithSetValue() { |
| + value_ = set_value_; |
| + property_set()->NotifyPropertyChanged(name()); |
| +} |
| + |
| +void PrivetDaemonManagerClient::PairingInfoProperty::ReplaceSetValueForTesting( |
| + const PairingInfo& value) { |
| + set_value_ = value; |
| +} |
| + |
| +PrivetDaemonManagerClient::Properties::Properties( |
| + dbus::ObjectProxy* object_proxy, |
| + const std::string& interface_name, |
| + const PropertyChangedCallback& callback) |
| + : dbus::PropertySet(object_proxy, interface_name, callback) { |
| + RegisterProperty(kWiFiBootstrapStateProperty, &wifi_bootstrap_state_); |
| + RegisterProperty(kGCDBootstrapStateProperty, &gcd_bootstrap_state_); |
| + RegisterProperty(kPairingInfoProperty, &pairing_info_); |
| + RegisterProperty(kDescriptionProperty, &description_); |
| + RegisterProperty(kNameProperty, &name_); |
| +} |
| + |
| +PrivetDaemonManagerClient::Properties::~Properties() { |
| +} |
| + |
| +PrivetDaemonManagerClient::Observer::~Observer() { |
| +} |
| + |
| +PrivetDaemonManagerClient::PrivetDaemonManagerClient() { |
| +} |
| + |
| +PrivetDaemonManagerClient::~PrivetDaemonManagerClient() { |
| +} |
| + |
| +// static |
| +PrivetDaemonManagerClient* PrivetDaemonManagerClient::Create() { |
| + return new PrivetDaemonManagerClientImpl(); |
| +} |
| + |
| +} // namespace chromeos |