96a0878f098f9390a73dd39bf2c2fe06f7419fb6
[platform/framework/web/crosswalk.git] / src / xwalk / dbus / object_manager_adaptor.cc
1 // Copyright (c) 2013 Intel Corporation. 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 "xwalk/dbus/object_manager_adaptor.h"
6
7 #include <vector>
8 #include "base/bind.h"
9 #include "dbus/bus.h"
10 #include "dbus/message.h"
11
12 namespace {
13
14 const char kDBusObjectManagerInterface[] = "org.freedesktop.DBus.ObjectManager";
15
16 }  // namespace
17
18 namespace dbus {
19
20 ObjectManagerAdaptor::ObjectManagerAdaptor(scoped_refptr<Bus> bus,
21                                            const ObjectPath& manager_path)
22     : weak_factory_(this),
23       manager_path_(manager_path),
24       manager_object_(bus->GetExportedObject(manager_path)),
25       bus_(bus),
26       is_exported_(false) {
27   manager_object_->ExportMethod(
28       kDBusObjectManagerInterface, "GetManagedObjects",
29       base::Bind(&ObjectManagerAdaptor::OnGetManagedObjects,
30                  weak_factory_.GetWeakPtr()),
31       base::Bind(&ObjectManagerAdaptor::OnExported,
32                  weak_factory_.GetWeakPtr()));
33 }
34
35 ObjectManagerAdaptor::~ObjectManagerAdaptor() {
36   RemoveAllManagedObjects();
37   bus_->UnregisterExportedObject(manager_path_);
38 }
39
40 void ObjectManagerAdaptor::AddManagedObject(scoped_ptr<ManagedObject> object) {
41   EmitInterfacesAdded(object.get());
42   managed_objects_.push_back(object.release());
43 }
44
45 namespace {
46
47 struct MatchObjectPath {
48  public:
49   explicit MatchObjectPath(const ObjectPath& path) : path_(path) {}
50   bool operator()(const ManagedObject* object) {
51     return path_ == object->path();
52   }
53   const ObjectPath path_;
54 };
55
56 }  // namespace
57
58 void ObjectManagerAdaptor::RemoveManagedObject(const ObjectPath& path) {
59   ScopedVector<ManagedObject>::iterator it = std::find_if(
60       managed_objects_.begin(), managed_objects_.end(), MatchObjectPath(path));
61   if (it == managed_objects_.end()) {
62     LOG(WARNING) << "Error removing unmanaged object with path: "
63                  << path.value();
64     return;
65   }
66
67   EmitInterfacesRemoved(*it);
68
69   // We need to explicitly unregister the exported object, otherwise the Bus
70   // would keep it alive.
71   bus_->UnregisterExportedObject(path);
72
73   // Since this is a ScopedVector, erasing will actually destroy the value.
74   managed_objects_.erase(it);
75 }
76
77 ManagedObject* ObjectManagerAdaptor::GetManagedObject(const ObjectPath& path) {
78   ScopedVector<ManagedObject>::iterator it = std::find_if(
79       managed_objects_.begin(), managed_objects_.end(), MatchObjectPath(path));
80   if (it == managed_objects_.end())
81     return NULL;
82   return *it;
83 }
84
85 void ObjectManagerAdaptor::OnGetManagedObjects(
86     MethodCall* method_call,
87     ExportedObject::ResponseSender response_sender) {
88   scoped_ptr<Response> response =
89       Response::FromMethodCall(method_call);
90   MessageWriter writer(response.get());
91
92   MessageWriter dict_writer(NULL);
93   writer.OpenArray("{oa{sa{sv}}}", &dict_writer);
94
95   ScopedVector<ManagedObject>::const_iterator it;
96   for (it = managed_objects_.begin(); it != managed_objects_.end(); ++it) {
97     ManagedObject* object = *it;
98     MessageWriter entry_writer(NULL);
99
100     dict_writer.OpenDictEntry(&entry_writer);
101     entry_writer.AppendObjectPath(object->path());
102     object->AppendAllPropertiesToWriter(&entry_writer);
103     dict_writer.CloseContainer(&entry_writer);
104   }
105
106   writer.CloseContainer(&dict_writer);
107   response_sender.Run(response.Pass());
108 }
109
110 void ObjectManagerAdaptor::OnExported(const std::string& interface_name,
111                                const std::string& method_name,
112                                bool success) {
113   if (!success) {
114     LOG(WARNING) << "Error exporting method '" << interface_name
115                  << "." << method_name << "' in '"
116                  << manager_path_.value() << "'.";
117     return;
118   }
119
120   is_exported_ = true;
121 }
122
123 void ObjectManagerAdaptor::RemoveAllManagedObjects() {
124   ScopedVector<ManagedObject>::iterator it = managed_objects_.begin();
125   for (; it != managed_objects_.end(); ++it) {
126     EmitInterfacesRemoved(*it);
127     bus_->UnregisterExportedObject((*it)->path());
128   }
129
130   // Since this is a ScopedVector, clearing will destroy all values.
131   managed_objects_.clear();
132 }
133
134 void ObjectManagerAdaptor::EmitInterfacesAdded(const ManagedObject* object) {
135   // We only start sending signals after the GetManagedObjects() was exported.
136   // This allow us to bootstrap the list of managed objects right after
137   // construction of the adaptor without sending unnecessary signals.
138   if (!is_exported_)
139     return;
140
141   Signal interfaces_added(kDBusObjectManagerInterface, "InterfacesAdded");
142   MessageWriter writer(&interfaces_added);
143
144   writer.AppendObjectPath(object->path());
145   object->AppendAllPropertiesToWriter(&writer);
146   manager_object_->SendSignal(&interfaces_added);
147 }
148
149 void ObjectManagerAdaptor::EmitInterfacesRemoved(const ManagedObject* object) {
150   // See comment in EmitInterfacesAdded().
151   if (!is_exported_)
152     return;
153
154   Signal interfaces_removed(kDBusObjectManagerInterface, "InterfacesRemoved");
155   MessageWriter writer(&interfaces_removed);
156
157   writer.AppendObjectPath(object->path());
158   object->AppendInterfacesToWriter(&writer);
159   manager_object_->SendSignal(&interfaces_removed);
160 }
161
162 ManagedObject::ManagedObject(scoped_refptr<Bus> bus, const ObjectPath& path)
163     : dbus_object_(bus->GetExportedObject(path)),
164       path_(path),
165       properties_(dbus_object_, path_) {}
166
167 ManagedObject::~ManagedObject() {}
168
169 ObjectPath ManagedObject::path() const {
170   return path_;
171 };
172
173 void ManagedObject::AppendAllPropertiesToWriter(MessageWriter* writer) const {
174   MessageWriter interfaces_writer(NULL);
175   writer->OpenArray("{sa{sv}}", &interfaces_writer);
176
177   std::vector<std::string> interfaces = properties_.interfaces();
178   for (int i = 0; i < interfaces.size(); i++) {
179     MessageWriter entry_writer(NULL);
180     interfaces_writer.OpenDictEntry(&entry_writer);
181     entry_writer.AppendString(interfaces[i]);
182     properties_.AppendPropertiesToWriter(interfaces[i], &entry_writer);
183     interfaces_writer.CloseContainer(&entry_writer);
184   }
185
186   writer->CloseContainer(&interfaces_writer);
187 }
188
189 void ManagedObject::AppendInterfacesToWriter(MessageWriter* writer) const {
190   writer->AppendArrayOfStrings(properties_.interfaces());
191 }
192
193 }  // namespace dbus