// Copyright (c) 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 "storage/browser/fileapi/external_mount_points.h"

#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "storage/browser/fileapi/file_system_url.h"

namespace {

// Normalizes file path so it has normalized separators and ends with exactly
// one separator. Paths have to be normalized this way for use in
// GetVirtualPath method. Separators cannot be completely stripped, or
// GetVirtualPath could not working in some edge cases.
// For example, /a/b/c(1)/d would be erroneously resolved as c/d if the
// following mount points were registered: "/a/b/c", "/a/b/c(1)". (Note:
// "/a/b/c" < "/a/b/c(1)" < "/a/b/c/").
base::FilePath NormalizeFilePath(const base::FilePath& path) {
  if (path.empty())
    return path;

  base::FilePath::StringType path_str = path.StripTrailingSeparators().value();
  if (!base::FilePath::IsSeparator(path_str.back()))
    path_str.append(FILE_PATH_LITERAL("/"));

  return base::FilePath(path_str).NormalizePathSeparators();
}

bool IsOverlappingMountPathForbidden(storage::FileSystemType type) {
  return type != storage::kFileSystemTypeNativeMedia &&
         type != storage::kFileSystemTypeDeviceMedia;
}

// Wrapper around ref-counted ExternalMountPoints that will be used to lazily
// create and initialize LazyInstance system ExternalMountPoints.
class SystemMountPointsLazyWrapper {
 public:
  SystemMountPointsLazyWrapper()
      : system_mount_points_(storage::ExternalMountPoints::CreateRefCounted()) {
  }

  ~SystemMountPointsLazyWrapper() {}

  storage::ExternalMountPoints* get() { return system_mount_points_.get(); }

 private:
  scoped_refptr<storage::ExternalMountPoints> system_mount_points_;
};

base::LazyInstance<SystemMountPointsLazyWrapper>::Leaky
    g_external_mount_points = LAZY_INSTANCE_INITIALIZER;

}  // namespace

namespace storage {

class ExternalMountPoints::Instance {
 public:
  Instance(FileSystemType type,
           const base::FilePath& path,
           const FileSystemMountOption& mount_option)
      : type_(type),
        path_(path.StripTrailingSeparators()),
        mount_option_(mount_option) {}
  ~Instance() {}

  FileSystemType type() const { return type_; }
  const base::FilePath& path() const { return path_; }
  const FileSystemMountOption& mount_option() const { return mount_option_; }

 private:
  const FileSystemType type_;
  const base::FilePath path_;
  const FileSystemMountOption mount_option_;

