Upstream version 6.35.132.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/linux/running_applications_manager.h"
15
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), Application::Normal),
62       base::Bind(&RunningApplicationObject::OnExported,
63                  base::Unretained(this)));
64
65   dbus_object()->ExportMethod(
66       kRunningApplicationDBusInterface, "ForceTerminate",
67       base::Bind(&RunningApplicationObject::OnTerminate,
68                  base::Unretained(this), Application::Immediate),
69       base::Bind(&RunningApplicationObject::OnExported,
70                  base::Unretained(this)));
71
72   dbus_object()->ExportMethod(
73       kRunningApplicationDBusInterface, "GetEPChannel",
74       base::Bind(&RunningApplicationObject::OnGetExtensionProcessChannel,
75                  base::Unretained(this)),
76       base::Bind(&RunningApplicationObject::OnExported,
77                  base::Unretained(this)));
78
79 #if defined(OS_TIZEN)
80   dbus_object()->ExportMethod(
81       kRunningApplicationDBusInterface, "Hide",
82       base::Bind(&RunningApplicationObject::OnHide,
83                  base::Unretained(this)),
84       base::Bind(&RunningApplicationObject::OnExported,
85                  base::Unretained(this)));
86 #endif
87 }
88
89 RunningApplicationObject::~RunningApplicationObject() {
90   UnlistenForOwnerChange();
91 }
92
93 void RunningApplicationObject::TerminateApplication(
94     Application::TerminationMode mode) {
95   // The application might be still running after 'Terminate' call
96   // (if 'mode == Normal' and it contains 'OnSuspend' handlers),
97   // so we do not call 'UnlistenForOwnerChange' here - it will
98   // be called anyway right before the actual 'Application' instance
99   // deletion.
100   application_->Terminate(mode);
101 }
102
103 void RunningApplicationObject::OnExported(const std::string& interface_name,
104                                           const std::string& method_name,
105                                           bool success) {
106   if (!success) {
107     LOG(WARNING) << "Error exporting method '" << interface_name
108                  << "." << method_name << "' in '"
109                  << path().value() << "'.";
110   }
111 }
112
113 void RunningApplicationObject::OnTerminate(
114     Application::TerminationMode mode,
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(mode);
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::PostTaskAndReplyWithResult(
138       content::BrowserThread::FILE,
139       FROM_HERE,
140       base::Bind(&RunningApplicationObject::CreateClientFileDescriptor,
141                  base::Unretained(this)),
142       base::Bind(&RunningApplicationObject::SendChannel,
143                  base::Unretained(this),
144                  method_call,
145                  response_sender));
146 }
147
148 #if defined(OS_TIZEN)
149 void RunningApplicationObject::OnHide(
150     dbus::MethodCall* method_call,
151     dbus::ExportedObject::ResponseSender response_sender) {
152   if (method_call->GetSender() != launcher_name_) {
153     scoped_ptr<dbus::ErrorResponse> error_response =
154         dbus::ErrorResponse::FromMethodCall(method_call,
155                                             kRunningApplicationDBusError,
156                                             "Not permitted");
157     response_sender.Run(error_response.PassAs<dbus::Response>());
158     return;
159   }
160
161   application_->Hide();
162
163   scoped_ptr<dbus::Response> response =
164       dbus::Response::FromMethodCall(method_call);
165   response_sender.Run(response.Pass());
166 }
167 #endif
168
169 void RunningApplicationObject::ListenForOwnerChange() {
170   owner_change_callback_ =
171       base::Bind(&RunningApplicationObject::OnNameOwnerChanged,
172                  base::Unretained(this));
173   bus_->ListenForServiceOwnerChange(launcher_name_, owner_change_callback_);
174 }
175
176 void RunningApplicationObject::UnlistenForOwnerChange() {
177   if (owner_change_callback_.is_null())
178     return;
179   bus_->UnlistenForServiceOwnerChange(launcher_name_, owner_change_callback_);
180   owner_change_callback_.Reset();
181 }
182
183 void RunningApplicationObject::OnNameOwnerChanged(
184     const std::string& service_owner) {
185   if (service_owner.empty()) {
186     // The process that sent the 'Launch' message has exited the session bus,
187     // we should kill the Running Application.
188     OnLauncherDisappeared();
189   }
190 }
191
192 void RunningApplicationObject::OnLauncherDisappeared() {
193   // Do not care about 'OnSuspend' handlers if the launcher is already killed.
194   TerminateApplication(Application::Immediate);
195 }
196
197 scoped_ptr<dbus::FileDescriptor>
198 RunningApplicationObject::CreateClientFileDescriptor() {
199   scoped_ptr<dbus::FileDescriptor> client_fd(
200       new dbus::FileDescriptor(ep_bp_channel_.socket.fd));
201   client_fd->CheckValidity();
202   return client_fd.Pass();
203 }
204
205 void RunningApplicationObject::SendChannel(
206     dbus::MethodCall* method_call,
207     dbus::ExportedObject::ResponseSender response_sender,
208     scoped_ptr<dbus::FileDescriptor> client_fd) {
209   scoped_ptr<dbus::Response> response =
210       dbus::Response::FromMethodCall(method_call);
211   dbus::MessageWriter writer(response.get());
212
213   writer.AppendString(ep_bp_channel_.name);
214   writer.AppendFileDescriptor(*client_fd);
215   response_sender.Run(response.Pass());
216 }
217
218 void RunningApplicationObject::ExtensionProcessCreated(
219     const IPC::ChannelHandle& handle) {
220   ep_bp_channel_ = handle;
221   dbus::Signal signal(kRunningApplicationDBusInterface, "EPChannelCreated");
222   dbus_object()->SendSignal(&signal);
223 }
224
225 }  // namespace application
226 }  // namespace xwalk