1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
6 #include "xwalk/application/browser/linux/running_application_object.h"
9 #include "base/values.h"
10 #include "base/bind.h"
11 #include "content/public/browser/browser_thread.h"
13 #include "dbus/message.h"
14 #include "dbus/exported_object.h"
15 #include "xwalk/application/browser/application_tizen.h"
16 #include "xwalk/application/browser/linux/running_applications_manager.h"
20 // D-Bus Interface implemented by objects that represent running
26 // Will terminate the running application. This object will be unregistered
31 // readonly string AppID
32 const char kRunningApplicationDBusInterface[] =
33 "org.crosswalkproject.Running.Application1";
35 const char kRunningApplicationDBusError[] =
36 "org.crosswalkproject.Running.Application.Error";
42 namespace application {
44 RunningApplicationObject::RunningApplicationObject(
45 scoped_refptr<dbus::Bus> bus,
46 const std::string& app_id,
47 const std::string& launcher_name,
48 Application* application)
49 : dbus::ManagedObject(bus, GetRunningPathForAppID(app_id)),
51 launcher_name_(launcher_name),
52 application_(application) {
53 ListenForOwnerChange();
56 kRunningApplicationDBusInterface, "AppID",
57 scoped_ptr<base::Value>(new base::StringValue(app_id)));
59 // FIXME: RemoveAllCookies and SetUserAgentString
60 // are exported for web_setting extension usage.
61 // This is a temporary solution - when another
62 // IPC on extension process side is implemented,
63 // these methods have to be removed.
64 dbus_object()->ExportMethod(
65 kRunningApplicationDBusInterface, "RemoveAllCookies",
66 base::Bind(&RunningApplicationObject::OnRemoveAllCookies,
67 base::Unretained(this)),
68 base::Bind(&RunningApplicationObject::OnExported,
69 base::Unretained(this)));
71 dbus_object()->ExportMethod(
72 kRunningApplicationDBusInterface, "SetUserAgentString",
73 base::Bind(&RunningApplicationObject::OnSetUserAgentString,
74 base::Unretained(this)),
75 base::Bind(&RunningApplicationObject::OnExported,
76 base::Unretained(this)));
78 dbus_object()->ExportMethod(
79 kRunningApplicationDBusInterface, "Terminate",
80 base::Bind(&RunningApplicationObject::OnTerminate,
81 base::Unretained(this)),
82 base::Bind(&RunningApplicationObject::OnExported,
83 base::Unretained(this)));
85 dbus_object()->ExportMethod(
86 kRunningApplicationDBusInterface, "GetEPChannel",
87 base::Bind(&RunningApplicationObject::OnGetExtensionProcessChannel,
88 base::Unretained(this)),
89 base::Bind(&RunningApplicationObject::OnExported,
90 base::Unretained(this)));
93 dbus_object()->ExportMethod(
94 kRunningApplicationDBusInterface, "Hide",
95 base::Bind(&RunningApplicationObject::OnHide,
96 base::Unretained(this)),
97 base::Bind(&RunningApplicationObject::OnExported,
98 base::Unretained(this)));
100 dbus_object()->ExportMethod(
101 kRunningApplicationDBusInterface, "Suspend",
102 base::Bind(&RunningApplicationObject::OnSuspend,
103 base::Unretained(this)),
104 base::Bind(&RunningApplicationObject::OnExported,
105 base::Unretained(this)));
107 dbus_object()->ExportMethod(
108 kRunningApplicationDBusInterface, "Resume",
109 base::Bind(&RunningApplicationObject::OnResume,
110 base::Unretained(this)),
111 base::Bind(&RunningApplicationObject::OnExported,
112 base::Unretained(this)));
116 RunningApplicationObject::~RunningApplicationObject() {
117 UnlistenForOwnerChange();
120 void RunningApplicationObject::TerminateApplication() {
121 application_->Terminate();
124 void RunningApplicationObject::OnExported(const std::string& interface_name,
125 const std::string& method_name,
128 LOG(WARNING) << "Error exporting method '" << interface_name
129 << "." << method_name << "' in '"
130 << path().value() << "'.";
134 void RunningApplicationObject::SetUserAgentStringOnIOThread(
135 const std::string& user_agent_string) {
136 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
137 ToApplicationTizen(application_)->SetUserAgentString(user_agent_string);
140 void RunningApplicationObject::OnRemoveAllCookies(dbus::MethodCall* method_call,
141 dbus::ExportedObject::ResponseSender response_sender) {
142 if (method_call->GetSender() != launcher_name_) {
143 scoped_ptr<dbus::ErrorResponse> error_response =
144 dbus::ErrorResponse::FromMethodCall(method_call,
145 kRunningApplicationDBusError,
147 response_sender.Run(error_response.PassAs<dbus::Response>());
151 ToApplicationTizen(application_)->RemoveAllCookies();
153 scoped_ptr<dbus::Response> response =
154 dbus::Response::FromMethodCall(method_call);
155 response_sender.Run(response.Pass());
158 void RunningApplicationObject::OnSetUserAgentString(
159 dbus::MethodCall* method_call,
160 dbus::ExportedObject::ResponseSender response_sender) {
161 if (method_call->GetSender() != launcher_name_) {
162 scoped_ptr<dbus::ErrorResponse> error_response =
163 dbus::ErrorResponse::FromMethodCall(method_call,
164 kRunningApplicationDBusError,
166 response_sender.Run(error_response.PassAs<dbus::Response>());
169 dbus::MessageReader reader(method_call);
170 std::string new_user_agent;
171 if (reader.PopString(&new_user_agent)) {
172 content::BrowserThread::PostTask(
173 content::BrowserThread::IO, FROM_HERE,
174 base::Bind(&RunningApplicationObject::SetUserAgentStringOnIOThread,
175 base::Unretained(this), new_user_agent));
176 scoped_ptr<dbus::Response> response =
177 dbus::Response::FromMethodCall(method_call);
178 response_sender.Run(response.Pass());
180 scoped_ptr<dbus::ErrorResponse> error_response =
181 dbus::ErrorResponse::FromMethodCall(method_call,
182 kRunningApplicationDBusError,
183 "Wrong user agent string");
184 response_sender.Run(error_response.PassAs<dbus::Response>());
188 void RunningApplicationObject::OnTerminate(
189 dbus::MethodCall* method_call,
190 dbus::ExportedObject::ResponseSender response_sender) {
191 // We only allow the caller of Launch() to call Terminate().
192 if (method_call->GetSender() != launcher_name_) {
193 scoped_ptr<dbus::ErrorResponse> error_response =
194 dbus::ErrorResponse::FromMethodCall(method_call,
195 kRunningApplicationDBusError,
197 response_sender.Run(error_response.PassAs<dbus::Response>());
201 TerminateApplication();
203 scoped_ptr<dbus::Response> response =
204 dbus::Response::FromMethodCall(method_call);
205 response_sender.Run(response.Pass());
208 void RunningApplicationObject::OnGetExtensionProcessChannel(
209 dbus::MethodCall* method_call,
210 dbus::ExportedObject::ResponseSender response_sender) {
211 content::BrowserThread::PostTask(
212 content::BrowserThread::FILE,
214 base::Bind(&RunningApplicationObject::SendChannel,
215 base::Unretained(this),
220 #if defined(OS_TIZEN)
221 void RunningApplicationObject::OnHide(
222 dbus::MethodCall* method_call,
223 dbus::ExportedObject::ResponseSender response_sender) {
224 if (method_call->GetSender() != launcher_name_) {
225 scoped_ptr<dbus::ErrorResponse> error_response =
226 dbus::ErrorResponse::FromMethodCall(method_call,
227 kRunningApplicationDBusError,
229 response_sender.Run(error_response.PassAs<dbus::Response>());
233 ToApplicationTizen(application_)->Hide();
235 scoped_ptr<dbus::Response> response =
236 dbus::Response::FromMethodCall(method_call);
237 response_sender.Run(response.Pass());
240 void RunningApplicationObject::OnSuspend(
241 dbus::MethodCall* method_call,
242 dbus::ExportedObject::ResponseSender response_sender) {
243 if (method_call->GetSender() != launcher_name_) {
244 scoped_ptr<dbus::ErrorResponse> error_response =
245 dbus::ErrorResponse::FromMethodCall(method_call,
246 kRunningApplicationDBusError,
248 response_sender.Run(error_response.PassAs<dbus::Response>());
252 ToApplicationTizen(application_)->Suspend();
254 scoped_ptr<dbus::Response> response =
255 dbus::Response::FromMethodCall(method_call);
256 response_sender.Run(response.Pass());
259 void RunningApplicationObject::OnResume(
260 dbus::MethodCall* method_call,
261 dbus::ExportedObject::ResponseSender response_sender) {
262 if (method_call->GetSender() != launcher_name_) {
263 scoped_ptr<dbus::ErrorResponse> error_response =
264 dbus::ErrorResponse::FromMethodCall(method_call,
265 kRunningApplicationDBusError,
267 response_sender.Run(error_response.PassAs<dbus::Response>());
271 ToApplicationTizen(application_)->Resume();
273 scoped_ptr<dbus::Response> response =
274 dbus::Response::FromMethodCall(method_call);
275 response_sender.Run(response.Pass());
279 void RunningApplicationObject::ListenForOwnerChange() {
280 owner_change_callback_ =
281 base::Bind(&RunningApplicationObject::OnNameOwnerChanged,
282 base::Unretained(this));
283 bus_->ListenForServiceOwnerChange(launcher_name_, owner_change_callback_);
286 void RunningApplicationObject::UnlistenForOwnerChange() {
287 if (owner_change_callback_.is_null())
289 bus_->UnlistenForServiceOwnerChange(launcher_name_, owner_change_callback_);
290 owner_change_callback_.Reset();
293 void RunningApplicationObject::OnNameOwnerChanged(
294 const std::string& service_owner) {
295 if (service_owner.empty()) {
296 // The process that sent the 'Launch' message has exited the session bus,
297 // we should kill the Running Application.
298 OnLauncherDisappeared();
302 void RunningApplicationObject::OnLauncherDisappeared() {
303 TerminateApplication();
306 void RunningApplicationObject::SendChannel(
307 dbus::MethodCall* method_call,
308 dbus::ExportedObject::ResponseSender response_sender) {
309 scoped_ptr<dbus::Response> response =
310 dbus::Response::FromMethodCall(method_call);
312 int fd = ep_bp_channel_.socket.fd;
313 if (fd == -1) { // EP was not yet created, return empty response.
314 response_sender.Run(response.Pass());
318 dbus::MessageWriter writer(response.get());
319 writer.AppendString(ep_bp_channel_.name);
321 scoped_ptr<dbus::FileDescriptor> client_fd(new dbus::FileDescriptor(fd));
322 client_fd->CheckValidity();
323 CHECK(client_fd->is_valid());
324 writer.AppendFileDescriptor(*client_fd);
326 response_sender.Run(response.Pass());
329 void RunningApplicationObject::ExtensionProcessCreated(
330 const IPC::ChannelHandle& handle) {
331 ep_bp_channel_ = handle;
332 dbus::Signal signal(kRunningApplicationDBusInterface, "EPChannelCreated");
333 dbus_object()->SendSignal(&signal);
336 } // namespace application