Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / file_manager / private_api_file_system.cc
index 5c30cbc..aa25486 100644 (file)
@@ -5,10 +5,7 @@
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h"
 
 #include <sys/statvfs.h>
-#include <sys/types.h>
-#include <utime.h>
 
-#include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h"
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
+#include "chrome/browser/chromeos/file_manager/volume_manager.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/extensions/api/file_browser_private.h"
+#include "chrome/common/extensions/api/file_browser_private_internal.h"
 #include "chromeos/disks/disk_mount_manager.h"
-#include "content/public/browser/browser_context.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_file_util.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
 #include "webkit/common/fileapi/file_system_util.h"
 
 using chromeos::disks::DiskMountManager;
-using content::BrowserContext;
 using content::BrowserThread;
 using content::ChildProcessSecurityPolicy;
-using content::WebContents;
+using file_manager::util::EntryDefinition;
+using file_manager::util::FileDefinition;
 using fileapi::FileSystemURL;
 
 namespace extensions {
 namespace {
 
-// Error messages.
-const char kFileError[] = "File error %d";
-
-const DiskMountManager::Disk* GetVolumeAsDisk(const std::string& mount_path) {
-  DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
-
-  DiskMountManager::MountPointMap::const_iterator mount_point_it =
-      disk_mount_manager->mount_points().find(mount_path);
-  if (mount_point_it == disk_mount_manager->mount_points().end())
-    return NULL;
-
-  const DiskMountManager::Disk* disk = disk_mount_manager->FindDiskBySourcePath(
-      mount_point_it->second.source_path);
-
-  return (disk && disk->is_hidden()) ? NULL : disk;
-}
-
-base::DictionaryValue* CreateValueFromDisk(
-    Profile* profile,
-    const std::string& extension_id,
-    const DiskMountManager::Disk* volume) {
-  base::DictionaryValue* volume_info = new base::DictionaryValue();
-
-  std::string mount_path;
-  if (!volume->mount_path().empty()) {
-    base::FilePath relative_mount_path;
-    file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
-        profile, extension_id, base::FilePath(volume->mount_path()),
-        &relative_mount_path);
-    mount_path = relative_mount_path.value();
-  }
-
-  volume_info->SetString("devicePath", volume->device_path());
-  volume_info->SetString("mountPath", mount_path);
-  volume_info->SetString("systemPath", volume->system_path());
-  volume_info->SetString("filePath", volume->file_path());
-  volume_info->SetString("deviceLabel", volume->device_label());
-  volume_info->SetString("driveLabel", volume->drive_label());
-  volume_info->SetString(
-      "deviceType",
-      DiskMountManager::DeviceTypeToString(volume->device_type()));
-  volume_info->SetDouble("totalSize",
-                         static_cast<double>(volume->total_size_in_bytes()));
-  volume_info->SetBoolean("isParent", volume->is_parent());
-  volume_info->SetBoolean("isReadOnly", volume->is_read_only());
-  volume_info->SetBoolean("hasMedia", volume->has_media());
-  volume_info->SetBoolean("isOnBootDevice", volume->on_boot_device());
-
-  return volume_info;
-}
-
-base::DictionaryValue* CreateDownloadsVolumeMetadata() {
-  base::DictionaryValue* volume_info = new base::DictionaryValue;
-  volume_info->SetString("mountPath", "Downloads");
-  volume_info->SetBoolean("isReadOnly", false);
-  return volume_info;
-}
-
-// Sets permissions for the Drive mount point so Files.app can access files
-// in the mount point directory. It's safe to call this function even if
-// Drive is disabled by the setting (i.e. prefs::kDisableDrive is true).
-void SetDriveMountPointPermissions(
-    Profile* profile,
-    const std::string& extension_id,
-    content::RenderViewHost* render_view_host) {
-  if (!render_view_host ||
-      !render_view_host->GetSiteInstance() || !render_view_host->GetProcess()) {
-    return;
-  }
-
-  fileapi::ExternalFileSystemBackend* backend =
-      file_manager::util::GetFileSystemContextForRenderViewHost(
-          profile, render_view_host)->external_backend();
-  if (!backend)
-    return;
-
-  const base::FilePath mount_point = drive::util::GetDriveMountPointPath();
-  // Grant R/W permissions to drive 'folder'. File API layer still
-  // expects this to be satisfied.
-  ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile(
-      render_view_host->GetProcess()->GetID(), mount_point);
-
-  base::FilePath mount_point_virtual;
-  if (backend->GetVirtualPath(mount_point, &mount_point_virtual))
-    backend->GrantFileAccessToExtension(extension_id, mount_point_virtual);
-}
-
 // Retrieves total and remaining available size on |mount_path|.
 void GetSizeStatsOnBlockingPool(const std::string& mount_path,
                                 uint64* total_size,
                                 uint64* remaining_size) {
   struct statvfs stat = {};  // Zero-clear
   if (HANDLE_EINTR(statvfs(mount_path.c_str(), &stat)) == 0) {
-    *total_size =
-        static_cast<uint64>(stat.f_blocks) * stat.f_frsize;
-    *remaining_size =
-        static_cast<uint64>(stat.f_bavail) * stat.f_frsize;
+    *total_size = static_cast<uint64>(stat.f_blocks) * stat.f_frsize;
+    *remaining_size = static_cast<uint64>(stat.f_bavail) * stat.f_frsize;
   }
 }
 
@@ -219,7 +127,7 @@ void NotifyCopyCompletion(
     fileapi::FileSystemOperationRunner::OperationID operation_id,
     const FileSystemURL& source_url,
     const FileSystemURL& destination_url,
-    base::PlatformFileError error) {
+    base::File::Error error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   file_manager::EventRouter* event_router =
@@ -237,7 +145,7 @@ void OnCopyCompleted(
     fileapi::FileSystemOperationRunner::OperationID* operation_id,
     const FileSystemURL& source_url,
     const FileSystemURL& destination_url,
-    base::PlatformFileError error) {
+    base::File::Error error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   BrowserThread::PostTask(
@@ -271,12 +179,12 @@ fileapi::FileSystemOperationRunner::OperationID StartCopyOnIOThread(
   return *operation_id;
 }
 
-void OnCopyCancelled(base::PlatformFileError error) {
+void OnCopyCancelled(base::File::Error error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // We just ignore the status if the copy is actually cancelled or not,
   // because failing cancellation means the operation is not running now.
-  DLOG_IF(WARNING, error != base::PLATFORM_FILE_OK)
+  DLOG_IF(WARNING, error != base::File::FILE_OK)
       << "Failed to cancel copy: " << error;
 }
 
@@ -293,10 +201,10 @@ void CancelCopyOnIOThread(
 }  // namespace
 
 void FileBrowserPrivateRequestFileSystemFunction::DidFail(
-    base::PlatformFileError error_code) {
+    base::File::Error error_code) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  error_ = base::StringPrintf(kFileError, static_cast<int>(error_code));
+  SetError(base::StringPrintf("File error %d", static_cast<int>(error_code)));
   SendResponse(false);
 }
 
@@ -304,6 +212,7 @@ bool FileBrowserPrivateRequestFileSystemFunction::
     SetupFileSystemAccessPermissions(
         scoped_refptr<fileapi::FileSystemContext> file_system_context,
         int child_id,
+        Profile* profile,
         scoped_refptr<const extensions::Extension> extension) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -333,66 +242,109 @@ bool FileBrowserPrivateRequestFileSystemFunction::
     ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile(
         child_id, root_dirs[i]);
   }
+
+  // Grant R/W permissions to profile-specific directories (Drive, Downloads)
+  // from other profiles. Those directories may not be mounted at this moment
+  // yet, so we need to do this separately from the above loop over
+  // GetRootDirectories().
+  const std::vector<Profile*>& profiles =
+      g_browser_process->profile_manager()->GetLoadedProfiles();
+  for (size_t i = 0; i < profiles.size(); ++i) {
+    if (!profiles[i]->IsOffTheRecord()) {
+      file_manager::util::SetupProfileFileAccessPermissions(child_id,
+                                                            profiles[i]);
+    }
+  }
+
   return true;
 }
 
-bool FileBrowserPrivateRequestFileSystemFunction::RunImpl() {
+bool FileBrowserPrivateRequestFileSystemFunction::RunAsync() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   using extensions::api::file_browser_private::RequestFileSystem::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  // TODO(satorux): Handle the file system ID. crbug.com/284963.
-  DCHECK_EQ("compatible", params->file_system_id);
-
   if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess())
     return false;
 
   set_log_on_completion(true);
 
+  using file_manager::VolumeManager;
+  using file_manager::VolumeInfo;
+  VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
+  if (!volume_manager)
+    return false;
+
+  VolumeInfo volume_info;
+  if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info)) {
+    DidFail(base::File::FILE_ERROR_NOT_FOUND);
+    return false;
+  }
+
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderViewHost(
           GetProfile(), render_view_host());
 
   // Set up file permission access.
   const int child_id = render_view_host()->GetProcess()->GetID();
