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.
5 #include "xwalk/application/browser/application_service.h"
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"
31 #include "xwalk/application/browser/application_tizen.h"
36 namespace application {
40 const base::FilePath::CharType kApplicationDataDirName[] =
41 FILE_PATH_LITERAL("Storage/ext");
43 base::FilePath GetStoragePartitionPath(
44 const base::FilePath& base_path, const std::string& app_id) {
45 return base_path.Append(kApplicationDataDirName).Append(app_id);
48 void CollectUnusedStoragePartitions(RuntimeContext* context,
49 ApplicationStorage* storage) {
50 std::vector<std::string> app_ids;
51 if (!storage->GetInstalledApplicationIDs(app_ids))
54 scoped_ptr<base::hash_set<base::FilePath> > active_paths(
55 new base::hash_set<base::FilePath>()); // NOLINT
57 for (unsigned i = 0; i < app_ids.size(); ++i) {
59 GetStoragePartitionPath(context->GetPath(), app_ids.at(i)));
62 content::BrowserContext::GarbageCollectStoragePartitions(
63 context, active_paths.Pass(), base::Bind(&base::DoNothing));
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);
75 ApplicationService::~ApplicationService() {
78 void ApplicationService::ChangeLocale(const std::string& locale) {
79 ApplicationData::ApplicationDataMap apps;
80 if (!application_storage_->GetInstalledApplications(apps))
83 ApplicationData::ApplicationDataMap::const_iterator it;
84 for (it = apps.begin(); it != apps.end(); ++it) {
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;
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.
97 OnApplicationNameChanged(it->second->ID(), it->second->Name()));
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.
113 #if defined(OS_TIZEN)
114 Application* application(new ApplicationTizen(application_data,
115 runtime_context_, this));
117 Application* application(new Application(application_data,
118 runtime_context_, this));
121 ScopedVector<Application>::iterator app_iter =
122 applications_.insert(applications_.end(), application);
124 if (!application->Launch(launch_params)) {
125 applications_.erase(app_iter);
129 FOR_EACH_OBSERVER(Observer, observers_,
130 DidLaunchApplication(application));
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.";
145 return Launch(application_data, params);
148 Application* ApplicationService::Launch(
149 const base::FilePath& path, const Application::LaunchParams& params) {
150 Application* application = NULL;
151 if (!base::DirectoryExists(path))
155 scoped_refptr<ApplicationData> application_data =
156 LoadApplication(path, Manifest::COMMAND_LINE, &error);
158 if (!application_data) {
159 LOG(ERROR) << "Error occurred while trying to launch application: "
164 return Launch(application_data, params);
169 struct ApplicationRenderHostIDComparator {
170 explicit ApplicationRenderHostIDComparator(int id) : id(id) { }
171 bool operator() (Application* application) {
172 return id == application->GetRenderProcessHostID();
177 struct ApplicationIDComparator {
178 explicit ApplicationIDComparator(const std::string& app_id)
180 bool operator() (Application* application) {
181 return app_id == application->id();
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())
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())
207 void ApplicationService::AddObserver(Observer* observer) {
208 observers_.AddObserver(observer);
211 void ApplicationService::RemoveObserver(Observer* observer) {
212 observers_.RemoveObserver(observer);
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());
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);
236 LOG(ERROR) << "No running application found with ID: "
238 callback.Run(UNDEFINED_RUNTIME_PERM);
241 if (!app->UseExtension(extension_name)) {
242 LOG(ERROR) << "Can not find extension: "
243 << extension_name << " of Application with ID: "
245 callback.Run(UNDEFINED_RUNTIME_PERM);
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);
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);
265 callback.Run(ALLOW_SESSION);
269 callback.Run(DENY_SESSION);
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);
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);
292 callback.Run(ALLOW_ALWAYS);
296 callback.Run(DENY_ALWAYS);
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);
307 LOG(ERROR) << "No running application found with ID: " << app_id;
310 if (!app->UseExtension(extension_name)) {
311 LOG(ERROR) << "Can not find extension: "
312 << extension_name << " of Application with ID: "
316 return app->RegisterPermissions(extension_name, perm_table);
319 } // namespace application