// Copyright 2014 The Chromium OS 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-bindings/proxy_generator.h" #include #include #include #include #include #include #include "chromeos-dbus-bindings/interface.h" #include "chromeos-dbus-bindings/test_utils.h" using std::string; using std::vector; using testing::Test; namespace chromeos_dbus_bindings { namespace { const char kDBusTypeArryOfObjects[] = "ao"; const char kDBusTypeArryOfStrings[] = "as"; const char kDBusTypeBool[] = "b"; const char kDBusTypeByte[] = "y"; const char kDBusTypeInt32[] = "i"; const char kDBusTypeInt64[] = "x"; const char kDBusTypeString[] = "s"; const char kExpectedContent[] = R"literal_string( #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace org { namespace chromium { // Abstract interface proxy for org::chromium::TestInterface. class TestInterfaceProxyInterface { public: virtual ~TestInterfaceProxyInterface() = default; virtual bool Elements( const std::string& in_space_walk, const std::vector& in_ramblin_man, std::string* out_3, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual void ElementsAsync( const std::string& in_space_walk, const std::vector& in_ramblin_man, const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual bool ReturnToPatagonia( int64_t* out_1, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual void ReturnToPatagoniaAsync( const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual bool NiceWeatherForDucks( bool in_1, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual void NiceWeatherForDucksAsync( bool in_1, const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; // Comment line1 // line2 virtual bool ExperimentNumberSix( brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; // Comment line1 // line2 virtual void ExperimentNumberSixAsync( const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0; virtual void RegisterTheCurseOfKaZarSignalHandler( const base::Callback&, uint8_t)>& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::TestInterface. class TestInterfaceProxy final : public TestInterfaceProxyInterface { public: TestInterfaceProxy( const scoped_refptr& bus, const std::string& service_name) : bus_{bus}, service_name_{service_name}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~TestInterfaceProxy() override { } void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override { brillo::dbus_utils::ConnectToSignal( dbus_object_proxy_, "org.chromium.TestInterface", "Closer", signal_callback, on_connected_callback); } void RegisterTheCurseOfKaZarSignalHandler( const base::Callback&, uint8_t)>& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override { brillo::dbus_utils::ConnectToSignal( dbus_object_proxy_, "org.chromium.TestInterface", "TheCurseOfKaZar", signal_callback, on_connected_callback); } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } bool Elements( const std::string& in_space_walk, const std::vector& in_ramblin_man, std::string* out_3, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "Elements", error, in_space_walk, in_ramblin_man); return response && brillo::dbus_utils::ExtractMethodCallResults( response.get(), error, out_3); } void ElementsAsync( const std::string& in_space_walk, const std::vector& in_ramblin_man, const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { brillo::dbus_utils::CallMethodWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "Elements", success_callback, error_callback, in_space_walk, in_ramblin_man); } bool ReturnToPatagonia( int64_t* out_1, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "ReturnToPatagonia", error); return response && brillo::dbus_utils::ExtractMethodCallResults( response.get(), error, out_1); } void ReturnToPatagoniaAsync( const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { brillo::dbus_utils::CallMethodWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "ReturnToPatagonia", success_callback, error_callback); } bool NiceWeatherForDucks( bool in_1, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "NiceWeatherForDucks", error, in_1); return response && brillo::dbus_utils::ExtractMethodCallResults( response.get(), error); } void NiceWeatherForDucksAsync( bool in_1, const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { brillo::dbus_utils::CallMethodWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "NiceWeatherForDucks", success_callback, error_callback, in_1); } // Comment line1 // line2 bool ExperimentNumberSix( brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "ExperimentNumberSix", error); return response && brillo::dbus_utils::ExtractMethodCallResults( response.get(), error); } // Comment line1 // line2 void ExperimentNumberSixAsync( const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { brillo::dbus_utils::CallMethodWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface", "ExperimentNumberSix", success_callback, error_callback); } private: scoped_refptr bus_; std::string service_name_; const dbus::ObjectPath object_path_{"/org/chromium/Test"}; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxy); }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Abstract interface proxy for org::chromium::TestInterface2. class TestInterface2ProxyInterface { public: virtual ~TestInterface2ProxyInterface() = default; virtual bool GetPersonInfo( std::string* out_name, int32_t* out_age, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual void GetPersonInfoAsync( const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::TestInterface2. class TestInterface2Proxy final : public TestInterface2ProxyInterface { public: TestInterface2Proxy( const scoped_refptr& bus, const std::string& service_name, const dbus::ObjectPath& object_path) : bus_{bus}, service_name_{service_name}, object_path_{object_path}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~TestInterface2Proxy() override { } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } bool GetPersonInfo( std::string* out_name, int32_t* out_age, brillo::ErrorPtr* error, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface2", "GetPersonInfo", error); return response && brillo::dbus_utils::ExtractMethodCallResults( response.get(), error, out_name, out_age); } void GetPersonInfoAsync( const base::Callback& success_callback, const base::Callback& error_callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override { brillo::dbus_utils::CallMethodWithTimeout( timeout_ms, dbus_object_proxy_, "org.chromium.TestInterface2", "GetPersonInfo", success_callback, error_callback); } private: scoped_refptr bus_; std::string service_name_; dbus::ObjectPath object_path_; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(TestInterface2Proxy); }; } // namespace chromium } // namespace org )literal_string"; const char kExpectedContentWithService[] = R"literal_string( #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace org { namespace chromium { // Abstract interface proxy for org::chromium::TestInterface. class TestInterfaceProxyInterface { public: virtual ~TestInterfaceProxyInterface() = default; virtual void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::TestInterface. class TestInterfaceProxy final : public TestInterfaceProxyInterface { public: TestInterfaceProxy(const scoped_refptr& bus) : bus_{bus}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~TestInterfaceProxy() override { } void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override { brillo::dbus_utils::ConnectToSignal( dbus_object_proxy_, "org.chromium.TestInterface", "Closer", signal_callback, on_connected_callback); } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } private: scoped_refptr bus_; const std::string service_name_{"org.chromium.Test"}; const dbus::ObjectPath object_path_{"/org/chromium/Test"}; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxy); }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Abstract interface proxy for org::chromium::TestInterface2. class TestInterface2ProxyInterface { public: virtual ~TestInterface2ProxyInterface() = default; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::TestInterface2. class TestInterface2Proxy final : public TestInterface2ProxyInterface { public: TestInterface2Proxy( const scoped_refptr& bus, const dbus::ObjectPath& object_path) : bus_{bus}, object_path_{object_path}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~TestInterface2Proxy() override { } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } private: scoped_refptr bus_; const std::string service_name_{"org.chromium.Test"}; dbus::ObjectPath object_path_; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(TestInterface2Proxy); }; } // namespace chromium } // namespace org )literal_string"; const char kExpectedContentWithObjectManager[] = R"literal_string( #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace org { namespace chromium { class ObjectManagerProxy; } // namespace chromium } // namespace org namespace org { namespace chromium { // Abstract interface proxy for org::chromium::Itf1. class Itf1ProxyInterface { public: virtual ~Itf1ProxyInterface() = default; virtual void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0; static const char* DataName() { return "Data"; } virtual const std::string& data() const = 0; static const char* NameName() { return "Name"; } virtual const std::string& name() const = 0; virtual void set_name(const std::string& value, const base::Callback& callback) = 0; virtual const dbus::ObjectPath& GetObjectPath() const = 0; virtual void SetPropertyChangedCallback( const base::Callback& callback) = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::Itf1. class Itf1Proxy final : public Itf1ProxyInterface { public: class PropertySet : public dbus::PropertySet { public: PropertySet(dbus::ObjectProxy* object_proxy, const PropertyChangedCallback& callback) : dbus::PropertySet{object_proxy, "org.chromium.Itf1", callback} { RegisterProperty(DataName(), &data); RegisterProperty(NameName(), &name); } brillo::dbus_utils::Property data; brillo::dbus_utils::Property name; private: DISALLOW_COPY_AND_ASSIGN(PropertySet); }; Itf1Proxy( const scoped_refptr& bus, const std::string& service_name, PropertySet* property_set) : bus_{bus}, service_name_{service_name}, property_set_{property_set}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~Itf1Proxy() override { } void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override { brillo::dbus_utils::ConnectToSignal( dbus_object_proxy_, "org.chromium.Itf1", "Closer", signal_callback, on_connected_callback); } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } void SetPropertyChangedCallback( const base::Callback& callback) override { on_property_changed_ = callback; } const PropertySet* GetProperties() const { return property_set_; } PropertySet* GetProperties() { return property_set_; } const std::string& data() const override { return property_set_->data.value(); } const std::string& name() const override { return property_set_->name.value(); } void set_name(const std::string& value, const base::Callback& callback) override { property_set_->name.Set(value, callback); } private: void OnPropertyChanged(const std::string& property_name) { if (!on_property_changed_.is_null()) on_property_changed_.Run(this, property_name); } scoped_refptr bus_; std::string service_name_; const dbus::ObjectPath object_path_{"/org/chromium/Test/Object"}; PropertySet* property_set_; base::Callback on_property_changed_; dbus::ObjectProxy* dbus_object_proxy_; friend class org::chromium::ObjectManagerProxy; DISALLOW_COPY_AND_ASSIGN(Itf1Proxy); }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Abstract interface proxy for org::chromium::Itf2. class Itf2ProxyInterface { public: virtual ~Itf2ProxyInterface() = default; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::Itf2. class Itf2Proxy final : public Itf2ProxyInterface { public: class PropertySet : public dbus::PropertySet { public: PropertySet(dbus::ObjectProxy* object_proxy, const PropertyChangedCallback& callback) : dbus::PropertySet{object_proxy, "org.chromium.Itf2", callback} { } private: DISALLOW_COPY_AND_ASSIGN(PropertySet); }; Itf2Proxy( const scoped_refptr& bus, const std::string& service_name, const dbus::ObjectPath& object_path) : bus_{bus}, service_name_{service_name}, object_path_{object_path}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~Itf2Proxy() override { } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } private: scoped_refptr bus_; std::string service_name_; dbus::ObjectPath object_path_; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(Itf2Proxy); }; } // namespace chromium } // namespace org namespace org { namespace chromium { class ObjectManagerProxy : public dbus::ObjectManager::Interface { public: ObjectManagerProxy(const scoped_refptr& bus, const std::string& service_name) : bus_{bus}, service_name_{service_name}, dbus_object_manager_{bus->GetObjectManager( service_name, dbus::ObjectPath{"/org/chromium/Test"})} { dbus_object_manager_->RegisterInterface("org.chromium.Itf1", this); dbus_object_manager_->RegisterInterface("org.chromium.Itf2", this); } ~ObjectManagerProxy() override { dbus_object_manager_->UnregisterInterface("org.chromium.Itf1"); dbus_object_manager_->UnregisterInterface("org.chromium.Itf2"); } dbus::ObjectManager* GetObjectManagerProxy() const { return dbus_object_manager_; } org::chromium::Itf1ProxyInterface* GetItf1Proxy() { if (itf1_instances_.empty()) return nullptr; return itf1_instances_.begin()->second.get(); } std::vector GetItf1Instances() const { std::vector values; values.reserve(itf1_instances_.size()); for (const auto& pair : itf1_instances_) values.push_back(pair.second.get()); return values; } void SetItf1AddedCallback( const base::Callback& callback) { on_itf1_added_ = callback; } void SetItf1RemovedCallback( const base::Callback& callback) { on_itf1_removed_ = callback; } org::chromium::Itf2ProxyInterface* GetItf2Proxy( const dbus::ObjectPath& object_path) { auto p = itf2_instances_.find(object_path); if (p != itf2_instances_.end()) return p->second.get(); return nullptr; } std::vector GetItf2Instances() const { std::vector values; values.reserve(itf2_instances_.size()); for (const auto& pair : itf2_instances_) values.push_back(pair.second.get()); return values; } void SetItf2AddedCallback( const base::Callback& callback) { on_itf2_added_ = callback; } void SetItf2RemovedCallback( const base::Callback& callback) { on_itf2_removed_ = callback; } private: void OnPropertyChanged(const dbus::ObjectPath& object_path, const std::string& interface_name, const std::string& property_name) { if (interface_name == "org.chromium.Itf1") { auto p = itf1_instances_.find(object_path); if (p == itf1_instances_.end()) return; p->second->OnPropertyChanged(property_name); return; } } void ObjectAdded( const dbus::ObjectPath& object_path, const std::string& interface_name) override { if (interface_name == "org.chromium.Itf1") { auto property_set = static_cast( dbus_object_manager_->GetProperties(object_path, interface_name)); std::unique_ptr itf1_proxy{ new org::chromium::Itf1Proxy{bus_, service_name_, property_set} }; auto p = itf1_instances_.emplace(object_path, std::move(itf1_proxy)); if (!on_itf1_added_.is_null()) on_itf1_added_.Run(p.first->second.get()); return; } if (interface_name == "org.chromium.Itf2") { std::unique_ptr itf2_proxy{ new org::chromium::Itf2Proxy{bus_, service_name_, object_path} }; auto p = itf2_instances_.emplace(object_path, std::move(itf2_proxy)); if (!on_itf2_added_.is_null()) on_itf2_added_.Run(p.first->second.get()); return; } } void ObjectRemoved( const dbus::ObjectPath& object_path, const std::string& interface_name) override { if (interface_name == "org.chromium.Itf1") { auto p = itf1_instances_.find(object_path); if (p != itf1_instances_.end()) { if (!on_itf1_removed_.is_null()) on_itf1_removed_.Run(object_path); itf1_instances_.erase(p); } return; } if (interface_name == "org.chromium.Itf2") { auto p = itf2_instances_.find(object_path); if (p != itf2_instances_.end()) { if (!on_itf2_removed_.is_null()) on_itf2_removed_.Run(object_path); itf2_instances_.erase(p); } return; } } dbus::PropertySet* CreateProperties( dbus::ObjectProxy* object_proxy, const dbus::ObjectPath& object_path, const std::string& interface_name) override { if (interface_name == "org.chromium.Itf1") { return new org::chromium::Itf1Proxy::PropertySet{ object_proxy, base::Bind(&ObjectManagerProxy::OnPropertyChanged, weak_ptr_factory_.GetWeakPtr(), object_path, interface_name) }; } if (interface_name == "org.chromium.Itf2") { return new org::chromium::Itf2Proxy::PropertySet{ object_proxy, base::Bind(&ObjectManagerProxy::OnPropertyChanged, weak_ptr_factory_.GetWeakPtr(), object_path, interface_name) }; } LOG(FATAL) << "Creating properties for unsupported interface " << interface_name; return nullptr; } scoped_refptr bus_; std::string service_name_; dbus::ObjectManager* dbus_object_manager_; std::map> itf1_instances_; base::Callback on_itf1_added_; base::Callback on_itf1_removed_; std::map> itf2_instances_; base::Callback on_itf2_added_; base::Callback on_itf2_removed_; base::WeakPtrFactory weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ObjectManagerProxy); }; } // namespace chromium } // namespace org )literal_string"; const char kExpectedContentWithObjectManagerAndServiceName[] = R"literal_string( #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace org { namespace chromium { class ObjectManagerProxy; } // namespace chromium } // namespace org namespace org { namespace chromium { // Abstract interface proxy for org::chromium::Itf1. class Itf1ProxyInterface { public: virtual ~Itf1ProxyInterface() = default; virtual void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::Itf1. class Itf1Proxy final : public Itf1ProxyInterface { public: class PropertySet : public dbus::PropertySet { public: PropertySet(dbus::ObjectProxy* object_proxy, const PropertyChangedCallback& callback) : dbus::PropertySet{object_proxy, "org.chromium.Itf1", callback} { } private: DISALLOW_COPY_AND_ASSIGN(PropertySet); }; Itf1Proxy(const scoped_refptr& bus) : bus_{bus}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~Itf1Proxy() override { } void RegisterCloserSignalHandler( const base::Closure& signal_callback, dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override { brillo::dbus_utils::ConnectToSignal( dbus_object_proxy_, "org.chromium.Itf1", "Closer", signal_callback, on_connected_callback); } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } private: scoped_refptr bus_; const std::string service_name_{"org.chromium.Test"}; const dbus::ObjectPath object_path_{"/org/chromium/Test/Object"}; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(Itf1Proxy); }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Abstract interface proxy for org::chromium::Itf2. class Itf2ProxyInterface { public: virtual ~Itf2ProxyInterface() = default; virtual const dbus::ObjectPath& GetObjectPath() const = 0; }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Interface proxy for org::chromium::Itf2. class Itf2Proxy final : public Itf2ProxyInterface { public: class PropertySet : public dbus::PropertySet { public: PropertySet(dbus::ObjectProxy* object_proxy, const PropertyChangedCallback& callback) : dbus::PropertySet{object_proxy, "org.chromium.Itf2", callback} { } private: DISALLOW_COPY_AND_ASSIGN(PropertySet); }; Itf2Proxy( const scoped_refptr& bus, const dbus::ObjectPath& object_path) : bus_{bus}, object_path_{object_path}, dbus_object_proxy_{ bus_->GetObjectProxy(service_name_, object_path_)} { } ~Itf2Proxy() override { } void ReleaseObjectProxy(const base::Closure& callback) { bus_->RemoveObjectProxy(service_name_, object_path_, callback); } const dbus::ObjectPath& GetObjectPath() const override { return object_path_; } dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; } private: scoped_refptr bus_; const std::string service_name_{"org.chromium.Test"}; dbus::ObjectPath object_path_; dbus::ObjectProxy* dbus_object_proxy_; DISALLOW_COPY_AND_ASSIGN(Itf2Proxy); }; } // namespace chromium } // namespace org namespace org { namespace chromium { class ObjectManagerProxy : public dbus::ObjectManager::Interface { public: ObjectManagerProxy(const scoped_refptr& bus) : bus_{bus}, dbus_object_manager_{bus->GetObjectManager( "org.chromium.Test", dbus::ObjectPath{"/org/chromium/Test"})} { dbus_object_manager_->RegisterInterface("org.chromium.Itf1", this); dbus_object_manager_->RegisterInterface("org.chromium.Itf2", this); } ~ObjectManagerProxy() override { dbus_object_manager_->UnregisterInterface("org.chromium.Itf1"); dbus_object_manager_->UnregisterInterface("org.chromium.Itf2"); } dbus::ObjectManager* GetObjectManagerProxy() const { return dbus_object_manager_; } org::chromium::Itf1ProxyInterface* GetItf1Proxy() { if (itf1_instances_.empty()) return nullptr; return itf1_instances_.begin()->second.get(); } std::vector GetItf1Instances() const { std::vector values; values.reserve(itf1_instances_.size()); for (const auto& pair : itf1_instances_) values.push_back(pair.second.get()); return values; } void SetItf1AddedCallback( const base::Callback& callback) { on_itf1_added_ = callback; } void SetItf1RemovedCallback( const base::Callback& callback) { on_itf1_removed_ = callback; } org::chromium::Itf2ProxyInterface* GetItf2Proxy( const dbus::ObjectPath& object_path) { auto p = itf2_instances_.find(object_path); if (p != itf2_instances_.end()) return p->second.get(); return nullptr; } std::vector GetItf2Instances() const { std::vector values; values.reserve(itf2_instances_.size()); for (const auto& pair : itf2_instances_) values.push_back(pair.second.get()); return values; } void SetItf2AddedCallback( const base::Callback& callback) { on_itf2_added_ = callback; } void SetItf2RemovedCallback( const base::Callback& callback) { on_itf2_removed_ = callback; } private: void OnPropertyChanged(const dbus::ObjectPath& /* object_path */, const std::string& /* interface_name */, const std::string& /* property_name */) {} void ObjectAdded( const dbus::ObjectPath& object_path, const std::string& interface_name) override { if (interface_name == "org.chromium.Itf1") { std::unique_ptr itf1_proxy{ new org::chromium::Itf1Proxy{bus_} }; auto p = itf1_instances_.emplace(object_path, std::move(itf1_proxy)); if (!on_itf1_added_.is_null()) on_itf1_added_.Run(p.first->second.get()); return; } if (interface_name == "org.chromium.Itf2") { std::unique_ptr itf2_proxy{ new org::chromium::Itf2Proxy{bus_, object_path} }; auto p = itf2_instances_.emplace(object_path, std::move(itf2_proxy)); if (!on_itf2_added_.is_null()) on_itf2_added_.Run(p.first->second.get()); return; } } void ObjectRemoved( const dbus::ObjectPath& object_path, const std::string& interface_name) override { if (interface_name == "org.chromium.Itf1") { auto p = itf1_instances_.find(object_path); if (p != itf1_instances_.end()) { if (!on_itf1_removed_.is_null()) on_itf1_removed_.Run(object_path); itf1_instances_.erase(p); } return; } if (interface_name == "org.chromium.Itf2") { auto p = itf2_instances_.find(object_path); if (p != itf2_instances_.end()) { if (!on_itf2_removed_.is_null()) on_itf2_removed_.Run(object_path); itf2_instances_.erase(p); } return; } } dbus::PropertySet* CreateProperties( dbus::ObjectProxy* object_proxy, const dbus::ObjectPath& object_path, const std::string& interface_name) override { if (interface_name == "org.chromium.Itf1") { return new org::chromium::Itf1Proxy::PropertySet{ object_proxy, base::Bind(&ObjectManagerProxy::OnPropertyChanged, weak_ptr_factory_.GetWeakPtr(), object_path, interface_name) }; } if (interface_name == "org.chromium.Itf2") { return new org::chromium::Itf2Proxy::PropertySet{ object_proxy, base::Bind(&ObjectManagerProxy::OnPropertyChanged, weak_ptr_factory_.GetWeakPtr(), object_path, interface_name) }; } LOG(FATAL) << "Creating properties for unsupported interface " << interface_name; return nullptr; } scoped_refptr bus_; dbus::ObjectManager* dbus_object_manager_; std::map> itf1_instances_; base::Callback on_itf1_added_; base::Callback on_itf1_removed_; std::map> itf2_instances_; base::Callback on_itf2_added_; base::Callback on_itf2_removed_; base::WeakPtrFactory weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ObjectManagerProxy); }; } // namespace chromium } // namespace org )literal_string"; } // namespace class ProxyGeneratorTest : public Test { public: void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } protected: base::FilePath CreateInputFile(const string& contents) { base::FilePath path; EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path)); int written = base::WriteFile(path, contents.c_str(), contents.size()); EXPECT_EQ(contents.size(), static_cast(written)); return path; } base::ScopedTempDir temp_dir_; }; TEST_F(ProxyGeneratorTest, GenerateAdaptors) { Interface interface; interface.name = "org.chromium.TestInterface"; interface.path = "/org/chromium/Test"; interface.methods.emplace_back( "Elements", vector{ {"space_walk", kDBusTypeString}, {"ramblin_man", kDBusTypeArryOfObjects}}, vector{{"", kDBusTypeString}}); interface.methods.emplace_back( "ReturnToPatagonia", vector{}, vector{{"", kDBusTypeInt64}}); interface.methods.emplace_back( "NiceWeatherForDucks", vector{{"", kDBusTypeBool}}, vector{}); interface.methods.emplace_back("ExperimentNumberSix"); interface.signals.emplace_back("Closer"); interface.signals.emplace_back( "TheCurseOfKaZar", vector{ {"", kDBusTypeArryOfStrings}, {"", kDBusTypeByte}}); interface.methods.back().doc_string = "Comment line1\nline2"; Interface interface2; interface2.name = "org.chromium.TestInterface2"; interface2.methods.emplace_back( "GetPersonInfo", vector{}, vector{ {"name", kDBusTypeString}, {"age", kDBusTypeInt32}}); vector interfaces{interface, interface2}; base::FilePath output_path = temp_dir_.path().Append("output.h"); ServiceConfig config; EXPECT_TRUE(ProxyGenerator::GenerateProxies(config, interfaces, output_path)); string contents; EXPECT_TRUE(base::ReadFileToString(output_path, &contents)); // The header guards contain the (temporary) filename, so we search for // the content we need within the string. test_utils::EXPECT_TEXT_CONTAINED(kExpectedContent, contents); } TEST_F(ProxyGeneratorTest, GenerateAdaptorsWithServiceName) { Interface interface; interface.name = "org.chromium.TestInterface"; interface.path = "/org/chromium/Test"; interface.signals.emplace_back("Closer"); Interface interface2; interface2.name = "org.chromium.TestInterface2"; vector interfaces{interface, interface2}; base::FilePath output_path = temp_dir_.path().Append("output2.h"); ServiceConfig config; config.service_name = "org.chromium.Test"; EXPECT_TRUE(ProxyGenerator::GenerateProxies(config, interfaces, output_path)); string contents; EXPECT_TRUE(base::ReadFileToString(output_path, &contents)); // The header guards contain the (temporary) filename, so we search for // the content we need within the string. test_utils::EXPECT_TEXT_CONTAINED(kExpectedContentWithService, contents); } TEST_F(ProxyGeneratorTest, GenerateAdaptorsWithObjectManager) { Interface interface; interface.name = "org.chromium.Itf1"; interface.path = "/org/chromium/Test/Object"; interface.signals.emplace_back("Closer"); interface.properties.emplace_back("Data", "s", "read"); interface.properties.emplace_back("Name", "s", "readwrite"); Interface interface2; interface2.name = "org.chromium.Itf2"; vector interfaces{interface, interface2}; base::FilePath output_path = temp_dir_.path().Append("output3.h"); ServiceConfig config; config.object_manager.name = "org.chromium.ObjectManager"; config.object_manager.object_path = "/org/chromium/Test"; EXPECT_TRUE(ProxyGenerator::GenerateProxies(config, interfaces, output_path)); string contents; EXPECT_TRUE(base::ReadFileToString(output_path, &contents)); // The header guards contain the (temporary) filename, so we search for // the content we need within the string. test_utils::EXPECT_TEXT_CONTAINED( kExpectedContentWithObjectManager, contents); } TEST_F(ProxyGeneratorTest, GenerateAdaptorsWithObjectManagerAndServiceName) { Interface interface; interface.name = "org.chromium.Itf1"; interface.path = "/org/chromium/Test/Object"; interface.signals.emplace_back("Closer"); Interface interface2; interface2.name = "org.chromium.Itf2"; vector interfaces{interface, interface2}; base::FilePath output_path = temp_dir_.path().Append("output4.h"); ServiceConfig config; config.service_name = "org.chromium.Test"; config.object_manager.name = "org.chromium.ObjectManager"; config.object_manager.object_path = "/org/chromium/Test"; EXPECT_TRUE(ProxyGenerator::GenerateProxies(config, interfaces, output_path)); string contents; EXPECT_TRUE(base::ReadFileToString(output_path, &contents)); // The header guards contain the (temporary) filename, so we search for // the content we need within the string. test_utils::EXPECT_TEXT_CONTAINED( kExpectedContentWithObjectManagerAndServiceName, contents); } } // namespace chromeos_dbus_bindings