Upstream version 7.35.139.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 #endif
80 }
81
82 RunningApplicationObject::~RunningApplicationObject() {
83   UnlistenForOwnerChange();
84 }
85
86 void RunningApplicationObject::TerminateApplication() {
87   application_->Terminate();
88 }
89
90 void RunningApplicationObject::OnExported(const std::string& interface_name,
91                                           const std::string& method_name,
92                                           bool success) {
93   if (!success) {
94     LOG(WARNING) << "Error exporting method '" << interface_name
95                  << "." << method_name << "' in '"
96                  << path().value() << "'.";
97   }
98 }
99
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,
108                                             "Not permitted");
109     response_sender.Run(error_response.PassAs<dbus::Response>());
110     return;
111   }
112
113   TerminateApplication();
114
115   scoped_ptr<dbus::Response> response =
116       dbus::Response::FromMethodCall(method_call);
117   response_sender.Run(response.Pass());
118 }
119
120 void RunningApplicationObject::OnGetExtensionProcessChannel(
121     dbus::MethodCall* method_call,
122     dbus::ExportedObject::ResponseSender response_sender) {
123   content::BrowserThread::PostTask(
124       content::BrowserThread::FILE,
125       FROM_HERE,
126       base::Bind(&RunningApplicationObject::SendChannel,
127                  base::Unretained(this),
128                  method_call,
129                  response_sender));
130 }
131
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,
140                                             "Not permitted");
141     response_sender.Run(error_response.PassAs<dbus::Response>());
142     return;
143   }
144
145   ToApplicationTizen(application_)->Hide();
146
147   scoped_ptr<dbus::Response> response =
148       dbus::Response::FromMethodCall(method_call);
149   response_sender.Run(response.Pass());
150 }
151 #endif
152
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_);
158 }
159
160 void RunningApplicationObject::UnlistenForOwnerChange() {
161   if (owner_change_callback_.is_null())
162     return;
163   bus_->UnlistenForServiceOwnerChange(launcher_name_, owner_change_callback_);
164   owner_change_callback_.Reset();
165 }
166
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();
173   }
174 }
175
176 void RunningApplicationObject::OnLauncherDisappeared() {
177   TerminateApplication();
178 }
179
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);
185
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());
189     return;
190   }
191
192   dbus::MessageWriter writer(response.get());
193   writer.AppendString(ep_bp_channel_.name);
194
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);
199
200   response_sender.Run(response.Pass());
201 }
202
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);
208 }
209
210 }  // namespace application
211 }  // namespace xwalk