// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/fileapi/file_system_backend.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/fileapi/file_access_permissions.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h"
#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
#include "chromeos/dbus/cros_disks_client.h"
#include "webkit/browser/blob/file_stream_reader.h"
#include "webkit/browser/fileapi/async_file_util.h"
#include "webkit/browser/fileapi/external_mount_points.h"
#include "webkit/browser/fileapi/file_stream_writer.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation.h"
#include "webkit/browser/fileapi/file_system_operation_context.h"
#include "webkit/browser/fileapi/file_system_url.h"

namespace chromeos {

// static
bool FileSystemBackend::CanHandleURL(const fileapi::FileSystemURL& url) {
  if (!url.is_valid())
    return false;
  return url.type() == fileapi::kFileSystemTypeNativeLocal ||
         url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
         url.type() == fileapi::kFileSystemTypeDrive ||
         url.type() == fileapi::kFileSystemTypeProvided ||
         url.type() == fileapi::kFileSystemTypeDeviceMediaAsFileStorage;
}

FileSystemBackend::FileSystemBackend(
    FileSystemBackendDelegate* drive_delegate,
    FileSystemBackendDelegate* file_system_provider_delegate,
    FileSystemBackendDelegate* mtp_delegate,
    scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
    scoped_refptr<fileapi::ExternalMountPoints> mount_points,
    fileapi::ExternalMountPoints* system_mount_points)
    : special_storage_policy_(special_storage_policy),
      file_access_permissions_(new FileAccessPermissions()),
      local_file_util_(fileapi::AsyncFileUtil::CreateForLocalFileSystem()),
      drive_delegate_(drive_delegate),
      file_system_provider_delegate_(file_system_provider_delegate),
      mtp_delegate_(mtp_delegate),
      mount_points_(mount_points),
      system_mount_points_(system_mount_points) {}

FileSystemBackend::~FileSystemBackend() {
}

void FileSystemBackend::AddSystemMountPoints() {
  // RegisterFileSystem() is no-op if the mount point with the same name
  // already exists, hence it's safe to call without checking if a mount
  // point already exists or not.
  system_mount_points_->RegisterFileSystem(
      "archive",
      fileapi::kFileSystemTypeNativeLocal,
      fileapi::FileSystemMountOption(),
      chromeos::CrosDisksClient::GetArchiveMountPoint());
  system_mount_points_->RegisterFileSystem(
      "removable",
      fileapi::kFileSystemTypeNativeLocal,
      fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_SYNC),
      chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
  system_mount_points_->RegisterFileSystem(
      "oem",
      fileapi::kFileSystemTypeRestrictedNativeLocal,
      fileapi::FileSystemMountOption(),
      base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
}

bool FileSystemBackend::CanHandleType(fileapi::FileSystemType type) const {
  switch (type) {
    case fileapi::kFileSystemTypeExternal:
    case fileapi::kFileSystemTypeDrive:
    case fileapi::kFileSystemTypeRestrictedNativeLocal:
    case fileapi::kFileSystemTypeNativeLocal:
    case fileapi::kFileSystemTypeNativeForPlatformApp:
    case fileapi::kFileSystemTypeDeviceMediaAsFileStorage:
    case fileapi::kFileSystemTypeProvided:
      return true;
    default:
      return false;
  }
}

void FileSystemBackend::Initialize(fileapi::FileSystemContext* context) {
}

void FileSystemBackend::ResolveURL(const fileapi::FileSystemURL& url,
                                   fileapi::OpenFileSystemMode mode,
                                   const OpenFileSystemCallback& callback) {
  std::string id;
  fileapi::FileSystemType type;
  std::string cracked_id;
  base::FilePath path;
  fileapi::FileSystemMountOption option;
  if (!mount_points_->CrackVirtualPath(
           url.virtual_path(), &id, &type, &cracked_id, &path, &option) &&
      !system_mount_points_->CrackVirtualPath(
           url.virtual_path(), &id, &type, &cracked_id, &path, &option)) {
    // Not under a mount point, so return an error, since the root is not
    // accessible.
    GURL root_url = GURL(fileapi::GetExternalFileSystemRootURIString(
        url.origin(), std::string()));
    callback.Run(root_url, std::string(), base::File::FILE_ERROR_SECURITY);
    return;
  }

  std::string name;
  // Construct a URL restricted to the found mount point.
  std::string root_url =
      fileapi::GetExternalFileSystemRootURIString(url.origin(), id);

  // For removable and archives, the file system root is the external mount
  // point plus the inner mount point.
  if (id == "archive" || id == "removable") {
    std::vector<std::string> components;
    url.virtual_path().GetComponents(&components);
    DCHECK_EQ(id, components.at(0));
    if (components.size() < 2) {
      // Unable to access /archive and /removable directories directly. The
      // inner mount name must be specified.
      callback.Run(
          GURL(root_url), std::string(), base::File::FILE_ERROR_SECURITY);
      return;
    }
    std::string inner_mount_name = components[1];
    root_url += inner_mount_name + "/";
    name = inner_mount_name;
  } else {
    name = id;
  }

  callback.Run(GURL(root_url), name, base::File::FILE_OK);
}

fileapi::FileSystemQuotaUtil* FileSystemBackend::GetQuotaUtil() {
  // No quota support.
  return NULL;
}

bool FileSystemBackend::IsAccessAllowed(
    const fileapi::FileSystemURL& url) const {
  if (!url.is_valid())
    return false;

  // No extra check is needed for isolated file systems.
  if (url.mount_type() == fileapi::kFileSystemTypeIsolated)
    return true;

  if (!CanHandleURL(url))
    return false;

  std::string extension_id = url.origin().host();
  // TODO(mtomasz): Temporarily whitelist TimeScapes. Remove this in M-31.
  // See: crbug.com/271946
  if (extension_id == "mlbmkoenclnokonejhlfakkeabdlmpek" &&
      url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal) {
    return true;
  }

  // Check first to make sure this extension has fileBrowserHander permissions.
  if (!special_storage_policy_ ||
      !special_storage_policy_->IsFileHandler(extension_id))
    return false;

  return file_access_permissions_->HasAccessPermission(extension_id,
                                                       url.virtual_path());
}

void FileSystemBackend::GrantFullAccessToExtension(
    const std::string& extension_id) {
  if (!special_storage_policy_)
    return;
  if (!special_storage_policy_->IsFileHandler(extension_id)) {
    NOTREACHED();
    return;
  }
  file_access_permissions_->GrantFullAccessPermission(extension_id);
}

void FileSystemBackend::GrantFileAccessToExtension(
    const std::string& extension_id, const base::FilePath& virtual_path) {
  if (!special_storage_policy_)
    return;
  // All we care about here is access from extensions for now.
  if (!special_storage_policy_->IsFileHandler(extension_id)) {
    NOTREACHED();
    return;
  }

  std::string id;
  fileapi::FileSystemType type;
  std::string cracked_id;
  base::FilePath path;
  fileapi::FileSystemMountOption option;
  if (!mount_points_->CrackVirtualPath(virtual_path, &id, &type, &cracked_id,
                                       &path, &option) &&
      !system_mount_points_->CrackVirtualPath(virtual_path, &id, &type,
                                              &cracked_id, &path, &option)) {
    return;
  }

  if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) {
    LOG(ERROR) << "Can't grant access for restricted mount point";
    return;
  }

  file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
}

void FileSystemBackend::RevokeAccessForExtension(
      const std::string& extension_id) {
  file_access_permissions_->RevokePermissions(extension_id);
}

std::vector<base::FilePath> FileSystemBackend::GetRootDirectories() const {
  std::vector<fileapi::MountPoints::MountPointInfo> mount_points;
  mount_points_->AddMountPointInfosTo(&mount_points);
  system_mount_points_->AddMountPointInfosTo(&mount_points);

  std::vector<base::FilePath> root_dirs;
  for (size_t i = 0; i < mount_points.size(); ++i)
    root_dirs.push_back(mount_points[i].path);
  return root_dirs;
}

fileapi::AsyncFileUtil* FileSystemBackend::GetAsyncFileUtil(
    fileapi::FileSystemType type) {
  switch (type) {
    case fileapi::kFileSystemTypeDrive:
      return drive_delegate_->GetAsyncFileUtil(type);
    case fileapi::kFileSystemTypeProvided:
      return file_system_provider_delegate_->GetAsyncFileUtil(type);
    case fileapi::kFileSystemTypeNativeLocal:
    case fileapi::kFileSystemTypeRestrictedNativeLocal:
      return local_file_util_.get();
    case fileapi::kFileSystemTypeDeviceMediaAsFileStorage:
      return mtp_delegate_->GetAsyncFileUtil(type);
    default:
      NOTREACHED();
  }
  return NULL;
}

fileapi::CopyOrMoveFileValidatorFactory*
FileSystemBackend::GetCopyOrMoveFileValidatorFactory(
    fileapi::FileSystemType type, base::File::Error* error_code) {
  DCHECK(error_code);
  *error_code = base::File::FILE_OK;
  return NULL;
}

fileapi::FileSystemOperation* FileSystemBackend::CreateFileSystemOperation(
    const fileapi::FileSystemURL& url,
    fileapi::FileSystemContext* context,
    base::File::Error* error_code) const {
  DCHECK(url.is_valid());

  if (!IsAccessAllowed(url)) {
    *error_code = base::File::FILE_ERROR_SECURITY;
    return NULL;
  }

  if (url.type() == fileapi::kFileSystemTypeDeviceMediaAsFileStorage) {
    // MTP file operations run on MediaTaskRunner.
    return fileapi::FileSystemOperation::Create(
        url, context,
        make_scoped_ptr(new fileapi::FileSystemOperationContext(
            context, MediaFileSystemBackend::MediaTaskRunner())));
  }

  DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal ||
         url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
         url.type() == fileapi::kFileSystemTypeDrive ||
         url.type() == fileapi::kFileSystemTypeProvided);
  return fileapi::FileSystemOperation::Create(
      url, context,
      make_scoped_ptr(new fileapi::FileSystemOperationContext(context)));
}

