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/file_util.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_observer.h"
16 #include "xwalk/application/browser/application.h"
17 #include "xwalk/application/common/application_manifest_constants.h"
18 #include "xwalk/application/common/application_file_util.h"
19 #include "xwalk/application/common/id_util.h"
20 #include "xwalk/runtime/browser/runtime_context.h"
21 #include "xwalk/runtime/browser/runtime.h"
22 #include "xwalk/runtime/common/xwalk_paths.h"
25 #include "xwalk/application/browser/application_service_tizen.h"
30 namespace application {
32 ApplicationService::ApplicationService(RuntimeContext* runtime_context)
33 : runtime_context_(runtime_context) {
36 scoped_ptr<ApplicationService> ApplicationService::Create(
37 RuntimeContext* runtime_context) {
39 return make_scoped_ptr<ApplicationService>(
40 new ApplicationServiceTizen(runtime_context));
42 return make_scoped_ptr(new ApplicationService(runtime_context));
46 ApplicationService::~ApplicationService() {
49 Application* ApplicationService::Launch(
50 scoped_refptr<ApplicationData> application_data,
51 const Application::LaunchParams& launch_params) {
52 if (GetApplicationByID(application_data->ID()) != NULL) {
53 LOG(INFO) << "Application with id: " << application_data->ID()
54 << " is already running.";
55 // FIXME: we need to notify application that it had been attempted
56 // to invoke and let the application to define the further behavior.
60 Application* application = Application::Create(application_data,
61 runtime_context_).release();
62 ScopedVector<Application>::iterator app_iter =
63 applications_.insert(applications_.end(), application);
65 if (!application->Launch(launch_params)) {
66 applications_.erase(app_iter);
70 application->set_observer(this);
72 FOR_EACH_OBSERVER(Observer, observers_,
73 DidLaunchApplication(application));
78 Application* ApplicationService::LaunchFromUnpackedPath(
79 const base::FilePath& path, const Application::LaunchParams& params) {
81 scoped_refptr<ApplicationData> application_data;
82 if (!base::DirectoryExists(path)) {
83 LOG(ERROR) << "Invalid input parameter: " << path.AsUTF8Unsafe();
88 LoadApplication(path, ApplicationData::LOCAL_DIRECTORY, &error);
90 if (!application_data) {
91 LOG(ERROR) << "Error occurred while trying to load application: "
96 return Launch(application_data, params);
99 Application* ApplicationService::LaunchFromPackagePath(
100 const base::FilePath& path, const Application::LaunchParams& params) {
101 scoped_ptr<Package> package = Package::Create(path);
102 if (!package || !package->IsValid()) {
103 LOG(ERROR) << "Failed to obtain valid package from "
104 << path.AsUTF8Unsafe();
108 base::FilePath tmp_dir, target_dir;
109 if (!GetTempDir(&tmp_dir)) {
110 LOG(ERROR) << "Failed to obtain system temp directory.";
115 scoped_refptr<ApplicationData> application_data;
117 base::CreateTemporaryDirInDir(tmp_dir, package->name(), &target_dir);
118 if (package->ExtractTo(target_dir)) {
119 std::string id = tmp_dir.BaseName().AsUTF8Unsafe();
122 target_dir, id, ApplicationData::TEMP_DIRECTORY, &error);
125 if (!application_data) {
126 LOG(ERROR) << "Error occurred while trying to load application: "
131 return Launch(application_data, params);
134 // Launch an application created from arbitrary url.
135 // FIXME: This application should have the same strict permissions
136 // as common browser apps.
137 Application* ApplicationService::LaunchHostedURL(
138 const GURL& url, const Application::LaunchParams& params) {
139 const std::string& url_spec = url.spec();
140 if (url_spec.empty()) {
141 LOG(ERROR) << "Failed to launch application from the URL: " << url;
145 const std::string& app_id = GenerateId(url_spec);
147 base::DictionaryValue manifest;
148 // FIXME: define permissions!
149 manifest.SetString(application_manifest_keys::kStartURLKey, url_spec);
150 // FIXME: Why use URL as name?
151 manifest.SetString(application_manifest_keys::kNameKey, url_spec);
152 manifest.SetString(application_manifest_keys::kXWalkVersionKey, "0");
155 scoped_refptr<ApplicationData> app_data =
156 ApplicationData::Create(base::FilePath(),
157 ApplicationData::EXTERNAL_URL, manifest, app_id, &error);
160 return Launch(app_data, params);
165 struct ApplicationRenderHostIDComparator {
166 explicit ApplicationRenderHostIDComparator(int id) : id(id) { }
167 bool operator() (Application* application) {
168 return id == application->GetRenderProcessHostID();
173 struct ApplicationIDComparator {
174 explicit ApplicationIDComparator(const std::string& app_id)
176 bool operator() (Application* application) {
177 return app_id == application->id();
184 Application* ApplicationService::GetApplicationByRenderHostID(int id) const {
185 ApplicationRenderHostIDComparator comparator(id);
186 ScopedVector<Application>::const_iterator found = std::find_if(
187 applications_.begin(), applications_.end(), comparator);
188 if (found != applications_.end())
193 Application* ApplicationService::GetApplicationByID(
194 const std::string& app_id) const {
195 ApplicationIDComparator comparator(app_id);
196 ScopedVector<Application>::const_iterator found = std::find_if(
197 applications_.begin(), applications_.end(), comparator);
198 if (found != applications_.end())
203 void ApplicationService::AddObserver(Observer* observer) {
204 observers_.AddObserver(observer);
207 void ApplicationService::RemoveObserver(Observer* observer) {
208 observers_.RemoveObserver(observer);
211 void ApplicationService::OnApplicationTerminated(
212 Application* application) {
213 ScopedVector<Application>::iterator found = std::find(
214 applications_.begin(), applications_.end(), application);
215 CHECK(found != applications_.end());
216 FOR_EACH_OBSERVER(Observer, observers_,
217 WillDestroyApplication(application));
218 scoped_refptr<ApplicationData> app_data = application->data();
219 applications_.erase(found);
221 if (app_data->source_type() == ApplicationData::TEMP_DIRECTORY) {
222 LOG(INFO) << "Deleting the app temporary directory "
223 << app_data->Path().AsUTF8Unsafe();
224 content::BrowserThread::PostTask(content::BrowserThread::FILE,
225 FROM_HERE, base::Bind(base::IgnoreResult(&base::DeleteFile),
226 app_data->Path(), true /*recursive*/));
227 // FIXME: So far we simply clean up all the app persistent data,
228 // further we need to add an appropriate logic to handle it.
229 content::BrowserContext::GarbageCollectStoragePartitions(
231 make_scoped_ptr(new base::hash_set<base::FilePath>()),
232 base::Bind(&base::DoNothing));
235 #if !defined(SHARED_PROCESS_MODE)
236 if (applications_.empty()) {
237 base::MessageLoop::current()->PostTask(
238 FROM_HERE, base::MessageLoop::QuitClosure());
243 void ApplicationService::CheckAPIAccessControl(const std::string& app_id,
244 const std::string& extension_name,
245 const std::string& api_name, const PermissionCallback& callback) {
246 Application* app = GetApplicationByID(app_id);
248 LOG(ERROR) << "No running application found with ID: "
250 callback.Run(UNDEFINED_RUNTIME_PERM);
253 if (!app->UseExtension(extension_name)) {
254 LOG(ERROR) << "Can not find extension: "
255 << extension_name << " of Application with ID: "
257 callback.Run(UNDEFINED_RUNTIME_PERM);
260 // Permission name should have been registered at extension initialization.
261 std::string permission_name =
262 app->GetRegisteredPermissionName(extension_name, api_name);
263 if (permission_name.empty()) {
264 LOG(ERROR) << "API: " << api_name << " of extension: "
265 << extension_name << " not registered!";
266 callback.Run(UNDEFINED_RUNTIME_PERM);
269 // Okay, since we have the permission name, let's get down to the policies.
270 // First, find out whether the permission is stored for the current session.
271 StoredPermission perm = app->GetPermission(
272 SESSION_PERMISSION, permission_name);
273 if (perm != UNDEFINED_STORED_PERM) {
274 // "PROMPT" should not be in the session storage.
275 DCHECK(perm != PROMPT);
277 callback.Run(ALLOW_SESSION);
281 callback.Run(DENY_SESSION);
286 // Then, query the persistent policy storage.
287 perm = app->GetPermission(PERSISTENT_PERMISSION, permission_name);
288 // Permission not found in persistent permission table, normally this should
289 // not happen because all the permission needed by the application should be
290 // contained in its manifest, so it also means that the application is asking
291 // for something wasn't allowed.
292 if (perm == UNDEFINED_STORED_PERM) {
293 callback.Run(UNDEFINED_RUNTIME_PERM);
296 if (perm == PROMPT) {
297 // TODO(Bai): We needed to pop-up a dialog asking user to chose one from
298 // either allow/deny for session/one shot/forever. Then, we need to update
299 // the session and persistent policy accordingly.
300 callback.Run(UNDEFINED_RUNTIME_PERM);
304 callback.Run(ALLOW_ALWAYS);
308 callback.Run(DENY_ALWAYS);
314 bool ApplicationService::RegisterPermissions(const std::string& app_id,
315 const std::string& extension_name,
316 const std::string& perm_table) {
317 Application* app = GetApplicationByID(app_id);
319 LOG(ERROR) << "No running application found with ID: " << app_id;
322 if (!app->UseExtension(extension_name)) {
323 LOG(ERROR) << "Can not find extension: "
324 << extension_name << " of Application with ID: "
328 return app->RegisterPermissions(extension_name, perm_table);
331 } // namespace application