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"
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>());
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 package_installer_(PackageInstaller::Create(app_storage)) {
73 CollectUnusedStoragePartitions(runtime_context, app_storage);
76 ApplicationService::~ApplicationService() {
79 bool ApplicationService::Install(const base::FilePath& path, std::string* id) {
80 if (!package_installer_->Install(path, id))
83 FOR_EACH_OBSERVER(Observer, observers_,
84 OnApplicationInstalled(*id));
89 bool ApplicationService::Update(const std::string& id,
90 const base::FilePath& path) {
91 if (Application* app = GetApplicationByID(id)) {
92 LOG(INFO) << "Try to terminate the running application before uninstall.";
96 if (!package_installer_->Update(id, path))
99 FOR_EACH_OBSERVER(Observer, observers_,
100 OnApplicationUpdated(id));
105 bool ApplicationService::Uninstall(const std::string& id) {
106 if (Application* app = GetApplicationByID(id)) {
107 LOG(INFO) << "Try to terminate the running application before uninstall.";
111 if (!package_installer_->Uninstall(id))
114 FOR_EACH_OBSERVER(Observer, observers_, OnApplicationUninstalled(id));
119 void ApplicationService::ChangeLocale(const std::string& locale) {
120 ApplicationData::ApplicationDataMap apps;
121 if (!application_storage_->GetInstalledApplications(apps))
124 ApplicationData::ApplicationDataMap::const_iterator it;
125 for (it = apps.begin(); it != apps.end(); ++it) {
126 base::string16 error;
127 std::string old_name = it->second->Name();
128 if (!it->second->SetApplicationLocale(locale, &error)) {
129 LOG(ERROR) << "Error when set locale " << locale
130 << " to application " << it->second->ID()
131 << "error : " << error;
133 if (old_name != it->second->Name()) {
134 // After we has changed the application locale, we might get a new name in
135 // the new locale, so call all observer for this event.
137 Observer, observers_,
138 OnApplicationNameChanged(it->second->ID(), it->second->Name()));
143 Application* ApplicationService::Launch(
144 scoped_refptr<ApplicationData> application_data,
145 const Application::LaunchParams& launch_params) {
146 if (GetApplicationByID(application_data->ID()) != NULL) {
147 LOG(INFO) << "Application with id: " << application_data->ID()
148 << " is already running.";
149 // FIXME: we need to notify application that it had been attempted
150 // to invoke and let the application to define the further behavior.
154 #if defined(OS_TIZEN)
155 Application* application(new ApplicationTizen(application_data,
156 runtime_context_, this));
158 Application* application(new Application(application_data,
159 runtime_context_, this));
162 ScopedVector<Application>::iterator app_iter =
163 applications_.insert(applications_.end(), application);
165 if (!application->Launch(launch_params)) {
166 applications_.erase(app_iter);
170 FOR_EACH_OBSERVER(Observer, observers_,
171 DidLaunchApplication(application));
176 Application* ApplicationService::Launch(
177 const std::string& id, const Application::LaunchParams& params) {
178 Application* application = NULL;
179 scoped_refptr<ApplicationData> application_data =
180 application_storage_->GetApplicationData(id);
181 if (!application_data) {
182 LOG(ERROR) << "Application with id " << id << " is not installed.";
186 return Launch(application_data, params);
189 Application* ApplicationService::Launch(
190 const base::FilePath& path, const Application::LaunchParams& params) {
191 Application* application = NULL;
192 if (!base::DirectoryExists(path))
196 scoped_refptr<ApplicationData> application_data =
197 LoadApplication(path, Manifest::COMMAND_LINE, &error);
199 if (!application_data) {
200 LOG(ERROR) << "Error occurred while trying to launch application: "
205 return Launch(application_data, params);
210 struct ApplicationRenderHostIDComparator {
211 explicit ApplicationRenderHostIDComparator(int id) : id(id) { }
212 bool operator() (Application* application) {
213 return id == application->GetRenderProcessHostID();
218 struct ApplicationIDComparator {
219 explicit ApplicationIDComparator(const std::string& app_id)
221 bool operator() (Application* application) {
222 return app_id == application->id();
229 Application* ApplicationService::GetApplicationByRenderHostID(int id) const {
230 ApplicationRenderHostIDComparator comparator(id);
231 ScopedVector<Application>::const_iterator found = std::find_if(
232 applications_.begin(), applications_.end(), comparator);
233 if (found != applications_.end())
238 Application* ApplicationService::GetApplicationByID(
239 const std::string& app_id) const {
240 ApplicationIDComparator comparator(app_id);
241 ScopedVector<Application>::const_iterator found = std::find_if(
242 applications_.begin(), applications_.end(), comparator);
243 if (found != applications_.end())
248 void ApplicationService::AddObserver(Observer* observer) {
249 observers_.AddObserver(observer);
252 void ApplicationService::RemoveObserver(Observer* observer) {
253 observers_.RemoveObserver(observer);
256 void ApplicationService::OnApplicationTerminated(
257 Application* application) {
258 ScopedVector<Application>::iterator found = std::find(
259 applications_.begin(), applications_.end(), application);
260 CHECK(found != applications_.end());
261 FOR_EACH_OBSERVER(Observer, observers_,
262 WillDestroyApplication(application));
263 applications_.erase(found);
264 if (!XWalkRunner::GetInstance()->is_running_as_service() &&
265 applications_.empty()) {
266 base::MessageLoop::current()->PostTask(
267 FROM_HERE, base::MessageLoop::QuitClosure());
271 void ApplicationService::CheckAPIAccessControl(const std::string& app_id,
272 const std::string& extension_name,
273 const std::string& api_name, const PermissionCallback& callback) {
274 Application* app = GetApplicationByID(app_id);
276 LOG(ERROR) << "No running application found with ID: "
278 callback.Run(UNDEFINED_RUNTIME_PERM);
281 if (!app->UseExtension(extension_name)) {
282 LOG(ERROR) << "Can not find extension: "
283 << extension_name << " of Application with ID: "
285 callback.Run(UNDEFINED_RUNTIME_PERM);
288 // Permission name should have been registered at extension initialization.
289 std::string permission_name =
290 app->GetRegisteredPermissionName(extension_name, api_name);
291 if (permission_name.empty()) {
292 LOG(ERROR) << "API: " << api_name << " of extension: "
293 << extension_name << " not registered!";
294 callback.Run(UNDEFINED_RUNTIME_PERM);
297 // Okay, since we have the permission name, let's get down to the policies.
298 // First, find out whether the permission is stored for the current session.
299 StoredPermission perm = app->GetPermission(
300 SESSION_PERMISSION, permission_name);
301 if (perm != UNDEFINED_STORED_PERM) {
302 // "PROMPT" should not be in the session storage.
303 DCHECK(perm != PROMPT);
305 callback.Run(ALLOW_SESSION);
309 callback.Run(DENY_SESSION);
314 // Then, query the persistent policy storage.
315 perm = app->GetPermission(PERSISTENT_PERMISSION, permission_name);
316 // Permission not found in persistent permission table, normally this should
317 // not happen because all the permission needed by the application should be
318 // contained in its manifest, so it also means that the application is asking
319 // for something wasn't allowed.
320 if (perm == UNDEFINED_STORED_PERM) {
321 callback.Run(UNDEFINED_RUNTIME_PERM);
324 if (perm == PROMPT) {
325 // TODO(Bai): We needed to pop-up a dialog asking user to chose one from
326 // either allow/deny for session/one shot/forever. Then, we need to update
327 // the session and persistent policy accordingly.
328 callback.Run(UNDEFINED_RUNTIME_PERM);
332 callback.Run(ALLOW_ALWAYS);
336 callback.Run(DENY_ALWAYS);
342 bool ApplicationService::RegisterPermissions(const std::string& app_id,
343 const std::string& extension_name,
344 const std::string& perm_table) {
345 Application* app = GetApplicationByID(app_id);
347 LOG(ERROR) << "No running application found with ID: " << app_id;
350 if (!app->UseExtension(extension_name)) {
351 LOG(ERROR) << "Can not find extension: "
352 << extension_name << " of Application with ID: "
356 return app->RegisterPermissions(extension_name, perm_table);
359 } // namespace application