Upstream version 8.36.169.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / application_service.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/application_service.h"
6
7 #include <set>
8 #include <string>
9 #include <vector>
10
11 #include "base/containers/hash_tables.h"
12 #include "base/files/file_enumerator.h"
13 #include "base/file_util.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/path_service.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_observer.h"
19 #include "xwalk/application/browser/application.h"
20 #include "xwalk/application/browser/application_system.h"
21 #include "xwalk/application/common/application_storage.h"
22 #include "xwalk/application/common/installer/package.h"
23 #include "xwalk/application/common/installer/package_installer.h"
24 #include "xwalk/application/common/application_file_util.h"
25 #include "xwalk/runtime/browser/runtime_context.h"
26 #include "xwalk/runtime/browser/runtime.h"
27 #include "xwalk/runtime/browser/xwalk_runner.h"
28 #include "xwalk/runtime/common/xwalk_paths.h"
29
30 #if defined(OS_TIZEN)
31 #include "xwalk/application/browser/application_tizen.h"
32 #endif
33
34 namespace xwalk {
35
36 namespace application {
37
38 namespace {
39
40 const base::FilePath::CharType kApplicationDataDirName[] =
41     FILE_PATH_LITERAL("Storage/ext");
42
43 base::FilePath GetStoragePartitionPath(
44     const base::FilePath& base_path, const std::string& app_id) {
45   return base_path.Append(kApplicationDataDirName).Append(app_id);
46 }
47
48 void CollectUnusedStoragePartitions(RuntimeContext* context,
49                                     ApplicationStorage* storage) {
50   std::vector<std::string> app_ids;
51   if (!storage->GetInstalledApplicationIDs(app_ids))
52     return;
53
54   scoped_ptr<base::hash_set<base::FilePath> > active_paths(
55       new base::hash_set<base::FilePath>()); // NOLINT
56
57   for (unsigned i = 0; i < app_ids.size(); ++i) {
58     active_paths->insert(
59         GetStoragePartitionPath(context->GetPath(), app_ids.at(i)));
60   }
61
62   content::BrowserContext::GarbageCollectStoragePartitions(
63       context, active_paths.Pass(), base::Bind(&base::DoNothing));
64 }
65
66 }  // namespace
67
68 ApplicationService::ApplicationService(RuntimeContext* runtime_context,
69                                        ApplicationStorage* app_storage)
70     : runtime_context_(runtime_context),
71       application_storage_(app_storage) {
72   CollectUnusedStoragePartitions(runtime_context, app_storage);
73 }
74
75 ApplicationService::~ApplicationService() {
76 }
77
78 void ApplicationService::ChangeLocale(const std::string& locale) {
79   ApplicationData::ApplicationDataMap apps;
80   if (!application_storage_->GetInstalledApplications(apps))
81     return;
82
83   ApplicationData::ApplicationDataMap::const_iterator it;
84   for (it = apps.begin(); it != apps.end(); ++it) {
85     base::string16 error;
86     std::string old_name = it->second->Name();
87     if (!it->second->SetApplicationLocale(locale, &error)) {
88       LOG(ERROR) << "Error when set locale " << locale
89                  << " to application " << it->second->ID()
90                  << "error : " << error;
91     }
92     if (old_name != it->second->Name()) {
93       // After we has changed the application locale, we might get a new name in
94       // the new locale, so call all observer for this event.
95       FOR_EACH_OBSERVER(
96           Observer, observers_,
97           OnApplicationNameChanged(it->second->ID(), it->second->Name()));
98     }
99   }
100 }
101
102 Application* ApplicationService::Launch(
103     scoped_refptr<ApplicationData> application_data,
104     const Application::LaunchParams& launch_params) {
105   if (GetApplicationByID(application_data->ID()) != NULL) {
106     LOG(INFO) << "Application with id: " << application_data->ID()
107               << " is already running.";
108     // FIXME: we need to notify application that it had been attempted
109     // to invoke and let the application to define the further behavior.
110     return NULL;
111   }
112
113 #if defined(OS_TIZEN)
114   Application* application(new ApplicationTizen(application_data,
115     runtime_context_, this));
116 #else
117   Application* application(new Application(application_data,
118     runtime_context_, this));
119 #endif
120
121   ScopedVector<Application>::iterator app_iter =
122       applications_.insert(applications_.end(), application);
123
124   if (!application->Launch(launch_params)) {
125     applications_.erase(app_iter);
126     return NULL;
127   }
128
129   FOR_EACH_OBSERVER(Observer, observers_,
130                     DidLaunchApplication(application));
131
132   return application;
133 }
134
135 Application* ApplicationService::Launch(
136     const std::string& id, const Application::LaunchParams& params) {
137   Application* application = NULL;
138   scoped_refptr<ApplicationData> application_data =
139     application_storage_->GetApplicationData(id);
140   if (!application_data) {
141     LOG(ERROR) << "Application with id " << id << " is not installed.";
142     return NULL;
143   }
144
145   return Launch(application_data, params);
146 }
147
148 Application* ApplicationService::Launch(
149     const base::FilePath& path, const Application::LaunchParams& params) {
150   Application* application = NULL;
151   if (!base::DirectoryExists(path))
152     return NULL;
153
154   std::string error;
155   scoped_refptr<ApplicationData> application_data =
156       LoadApplication(path, Manifest::COMMAND_LINE, &error);
157
158   if (!application_data) {
159     LOG(ERROR) << "Error occurred while trying to launch application: "
160                << error;
161     return NULL;
162   }
163
164   return Launch(application_data, params);
165 }
166
167 namespace {
168
169 struct ApplicationRenderHostIDComparator {
170     explicit ApplicationRenderHostIDComparator(int id) : id(id) { }
171     bool operator() (Application* application) {
172       return id == application->GetRenderProcessHostID();
173     }
174     int id;
175 };
176
177 struct ApplicationIDComparator {
178     explicit ApplicationIDComparator(const std::string& app_id)
179       : app_id(app_id) { }
180     bool operator() (Application* application) {
181       return app_id == application->id();
182     }
183     std::string app_id;
184 };
185
186 }  // namespace
187
188 Application* ApplicationService::GetApplicationByRenderHostID(int id) const {
189   ApplicationRenderHostIDComparator comparator(id);
190   ScopedVector<Application>::const_iterator found = std::find_if(
191       applications_.begin(), applications_.end(), comparator);
192   if (found != applications_.end())
193     return *found;
194   return NULL;
195 }
196
197 Application* ApplicationService::GetApplicationByID(
198     const std::string& app_id) const {
199   ApplicationIDComparator comparator(app_id);
200   ScopedVector<Application>::const_iterator found = std::find_if(
201       applications_.begin(), applications_.end(), comparator);
202   if (found != applications_.end())
203     return *found;
204   return NULL;
205 }
206
207 void ApplicationService::AddObserver(Observer* observer) {
208   observers_.AddObserver(observer);
209 }
210
211 void ApplicationService::RemoveObserver(Observer* observer) {
212   observers_.RemoveObserver(observer);
213 }
214
215 void ApplicationService::OnApplicationTerminated(
216                                       Application* application) {
217   ScopedVector<Application>::iterator found = std::find(
218       applications_.begin(), applications_.end(), application);
219   CHECK(found != applications_.end());
220   FOR_EACH_OBSERVER(Observer, observers_,
221                     WillDestroyApplication(application));
222   applications_.erase(found);
223 #if !defined(SHARED_PROCESS_MODE)
224   if (applications_.empty()) {
225     base::MessageLoop::current()->PostTask(
226             FROM_HERE, base::MessageLoop::QuitClosure());
227   }
228 #endif
229 }
230
231 void ApplicationService::CheckAPIAccessControl(const std::string& app_id,
232     const std::string& extension_name,
233     const std::string& api_name, const PermissionCallback& callback) {
234   Application* app = GetApplicationByID(app_id);
235   if (!app) {
236     LOG(ERROR) << "No running application found with ID: "
237       << app_id;
238     callback.Run(UNDEFINED_RUNTIME_PERM);
239     return;
240   }
241   if (!app->UseExtension(extension_name)) {
242     LOG(ERROR) << "Can not find extension: "
243       << extension_name << " of Application with ID: "
244       << app_id;
245     callback.Run(UNDEFINED_RUNTIME_PERM);
246     return;
247   }
248   // Permission name should have been registered at extension initialization.
249   std::string permission_name =
250       app->GetRegisteredPermissionName(extension_name, api_name);
251   if (permission_name.empty()) {
252     LOG(ERROR) << "API: " << api_name << " of extension: "
253       << extension_name << " not registered!";
254     callback.Run(UNDEFINED_RUNTIME_PERM);
255     return;
256   }
257   // Okay, since we have the permission name, let's get down to the policies.
258   // First, find out whether the permission is stored for the current session.
259   StoredPermission perm = app->GetPermission(
260       SESSION_PERMISSION, permission_name);
261   if (perm != UNDEFINED_STORED_PERM) {
262     // "PROMPT" should not be in the session storage.
263     DCHECK(perm != PROMPT);
264     if (perm == ALLOW) {
265       callback.Run(ALLOW_SESSION);
266       return;
267     }
268     if (perm == DENY) {
269       callback.Run(DENY_SESSION);
270       return;
271     }
272     NOTREACHED();
273   }
274   // Then, query the persistent policy storage.
275   perm = app->GetPermission(PERSISTENT_PERMISSION, permission_name);
276   // Permission not found in persistent permission table, normally this should
277   // not happen because all the permission needed by the application should be
278   // contained in its manifest, so it also means that the application is asking
279   // for something wasn't allowed.
280   if (perm == UNDEFINED_STORED_PERM) {
281     callback.Run(UNDEFINED_RUNTIME_PERM);
282     return;
283   }
284   if (perm == PROMPT) {
285     // TODO(Bai): We needed to pop-up a dialog asking user to chose one from
286     // either allow/deny for session/one shot/forever. Then, we need to update
287     // the session and persistent policy accordingly.
288     callback.Run(UNDEFINED_RUNTIME_PERM);
289     return;
290   }
291   if (perm == ALLOW) {
292     callback.Run(ALLOW_ALWAYS);
293     return;
294   }
295   if (perm == DENY) {
296     callback.Run(DENY_ALWAYS);
297     return;
298   }
299   NOTREACHED();
300 }
301
302 bool ApplicationService::RegisterPermissions(const std::string& app_id,
303     const std::string& extension_name,
304     const std::string& perm_table) {
305   Application* app = GetApplicationByID(app_id);
306   if (!app) {
307     LOG(ERROR) << "No running application found with ID: " << app_id;
308     return false;
309   }
310   if (!app->UseExtension(extension_name)) {
311     LOG(ERROR) << "Can not find extension: "
312                << extension_name << " of Application with ID: "
313                << app_id;
314     return false;
315   }
316   return app->RegisterPermissions(extension_name, perm_table);
317 }
318
319 }  // namespace application
320 }  // namespace xwalk