09fd3b4932f4db0ad3e047ab8d0e7a54ff03590c
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / linux / running_applications_manager.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_applications_manager.h"
6
7 #include <string>
8 #include "base/bind.h"
9 #include "dbus/bus.h"
10 #include "dbus/message.h"
11
12 #include "xwalk/application/browser/linux/running_application_object.h"
13 #include "xwalk/application/common/application_data.h"
14 #include "xwalk/runtime/browser/xwalk_runner.h"
15
16 namespace {
17
18 // D-Bus Interface implemented by the manager object of running applications.
19 //
20 // Methods:
21 //
22 //   Launch(string app_id) -> ObjectPath
23 //     Launches the application with 'app_id'.
24 const char kRunningManagerDBusInterface[] =
25     "org.crosswalkproject.Running.Manager1";
26
27 const char kRunningManagerDBusError[] =
28     "org.crosswalkproject.Running.Manager.Error";
29
30 const dbus::ObjectPath kRunningManagerDBusPath("/running1");
31
32
33 }  // namespace
34
35 namespace xwalk {
36 namespace application {
37
38 // The [tizen_app_id] contains a dot, making it an invalid object path.
39 // For this reason we replace it with an underscore '_'.
40 std::string GetAppObjectPathFromAppId(const std::string& app_id) {
41 #if defined(OS_TIZEN)
42   std::string ret(app_id);
43   std::replace(ret.begin(), ret.end(), '.', '_');
44   return ret;
45 #else
46   return app_id;
47 #endif
48 }
49
50 dbus::ObjectPath GetRunningPathForAppID(const std::string& app_id) {
51   return dbus::ObjectPath(kRunningManagerDBusPath.value() + "/" +
52                           GetAppObjectPathFromAppId(app_id));
53 }
54
55 RunningApplicationsManager::RunningApplicationsManager(
56     scoped_refptr<dbus::Bus> bus, ApplicationService* service)
57     : weak_factory_(this),
58       application_service_(service),
59       adaptor_(bus, kRunningManagerDBusPath) {
60   application_service_->AddObserver(this);
61
62   adaptor_.manager_object()->ExportMethod(
63       kRunningManagerDBusInterface, "EnableRemoteDebugging",
64       base::Bind(&RunningApplicationsManager::OnRemoteDebuggingEnabled,
65                  weak_factory_.GetWeakPtr()),
66       base::Bind(&RunningApplicationsManager::OnExported,
67                  weak_factory_.GetWeakPtr()));
68
69   adaptor_.manager_object()->ExportMethod(
70       kRunningManagerDBusInterface, "Launch",
71       base::Bind(&RunningApplicationsManager::OnLaunch,
72                  weak_factory_.GetWeakPtr()),
73       base::Bind(&RunningApplicationsManager::OnExported,
74                  weak_factory_.GetWeakPtr()));
75
76   adaptor_.manager_object()->ExportMethod(
77       kRunningManagerDBusInterface, "TerminateIfRunning",
78       base::Bind(&RunningApplicationsManager::OnTerminateIfRunning,
79                  weak_factory_.GetWeakPtr()),
80       base::Bind(&RunningApplicationsManager::OnExported,
81                  weak_factory_.GetWeakPtr()));
82 }
83
84 RunningApplicationsManager::~RunningApplicationsManager() {}
85
86 RunningApplicationObject* RunningApplicationsManager::GetRunningApp(
87     const std::string& app_id) {
88   dbus::ManagedObject* managed_object =
89       adaptor_.GetManagedObject(GetRunningPathForAppID(app_id));
90   DCHECK(managed_object);
91   return static_cast<RunningApplicationObject*>(managed_object);
92 }
93
94 namespace {
95
96 scoped_ptr<dbus::Response> CreateError(dbus::MethodCall* method_call,
97                                        const std::string& message) {
98     scoped_ptr<dbus::ErrorResponse> error_response =
99         dbus::ErrorResponse::FromMethodCall(
100             method_call, kRunningManagerDBusError, message);
101     return error_response.PassAs<dbus::Response>();
102 }
103
104 }  // namespace
105
106 void RunningApplicationsManager::OnRemoteDebuggingEnabled(
107     dbus::MethodCall* method_call,
108     dbus::ExportedObject::ResponseSender response_sender) {
109   dbus::MessageReader reader(method_call);
110   unsigned int debugging_port;
111
112   if (!reader.PopUint32(&debugging_port)) {
113     scoped_ptr<dbus::Response> response =
114         CreateError(method_call,
115                     "Error parsing message. Missing arguments.");
116     response_sender.Run(response.Pass());
117     return;
118   }
119
120   if (debugging_port != 0) {
121     XWalkRunner::GetInstance()->EnableRemoteDebugging(debugging_port);
122   } else {
123     XWalkRunner::GetInstance()->DisableRemoteDebugging();
124   }
125
126   scoped_ptr<dbus::Response> response =
127       dbus::Response::FromMethodCall(method_call);
128   dbus::MessageWriter writer(response.get());
129   writer.AppendUint32(debugging_port);
130   response_sender.Run(response.Pass());
131 }
132
133 void RunningApplicationsManager::OnLaunch(
134     dbus::MethodCall* method_call,
135     dbus::ExportedObject::ResponseSender response_sender) {
136
137   dbus::MessageReader reader(method_call);
138   std::string app_id_or_url;
139   // We might want to pass key-value pairs if have more parameters in future.
140   unsigned int launcher_pid;
141   bool fullscreen;
142
143   if (!reader.PopString(&app_id_or_url) ||
144       !reader.PopUint32(&launcher_pid) ||
145       !reader.PopBool(&fullscreen)) {
146     scoped_ptr<dbus::Response> response =
147         CreateError(method_call,
148                     "Error parsing message. Missing arguments.");
149     response_sender.Run(response.Pass());
150     return;
151   }
152
153   Application::LaunchParams params;
154   params.launcher_pid = launcher_pid;
155   params.force_fullscreen = fullscreen;
156
157   Application* application;
158   if (GURL(app_id_or_url).spec().empty()) {
159     application = application_service_->Launch(app_id_or_url, params);
160   } else {
161     params.entry_points = Application::StartURLKey;
162     std::string error;
163     scoped_refptr<ApplicationData> application_data =
164         ApplicationData::Create(GURL(app_id_or_url), &error);
165     if (!application_data) {
166       scoped_ptr<dbus::Response> response = CreateError(method_call, error);
167       response_sender.Run(response.Pass());
168       return;
169     }
170
171     application = application_service_->Launch(application_data, params);
172   }
173
174   if (!application) {
175     scoped_ptr<dbus::Response> response =
176         CreateError(method_call,
177                     "Error launching application with id or url"
178                     + app_id_or_url);
179     response_sender.Run(response.Pass());
180     return;
181   }
182
183   // FIXME(cmarcelo): ApplicationService will tell us when new applications
184   // appear (with DidLaunchApplication()) and we create new managed objects
185   // in D-Bus based on that.
186   dbus::ObjectPath path =
187       AddObject(GetAppObjectPathFromAppId(application->id()),
188                 method_call->GetSender(),
189                 application);
190
191   scoped_ptr<dbus::Response> response =
192       dbus::Response::FromMethodCall(method_call);
193   dbus::MessageWriter writer(response.get());
194   writer.AppendObjectPath(path);
195   response_sender.Run(response.Pass());
196 }
197
198 void RunningApplicationsManager::OnTerminateIfRunning(
199     dbus::MethodCall* method_call,
200     dbus::ExportedObject::ResponseSender response_sender) {
201
202   dbus::MessageReader reader(method_call);
203   std::string app_id;
204
205   if (!reader.PopString(&app_id)) {
206     scoped_ptr<dbus::Response> response =
207         CreateError(method_call,
208                     "Error parsing message. Missing argument.");
209     response_sender.Run(response.Pass());
210     return;
211   }
212
213   if (Application* app = application_service_->GetApplicationByID(app_id)) {
214     CHECK(app_id == app->id());
215     app->Terminate();
216   }
217
218   scoped_ptr<dbus::Response> response =
219       dbus::Response::FromMethodCall(method_call);
220   response_sender.Run(response.Pass());
221 }
222
223 void RunningApplicationsManager::OnExported(
224     const std::string& interface_name,
225     const std::string& method_name,
226     bool success) {
227   if (!success) {
228     LOG(WARNING) << "Error exporting method '" << interface_name
229                  << "." << method_name << "' in '"
230                  << kRunningManagerDBusPath.value() << "'.";
231   }
232 }
233
234 void RunningApplicationsManager::WillDestroyApplication(Application* app) {
235   dbus::ObjectPath path = GetRunningPathForAppID(app->id());
236
237   adaptor_.RemoveManagedObject(path);
238 }
239
240 dbus::ObjectPath RunningApplicationsManager::AddObject(
241     const std::string& app_id, const std::string& launcher_name,
242     Application* application) {
243   scoped_ptr<RunningApplicationObject> running_application(
244       new RunningApplicationObject(adaptor_.bus(), app_id,
245                                    launcher_name, application));
246
247   dbus::ObjectPath path = running_application->path();
248
249   adaptor_.AddManagedObject(running_application.PassAs<dbus::ManagedObject>());
250
251   return path;
252 }
253
254 }  // namespace application
255 }  // namespace xwalk