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/browser/linux/running_application_object.h"
8 #include "base/values.h"
10 #include "content/public/browser/browser_thread.h"
12 #include "dbus/message.h"
13 #include "dbus/exported_object.h"
14 #include "xwalk/application/browser/application_tizen.h"
15 #include "xwalk/application/browser/linux/running_applications_manager.h"
19 // D-Bus Interface implemented by objects that represent running
25 // Will terminate the running application. This object will be unregistered
30 // readonly string AppID
31 const char kRunningApplicationDBusInterface[] =
32 "org.crosswalkproject.Running.Application1";
34 const char kRunningApplicationDBusError[] =
35 "org.crosswalkproject.Running.Application.Error";
41 namespace application {
43 RunningApplicationObject::RunningApplicationObject(
44 scoped_refptr<dbus::Bus> bus,
45 const std::string& app_id,
46 const std::string& launcher_name,
47 Application* application)
48 : dbus::ManagedObject(bus, GetRunningPathForAppID(app_id)),
50 launcher_name_(launcher_name),
51 application_(application) {
52 ListenForOwnerChange();
55 kRunningApplicationDBusInterface, "AppID",
56 scoped_ptr<base::Value>(base::Value::CreateStringValue(app_id)));
58 dbus_object()->ExportMethod(
59 kRunningApplicationDBusInterface, "Terminate",
60 base::Bind(&RunningApplicationObject::OnTerminate,
61 base::Unretained(this)),
62 base::Bind(&RunningApplicationObject::OnExported,
63 base::Unretained(this)));
65 dbus_object()->ExportMethod(
66 kRunningApplicationDBusInterface, "GetEPChannel",
67 base::Bind(&RunningApplicationObject::OnGetExtensionProcessChannel,
68 base::Unretained(this)),
69 base::Bind(&RunningApplicationObject::OnExported,
70 base::Unretained(this)));
73 dbus_object()->ExportMethod(
74 kRunningApplicationDBusInterface, "Hide",
75 base::Bind(&RunningApplicationObject::OnHide,
76 base::Unretained(this)),
77 base::Bind(&RunningApplicationObject::OnExported,
78 base::Unretained(this)));
82 RunningApplicationObject::~RunningApplicationObject() {
83 UnlistenForOwnerChange();
86 void RunningApplicationObject::TerminateApplication() {
87 application_->Terminate();
90 void RunningApplicationObject::OnExported(const std::string& interface_name,
91 const std::string& method_name,
94 LOG(WARNING) << "Error exporting method '" << interface_name
95 << "." << method_name << "' in '"
96 << path().value() << "'.";
100 void RunningApplicationObject::OnTerminate(
101 dbus::MethodCall* method_call,
102 dbus::ExportedObject::ResponseSender response_sender) {
103 // We only allow the caller of Launch() to call Terminate().
104 if (method_call->GetSender() != launcher_name_) {
105 scoped_ptr<dbus::ErrorResponse> error_response =
106 dbus::ErrorResponse::FromMethodCall(method_call,
107 kRunningApplicationDBusError,
109 response_sender.Run(error_response.PassAs<dbus::Response>());
113 TerminateApplication();
115 scoped_ptr<dbus::Response> response =
116 dbus::Response::FromMethodCall(method_call);
117 response_sender.Run(response.Pass());
120 void RunningApplicationObject::OnGetExtensionProcessChannel(
121 dbus::MethodCall* method_call,
122 dbus::ExportedObject::ResponseSender response_sender) {
123 content::BrowserThread::PostTask(
124 content::BrowserThread::FILE,
126 base::Bind(&RunningApplicationObject::SendChannel,
127 base::Unretained(this),
132 #if defined(OS_TIZEN)
133 void RunningApplicationObject::OnHide(
134 dbus::MethodCall* method_call,
135 dbus::ExportedObject::ResponseSender response_sender) {
136 if (method_call->GetSender() != launcher_name_) {
137 scoped_ptr<dbus::ErrorResponse> error_response =
138 dbus::ErrorResponse::FromMethodCall(method_call,
139 kRunningApplicationDBusError,
141 response_sender.Run(error_response.PassAs<dbus::Response>());
145 ToApplicationTizen(application_)->Hide();
147 scoped_ptr<dbus::Response> response =
148 dbus::Response::FromMethodCall(method_call);
149 response_sender.Run(response.Pass());
153 void RunningApplicationObject::ListenForOwnerChange() {
154 owner_change_callback_ =
155 base::Bind(&RunningApplicationObject::OnNameOwnerChanged,
156 base::Unretained(this));
157 bus_->ListenForServiceOwnerChange(launcher_name_, owner_change_callback_);
160 void RunningApplicationObject::UnlistenForOwnerChange() {
161 if (owner_change_callback_.is_null())
163 bus_->UnlistenForServiceOwnerChange(launcher_name_, owner_change_callback_);
164 owner_change_callback_.Reset();
167 void RunningApplicationObject::OnNameOwnerChanged(
168 const std::string& service_owner) {
169 if (service_owner.empty()) {
170 // The process that sent the 'Launch' message has exited the session bus,
171 // we should kill the Running Application.
172 OnLauncherDisappeared();
176 void RunningApplicationObject::OnLauncherDisappeared() {
177 TerminateApplication();
180 void RunningApplicationObject::SendChannel(
181 dbus::MethodCall* method_call,
182 dbus::ExportedObject::ResponseSender response_sender) {
183 scoped_ptr<dbus::Response> response =
184 dbus::Response::FromMethodCall(method_call);
186 int fd = ep_bp_channel_.socket.fd;
187 if (fd == -1) { // EP was not yet created, return empty response.
188 response_sender.Run(response.Pass());
192 dbus::MessageWriter writer(response.get());
193 writer.AppendString(ep_bp_channel_.name);
195 scoped_ptr<dbus::FileDescriptor> client_fd(new dbus::FileDescriptor(fd));
196 client_fd->CheckValidity();
197 CHECK(client_fd->is_valid());
198 writer.AppendFileDescriptor(*client_fd);
200 response_sender.Run(response.Pass());
203 void RunningApplicationObject::ExtensionProcessCreated(
204 const IPC::ChannelHandle& handle) {
205 ep_bp_channel_ = handle;
206 dbus::Signal signal(kRunningApplicationDBusInterface, "EPChannelCreated");
207 dbus_object()->SendSignal(&signal);
210 } // namespace application