0e0a7ade4c7bdfeb34834c77585f043db01d6182
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / linux / installed_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/installed_applications_manager.h"
6
7 #include <string>
8 #include "base/bind.h"
9 #include "base/files/file_path.h"
10 #include "dbus/bus.h"
11 #include "dbus/message.h"
12 #include "xwalk/application/browser/application_storage.h"
13 #include "xwalk/application/browser/linux/installed_application_object.h"
14
15 namespace {
16
17 // D-Bus Interface implemented by the manager object of installed applications.
18 //
19 // Methods:
20 //
21 //   Install(string path) -> ObjectPath
22 //     Will install application at "path", that should be an absolute path to
23 //     the package file. If installation is successful, returns the ObjectPath
24 //     of the InstalledApplication object that represents it.
25 const char kInstalledManagerDBusInterface[] =
26     "org.crosswalkproject.Installed.Manager1";
27
28 const char kInstalledManagerDBusError[] =
29     "org.crosswalkproject.Installed.Manager.Error";
30
31 const dbus::ObjectPath kInstalledManagerDBusPath("/installed1");
32
33 dbus::ObjectPath GetInstalledPathForAppID(const std::string& app_id) {
34   return dbus::ObjectPath(kInstalledManagerDBusPath.value() + "/" + app_id);
35 }
36
37 }  // namespace
38
39 namespace xwalk {
40 namespace application {
41
42 InstalledApplicationsManager::InstalledApplicationsManager(
43     scoped_refptr<dbus::Bus> bus, ApplicationService* service,
44     ApplicationStorage* app_storage)
45     : weak_factory_(this),
46       application_service_(service),
47       app_storage_(app_storage),
48       adaptor_(bus, kInstalledManagerDBusPath) {
49   application_service_->AddObserver(this);
50
51   adaptor_.manager_object()->ExportMethod(
52       kInstalledManagerDBusInterface, "Install",
53       base::Bind(&InstalledApplicationsManager::OnInstall,
54                  weak_factory_.GetWeakPtr()),
55       base::Bind(&InstalledApplicationsManager::OnExported,
56                  weak_factory_.GetWeakPtr()));
57
58   AddInitialObjects();
59 }
60
61 InstalledApplicationsManager::~InstalledApplicationsManager() {
62   application_service_->RemoveObserver(this);
63 }
64
65 void InstalledApplicationsManager::OnApplicationInstalled(
66     const std::string& app_id) {
67   AddObject(app_storage_->GetApplicationData(app_id));
68 }
69
70 void InstalledApplicationsManager::OnApplicationUninstalled(
71     const std::string& app_id) {
72   adaptor_.RemoveManagedObject(GetInstalledPathForAppID(app_id));
73 }
74
75 void InstalledApplicationsManager::OnApplicationNameChanged(
76     const std::string& app_id, const std::string& app_name) {
77   InstalledApplicationObject* object =
78       static_cast<InstalledApplicationObject*>(
79           adaptor_.GetManagedObject(GetInstalledPathForAppID(app_id)));
80   object->OnApplicationNameChanged(app_name);
81 }
82
83 void InstalledApplicationsManager::AddInitialObjects() {
84   const ApplicationData::ApplicationDataMap& apps =
85       app_storage_->GetInstalledApplications();
86   ApplicationData::ApplicationDataMap::const_iterator it;
87   for (it = apps.begin(); it != apps.end(); ++it)
88     AddObject(it->second);
89 }
90
91 void InstalledApplicationsManager::AddObject(
92     scoped_refptr<const ApplicationData> app) {
93   scoped_ptr<InstalledApplicationObject> object(
94       new InstalledApplicationObject(
95           adaptor_.bus(), GetInstalledPathForAppID(app->ID()), app));
96
97   // See comment in InstalledApplicationsManager::OnUninstall().
98   object->ExportUninstallMethod(
99       base::Bind(&InstalledApplicationsManager::OnUninstall,
100                  weak_factory_.GetWeakPtr(),
101                  base::Unretained(object.get())),
102       base::Bind(&InstalledApplicationsManager::OnExported,
103                  weak_factory_.GetWeakPtr()));
104
105   adaptor_.AddManagedObject(object.PassAs<dbus::ManagedObject>());
106 }
107
108 namespace {
109
110 scoped_ptr<dbus::Response> CreateError(dbus::MethodCall* method_call,
111                                        const std::string& message) {
112     scoped_ptr<dbus::ErrorResponse> error_response =
113         dbus::ErrorResponse::FromMethodCall(
114             method_call, kInstalledManagerDBusError, message);
115     return error_response.PassAs<dbus::Response>();
116 }
117
118 }  // namespace
119
120 void InstalledApplicationsManager::OnInstall(
121     dbus::MethodCall* method_call,
122     dbus::ExportedObject::ResponseSender response_sender) {
123   dbus::MessageReader reader(method_call);
124   std::string file_path_str;
125   if (!reader.PopString(&file_path_str)) {
126     scoped_ptr<dbus::Response> response =
127         CreateError(method_call, "Error parsing message.");
128     response_sender.Run(response.Pass());
129     return;
130   }
131
132   const base::FilePath file_path(file_path_str);
133   if (!file_path.IsAbsolute()) {
134     scoped_ptr<dbus::Response> response =
135         CreateError(method_call, "Path to install must be absolute.");
136     response_sender.Run(response.Pass());
137     return;
138   }
139
140   std::string app_id;
141   if (!application_service_->Install(file_path, &app_id) &&
142       (app_id.empty() || !application_service_->Update(app_id, file_path))) {
143     scoped_ptr<dbus::Response> response =
144         CreateError(method_call,
145                     "Error installing/updating application with path: "
146                     + file_path_str);
147     response_sender.Run(response.Pass());
148     return;
149   }
150
151   dbus::ManagedObject* managed_object =
152       adaptor_.GetManagedObject(GetInstalledPathForAppID(app_id));
153   CHECK(managed_object);
154
155   scoped_ptr<dbus::Response> response =
156       dbus::Response::FromMethodCall(method_call);
157   dbus::MessageWriter writer(response.get());
158   writer.AppendObjectPath(managed_object->path());
159   response_sender.Run(response.Pass());
160 }
161
162 // InstalledApplicationsManager implements the callback exposed in the child
163 // objects interface, we bind the actual child to the first parameter. There are
164 // two reasons to do this: we save the need of creating WeakPtrFactories for all
165 // individual objects, and we ensure that is safe to destroy the object when
166 // handling the callback -- which is done by our OnApplicationUninstalled
167 // implementation.
168 void InstalledApplicationsManager::OnUninstall(
169     InstalledApplicationObject* installed_app_object,
170     dbus::MethodCall* method_call,
171     dbus::ExportedObject::ResponseSender response_sender) {
172   if (!application_service_->Uninstall(installed_app_object->app_id())) {
173     scoped_ptr<dbus::ErrorResponse> error_response =
174         dbus::ErrorResponse::FromMethodCall(
175             method_call, kInstalledApplicationDBusError,
176             "Error trying to uninstall application with id "
177             + installed_app_object->app_id());
178     response_sender.Run(error_response.PassAs<dbus::Response>());
179     return;
180   }
181
182   scoped_ptr<dbus::Response> response =
183       dbus::Response::FromMethodCall(method_call);
184   response_sender.Run(response.Pass());
185 }
186
187 void InstalledApplicationsManager::OnExported(
188     const std::string& interface_name,
189     const std::string& method_name,
190     bool success) {
191   if (!success) {
192     LOG(WARNING) << "Error exporting method '" << interface_name
193                  << "." << method_name << "' in '"
194                  << kInstalledManagerDBusPath.value() << "'.";
195   }
196 }
197
198 }  // namespace application
199 }  // namespace xwalk