Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / linux / running_application_object.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/application/browser/linux/running_application_object.h"
6
7 #include <string>
8 #include "base/values.h"
9 #include "base/bind.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "dbus/bus.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"
16
17 namespace {
18
19 // D-Bus Interface implemented by objects that represent running
20 // applications.
21 //
22 // Methods:
23 //
24 //   Terminate()
25 //     Will terminate the running application. This object will be unregistered
26 //     from D-Bus.
27 //
28 // Properties:
29 //
30 //   readonly string AppID
31 const char kRunningApplicationDBusInterface[] =
32     "org.crosswalkproject.Running.Application1";
33
34 const char kRunningApplicationDBusError[] =
35     "org.crosswalkproject.Running.Application.Error";
36
37
38 }  // namespace
39
40 namespace xwalk {
41 namespace application {
42
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)),
49       bus_(bus),
50       launcher_name_(launcher_name),
51       application_(application) {
52   ListenForOwnerChange();
53
54   properties()->Set(
55       kRunningApplicationDBusInterface, "AppID",
56       scoped_ptr<base::Value>(base::Value::CreateStringValue(app_id)));
57
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)));
64
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)));
71
72 #if defined(OS_TIZEN)
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)));
79
80   dbus_object()->ExportMethod(
81       kRunningApplicationDBusInterface, "Suspend",
82       base::Bind(&RunningApplicationObject::OnSuspend,
83                  base::Unretained(this)),
84       base::Bind(&RunningApplicationObject::OnExported,
85                  base::Unretained(this)));
86
87   dbus_object()->ExportMethod(
88       kRunningApplicationDBusInterface, "Resume",
89       base::Bind(&RunningApplicationObject::OnResume,
90                  base::Unretained(this)),
91       base::Bind(&RunningApplicationObject::OnExported,
92                  base::Unretained(this)));
93 #endif
94 }
95
96 RunningApplicationObject::~RunningApplicationObject() {
97   UnlistenForOwnerChange();
98 }
99
100 void RunningApplicationObject::TerminateApplication() {
101   application_->Terminate();
102 }
103
104 void RunningApplicationObject::OnExported(const std::string& interface_name,
105                                           const std::string& method_name,
106                                           bool success) {
107   if (!success) {
108     LOG(WARNING) << "Error exporting method '" << interface_name
109                  << "." << method_name << "' in '"
110                  << path().value() << "'.";
111   }
112 }
113
114 void RunningApplicationObject::OnTerminate(
115     dbus::MethodCall* method_call,
116     dbus::ExportedObject::ResponseSender response_sender) {
117   // We only allow the caller of Launch() to call Terminate().
118   if (method_call->GetSender() != launcher_name_) {
119     scoped_ptr<dbus::ErrorResponse> error_response =
120         dbus::ErrorResponse::FromMethodCall(method_call,
121                                             kRunningApplicationDBusError,
122                                             "Not permitted");
123     response_sender.Run(error_response.PassAs<dbus::Response>());
124     return;
125   }
126
127   TerminateApplication();
128
129   scoped_ptr<dbus::Response> response =
130       dbus::Response::FromMethodCall(method_call);
131   response_sender.Run(response.Pass());
132 }
133
134 void RunningApplicationObject::OnGetExtensionProcessChannel(
135     dbus::MethodCall* method_call,
136     dbus::ExportedObject::ResponseSender response_sender) {
137   content::BrowserThread::PostTask(
138       content::BrowserThread::FILE,
139       FROM_HERE,
140       base::Bind(&RunningApplicationObject::SendChannel,
141                  base::Unretained(this),
142                  method_call,
143                  response_sender));
144 }
145
146 #if defined(OS_TIZEN)
147 void RunningApplicationObject::OnHide(
148     dbus::MethodCall* method_call,
149     dbus::ExportedObject::ResponseSender response_sender) {
150   if (method_call->GetSender() != launcher_name_) {
151     scoped_ptr<dbus::ErrorResponse> error_response =
152         dbus::ErrorResponse::FromMethodCall(method_call,
153                                             kRunningApplicationDBusError,
154                                             "Not permitted");
155     response_sender.Run(error_response.PassAs<dbus::Response>());
156     return;
157   }
158
159   ToApplicationTizen(application_)->Hide();
160
161   scoped_ptr<dbus::Response> response =
162       dbus::Response::FromMethodCall(method_call);
163   response_sender.Run(response.Pass());
164 }
165
166 void RunningApplicationObject::OnSuspend(
167     dbus::MethodCall* method_call,
168     dbus::ExportedObject::ResponseSender response_sender) {
169   if (method_call->GetSender() != launcher_name_) {
170     scoped_ptr<dbus::ErrorResponse> error_response =
171         dbus::ErrorResponse::FromMethodCall(method_call,
172                                             kRunningApplicationDBusError,
173                                             "Not permitted");
174     response_sender.Run(error_response.PassAs<dbus::Response>());
175     return;
176   }
177
178   ToApplicationTizen(application_)->Suspend();
179
180   scoped_ptr<dbus::Response> response =
181       dbus::Response::FromMethodCall(method_call);
182   response_sender.Run(response.Pass());
183 }
184
185 void RunningApplicationObject::OnResume(
186     dbus::MethodCall* method_call,
187     dbus::ExportedObject::ResponseSender response_sender) {
188   if (method_call->GetSender() != launcher_name_) {
189     scoped_ptr<dbus::ErrorResponse> error_response =
190         dbus::ErrorResponse::FromMethodCall(method_call,
191                                             kRunningApplicationDBusError,
192                                             "Not permitted");
193     response_sender.Run(error_response.PassAs<dbus::Response>());
194     return;
195   }
196
197   ToApplicationTizen(application_)->Resume();
198
199   scoped_ptr<dbus::Response> response =
200       dbus::Response::FromMethodCall(method_call);
201   response_sender.Run(response.Pass());
202 }
203 #endif
204
205 void RunningApplicationObject::ListenForOwnerChange() {
206   owner_change_callback_ =
207       base::Bind(&RunningApplicationObject::OnNameOwnerChanged,
208                  base::Unretained(this));
209   bus_->ListenForServiceOwnerChange(launcher_name_, owner_change_callback_);
210 }
211
212 void RunningApplicationObject::UnlistenForOwnerChange() {
213   if (owner_change_callback_.is_null())
214     return;
215   bus_->UnlistenForServiceOwnerChange(launcher_name_, owner_change_callback_);
216   owner_change_callback_.Reset();
217 }
218
219 void RunningApplicationObject::OnNameOwnerChanged(
220     const std::string& service_owner) {
221   if (service_owner.empty()) {
222     // The process that sent the 'Launch' message has exited the session bus,
223     // we should kill the Running Application.
224     OnLauncherDisappeared();
225   }
226 }
227
228 void RunningApplicationObject::OnLauncherDisappeared() {
229   TerminateApplication();
230 }
231
232 void RunningApplicationObject::SendChannel(
233     dbus::MethodCall* method_call,
234     dbus::ExportedObject::ResponseSender response_sender) {
235   scoped_ptr<dbus::Response> response =
236       dbus::Response::FromMethodCall(method_call);
237
238   int fd = ep_bp_channel_.socket.fd;
239   if (fd == -1) {  // EP was not yet created, return empty response.
240     response_sender.Run(response.Pass());
241     return;
242   }
243
244   dbus::MessageWriter writer(response.get());
245   writer.AppendString(ep_bp_channel_.name);
246
247   scoped_ptr<dbus::FileDescriptor> client_fd(new dbus::FileDescriptor(fd));
248   client_fd->CheckValidity();
249   CHECK(client_fd->is_valid());
250   writer.AppendFileDescriptor(*client_fd);
251
252   response_sender.Run(response.Pass());
253 }
254
255 void RunningApplicationObject::ExtensionProcessCreated(
256     const IPC::ChannelHandle& handle) {
257   ep_bp_channel_ = handle;
258   dbus::Signal signal(kRunningApplicationDBusInterface, "EPChannelCreated");
259   dbus_object()->SendSignal(&signal);
260 }
261
262 }  // namespace application
263 }  // namespace xwalk