  DISALLOW_COPY_AND_ASSIGN(Instance);
};

//--------------------------------------------------------------------------

// static
ExternalMountPoints* ExternalMountPoints::GetSystemInstance() {
  return g_external_mount_points.Pointer()->get();
}

// static
scoped_refptr<ExternalMountPoints> ExternalMountPoints::CreateRefCounted() {
  return new ExternalMountPoints();
}

bool ExternalMountPoints::RegisterFileSystem(
    const std::string& mount_name,
    FileSystemType type,
    const FileSystemMountOption& mount_option,
    const base::FilePath& path_in) {
  base::AutoLock locker(lock_);

  base::FilePath path = NormalizeFilePath(path_in);
  if (!ValidateNewMountPoint(mount_name, type, path))
    return false;

  instance_map_[mount_name] = new Instance(type, path, mount_option);
  if (!path.empty() && IsOverlappingMountPathForbidden(type))
    path_to_name_map_.insert(std::make_pair(path, mount_name));
  return true;
}

bool ExternalMountPoints::HandlesFileSystemMountType(
    FileSystemType type) const {
  return type == kFileSystemTypeExternal ||
         type == kFileSystemTypeNativeForPlatformApp;
}

bool ExternalMountPoints::RevokeFileSystem(const std::string& mount_name) {
  base::AutoLock locker(lock_);
  NameToInstance::iterator found = instance_map_.find(mount_name);
  if (found == instance_map_.end())
    return false;
  Instance* instance = found->second;
  if (IsOverlappingMountPathForbidden(instance->type()))
    path_to_name_map_.erase(NormalizeFilePath(instance->path()));
  delete found->second;
  instance_map_.erase(found);
  return true;
}

bool ExternalMountPoints::GetRegisteredPath(
    const std::string& filesystem_id, base::FilePath* path) const {
  DCHECK(path);
  base::AutoLock locker(lock_);
  NameToInstance::const_iterator found = instance_map_.find(filesystem_id);
  if (found == instance_map_.end())
    return false;
  *path = found->second->path();
  return true;
}

bool ExternalMountPoints::CrackVirtualPath(
    const base::FilePath& virtual_path,
    std::string* mount_name,
    FileSystemType* type,
    std::string* cracked_id,
    base::FilePath* path,
    FileSystemMountOption* mount_option) const {
  DCHECK(mount_name);
  DCHECK(path);

  // The path should not contain any '..' references.
  if (virtual_path.ReferencesParent())
    return false;

  // The virtual_path should comprise of <mount_name> and <relative_path> parts.
  std::vector<base::FilePath::StringType> components;
  virtual_path.GetComponents(&components);
  if (components.size() < 1)
    return false;

  std::vector<base::FilePath::StringType>::iterator component_iter =
      components.begin();
  std::string maybe_mount_name =
      base::FilePath(*component_iter++).AsUTF8Unsafe();

  base::FilePath cracked_path;
  {
    base::AutoLock locker(lock_);
    NameToInstance::const_iterator found_instance =
        instance_map_.find(maybe_mount_name);
    if (found_instance == instance_map_.end())
      return false;

    *mount_name = maybe_mount_name;
    const Instance* instance = found_instance->second;
    if (type)
      *type = instance->type();
    cracked_path = instance->path();
    *mount_option = instance->mount_option();
  }

  for (; component_iter != components.end(); ++component_iter)
    cracked_path = cracked_path.Append(*component_iter);
  *path = cracked_path;
  return true;
}

FileSystemURL ExternalMountPoints::CrackURL(const GURL& url) const {
  FileSystemURL filesystem_url = FileSystemURL(url);
  if (!filesystem_url.is_valid())
    return FileSystemURL();
  return CrackFileSystemURL(filesystem_url);
}

FileSystemURL ExternalMountPoints::CreateCrackedFileSystemURL(
    const GURL& origin,
    FileSystemType type,
    const base::FilePath& path) const {
  return CrackFileSystemURL(FileSystemURL(origin, type, path));
}

void ExternalMountPoints::AddMountPointInfosTo(
    std::vector<MountPointInfo>* mount_points) const {
  base::AutoLock locker(lock_);
  DCHECK(mount_points);
  for (NameToInstance::const_iterator iter = instance_map_.begin();
       iter != instance_map_.end(); ++iter) {
    mount_points->push_back(MountPointInfo(iter->first, iter->second->path()));
  }
}

bool ExternalMountPoints::GetVirtualPath(const base::FilePath& path_in,
                                         base::FilePath* virtual_path) const {
  DCHECK(virtual_path);

  base::AutoLock locker(lock_);

  base::FilePath path = NormalizeFilePath(path_in);
  std::map<base::FilePath, std::string>::const_reverse_iterator iter(
      path_to_name_map_.upper_bound(path));
  if (iter == path_to_name_map_.rend())
    return false;

  *virtual_path = CreateVirtualRootPath(iter->second);
  if (iter->first == path)
    return true;
  return iter->first.AppendRelativePath(path, virtual_path);
}

base::FilePath ExternalMountPoints::CreateVirtualRootPath(
    const std::string& mount_name) const {
  return base::FilePath().Append(base::FilePath::FromUTF8Unsafe(mount_name));
}

FileSystemURL ExternalMountPoints::CreateExternalFileSystemURL(
    const GURL& origin,
    const std::string& mount_name,
    const base::FilePath& path) const {
  return CreateCrackedFileSystemURL(
      origin,
      storage::kFileSystemTypeExternal,
      // Avoid using FilePath::Append as path may be an absolute path.
      base::FilePath(CreateVirtualRootPath(mount_name).value() +
                     base::FilePath::kSeparators[0] + path.value()));
}

void ExternalMountPoints::RevokeAllFileSystems() {
  NameToInstance instance_map_copy;
  {
    base::AutoLock locker(lock_);
    instance_map_copy = instance_map_;
    instance_map_.clear();
    path_to_name_map_.clear();
  }
  base::STLDeleteContainerPairSecondPointers(instance_map_copy.begin(),
                                             instance_map_copy.end());
}

ExternalMountPoints::ExternalMountPoints() {}

ExternalMountPoints::~ExternalMountPoints() {
  base::STLDeleteContainerPairSecondPointers(instance_map_.begin(),
                                             instance_map_.end());
}

FileSystemURL ExternalMountPoints::CrackFileSystemURL(
    const FileSystemURL& url) const {
  if (!HandlesFileSystemMountType(url.type()))
    return FileSystemURL();

  base::FilePath virtual_path = url.path();
  if (url.type() == kFileSystemTypeNativeForPlatformApp) {
#if defined(OS_CHROMEOS)
    // On Chrome OS, find a mount point and virtual path for the external fs.
    if (!GetVirtualPath(url.path(), &virtual_path))
      return FileSystemURL();
#else
    // On other OS, it is simply a native local path.
    return FileSystemURL(
        url.origin(), url.mount_type(), url.virtual_path(),
        url.mount_filesystem_id(), kFileSystemTypeNativeLocal,
        url.path(), url.filesystem_id(), url.mount_option());
#endif
  }

  std::string mount_name;
  FileSystemType cracked_type;
  std::string cracked_id;
  base::FilePath cracked_path;
  FileSystemMountOption cracked_mount_option;

  if (!CrackVirtualPath(virtual_path, &mount_name, &cracked_type,
                        &cracked_id, &cracked_path, &cracked_mount_option)) {
    return FileSystemURL();
  }

  return FileSystemURL(
      url.origin(), url.mount_type(), url.virtual_path(),
      !url.filesystem_id().empty() ? url.filesystem_id() : mount_name,
      cracked_type, cracked_path,
      cracked_id.empty() ? mount_name : cracked_id, cracked_mount_option);
}

bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name,
                                                FileSystemType type,
                                                const base::FilePath& path) {
  lock_.AssertAcquired();

  // Mount name must not be empty.
  if (mount_name.empty())
    return false;

  // Verify there is no registered mount point with the same name.
  NameToInstance::iterator found = instance_map_.find(mount_name);
  if (found != instance_map_.end())
    return false;

  // Allow empty paths.
  if (path.empty())
    return true;

  // Verify path is legal.
  if (path.ReferencesParent() || !path.IsAbsolute())
    return false;

  if (IsOverlappingMountPathForbidden(type)) {
    // Check there the new path does not overlap with one of the existing ones.
    std::map<base::FilePath, std::string>::reverse_iterator potential_parent(
        path_to_name_map_.upper_bound(path));
    if (potential_parent != path_to_name_map_.rend()) {
      if (potential_parent->first == path ||
          potential_parent->first.IsParent(path)) {
        return false;
      }
    }

    std::map<base::FilePath, std::string>::iterator potential_child =
        path_to_name_map_.upper_bound(path);
    if (potential_child != path_to_name_map_.end()) {
      if (potential_child->first == path ||
          path.IsParent(potential_child->first)) {
        return false;
      }
    }
  }

  return true;
}

}  // namespace storage