bool FileSystemBackend::SupportsStreaming(
    const fileapi::FileSystemURL& url) const {
  return url.type() == fileapi::kFileSystemTypeDrive ||
         url.type() == fileapi::kFileSystemTypeProvided ||
         url.type() == fileapi::kFileSystemTypeDeviceMediaAsFileStorage;
}

scoped_ptr<webkit_blob::FileStreamReader>
FileSystemBackend::CreateFileStreamReader(
    const fileapi::FileSystemURL& url,
    int64 offset,
    const base::Time& expected_modification_time,
    fileapi::FileSystemContext* context) const {
  DCHECK(url.is_valid());

  if (!IsAccessAllowed(url))
    return scoped_ptr<webkit_blob::FileStreamReader>();

  switch (url.type()) {
    case fileapi::kFileSystemTypeDrive:
      return drive_delegate_->CreateFileStreamReader(
          url, offset, expected_modification_time, context);
    case fileapi::kFileSystemTypeProvided:
      return file_system_provider_delegate_->CreateFileStreamReader(
          url, offset, expected_modification_time, context);
    case fileapi::kFileSystemTypeNativeLocal:
    case fileapi::kFileSystemTypeRestrictedNativeLocal:
      return scoped_ptr<webkit_blob::FileStreamReader>(
          webkit_blob::FileStreamReader::CreateForFileSystemFile(
              context, url, offset, expected_modification_time));
    case fileapi::kFileSystemTypeDeviceMediaAsFileStorage:
      return mtp_delegate_->CreateFileStreamReader(
          url, offset, expected_modification_time, context);
    default:
      NOTREACHED();
  }
  return scoped_ptr<webkit_blob::FileStreamReader>();
}

