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.
5 #include "xwalk/application/tools/linux/dbus_object_manager.h"
7 #include "base/message_loop/message_loop.h"
11 const char kServiceName[] = "org.crosswalkproject.Runtime1";
12 const char kRunningManagerIface[] = "org.crosswalkproject.Running.Manager1";
13 const char kRunningAppIface[] = "org.crosswalkproject.Running.Application1";
14 const char kRunningManagerDBusPath[] = "/running1";
15 const char kEPChannelCreatedSignalName[] = "EPChannelCreated";
17 struct Properties : public dbus::PropertySet {
18 dbus::Property<std::string> app_id;
20 Properties(dbus::ObjectProxy* object_proxy,
21 const std::string& interface_name,
22 PropertyChangedCallback property_changed_callback)
23 : PropertySet(object_proxy, interface_name, property_changed_callback) {
24 RegisterProperty("AppID", &app_id);
30 DBusObjectManager::DBusObjectManager(dbus::Bus* bus,
31 base::MessageLoop* main_loop)
33 main_loop_(main_loop),
34 weak_ptr_factory_(this) {
35 ConnectToApplicationManager();
38 bool DBusObjectManager::Launch(const std::string& appid_or_url,
39 int launcher_pid, bool fullscreen, bool remote_debugging) {
42 dbus::MethodCall method_call(
43 kRunningManagerIface, "Launch");
44 dbus::MessageWriter writer(&method_call);
45 writer.AppendString(appid_or_url);
46 writer.AppendUint32(launcher_pid);
47 writer.AppendBool(fullscreen);
48 writer.AppendBool(remote_debugging);
49 scoped_ptr<dbus::Response> response(
50 running_proxy_->CallMethodAndBlock(&method_call,
51 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
54 if (!response->GetErrorName().empty()) {
55 LOG(ERROR) << "Error during call to 'Launch': "
56 << response->GetErrorName();
60 dbus::MessageReader reader(response.get());
61 dbus::ObjectPath running_application_path;
62 if (!reader.PopObjectPath(&running_application_path)) {
63 LOG(WARNING) << "Failed to create app proxy.";
65 app_proxy_ = bus_->GetObjectProxy(kServiceName, running_application_path);
67 ConnectToApplicationSignal(kEPChannelCreatedSignalName);
72 std::pair<std::string, int> DBusObjectManager::GetEPChannel() const {
73 std::pair<std::string, int> fd;
78 dbus::MethodCall method_call(kRunningAppIface, "GetEPChannel");
79 scoped_ptr<dbus::Response> response = app_proxy_->CallMethodAndBlock(
80 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
81 const std::string& error = response->GetErrorName();
83 LOG(ERROR) << "Error during call to 'GetEPChannel': "
88 dbus::MessageReader reader(response.release());
89 dbus::FileDescriptor extension_process_fd_;
90 if (!reader.PopString(&fd.first) ||
91 !reader.PopFileDescriptor(&extension_process_fd_)) {
92 LOG(ERROR) << "Couldn't get EP Channel";
96 extension_process_fd_.CheckValidity();
97 fd.second = extension_process_fd_.TakeValue();
101 bool DBusObjectManager::Suspend() {
104 dbus::MethodCall method_call(kRunningAppIface, "Suspend");
105 scoped_ptr<dbus::Response> response = app_proxy_->CallMethodAndBlock(
106 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
107 if (!response->GetErrorName().empty()) {
108 LOG(ERROR) << "Error during call to 'Suspend': "
109 << response->GetErrorName();
115 bool DBusObjectManager::Resume() {
118 dbus::MethodCall method_call(kRunningAppIface, "Resume");
119 scoped_ptr<dbus::Response> response = app_proxy_->CallMethodAndBlock(
120 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
121 if (!response->GetErrorName().empty()) {
122 LOG(ERROR) << "Error during call to 'Resume': "
123 << response->GetErrorName();
129 void DBusObjectManager::OnOwnershipCallback(const std::string& service_name,
131 LOG(WARNING) << "Couldn't get ownership of D-Bus service name: "
132 << service_name << ".";
135 void DBusObjectManager::ConnectToApplicationManager() {
136 running_apps_manager_ = bus_->GetObjectManager(kServiceName,
137 dbus::ObjectPath(kRunningManagerDBusPath));
138 running_apps_manager_->RegisterInterface(kRunningAppIface, this);
139 running_proxy_ = bus_->GetObjectProxy(kServiceName,
140 dbus::ObjectPath(kRunningManagerDBusPath));
143 void DBusObjectManager::ObjectAdded(const dbus::ObjectPath& object_path,
144 const std::string& interface_name) {
147 void DBusObjectManager::ObjectRemoved(const dbus::ObjectPath& object_path,
148 const std::string& interface_name) {
149 if (object_path != app_proxy_->object_path())
151 LOG(INFO) << "Application '" << object_path.value()
152 << "' disappeared, exiting.";
153 main_loop_->QuitNow();
156 dbus::PropertySet* DBusObjectManager::CreateProperties(
157 dbus::ObjectProxy *object_proxy,
158 const dbus::ObjectPath& object_path,
159 const std::string& interface_name) {
160 Properties* properties = new Properties(
161 object_proxy, interface_name,
162 base::Bind(&DBusObjectManager::OnPropertyChanged,
163 base::Unretained(this), object_path));
164 return static_cast<dbus::PropertySet*>(properties);
167 void DBusObjectManager::OnPropertyChanged(const dbus::ObjectPath& object_path,
168 const std::string& name) {
169 if (!running_apps_manager_)
170 ConnectToApplicationManager();
173 void DBusObjectManager::ConnectToApplicationSignal(
174 const std::string& signal_name) {
176 app_proxy_->ConnectToSignal(kRunningAppIface, signal_name,
177 base::Bind(&DBusObjectManager::OnAppSignal,
178 weak_ptr_factory_.GetWeakPtr()),
179 base::Bind(&DBusObjectManager::OnAppSignalConnected,
180 weak_ptr_factory_.GetWeakPtr()));
183 bool DBusObjectManager::IsApplicationRunning(const std::string& app_id) {
184 std::vector<dbus::ObjectPath> objects = running_apps_manager_->GetObjects();
185 bool is_running = false;
186 for (dbus::ObjectPath obj : objects) {
187 Properties* properties =
188 static_cast<Properties*>(
189 running_apps_manager_->GetProperties(
190 obj, kRunningAppIface));
193 if (properties->app_id.value() == app_id) {
198 LOG(INFO) << "Application " << app_id << " is "
199 << (is_running ? "running." : "not running.");
203 void DBusObjectManager::OnAppSignal(dbus::Signal* signal) {
204 std::string signal_name = signal->GetMember();
205 if (signal_name == kEPChannelCreatedSignalName) {
207 observer_->OnEPChannelCreated();
209 LOG(INFO) << "Unknown signal received: " << signal_name;
213 void DBusObjectManager::OnAppSignalConnected(
214 const std::string& interface_name,
215 const std::string& signal_name,
218 LOG(WARNING) << "Failed to connect signal: " << signal_name;