-  if (!SetupFileSystemAccessPermissions(file_system_context,
-                                        child_id,
-                                        GetExtension())) {
-    DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
+  if (!SetupFileSystemAccessPermissions(
+          file_system_context, child_id, GetProfile(), extension())) {
+    DidFail(base::File::FILE_ERROR_SECURITY);
     return false;
   }
 
-  // Set permissions for the Drive mount point immediately when we kick of
-  // first instance of file manager. The actual mount event will be sent to
-  // UI only when we perform proper authentication.
-  //
-  // Note that we call this function even when Drive is disabled by the
-  // setting. Otherwise, we need to call this when the setting is changed at
-  // a later time, which complicates the code.
-  SetDriveMountPointPermissions(
-      GetProfile(), extension_id(), render_view_host());
+  FileDefinition file_definition;
+  if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+           GetProfile(),
+           extension_id(),
+           volume_info.mount_path,
+           &file_definition.virtual_path)) {
+    DidFail(base::File::FILE_ERROR_INVALID_OPERATION);
+    return false;
+  }
+  file_definition.is_directory = true;
+
+  file_manager::util::ConvertFileDefinitionToEntryDefinition(
+      GetProfile(),
+      extension_id(),
+      file_definition,
+      base::Bind(
+          &FileBrowserPrivateRequestFileSystemFunction::OnEntryDefinition,
+          this));
+  return true;
+}
 