scoped_ptr<fileapi::FileStreamWriter>
FileSystemBackend::CreateFileStreamWriter(
    const fileapi::FileSystemURL& url,
    int64 offset,
    fileapi::FileSystemContext* context) const {
  DCHECK(url.is_valid());

  if (!IsAccessAllowed(url))
    return scoped_ptr<fileapi::FileStreamWriter>();

  switch (url.type()) {
    case fileapi::kFileSystemTypeDrive:
      return drive_delegate_->CreateFileStreamWriter(url, offset, context);
    case fileapi::kFileSystemTypeProvided:
      return file_system_provider_delegate_->CreateFileStreamWriter(
          url, offset, context);
    case fileapi::kFileSystemTypeNativeLocal:
      return scoped_ptr<fileapi::FileStreamWriter>(
          fileapi::FileStreamWriter::CreateForLocalFile(
              context->default_file_task_runner(), url.path(), offset,
              fileapi::FileStreamWriter::OPEN_EXISTING_FILE));
    case fileapi::kFileSystemTypeRestrictedNativeLocal:
      // Restricted native local file system is read only.
      return scoped_ptr<fileapi::FileStreamWriter>();
    case fileapi::kFileSystemTypeDeviceMediaAsFileStorage:
      return mtp_delegate_->CreateFileStreamWriter(url, offset, context);
    default:
      NOTREACHED();
  }
  return scoped_ptr<fileapi::FileStreamWriter>();
}

bool FileSystemBackend::GetVirtualPath(
    const base::FilePath& filesystem_path,
    base::FilePath* virtual_path) {
  return mount_points_->GetVirtualPath(filesystem_path, virtual_path) ||
         system_mount_points_->GetVirtualPath(filesystem_path, virtual_path);
}

}  // namespace chromeos
