Upstream version 9.38.204.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / application_service.cc
index e4c6005..6a68e4e 100644 (file)
@@ -4,79 +4,45 @@
 
 #include "xwalk/application/browser/application_service.h"
 
+#include <hash_set>
 #include <set>
 #include <string>
 #include <vector>
 
-#include "base/containers/hash_tables.h"
-#include "base/files/file_enumerator.h"
 #include "base/file_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "xwalk/application/browser/application.h"
-#include "xwalk/application/browser/application_system.h"
-#include "xwalk/application/common/application_storage.h"
-#include "xwalk/application/common/installer/package.h"
-#include "xwalk/application/common/installer/package_installer.h"
+#include "xwalk/application/common/application_manifest_constants.h"
 #include "xwalk/application/common/application_file_util.h"
+#include "xwalk/application/common/id_util.h"
 #include "xwalk/runtime/browser/runtime_context.h"
 #include "xwalk/runtime/browser/runtime.h"
-#include "xwalk/runtime/browser/xwalk_runner.h"
 #include "xwalk/runtime/common/xwalk_paths.h"
 
 #if defined(OS_TIZEN)
-#include "xwalk/application/browser/application_tizen.h"
+#include "xwalk/application/browser/application_service_tizen.h"
 #endif
 
 namespace xwalk {
 
 namespace application {
 
-namespace {
-
-const base::FilePath::CharType kApplicationDataDirName[] =
-    FILE_PATH_LITERAL("Storage/ext");
+ApplicationService::ApplicationService(RuntimeContext* runtime_context)
+  : runtime_context_(runtime_context) {
+}
 
-base::FilePath GetStoragePartitionPath(
-    const base::FilePath& base_path, const std::string& app_id) {
-#if defined(OS_WIN)
-  std::wstring application_id(app_id.begin(), app_id.end());
-  return base_path.Append(kApplicationDataDirName).Append(application_id);
+scoped_ptr<ApplicationService> ApplicationService::Create(
+    RuntimeContext* runtime_context) {
+#if defined(OS_TIZEN)
+  return make_scoped_ptr<ApplicationService>(
+    new ApplicationServiceTizen(runtime_context));
 #else
-  return base_path.Append(kApplicationDataDirName).Append(app_id);
+  return make_scoped_ptr(new ApplicationService(runtime_context));
 #endif
 }
 
-void CollectUnusedStoragePartitions(RuntimeContext* context,
-                                    ApplicationStorage* storage) {
-  std::vector<std::string> app_ids;
-  if (!storage->GetInstalledApplicationIDs(app_ids))
-    return;
-
-  scoped_ptr<base::hash_set<base::FilePath> > active_paths(
-      new base::hash_set<base::FilePath>()); // NOLINT
-
-  for (unsigned i = 0; i < app_ids.size(); ++i) {
-    active_paths->insert(
-        GetStoragePartitionPath(context->GetPath(), app_ids.at(i)));
-  }
-
-  content::BrowserContext::GarbageCollectStoragePartitions(
-      context, active_paths.Pass(), base::Bind(&base::DoNothing));
-}
-
-}  // namespace
-
-ApplicationService::ApplicationService(RuntimeContext* runtime_context,
-                                       ApplicationStorage* app_storage)
-    : runtime_context_(runtime_context),
-      application_storage_(app_storage) {
-  CollectUnusedStoragePartitions(runtime_context, app_storage);
-}
-
 ApplicationService::~ApplicationService() {
 }
 
@@ -91,14 +57,8 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
-#if defined(OS_TIZEN)
-  Application* application(new ApplicationTizen(application_data,
-    runtime_context_, this));
-#else
-  Application* application(new Application(application_data,
-    runtime_context_, this));
-#endif
-
+  Application* application = Application::Create(application_data,
+    runtime_context_).release();
   ScopedVector<Application>::iterator app_iter =
       applications_.insert(applications_.end(), application);
 
@@ -107,35 +67,63 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
+  application->set_observer(this);
+
   FOR_EACH_OBSERVER(Observer, observers_,
                     DidLaunchApplication(application));
 
   return application;
 }
 
-Application* ApplicationService::Launch(
-    const std::string& id, const Application::LaunchParams& params) {
-  scoped_refptr<ApplicationData> application_data =
-    application_storage_->GetApplicationData(id);
+Application* ApplicationService::LaunchFromUnpackedPath(
+    const base::FilePath& path, const Application::LaunchParams& params) {
+  std::string error;
+  scoped_refptr<ApplicationData> application_data;
+  if (!base::DirectoryExists(path)) {
+    LOG(ERROR) << "Invalid input parameter: " << path.AsUTF8Unsafe();
+    return NULL;
+  }
+
+  application_data =
+      LoadApplication(path, ApplicationData::LOCAL_DIRECTORY, &error);
+
   if (!application_data) {
-    LOG(ERROR) << "Application with id " << id << " is not installed.";
+    LOG(ERROR) << "Error occurred while trying to load application: "
+               << error;
     return NULL;
   }
 
   return Launch(application_data, params);
 }
 
-Application* ApplicationService::Launch(
+Application* ApplicationService::LaunchFromPackagePath(
     const base::FilePath& path, const Application::LaunchParams& params) {
-  if (!base::DirectoryExists(path))
+  scoped_ptr<Package> package = Package::Create(path);
+  if (!package || !package->IsValid()) {
+    LOG(ERROR) << "Failed to obtain valid package from "
+               << path.AsUTF8Unsafe();
     return NULL;
+  }
+
+  base::FilePath tmp_dir, target_dir;
+  if (!GetTempDir(&tmp_dir)) {
+    LOG(ERROR) << "Failed to obtain system temp directory.";
+    return NULL;
+  }
 
   std::string error;
-  scoped_refptr<ApplicationData> application_data =
-      LoadApplication(path, Manifest::COMMAND_LINE, &error);
+  scoped_refptr<ApplicationData> application_data;
+
+  base::CreateTemporaryDirInDir(tmp_dir, package->name(), &target_dir);
+  if (package->ExtractTo(target_dir)) {
+    std::string id = tmp_dir.BaseName().AsUTF8Unsafe();
+    application_data =
+        LoadApplication(
+            target_dir, id, ApplicationData::TEMP_DIRECTORY, &error);
+  }
 
   if (!application_data) {
-    LOG(ERROR) << "Error occurred while trying to launch application: "
+    LOG(ERROR) << "Error occurred while trying to load application: "
                << error;
     return NULL;
   }
@@ -143,6 +131,35 @@ Application* ApplicationService::Launch(
   return Launch(application_data, params);
 }
 
+// Launch an application created from arbitrary url.
+// FIXME: This application should have the same strict permissions
+// as common browser apps.
+Application* ApplicationService::LaunchHostedURL(
+    const GURL& url, const Application::LaunchParams& params) {
+  const std::string& url_spec = url.spec();
+  if (url_spec.empty()) {
+      LOG(ERROR) << "Failed to launch application from the URL: " << url;
+      return NULL;
+  }
+
+  const std::string& app_id = GenerateId(url_spec);
+
+  base::DictionaryValue manifest;
+  // FIXME: define permissions!
+  manifest.SetString(application_manifest_keys::kStartURLKey, url_spec);
+  // FIXME: Why use URL as name?
+  manifest.SetString(application_manifest_keys::kNameKey, url_spec);
+  manifest.SetString(application_manifest_keys::kXWalkVersionKey, "0");
+
+  std::string error;
+  scoped_refptr<ApplicationData> app_data =
+        ApplicationData::Create(base::FilePath(),
+            ApplicationData::EXTERNAL_URL, manifest, app_id, &error);
+  DCHECK(app_data);
+
+  return Launch(app_data, params);
+}
+
 namespace {
 
 struct ApplicationRenderHostIDComparator {
@@ -198,7 +215,23 @@ void ApplicationService::OnApplicationTerminated(
   CHECK(found != applications_.end());
   FOR_EACH_OBSERVER(Observer, observers_,
                     WillDestroyApplication(application));
+  scoped_refptr<ApplicationData> app_data = application->data();
   applications_.erase(found);
+
+  if (app_data->source_type() == ApplicationData::TEMP_DIRECTORY) {
+      LOG(INFO) << "Deleting the app temporary directory "
+                << app_data->Path().AsUTF8Unsafe();
+      content::BrowserThread::PostTask(content::BrowserThread::FILE,
+          FROM_HERE, base::Bind(base::IgnoreResult(&base::DeleteFile),
+                                app_data->Path(), true /*recursive*/));
+      // FIXME: So far we simply clean up all the app persistent data,
+      // further we need to add an appropriate logic to handle it.
+      content::BrowserContext::GarbageCollectStoragePartitions(
+          runtime_context_,
+          make_scoped_ptr(new base::hash_set<base::FilePath>()),
+          base::Bind(&base::DoNothing));
+  }
+
 #if !defined(SHARED_PROCESS_MODE)
   if (applications_.empty()) {
     base::MessageLoop::current()->PostTask(