Upstream version 8.37.183.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / application_service.cc
index a99d8a3..e4c6005 100644 (file)
@@ -6,24 +6,22 @@
 
 #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 "base/version.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "xwalk/application/browser/application_event_manager.h"
 #include "xwalk/application/browser/application.h"
-#include "xwalk/application/browser/application_storage.h"
 #include "xwalk/application/browser/application_system.h"
-#include "xwalk/application/browser/installer/package.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_file_util.h"
-#include "xwalk/application/common/event_names.h"
-#include "xwalk/application/common/permission_policy_manager.h"
 #include "xwalk/runtime/browser/runtime_context.h"
 #include "xwalk/runtime/browser/runtime.h"
 #include "xwalk/runtime/browser/xwalk_runner.h"
 
 #if defined(OS_TIZEN)
 #include "xwalk/application/browser/application_tizen.h"
-#include "xwalk/application/browser/installer/tizen/service_package_installer.h"
 #endif
 
 namespace xwalk {
+
 namespace application {
 
 namespace {
 
-void WaitForEventAndClose(
-    const std::string& app_id,
-    const std::string& event_name,
-    ApplicationService* application_service,
-    ApplicationEventManager* event_manager) {
-
-  class CloseOnEventArrived : public EventObserver {
-   public:
-    CloseOnEventArrived(
-        const std::string& event_name,
-        ApplicationService* application_service,
-        ApplicationEventManager* event_manager)
-        : EventObserver(event_manager),
-          event_name_(event_name),
-          application_service_(application_service) {}
-
-    virtual void Observe(
-        const std::string& app_id,
-        scoped_refptr<Event> event) OVERRIDE {
-      DCHECK(kOnJavaScriptEventAck == event->name());
-      std::string ack_event_name;
-      event->args()->GetString(0, &ack_event_name);
-      if (ack_event_name != event_name_)
-        return;
-
-      if (Application* app = application_service_->GetApplicationByID(app_id))
-        app->Terminate(Application::Immediate);
-
-      delete this;
-    }
-
-   private:
-    std::string event_name_;
-    ApplicationService* application_service_;
-  };
-
-  DCHECK(event_manager);
-  CloseOnEventArrived* observer =
-      new CloseOnEventArrived(event_name, application_service, event_manager);
-  event_manager->AttachObserver(app_id,
-      kOnJavaScriptEventAck, observer);
-}
-
-void WaitForFinishLoad(
-    const std::string& app_id,
-    ApplicationService* application_service,
-    ApplicationEventManager* event_manager,
-    content::WebContents* contents) {
-  class CloseAfterLoadObserver : public content::WebContentsObserver {
-   public:
-    CloseAfterLoadObserver(
-        const std::string& app_id,
-        ApplicationService* application_service,
-        ApplicationEventManager* event_manager,
-        content::WebContents* contents)
-        : content::WebContentsObserver(contents),
-          id_(app_id),
-          application_service_(application_service),
-          event_manager_(event_manager) {
-      DCHECK(application_service_);
-      DCHECK(event_manager_);
-    }
+const base::FilePath::CharType kApplicationDataDirName[] =
+    FILE_PATH_LITERAL("Storage/ext");
 
-    virtual void DidFinishLoad(
-        int64 frame_id,
-        const GURL& validate_url,
-        bool is_main_frame,
-        content::RenderViewHost* render_view_host) OVERRIDE {
-      Application* app = application_service_->GetApplicationByID(id_);
-      if (!app) {
-        delete this;
-        return;
-      }
-
-      if (!IsEventHandlerRegistered(app->data(), kOnInstalled)) {
-          app->Terminate(Application::Immediate);
-      } else {
-        scoped_ptr<base::ListValue> event_args(new base::ListValue);
-        scoped_refptr<Event> event =
-            Event::CreateEvent(kOnInstalled, event_args.Pass());
-        event_manager_->SendEvent(id_, event);
-
-        WaitForEventAndClose(
-            id_, event->name(), application_service_, event_manager_);
-      }
-      delete this;
-    }
-
-   private:
-    bool IsEventHandlerRegistered(scoped_refptr<ApplicationData> app_data,
-                                  const std::string& event_name) const {
-      const std::set<std::string>& events = app_data->GetEvents();
-      return events.find(event_name) != events.end();
-    }
-
-    std::string id_;
-    ApplicationService* application_service_;
-    ApplicationEventManager* event_manager_;
-  };
-
-  // This object is self-destroyed when an event occurs.
-  new CloseAfterLoadObserver(
-      app_id, application_service, event_manager, contents);
-}
-
-void SaveSystemEventsInfo(
-    scoped_refptr<ApplicationData> application_data,
-    ApplicationService* application_service,
-    ApplicationEventManager* event_manager) {
-  // We need to run main document after installation in order to
-  // register system events.
-  if (application_data->HasMainDocument()) {
-    if (Application* application =
-        application_service->Launch(application_data->ID())) {
-      WaitForFinishLoad(application->id(), application_service, event_manager,
-                        application->GetMainDocumentRuntime()->web_contents());
-    }
-  }
+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);
+#else
+  return base_path.Append(kApplicationDataDirName).Append(app_id);
+#endif
 }
 
-#if defined(OS_TIZEN)
-bool InstallPackageOnTizen(ApplicationData* application_data,
-                           const base::FilePath& data_dir) {
-  if (!XWalkRunner::GetInstance()->is_running_as_service()) {
-    LOG(ERROR) << "Installation on Tizen is only possible in"
-               << "service mode via 'xwalkctl' utility.";
-    return false;
-  }
-
-  return InstallApplicationForTizen(application_data, data_dir);
-}
+void CollectUnusedStoragePartitions(RuntimeContext* context,
+                                    ApplicationStorage* storage) {
+  std::vector<std::string> app_ids;
+  if (!storage->GetInstalledApplicationIDs(app_ids))
+    return;
 
-bool UninstallPackageOnTizen(ApplicationData* application_data,
-                             const base::FilePath& data_dir) {
-  if (!XWalkRunner::GetInstance()->is_running_as_service()) {
-    LOG(ERROR) << "Uninstallation on Tizen is only possible in"
-               << "service mode using 'xwalkctl' utility.";
-    return false;
-  }
+  scoped_ptr<base::hash_set<base::FilePath> > active_paths(
+      new base::hash_set<base::FilePath>()); // NOLINT
 
-  return UninstallApplicationForTizen(application_data, data_dir);
-}
-#endif  // OS_TIZEN
-
-bool CopyDirectoryContents(const base::FilePath& from,
-    const base::FilePath& to) {
-  base::FileEnumerator iter(from, false,
-      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
-  for (base::FilePath path = iter.Next(); !path.empty(); path = iter.Next()) {
-    if (iter.GetInfo().IsDirectory()) {
-      if (!base::CopyDirectory(path, to, true))
-        return false;
-    } else if (!base::CopyFile(path, to.Append(path.BaseName()))) {
-        return false;
-    }
+  for (unsigned i = 0; i < app_ids.size(); ++i) {
+    active_paths->insert(
+        GetStoragePartitionPath(context->GetPath(), app_ids.at(i)));
   }
 
-  return true;
-}
-
-void RemoveWidgetStorageFiles(const base::FilePath& storage_path,
-                              const std::string& app_id) {
-  base::FileEnumerator iter(storage_path, true,
-                            base::FileEnumerator::FILES);
-  for (base::FilePath file = iter.Next(); !file.empty(); file = iter.Next()) {
-    if (file.MaybeAsASCII().find(app_id) != std::string::npos)
-      base::DeleteFile(file, false);
-  }
+  content::BrowserContext::GarbageCollectStoragePartitions(
+      context, active_paths.Pass(), base::Bind(&base::DoNothing));
 }
 
 }  // namespace
 
-const base::FilePath::CharType kApplicationsDir[] =
-    FILE_PATH_LITERAL("applications");
-
 ApplicationService::ApplicationService(RuntimeContext* runtime_context,
-                                       ApplicationStorage* app_storage,
-                                       ApplicationEventManager* event_manager)
+                                       ApplicationStorage* app_storage)
     : runtime_context_(runtime_context),
-      application_storage_(app_storage),
-      event_manager_(event_manager),
-      permission_policy_handler_(new PermissionPolicyManager()) {
-  AddObserver(event_manager);
+      application_storage_(app_storage) {
+  CollectUnusedStoragePartitions(runtime_context, app_storage);
 }
 
 ApplicationService::~ApplicationService() {
 }
 
-bool ApplicationService::Install(const base::FilePath& path, std::string* id) {
-  // FIXME(leandro): Installation is not robust enough -- should any step
-  // fail, it can't roll back to a consistent state.
-  if (!base::PathExists(path))
-    return false;
-
-  const base::FilePath data_dir =
-      runtime_context_->GetPath().Append(kApplicationsDir);
-
-  // Make sure the kApplicationsDir exists under data_path, otherwise,
-  // the installation will always fail because of moving application
-  // resources into an invalid directory.
-  if (!base::DirectoryExists(data_dir) &&
-      !base::CreateDirectory(data_dir))
-    return false;
-
-  std::string app_id;
-  base::FilePath unpacked_dir;
-  scoped_ptr<Package> package;
-  if (!base::DirectoryExists(path)) {
-    package = Package::Create(path);
-    package->Extract(&unpacked_dir);
-    app_id = package->Id();
-  } else {
-    unpacked_dir = path;
-  }
-
-  std::string error;
-  scoped_refptr<ApplicationData> application_data = LoadApplication(
-      unpacked_dir, app_id, Manifest::COMMAND_LINE, &error);
-  if (!application_data) {
-    LOG(ERROR) << "Error during application installation: " << error;
-    return false;
-  }
-  if (!permission_policy_handler_->
-      InitApplicationPermission(application_data)) {
-    LOG(ERROR) << "Application permission data is invalid";
-    return false;
-  }
-
-  if (application_storage_->Contains(application_data->ID())) {
-    *id = application_data->ID();
-    LOG(INFO) << "Already installed: " << *id;
-    return false;
-  }
-
-  base::FilePath app_dir = data_dir.AppendASCII(application_data->ID());
-  if (base::DirectoryExists(app_dir)) {
-    if (!base::DeleteFile(app_dir, true))
-      return false;
-  }
-  if (!package) {
-    if (!base::CreateDirectory(app_dir))
-      return false;
-    if (!CopyDirectoryContents(unpacked_dir, app_dir))
-      return false;
-  } else {
-    if (!base::Move(unpacked_dir, app_dir))
-      return false;
-  }
-
-  application_data->SetPath(app_dir);
-
-  if (!application_storage_->AddApplication(application_data)) {
-    LOG(ERROR) << "Application with id " << application_data->ID()
-               << " couldn't be installed.";
-    return false;
-  }
-
-#if defined(OS_TIZEN)
-  if (!InstallPackageOnTizen(application_data,
-                             runtime_context_->GetPath())) {
-    application_storage_->RemoveApplication(application_data->ID());
-    return false;
-  }
-#endif
-
-  LOG(INFO) << "Application be installed in: " << app_dir.MaybeAsASCII();
-  LOG(INFO) << "Installed application with id: " << application_data->ID()
-            << " successfully.";
-  *id = application_data->ID();
-
-  SaveSystemEventsInfo(application_data, this, event_manager_);
-
-  FOR_EACH_OBSERVER(Observer, observers_,
-                    OnApplicationInstalled(application_data->ID()));
-
-  return true;
-}
-
-bool ApplicationService::Update(const std::string& id,
-                                const base::FilePath& path) {
-  if (!base::PathExists(path)) {
-    LOG(ERROR) << "The XPK/WGT package file " << path.value() << " is invalid.";
-    return false;
-  }
-
-  if (base::DirectoryExists(path)) {
-    LOG(WARNING) << "Can not update an unpacked XPK/WGT package.";
-    return false;
-  }
-
-  base::FilePath unpacked_dir;
-  base::FilePath origin_dir;
-  std::string app_id;
-  scoped_ptr<Package> package = Package::Create(path);
-  if (!package) {
-    LOG(ERROR) << "XPK/WGT file is invalid.";
-    return false;
-  }
-
-  app_id = package->Id();
-
-  if (app_id.empty()) {
-    LOG(ERROR) << "XPK/WGT file is invalid, and the application id is empty.";
-    return false;
-  }
-
-  if (id.empty() ||
-      id.compare(app_id) != 0) {
-    LOG(ERROR) << "The XPK/WGT file is not the same as expecting.";
-    return false;
-  }
-
-  if (!package->Extract(&unpacked_dir))
-    return false;
-
-  std::string error;
-  scoped_refptr<ApplicationData> new_application =
-      LoadApplication(unpacked_dir,
-                      app_id,
-                      Manifest::COMMAND_LINE,
-                      &error);
-  if (!new_application) {
-    LOG(ERROR) << "An error occurred during application updating: " << error;
-    return false;
-  }
-
-  scoped_refptr<ApplicationData> old_application =
-      application_storage_->GetApplicationData(app_id);
-  if (!old_application) {
-    LOG(INFO) << "Application haven't installed yet: " << app_id;
-    return false;
-  }
-
-  if (old_application->Version()->CompareTo(
-          *(new_application->Version())) >= 0) {
-    LOG(INFO) << "The version number of new XPK/WGT package "
-                 "should be higher than "
-              << old_application->VersionString();
-    return false;
-  }
-
-  const base::FilePath& app_dir = old_application->Path();
-  const base::FilePath tmp_dir(app_dir.value()
-                               + FILE_PATH_LITERAL(".tmp"));
-
-  if (Application* app = GetApplicationByID(app_id)) {
-    LOG(INFO) << "Try to terminate the running application before update.";
-    app->Terminate(Application::Immediate);
-  }
-
-  if (!base::Move(app_dir, tmp_dir) ||
-      !base::Move(unpacked_dir, app_dir))
-    return false;
-
-  new_application = LoadApplication(app_dir,
-                                    app_id,
-                                    Manifest::COMMAND_LINE,
-                                    &error);
-  if (!new_application) {
-    LOG(ERROR) << "Error during loading new package: " << error;
-    base::DeleteFile(app_dir, true);
-    base::Move(tmp_dir, app_dir);
-    return false;
-  }
-
-#if defined(OS_TIZEN)
-  if (!UninstallPackageOnTizen(old_application,
-                               runtime_context_->GetPath())) {
-    base::DeleteFile(app_dir, true);
-    base::Move(tmp_dir, app_dir);
-    return false;
-  }
-#endif
-
-  if (!application_storage_->UpdateApplication(new_application)) {
-    LOG(ERROR) << "An Error occurred when updating the application.";
-    base::DeleteFile(app_dir, true);
-    base::Move(tmp_dir, app_dir);
-#if defined(OS_TIZEN)
-    InstallPackageOnTizen(old_application,
-                          runtime_context_->GetPath());
-#endif
-    return false;
-  }
-#if defined(OS_TIZEN)
-  if (!InstallPackageOnTizen(new_application,
-                             runtime_context_->GetPath()))
-    return false;
-#endif
-  base::DeleteFile(tmp_dir, true);
-
-  SaveSystemEventsInfo(new_application, this, event_manager_);
-
-  FOR_EACH_OBSERVER(Observer, observers_,
-                    OnApplicationUpdated(app_id));
-
-  return true;
-}
-
-bool ApplicationService::Uninstall(const std::string& id) {
-  bool result = true;
-
-  scoped_refptr<ApplicationData> application =
-      application_storage_->GetApplicationData(id);
-  if (!application) {
-    LOG(ERROR) << "Cannot uninstall application with id " << id
-               << "; invalid application id";
-    return false;
-  }
-
-  if (Application* app = GetApplicationByID(id)) {
-    LOG(INFO) << "Try to terminate the running application before uninstall.";
-    app->Terminate(Application::Immediate);
-  }
-
-#if defined(OS_TIZEN)
-  if (!UninstallPackageOnTizen(application,
-                               runtime_context_->GetPath()))
-    result = false;
-#endif
-
-  if (!application_storage_->RemoveApplication(id)) {
-    LOG(ERROR) << "Cannot uninstall application with id " << id
-               << "; application is not installed.";
-    result = false;
-  }
-
-  const base::FilePath resources =
-      runtime_context_->GetPath().Append(kApplicationsDir).AppendASCII(id);
-  if (base::DirectoryExists(resources) &&
-      !base::DeleteFile(resources, true)) {
-    LOG(ERROR) << "Error occurred while trying to remove application with id "
-               << id << "; Cannot remove all resources.";
-    result = false;
-  }
-
-  content::StoragePartition* partition =
-      content::BrowserContext::GetStoragePartitionForSite(
-          runtime_context_, application->GetBaseURLFromApplicationId(id));
-  partition->ClearDataForOrigin(
-      content::StoragePartition::REMOVE_DATA_MASK_ALL,
-      content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
-      application->URL(),
-      partition->GetURLRequestContext());
-
-  base::FilePath path;
-  PathService::Get(xwalk::DIR_WGT_STORAGE_PATH, &path);
-  RemoveWidgetStorageFiles(path, id);
-
-  FOR_EACH_OBSERVER(Observer, observers_, OnApplicationUninstalled(id));
-
-  return result;
-}
-
-void ApplicationService::ChangeLocale(const std::string& locale) {
-  const ApplicationData::ApplicationDataMap& apps =
-      application_storage_->GetInstalledApplications();
-  ApplicationData::ApplicationDataMap::const_iterator it;
-  for (it = apps.begin(); it != apps.end(); ++it) {
-    base::string16 error;
-    std::string old_name = it->second->Name();
-    if (!it->second->SetApplicationLocale(locale, &error)) {
-      LOG(ERROR) << "Error when set locale " << locale
-                 << " to application " << it->second->ID()
-                 << "error : " << error;
-    }
-    if (old_name != it->second->Name()) {
-      // After we has changed the application locale, we might get a new name in
-      // the new locale, so call all observer for this event.
-      FOR_EACH_OBSERVER(
-          Observer, observers_,
-          OnApplicationNameChanged(it->second->ID(), it->second->Name()));
-    }
-  }
-}
-
 Application* ApplicationService::Launch(
     scoped_refptr<ApplicationData> application_data,
     const Application::LaunchParams& launch_params) {
@@ -526,8 +91,6 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
-  event_manager_->AddEventRouterForApp(application_data);
-
 #if defined(OS_TIZEN)
   Application* application(new ApplicationTizen(application_data,
     runtime_context_, this));
@@ -540,7 +103,6 @@ Application* ApplicationService::Launch(
       applications_.insert(applications_.end(), application);
 
   if (!application->Launch(launch_params)) {
-    event_manager_->RemoveEventRouterForApp(application_data);
     applications_.erase(app_iter);
     return NULL;
   }
@@ -553,7 +115,6 @@ Application* ApplicationService::Launch(
 
 Application* ApplicationService::Launch(
     const std::string& id, const Application::LaunchParams& params) {
-  Application* application = NULL;
   scoped_refptr<ApplicationData> application_data =
     application_storage_->GetApplicationData(id);
   if (!application_data) {
@@ -561,17 +122,11 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
-  if ((application = Launch(application_data, params))) {
-    scoped_refptr<Event> event = Event::CreateEvent(
-        kOnLaunched, scoped_ptr<base::ListValue>(new base::ListValue));
-    event_manager_->SendEvent(application->id(), event);
-  }
-  return application;
+  return Launch(application_data, params);
 }
 
 Application* ApplicationService::Launch(
     const base::FilePath& path, const Application::LaunchParams& params) {
-  Application* application = NULL;
   if (!base::DirectoryExists(path))
     return NULL;
 
@@ -585,12 +140,7 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
-  if ((application = Launch(application_data, params))) {
-    scoped_refptr<Event> event = Event::CreateEvent(
-        kOnLaunched, scoped_ptr<base::ListValue>(new base::ListValue));
-    event_manager_->SendEvent(application->id(), event);
-  }
-  return application;
+  return Launch(application_data, params);
 }
 
 namespace {
@@ -649,11 +199,12 @@ void ApplicationService::OnApplicationTerminated(
   FOR_EACH_OBSERVER(Observer, observers_,
                     WillDestroyApplication(application));
   applications_.erase(found);
-  if (!XWalkRunner::GetInstance()->is_running_as_service() &&
-      applications_.empty()) {
+#if !defined(SHARED_PROCESS_MODE)
+  if (applications_.empty()) {
     base::MessageLoop::current()->PostTask(
             FROM_HERE, base::MessageLoop::QuitClosure());
   }
+#endif
 }
 
 void ApplicationService::CheckAPIAccessControl(const std::string& app_id,