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, "Terminate",
66 base::Bind(&RunningApplicationObject::OnTerminate,
67 base::Unretained(this)),
68 base::Bind(&RunningApplicationObject::OnExported,
69 base::Unretained(this)));
71 dbus_object()->ExportMethod(
72 kRunningApplicationDBusInterface, "GetEPChannel",
73 base::Bind(&RunningApplicationObject::OnGetExtensionProcessChannel,
74 base::Unretained(this)),
75 base::Bind(&RunningApplicationObject::OnExported,
76 base::Unretained(this)));
79 dbus_object()->ExportMethod(
80 kRunningApplicationDBusInterface, "Hide",
81 base::Bind(&RunningApplicationObject::OnHide,
82 base::Unretained(this)),
83 base::Bind(&RunningApplicationObject::OnExported,
84 base::Unretained(this)));
86 dbus_object()->ExportMethod(
87 kRunningApplicationDBusInterface, "Suspend",
88 base::Bind(&RunningApplicationObject::OnSuspend,
89 base::Unretained(this)),
90 base::Bind(&RunningApplicationObject::OnExported,
91 base::Unretained(this)));
93 dbus_object()->ExportMethod(
94 kRunningApplicationDBusInterface, "Resume",
95 base::Bind(&RunningApplicationObject::OnResume,
96 base::Unretained(this)),
97 base::Bind(&RunningApplicationObject::OnExported,
98 base::Unretained(this)));
100 dbus_object()->ExportMethod(
101 kRunningApplicationDBusInterface, "RemoveAllCookies",
102 base::Bind(&RunningApplicationObject::OnRemoveAllCookies,
103 base::Unretained(this)),
104 base::Bind(&RunningApplicationObject::OnExported,
105 base::Unretained(this)));
107 dbus_object()->ExportMethod(
108 kRunningApplicationDBusInterface, "SetUserAgentString",
109 base::Bind(&RunningApplicationObject::OnSetUserAgentString,
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();
123 if (ep_bp_channel_.socket.fd != -1)
124 close(ep_bp_channel_.socket.fd);
127 void RunningApplicationObject::OnExported(const std::string& interface_name,
128 const std::string& method_name,
131 LOG(WARNING) << "Error exporting method '" << interface_name
132 << "." << method_name << "' in '"
133 << path().value() << "'.";
137 void RunningApplicationObject::OnTerminate(
138 dbus::MethodCall* method_call,
139 dbus::ExportedObject::ResponseSender response_sender) {
140 // We only allow the caller of Launch() to call Terminate().
141 if (method_call->GetSender() != launcher_name_) {
142 scoped_ptr<dbus::ErrorResponse> error_response =
143 dbus::ErrorResponse::FromMethodCall(method_call,
144 kRunningApplicationDBusError,
146 response_sender.Run(error_response.Pass());
150 TerminateApplication();
152 scoped_ptr<dbus::Response> response =
153 dbus::Response::FromMethodCall(method_call);
154 response_sender.Run(response.Pass());
157 void RunningApplicationObject::OnGetExtensionProcessChannel(
158 dbus::MethodCall* method_call,
159 dbus::ExportedObject::ResponseSender response_sender) {
160 content::BrowserThread::PostTask(
161 content::BrowserThread::FILE,
163 base::Bind(&RunningApplicationObject::SendChannel,
164 base::Unretained(this),
169 #if defined(OS_TIZEN)
170 void RunningApplicationObject::OnHide(
171 dbus::MethodCall* method_call,
172 dbus::ExportedObject::ResponseSender response_sender) {
173 if (method_call->GetSender() != launcher_name_) {
174 scoped_ptr<dbus::ErrorResponse> error_response =
175 dbus::ErrorResponse::FromMethodCall(method_call,
176 kRunningApplicationDBusError,
178 response_sender.Run(error_response.Pass());
182 ToApplicationTizen(application_)->Hide();
184 scoped_ptr<dbus::Response> response =
185 dbus::Response::FromMethodCall(method_call);
186 response_sender.Run(response.Pass());
189 void RunningApplicationObject::OnSuspend(
190 dbus::MethodCall* method_call,
191 dbus::ExportedObject::ResponseSender response_sender) {
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.Pass());
201 ToApplicationTizen(application_)->Suspend();
203 scoped_ptr<dbus::Response> response =
204 dbus::Response::FromMethodCall(method_call);
205 response_sender.Run(response.Pass());
208 void RunningApplicationObject::OnResume(
209 dbus::MethodCall* method_call,
210 dbus::ExportedObject::ResponseSender response_sender) {
211 if (method_call->GetSender() != launcher_name_) {
212 scoped_ptr<dbus::ErrorResponse> error_response =
213 dbus::ErrorResponse::FromMethodCall(method_call,
214 kRunningApplicationDBusError,
216 response_sender.Run(error_response.Pass());
220 ToApplicationTizen(application_)->Resume();
221 ToApplicationTizen(application_)->Show();
223 scoped_ptr<dbus::Response> response =
224 dbus::Response::FromMethodCall(method_call);
225 response_sender.Run(response.Pass());
228 void RunningApplicationObject::OnRemoveAllCookies(dbus::MethodCall* method_call,
229 dbus::ExportedObject::ResponseSender response_sender) {
230 if (method_call->GetSender() != launcher_name_) {
231 scoped_ptr<dbus::ErrorResponse> error_response =
232 dbus::ErrorResponse::FromMethodCall(method_call,
233 kRunningApplicationDBusError,
235 response_sender.Run(error_response.Pass());
239 ToApplicationTizen(application_)->RemoveAllCookies();
241 scoped_ptr<dbus::Response> response =
242 dbus::Response::FromMethodCall(method_call);
243 response_sender.Run(response.Pass());
246 void RunningApplicationObject::SetUserAgentStringOnIOThread(
247 const std::string& user_agent_string) {
248 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
249 ToApplicationTizen(application_)->SetUserAgentString(user_agent_string);
252 void RunningApplicationObject::OnSetUserAgentString(
253 dbus::MethodCall* method_call,
254 dbus::ExportedObject::ResponseSender response_sender) {
255 if (method_call->GetSender() != launcher_name_) {
256 scoped_ptr<dbus::ErrorResponse> error_response =
257 dbus::ErrorResponse::FromMethodCall(method_call,
258 kRunningApplicationDBusError,
260 response_sender.Run(error_response.Pass());
263 dbus::MessageReader reader(method_call);
264 std::string new_user_agent;
265 if (reader.PopString(&new_user_agent)) {
266 content::BrowserThread::PostTask(
267 content::BrowserThread::IO, FROM_HERE,
268 base::Bind(&RunningApplicationObject::SetUserAgentStringOnIOThread,
269 base::Unretained(this), new_user_agent));
270 scoped_ptr<dbus::Response> response =
271 dbus::Response::FromMethodCall(method_call);
272 response_sender.Run(response.Pass());
274 scoped_ptr<dbus::ErrorResponse> error_response =
275 dbus::ErrorResponse::FromMethodCall(method_call,
276 kRunningApplicationDBusError,
277 "Wrong user agent string");
278 response_sender.Run(error_response.Pass());
283 void RunningApplicationObject::ListenForOwnerChange() {
284 owner_change_callback_ =
285 base::Bind(&RunningApplicationObject::OnNameOwnerChanged,
286 base::Unretained(this));
287 bus_->ListenForServiceOwnerChange(launcher_name_, owner_change_callback_);
290 void RunningApplicationObject::UnlistenForOwnerChange() {
291 if (owner_change_callback_.is_null())
293 bus_->UnlistenForServiceOwnerChange(launcher_name_, owner_change_callback_);
294 owner_change_callback_.Reset();
297 void RunningApplicationObject::OnNameOwnerChanged(
298 const std::string& service_owner) {
299 if (service_owner.empty()) {
300 // The process that sent the 'Launch' message has exited the session bus,
301 // we should kill the Running Application.
302 OnLauncherDisappeared();
306 void RunningApplicationObject::OnLauncherDisappeared() {
307 TerminateApplication();
310 void RunningApplicationObject::SendChannel(
311 dbus::MethodCall* method_call,
312 dbus::ExportedObject::ResponseSender response_sender) {
313 scoped_ptr<dbus::Response> response =
314 dbus::Response::FromMethodCall(method_call);
316 int fd = ep_bp_channel_.socket.fd;
317 if (fd == -1) { // EP was not yet created, return empty response.
318 response_sender.Run(response.Pass());
322 dbus::MessageWriter writer(response.get());
323 writer.AppendString(ep_bp_channel_.name);
325 scoped_ptr<dbus::FileDescriptor> client_fd(new dbus::FileDescriptor(fd));
326 client_fd->CheckValidity();
327 CHECK(client_fd->is_valid());
328 writer.AppendFileDescriptor(*client_fd);
330 response_sender.Run(response.Pass());
333 void RunningApplicationObject::ExtensionProcessCreated(
334 const IPC::ChannelHandle& handle) {
335 ep_bp_channel_ = handle;
336 dbus::Signal signal(kRunningApplicationDBusInterface, "EPChannelCreated");
337 dbus_object()->SendSignal(&signal);
340 } // namespace application