-  fileapi::FileSystemInfo info =
-      fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin());
+void FileBrowserPrivateRequestFileSystemFunction::OnEntryDefinition(
+    const EntryDefinition& entry_definition) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  DictionaryValue* dict = new DictionaryValue();
+  if (entry_definition.error != base::File::FILE_OK) {
+    DidFail(entry_definition.error);
+    return;
+  }
+
+  if (!entry_definition.is_directory) {
+    DidFail(base::File::FILE_ERROR_NOT_A_DIRECTORY);
+    return;
+  }
+
+  base::DictionaryValue* dict = new base::DictionaryValue();
   SetResult(dict);
-  dict->SetString("name", info.name);
-  dict->SetString("root_url", info.root_url.spec());
+  dict->SetString("name", entry_definition.file_system_name);
+  dict->SetString("root_url", entry_definition.file_system_root_url);
   dict->SetInteger("error", drive::FILE_ERROR_OK);
   SendResponse(true);
-  return true;
 }
 
 void FileWatchFunctionBase::Respond(bool success) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  SetResult(Value::CreateBooleanValue(success));
+  SetResult(new base::FundamentalValue(success));
   SendResponse(success);
 }
 
-bool FileWatchFunctionBase::RunImpl() {
+bool FileWatchFunctionBase::RunAsync() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   if (!render_view_host() || !render_view_host()->GetProcess())
@@ -446,17 +398,22 @@ void FileBrowserPrivateRemoveFileWatchFunction::PerformFileWatchOperation(
   Respond(true);
 }
 
-bool FileBrowserPrivateGetSizeStatsFunction::RunImpl() {
+bool FileBrowserPrivateGetSizeStatsFunction::RunAsync() {
   using extensions::api::file_browser_private::GetSizeStats::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
-      render_view_host(), GetProfile(), GURL(params->mount_path));
-  if (file_path.empty())
+  using file_manager::VolumeManager;
+  using file_manager::VolumeInfo;
+  VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
+  if (!volume_manager)
+    return false;
+
+  VolumeInfo volume_info;
+  if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info))
     return false;
 
