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