-  if (file_path == drive::util::GetDriveMountPointPath()) {
+  if (volume_info.type == file_manager::VOLUME_TYPE_GOOGLE_DRIVE) {
     drive::FileSystemInterface* file_system =
         drive::util::GetFileSystemByProfile(GetProfile());
     if (!file_system) {
@@ -477,7 +434,7 @@ bool FileBrowserPrivateGetSizeStatsFunction::RunImpl() {
     BrowserThread::PostBlockingPoolTaskAndReply(
         FROM_HERE,
         base::Bind(&GetSizeStatsOnBlockingPool,
-                   file_path.value(),
+                   volume_info.mount_path.value(),
                    total_size,
                    remaining_size),
         base::Bind(&FileBrowserPrivateGetSizeStatsFunction::
@@ -516,7 +473,7 @@ void FileBrowserPrivateGetSizeStatsFunction::GetSizeStatsCallback(
   SendResponse(true);
 }
 
-bool FileBrowserPrivateValidatePathNameLengthFunction::RunImpl() {
+bool FileBrowserPrivateValidatePathNameLengthFunction::RunAsync() {
   using extensions::api::file_browser_private::ValidatePathNameLength::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
@@ -555,22 +512,28 @@ void FileBrowserPrivateValidatePathNameLengthFunction::OnFilePathLimitRetrieved(
   SendResponse(true);
 }
 
-bool FileBrowserPrivateFormatDeviceFunction::RunImpl() {
-  using extensions::api::file_browser_private::FormatDevice::Params;
+bool FileBrowserPrivateFormatVolumeFunction::RunAsync() {
+  using extensions::api::file_browser_private::FormatVolume::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
-      render_view_host(), GetProfile(), GURL(params->mount_path));
-  if (file_path.empty())
+  using file_manager::VolumeManager;
+  using file_manager::VolumeInfo;
+  VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
+  if (!volume_manager)
+    return false;
+
+  VolumeInfo volume_info;
+  if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info))
     return false;
 
-  DiskMountManager::GetInstance()->FormatMountedDevice(file_path.value());
+  DiskMountManager::GetInstance()->FormatMountedDevice(
+      volume_info.mount_path.AsUTF8Unsafe());
   SendResponse(true);
   return true;
 }
 
-bool FileBrowserPrivateStartCopyFunction::RunImpl() {
+bool FileBrowserPrivateStartCopyFunction::RunAsync() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   using  extensions::api::file_browser_private::StartCopy::Params;
@@ -579,8 +542,8 @@ bool FileBrowserPrivateStartCopyFunction::RunImpl() {
 
   if (params->source_url.empty() || params->parent.empty() ||
       params->new_name.empty()) {
-    error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
-        base::PLATFORM_FILE_ERROR_INVALID_URL));
+    // Error code in format of DOMError.name.
+    SetError("EncodingError");
     return false;
   }
 
@@ -588,14 +551,20 @@ bool FileBrowserPrivateStartCopyFunction::RunImpl() {
       file_manager::util::GetFileSystemContextForRenderViewHost(
           GetProfile(), render_view_host());
 
+  // |parent| may have a trailing slash if it is a root directory.
+  std::string destination_url_string = params->parent;
+  if (destination_url_string[destination_url_string.size() - 1] != '/')
+    destination_url_string += '/';
+  destination_url_string += net::EscapePath(params->new_name);
+
   fileapi::FileSystemURL source_url(
       file_system_context->CrackURL(GURL(params->source_url)));
-  fileapi::FileSystemURL destination_url(file_system_context->CrackURL(
-      GURL(params->parent + "/" + params->new_name)));
+  fileapi::FileSystemURL destination_url(
+      file_system_context->CrackURL(GURL(destination_url_string)));
 
   if (!source_url.is_valid() || !destination_url.is_valid()) {
-    error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
-        base::PLATFORM_FILE_ERROR_INVALID_URL));
+    // Error code in format of DOMError.name.
+    SetError("EncodingError");
     return false;
   }
 
@@ -615,14 +584,14 @@ void FileBrowserPrivateStartCopyFunction::RunAfterStartCopy(
     int operation_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  SetResult(Value::CreateIntegerValue(operation_id));
+  SetResult(new base::FundamentalValue(operation_id));
   SendResponse(true);
 }
 
-bool FileBrowserPrivateCancelCopyFunction::RunImpl() {
+bool FileBrowserPrivateCancelCopyFunction::RunAsync() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  using  extensions::api::file_browser_private::CancelCopy::Params;
+  using extensions::api::file_browser_private::CancelCopy::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
@@ -639,4 +608,72 @@ bool FileBrowserPrivateCancelCopyFunction::RunImpl() {
   return true;
 }
 
+bool FileBrowserPrivateInternalResolveIsolatedEntriesFunction::RunAsync() {
+  using extensions::api::file_browser_private_internal::ResolveIsolatedEntries::
+      Params;
+  const scoped_ptr<Params> params(Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  scoped_refptr<fileapi::FileSystemContext> file_system_context =
+      file_manager::util::GetFileSystemContextForRenderViewHost(
+          GetProfile(), render_view_host());
+  DCHECK(file_system_context);
+
+  const fileapi::ExternalFileSystemBackend* external_backend =
+      file_system_context->external_backend();
+  DCHECK(external_backend);
+
+  file_manager::util::FileDefinitionList file_definition_list;
+  for (size_t i = 0; i < params->urls.size(); ++i) {
+    FileSystemURL fileSystemUrl =
+        file_system_context->CrackURL(GURL(params->urls[i]));
+    DCHECK(external_backend->CanHandleType(fileSystemUrl.type()));
+
+    FileDefinition file_definition;
+    const bool result =
+        file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+            GetProfile(),
+            extension_->id(),
+            fileSystemUrl.path(),
+            &file_definition.virtual_path);
+    if (!result)
+      continue;
+    // The API only supports isolated files.
+    file_definition.is_directory = false;
+    file_definition_list.push_back(file_definition);
+  }
+
+  file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
+      GetProfile(),
+      extension_->id(),
+      file_definition_list,  // Safe, since copied internally.
+      base::Bind(
+          &FileBrowserPrivateInternalResolveIsolatedEntriesFunction::
+              RunAsyncAfterConvertFileDefinitionListToEntryDefinitionList,
+          this));
+  return true;
+}
+
+void FileBrowserPrivateInternalResolveIsolatedEntriesFunction::
+    RunAsyncAfterConvertFileDefinitionListToEntryDefinitionList(scoped_ptr<
+        file_manager::util::EntryDefinitionList> entry_definition_list) {
+  using extensions::api::file_browser_private_internal::EntryDescription;
+  std::vector<linked_ptr<EntryDescription> > entries;
+
+  for (size_t i = 0; i < entry_definition_list->size(); ++i) {
+    if (entry_definition_list->at(i).error != base::File::FILE_OK)
+      continue;
+    linked_ptr<EntryDescription> entry(new EntryDescription);
+    entry->file_system_name = entry_definition_list->at(i).file_system_name;
+    entry->file_system_root = entry_definition_list->at(i).file_system_root_url;
+    entry->file_full_path =
+        "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe();
+    entry->file_is_directory = entry_definition_list->at(i).is_directory;
+    entries.push_back(entry);
+  }
+
+  results_ = extensions::api::file_browser_private_internal::
+      ResolveIsolatedEntries::Results::Create(entries);
+  SendResponse(true);
+}
 }  // namespace extensions