// Copyright (c) 2012 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/obfuscated_file_util.h"

#include <stddef.h>
#include <stdint.h>

#include <queue>

#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "storage/browser/fileapi/file_observers.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_operation_context.h"
#include "storage/browser/fileapi/native_file_util.h"
#include "storage/browser/fileapi/sandbox_file_system_backend.h"
#include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
#include "storage/browser/fileapi/sandbox_origin_database.h"
#include "storage/browser/fileapi/sandbox_prioritized_origin_database.h"
#include "storage/browser/fileapi/timed_task_helper.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/common/database/database_identifier.h"
#include "storage/common/fileapi/file_system_util.h"
#include "url/gurl.h"

// Example of various paths:
//   void ObfuscatedFileUtil::DoSomething(const FileSystemURL& url) {
//     base::FilePath virtual_path = url.path();
//     base::FilePath local_path = GetLocalFilePath(url);
//
//     NativeFileUtil::DoSomething(local_path);
//     file_util::DoAnother(local_path);
//  }

namespace storage {

namespace {

typedef SandboxDirectoryDatabase::FileId FileId;
typedef SandboxDirectoryDatabase::FileInfo FileInfo;

void InitFileInfo(
    SandboxDirectoryDatabase::FileInfo* file_info,
    SandboxDirectoryDatabase::FileId parent_id,
    const base::FilePath::StringType& file_name) {
  DCHECK(file_info);
  file_info->parent_id = parent_id;
  file_info->name = file_name;
}

// Costs computed as per crbug.com/86114, based on the LevelDB implementation of
// path storage under Linux.  It's not clear if that will differ on Windows, on
// which base::FilePath uses wide chars [since they're converted to UTF-8 for
// storage anyway], but as long as the cost is high enough that one can't cheat
// on quota by storing data in paths, it doesn't need to be all that accurate.
const int64_t kPathCreationQuotaCost = 146;  // Bytes per inode, basically.
const int64_t kPathByteQuotaCost =
    2;  // Bytes per byte of path length in UTF-8.

const char kDirectoryDatabaseKeySeparator = ' ';

int64_t UsageForPath(size_t length) {
  return kPathCreationQuotaCost +
         static_cast<int64_t>(length) * kPathByteQuotaCost;
}

bool AllocateQuota(FileSystemOperationContext* context, int64_t growth) {
  if (context->allowed_bytes_growth() == storage::QuotaManager::kNoLimit)
    return true;

  int64_t new_quota = context->allowed_bytes_growth() - growth;
  if (growth > 0 && new_quota < 0)
    return false;
  context->set_allowed_bytes_growth(new_quota);
  return true;
}

void UpdateUsage(FileSystemOperationContext* context,
                 const FileSystemURL& url,
                 int64_t growth) {
  context->update_observers()->Notify(
      &FileUpdateObserver::OnUpdate, base::MakeTuple(url, growth));
}

void TouchDirectory(SandboxDirectoryDatabase* db, FileId dir_id) {
  DCHECK(db);
  if (!db->UpdateModificationTime(dir_id, base::Time::Now()))
    NOTREACHED();
}

enum IsolatedOriginStatus {
  kIsolatedOriginMatch,
  kIsolatedOriginDontMatch,
  kIsolatedOriginStatusMax,
};

}  // namespace

class ObfuscatedFileEnumerator
    : public FileSystemFileUtil::AbstractFileEnumerator {
 public:
  ObfuscatedFileEnumerator(
      SandboxDirectoryDatabase* db,
      FileSystemOperationContext* context,
      ObfuscatedFileUtil* obfuscated_file_util,
      const FileSystemURL& root_url,
      bool recursive)
      : db_(db),
        context_(context),
        obfuscated_file_util_(obfuscated_file_util),
        root_url_(root_url),
        recursive_(recursive),
        current_file_id_(0) {
    base::FilePath root_virtual_path = root_url.path();
    FileId file_id;

    if (!db_->GetFileWithPath(root_virtual_path, &file_id))
      return;

    FileRecord record = { file_id, root_virtual_path };
    recurse_queue_.push(record);
  }

  ~ObfuscatedFileEnumerator() override {}

  base::FilePath Next() override {
    ProcessRecurseQueue();
    if (display_stack_.empty())
      return base::FilePath();

    current_file_id_ = display_stack_.back();
    display_stack_.pop_back();

    FileInfo file_info;
    base::FilePath platform_file_path;
    base::File::Error error =
        obfuscated_file_util_->GetFileInfoInternal(
            db_, context_, root_url_, current_file_id_,
            &file_info, &current_platform_file_info_, &platform_file_path);
    if (error != base::File::FILE_OK)
      return Next();

    base::FilePath virtual_path =
        current_parent_virtual_path_.Append(file_info.name);
    if (recursive_ && file_info.is_directory()) {
      FileRecord record = { current_file_id_, virtual_path };
      recurse_queue_.push(record);
    }
    return virtual_path;
  }

  int64_t Size() override { return current_platform_file_info_.size; }

  base::Time LastModifiedTime() override {
    return current_platform_file_info_.last_modified;
  }

  bool IsDirectory() override {
    return current_platform_file_info_.is_directory;
  }

 private:
  typedef SandboxDirectoryDatabase::FileId FileId;
  typedef SandboxDirectoryDatabase::FileInfo FileInfo;

  struct FileRecord {
    FileId file_id;
    base::FilePath virtual_path;
  };

  void ProcessRecurseQueue() {
    while (display_stack_.empty() && !recurse_queue_.empty()) {
      FileRecord entry = recurse_queue_.front();
      recurse_queue_.pop();
      if (!db_->ListChildren(entry.file_id, &display_stack_)) {
        display_stack_.clear();
        return;
      }
      current_parent_virtual_path_ = entry.virtual_path;
    }
  }

  SandboxDirectoryDatabase* db_;
  FileSystemOperationContext* context_;
  ObfuscatedFileUtil* obfuscated_file_util_;
  FileSystemURL root_url_;
  bool recursive_;

  std::queue<FileRecord> recurse_queue_;
  std::vector<FileId> display_stack_;
  base::FilePath current_parent_virtual_path_;

  FileId current_file_id_;
  base::File::Info current_platform_file_info_;
};

class ObfuscatedOriginEnumerator
    : public ObfuscatedFileUtil::AbstractOriginEnumerator {
 public:
  typedef SandboxOriginDatabase::OriginRecord OriginRecord;
  ObfuscatedOriginEnumerator(
      SandboxOriginDatabaseInterface* origin_database,
      const base::FilePath& base_file_path)
      : base_file_path_(base_file_path) {
    if (origin_database)
      origin_database->ListAllOrigins(&origins_);
  }

  ~ObfuscatedOriginEnumerator() override {}

  // Returns the next origin.  Returns empty if there are no more origins.
  GURL Next() override {
    OriginRecord record;
    if (!origins_.empty()) {
      record = origins_.back();
      origins_.pop_back();
    }
    current_ = record;
    return storage::GetOriginFromIdentifier(record.origin);
  }

  // Returns the current origin's information.
  bool HasTypeDirectory(const std::string& type_string) const override {
    if (current_.path.empty())
      return false;
    if (type_string.empty()) {
      NOTREACHED();
      return false;
    }
    base::FilePath path =
        base_file_path_.Append(current_.path).AppendASCII(type_string);
    return base::DirectoryExists(path);
  }

 private:
  std::vector<OriginRecord> origins_;
  OriginRecord current_;
  base::FilePath base_file_path_;
};

ObfuscatedFileUtil::ObfuscatedFileUtil(
    storage::SpecialStoragePolicy* special_storage_policy,
    const base::FilePath& file_system_directory,
    leveldb::Env* env_override,
    base::SequencedTaskRunner* file_task_runner,
    const GetTypeStringForURLCallback& get_type_string_for_url,
    const std::set<std::string>& known_type_strings,
    SandboxFileSystemBackendDelegate* sandbox_delegate)
    : special_storage_policy_(special_storage_policy),
      file_system_directory_(file_system_directory),
      env_override_(env_override),
      db_flush_delay_seconds_(10 * 60),  // 10 mins.
      file_task_runner_(file_task_runner),
      get_type_string_for_url_(get_type_string_for_url),
      known_type_strings_(known_type_strings),
      sandbox_delegate_(sandbox_delegate) {
}

ObfuscatedFileUtil::~ObfuscatedFileUtil() {
  DropDatabases();
}

base::File ObfuscatedFileUtil::CreateOrOpen(
    FileSystemOperationContext* context,
    const FileSystemURL& url, int file_flags) {
  base::File file = CreateOrOpenInternal(context, url, file_flags);
  if (file.IsValid() && file_flags & base::File::FLAG_WRITE &&
      context->quota_limit_type() == storage::kQuotaLimitTypeUnlimited &&
      sandbox_delegate_) {
    sandbox_delegate_->StickyInvalidateUsageCache(url.origin(), url.type());
  }
  return file;
}

base::File::Error ObfuscatedFileUtil::EnsureFileExists(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    bool* created) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
  if (!db)
    return base::File::FILE_ERROR_FAILED;

  FileId file_id;
  if (db->GetFileWithPath(url.path(), &file_id)) {
    FileInfo file_info;
    if (!db->GetFileInfo(file_id, &file_info)) {
      NOTREACHED();
      return base::File::FILE_ERROR_FAILED;
    }
    if (file_info.is_directory())
      return base::File::FILE_ERROR_NOT_A_FILE;
    if (created)
      *created = false;
    return base::File::FILE_OK;
  }
  FileId parent_id;
  if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id))
    return base::File::FILE_ERROR_NOT_FOUND;

  FileInfo file_info;
  InitFileInfo(&file_info, parent_id,
               VirtualPath::BaseName(url.path()).value());

  int64_t growth = UsageForPath(file_info.name.size());
  if (!AllocateQuota(context, growth))
    return base::File::FILE_ERROR_NO_SPACE;
  base::File::Error error = CreateFile(context, base::FilePath(), url,
                                       &file_info);
  if (created && base::File::FILE_OK == error) {
    *created = true;
    UpdateUsage(context, url, growth);
    context->change_observers()->Notify(
        &FileChangeObserver::OnCreateFile, base::MakeTuple(url));
  }
  return error;
}

base::File::Error ObfuscatedFileUtil::CreateDirectory(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    bool exclusive,
    bool recursive) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
  if (!db)
    return base::File::FILE_ERROR_FAILED;

  FileId file_id;
  if (db->GetFileWithPath(url.path(), &file_id)) {
    FileInfo file_info;
    if (exclusive)
      return base::File::FILE_ERROR_EXISTS;
    if (!db->GetFileInfo(file_id, &file_info)) {
      NOTREACHED();
      return base::File::FILE_ERROR_FAILED;
    }
    if (!file_info.is_directory())
      return base::File::FILE_ERROR_NOT_A_DIRECTORY;
    return base::File::FILE_OK;
  }

  std::vector<base::FilePath::StringType> components;
  VirtualPath::GetComponents(url.path(), &components);
  FileId parent_id = 0;
  size_t index;
  for (index = 0; index < components.size(); ++index) {
    base::FilePath::StringType name = components[index];
    if (name == FILE_PATH_LITERAL("/"))
      continue;
    if (!db->GetChildWithName(parent_id, name, &parent_id))
      break;
  }
  if (!db->IsDirectory(parent_id))
    return base::File::FILE_ERROR_NOT_A_DIRECTORY;
  if (!recursive && components.size() - index > 1)
    return base::File::FILE_ERROR_NOT_FOUND;
  bool first = true;
  for (; index < components.size(); ++index) {
    FileInfo file_info;
    file_info.name = components[index];
    if (file_info.name == FILE_PATH_LITERAL("/"))
      continue;
    file_info.modification_time = base::Time::Now();
    file_info.parent_id = parent_id;
    int64_t growth = UsageForPath(file_info.name.size());
    if (!AllocateQuota(context, growth))
      return base::File::FILE_ERROR_NO_SPACE;
    base::File::Error error = db->AddFileInfo(file_info, &parent_id);
    if (error != base::File::FILE_OK)
      return error;
    UpdateUsage(context, url, growth);
    context->change_observers()->Notify(
        &FileChangeObserver::OnCreateDirectory, base::MakeTuple(url));
    if (first) {
      first = false;
      TouchDirectory(db, file_info.parent_id);
    }
  }
  return base::File::FILE_OK;
}

base::File::Error ObfuscatedFileUtil::GetFileInfo(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    base::File::Info* file_info,
    base::FilePath* platform_file_path) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
  if (!db)
    return base::File::FILE_ERROR_NOT_FOUND;
  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id))
    return base::File::FILE_ERROR_NOT_FOUND;
  FileInfo local_info;
  return GetFileInfoInternal(db, context, url,
                             file_id, &local_info,
                             file_info, platform_file_path);
}

scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator>
    ObfuscatedFileUtil::CreateFileEnumerator(
    FileSystemOperationContext* context,
    const FileSystemURL& root_url) {
  return CreateFileEnumerator(context, root_url, false /* recursive */);
}

base::File::Error ObfuscatedFileUtil::GetLocalFilePath(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    base::FilePath* local_path) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
  if (!db)
    return base::File::FILE_ERROR_NOT_FOUND;
  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id))
    return base::File::FILE_ERROR_NOT_FOUND;
  FileInfo file_info;
  if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) {
    NOTREACHED();
    // Directories have no local file path.
    return base::File::FILE_ERROR_NOT_FOUND;
  }
  *local_path = DataPathToLocalPath(url, file_info.data_path);

  if (local_path->empty())
    return base::File::FILE_ERROR_NOT_FOUND;
  return base::File::FILE_OK;
}

base::File::Error ObfuscatedFileUtil::Touch(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    const base::Time& last_access_time,
    const base::Time& last_modified_time) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
  if (!db)
    return base::File::FILE_ERROR_NOT_FOUND;
  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id))
    return base::File::FILE_ERROR_NOT_FOUND;

  FileInfo file_info;
  if (!db->GetFileInfo(file_id, &file_info)) {
    NOTREACHED();
    return base::File::FILE_ERROR_FAILED;
  }
  if (file_info.is_directory()) {
    if (!db->UpdateModificationTime(file_id, last_modified_time))
      return base::File::FILE_ERROR_FAILED;
    return base::File::FILE_OK;
  }
  return NativeFileUtil::Touch(
      DataPathToLocalPath(url, file_info.data_path),
      last_access_time, last_modified_time);
}

base::File::Error ObfuscatedFileUtil::Truncate(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    int64_t length) {
  base::File::Info file_info;
  base::FilePath local_path;
  base::File::Error error =
      GetFileInfo(context, url, &file_info, &local_path);
  if (error != base::File::FILE_OK)
    return error;

  int64_t growth = length - file_info.size;
  if (!AllocateQuota(context, growth))
    return base::File::FILE_ERROR_NO_SPACE;
  error = NativeFileUtil::Truncate(local_path, length);
  if (error == base::File::FILE_OK) {
    UpdateUsage(context, url, growth);
    context->change_observers()->Notify(
        &FileChangeObserver::OnModifyFile, base::MakeTuple(url));
  }
  return error;
}

base::File::Error ObfuscatedFileUtil::CopyOrMoveFile(
    FileSystemOperationContext* context,
    const FileSystemURL& src_url,
    const FileSystemURL& dest_url,
    CopyOrMoveOption option,
    bool copy) {
  // Cross-filesystem copies and moves should be handled via CopyInForeignFile.
  DCHECK(src_url.origin() == dest_url.origin());
  DCHECK(src_url.type() == dest_url.type());

  SandboxDirectoryDatabase* db = GetDirectoryDatabase(src_url, true);
  if (!db)
    return base::File::FILE_ERROR_FAILED;

  FileId src_file_id;
  if (!db->GetFileWithPath(src_url.path(), &src_file_id))
    return base::File::FILE_ERROR_NOT_FOUND;

  FileId dest_file_id;
  bool overwrite = db->GetFileWithPath(dest_url.path(),
                                       &dest_file_id);

  FileInfo src_file_info;
  base::File::Info src_platform_file_info;
  base::FilePath src_local_path;
  base::File::Error error = GetFileInfoInternal(
      db, context, src_url, src_file_id,
      &src_file_info, &src_platform_file_info, &src_local_path);
  if (error != base::File::FILE_OK)
    return error;
  if (src_file_info.is_directory())
    return base::File::FILE_ERROR_NOT_A_FILE;

  FileInfo dest_file_info;
  base::File::Info dest_platform_file_info;  // overwrite case only
  base::FilePath dest_local_path;  // overwrite case only
  if (overwrite) {
    base::File::Error error = GetFileInfoInternal(
        db, context, dest_url, dest_file_id,
        &dest_file_info, &dest_platform_file_info, &dest_local_path);
    if (error == base::File::FILE_ERROR_NOT_FOUND)
      overwrite = false;  // fallback to non-overwrite case
    else if (error != base::File::FILE_OK)
      return error;
    else if (dest_file_info.is_directory())
      return base::File::FILE_ERROR_INVALID_OPERATION;
  }
  if (!overwrite) {
    FileId dest_parent_id;
    if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()),
                             &dest_parent_id)) {
      return base::File::FILE_ERROR_NOT_FOUND;
    }

    dest_file_info = src_file_info;
    dest_file_info.parent_id = dest_parent_id;
    dest_file_info.name =
        VirtualPath::BaseName(dest_url.path()).value();
  }

  int64_t growth = 0;
  if (copy)
    growth += src_platform_file_info.size;
  else
    growth -= UsageForPath(src_file_info.name.size());
  if (overwrite)
    growth -= dest_platform_file_info.size;
  else
    growth += UsageForPath(dest_file_info.name.size());
  if (!AllocateQuota(context, growth))
    return base::File::FILE_ERROR_NO_SPACE;

  /*
   * Copy-with-overwrite
   *  Just overwrite data file
   * Copy-without-overwrite
   *  Copy backing file
   *  Create new metadata pointing to new backing file.
   * Move-with-overwrite
   *  transaction:
   *    Remove source entry.
   *    Point target entry to source entry's backing file.
   *  Delete target entry's old backing file
   * Move-without-overwrite
   *  Just update metadata
   */
  error = base::File::FILE_ERROR_FAILED;
  if (copy) {
    if (overwrite) {
      error = NativeFileUtil::CopyOrMoveFile(
          src_local_path,
          dest_local_path,
          option,
          storage::NativeFileUtil::CopyOrMoveModeForDestination(
              dest_url, true /* copy */));
    } else {  // non-overwrite
      error = CreateFile(context, src_local_path, dest_url, &dest_file_info);
    }
  } else {
    if (overwrite) {
      if (db->OverwritingMoveFile(src_file_id, dest_file_id)) {
        if (base::File::FILE_OK !=
            NativeFileUtil::DeleteFile(dest_local_path))
          LOG(WARNING) << "Leaked a backing file.";
        error = base::File::FILE_OK;
      } else {
        error = base::File::FILE_ERROR_FAILED;
      }
    } else {  // non-overwrite
      if (db->UpdateFileInfo(src_file_id, dest_file_info))
        error = base::File::FILE_OK;
      else
        error = base::File::FILE_ERROR_FAILED;
    }
  }

  if (error != base::File::FILE_OK)
    return error;

  if (overwrite) {
    context->change_observers()->Notify(
        &FileChangeObserver::OnModifyFile,
        base::MakeTuple(dest_url));
  } else {
    context->change_observers()->Notify(
        &FileChangeObserver::OnCreateFileFrom,
        base::MakeTuple(dest_url, src_url));
  }

  if (!copy) {
    context->change_observers()->Notify(
        &FileChangeObserver::OnRemoveFile, base::MakeTuple(src_url));
    TouchDirectory(db, src_file_info.parent_id);
  }

  TouchDirectory(db, dest_file_info.parent_id);

  UpdateUsage(context, dest_url, growth);
  return error;
}

base::File::Error ObfuscatedFileUtil::CopyInForeignFile(
    FileSystemOperationContext* context,
    const base::FilePath& src_file_path,
    const FileSystemURL& dest_url) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true);
  if (!db)
    return base::File::FILE_ERROR_FAILED;

  base::File::Info src_platform_file_info;
  if (!base::GetFileInfo(src_file_path, &src_platform_file_info))
    return base::File::FILE_ERROR_NOT_FOUND;

  FileId dest_file_id;
  bool overwrite = db->GetFileWithPath(dest_url.path(),
                                       &dest_file_id);

  FileInfo dest_file_info;
  base::File::Info dest_platform_file_info;  // overwrite case only
  if (overwrite) {
    base::FilePath dest_local_path;
    base::File::Error error = GetFileInfoInternal(
        db, context, dest_url, dest_file_id,
        &dest_file_info, &dest_platform_file_info, &dest_local_path);
    if (error == base::File::FILE_ERROR_NOT_FOUND)
      overwrite = false;  // fallback to non-overwrite case
    else if (error != base::File::FILE_OK)
      return error;
    else if (dest_file_info.is_directory())
      return base::File::FILE_ERROR_INVALID_OPERATION;
  }
  if (!overwrite) {
    FileId dest_parent_id;
    if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()),
                             &dest_parent_id)) {
      return base::File::FILE_ERROR_NOT_FOUND;
    }
    if (!dest_file_info.is_directory())
      return base::File::FILE_ERROR_FAILED;
    InitFileInfo(&dest_file_info, dest_parent_id,
                 VirtualPath::BaseName(dest_url.path()).value());
  }

  int64_t growth = src_platform_file_info.size;
  if (overwrite)
    growth -= dest_platform_file_info.size;
  else
    growth += UsageForPath(dest_file_info.name.size());
  if (!AllocateQuota(context, growth))
    return base::File::FILE_ERROR_NO_SPACE;

  base::File::Error error;
  if (overwrite) {
    base::FilePath dest_local_path =
        DataPathToLocalPath(dest_url, dest_file_info.data_path);
    error = NativeFileUtil::CopyOrMoveFile(
        src_file_path,
        dest_local_path,
        FileSystemOperation::OPTION_NONE,
        storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
                                                              true /* copy */));
  } else {
    error = CreateFile(context, src_file_path, dest_url, &dest_file_info);
  }

  if (error != base::File::FILE_OK)
    return error;

  if (overwrite) {
    context->change_observers()->Notify(
        &FileChangeObserver::OnModifyFile, base::MakeTuple(dest_url));
  } else {
    context->change_observers()->Notify(
        &FileChangeObserver::OnCreateFile, base::MakeTuple(dest_url));
  }

  UpdateUsage(context, dest_url, growth);
  TouchDirectory(db, dest_file_info.parent_id);
  return base::File::FILE_OK;
}

base::File::Error ObfuscatedFileUtil::DeleteFile(
    FileSystemOperationContext* context,
    const FileSystemURL& url) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
  if (!db)
    return base::File::FILE_ERROR_FAILED;
  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id))
    return base::File::FILE_ERROR_NOT_FOUND;

  FileInfo file_info;
  base::File::Info platform_file_info;
  base::FilePath local_path;
  base::File::Error error = GetFileInfoInternal(
      db, context, url, file_id, &file_info, &platform_file_info, &local_path);
  if (error != base::File::FILE_ERROR_NOT_FOUND &&
      error != base::File::FILE_OK)
    return error;

  if (file_info.is_directory())
    return base::File::FILE_ERROR_NOT_A_FILE;

  int64_t growth =
      -UsageForPath(file_info.name.size()) - platform_file_info.size;
  AllocateQuota(context, growth);
  if (!db->RemoveFileInfo(file_id)) {
    NOTREACHED();
    return base::File::FILE_ERROR_FAILED;
  }
  UpdateUsage(context, url, growth);
  TouchDirectory(db, file_info.parent_id);

  context->change_observers()->Notify(
      &FileChangeObserver::OnRemoveFile, base::MakeTuple(url));

  if (error == base::File::FILE_ERROR_NOT_FOUND)
    return base::File::FILE_OK;

  error = NativeFileUtil::DeleteFile(local_path);
  if (base::File::FILE_OK != error)
    LOG(WARNING) << "Leaked a backing file.";
  return base::File::FILE_OK;
}

base::File::Error ObfuscatedFileUtil::DeleteDirectory(
    FileSystemOperationContext* context,
    const FileSystemURL& url) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
  if (!db)
    return base::File::FILE_ERROR_FAILED;

  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id))
    return base::File::FILE_ERROR_NOT_FOUND;
  FileInfo file_info;
  if (!db->GetFileInfo(file_id, &file_info)) {
    NOTREACHED();
    return base::File::FILE_ERROR_FAILED;
  }
  if (!file_info.is_directory())
    return base::File::FILE_ERROR_NOT_A_DIRECTORY;
  if (!db->RemoveFileInfo(file_id))
    return base::File::FILE_ERROR_NOT_EMPTY;
  int64_t growth = -UsageForPath(file_info.name.size());
  AllocateQuota(context, growth);
  UpdateUsage(context, url, growth);
  TouchDirectory(db, file_info.parent_id);
  context->change_observers()->Notify(
      &FileChangeObserver::OnRemoveDirectory, base::MakeTuple(url));
  return base::File::FILE_OK;
}

storage::ScopedFile ObfuscatedFileUtil::CreateSnapshotFile(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    base::File::Error* error,
    base::File::Info* file_info,
    base::FilePath* platform_path) {
  // We're just returning the local file information.
  *error = GetFileInfo(context, url, file_info, platform_path);
  if (*error == base::File::FILE_OK && file_info->is_directory) {
    *file_info = base::File::Info();
    *error = base::File::FILE_ERROR_NOT_A_FILE;
  }
  return storage::ScopedFile();
}

scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator>
    ObfuscatedFileUtil::CreateFileEnumerator(
    FileSystemOperationContext* context,
    const FileSystemURL& root_url,
    bool recursive) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(root_url, false);
  if (!db) {
    return scoped_ptr<AbstractFileEnumerator>(new EmptyFileEnumerator());
  }
  return scoped_ptr<AbstractFileEnumerator>(
      new ObfuscatedFileEnumerator(db, context, this, root_url, recursive));
}

bool ObfuscatedFileUtil::IsDirectoryEmpty(
    FileSystemOperationContext* context,
    const FileSystemURL& url) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
  if (!db)
    return true;  // Not a great answer, but it's what others do.
  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id))
    return true;  // Ditto.
  FileInfo file_info;
  if (!db->GetFileInfo(file_id, &file_info)) {
    DCHECK(!file_id);
    // It's the root directory and the database hasn't been initialized yet.
    return true;
  }
  if (!file_info.is_directory())
    return true;
  std::vector<FileId> children;
  // TODO(ericu): This could easily be made faster with help from the database.
  if (!db->ListChildren(file_id, &children))
    return true;
  return children.empty();
}

base::FilePath ObfuscatedFileUtil::GetDirectoryForOriginAndType(
    const GURL& origin,
    const std::string& type_string,
    bool create,
    base::File::Error* error_code) {
  base::FilePath origin_dir = GetDirectoryForOrigin(origin, create, error_code);
  if (origin_dir.empty())
    return base::FilePath();
  if (type_string.empty())
    return origin_dir;
  base::FilePath path = origin_dir.AppendASCII(type_string);
  base::File::Error error = base::File::FILE_OK;
  if (!base::DirectoryExists(path) &&
      (!create || !base::CreateDirectory(path))) {
    error = create ?
          base::File::FILE_ERROR_FAILED :
          base::File::FILE_ERROR_NOT_FOUND;
  }

  if (error_code)
    *error_code = error;
  return path;
}

bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType(
    const GURL& origin,
    const std::string& type_string) {
  DestroyDirectoryDatabase(origin, type_string);

  const base::FilePath origin_path = GetDirectoryForOrigin(origin, false, NULL);
  if (!type_string.empty()) {
    // Delete the filesystem type directory.
    base::File::Error error = base::File::FILE_OK;
    const base::FilePath origin_type_path =
        GetDirectoryForOriginAndType(origin, type_string, false, &error);
    if (error == base::File::FILE_ERROR_FAILED)
      return false;
    if (error == base::File::FILE_OK &&
        !origin_type_path.empty() &&
        !base::DeleteFile(origin_type_path, true /* recursive */)) {
      return false;
    }

    // At this point we are sure we had successfully deleted the origin/type
    // directory (i.e. we're ready to just return true).
    // See if we have other directories in this origin directory.
    for (std::set<std::string>::iterator iter = known_type_strings_.begin();
         iter != known_type_strings_.end();
         ++iter) {
      if (*iter == type_string)
        continue;
      if (base::DirectoryExists(origin_path.AppendASCII(*iter))) {
        // Other type's directory exists; just return true here.
        return true;
      }
    }
  }

  // No other directories seem exist. Try deleting the entire origin directory.
  InitOriginDatabase(origin, false);
  if (origin_database_) {
    origin_database_->RemovePathForOrigin(
        storage::GetIdentifierFromOrigin(origin));
  }
  return base::DeleteFile(origin_path, true /* recursive */);
}

void ObfuscatedFileUtil::CloseFileSystemForOriginAndType(
    const GURL& origin,
    const std::string& type_string) {
  const std::string key_prefix = GetDirectoryDatabaseKey(origin, type_string);
  for (DirectoryMap::iterator iter = directories_.lower_bound(key_prefix);
       iter != directories_.end();) {
    if (!base::StartsWith(iter->first, key_prefix,
                          base::CompareCase::SENSITIVE))
      break;
    DCHECK(type_string.empty() || iter->first == key_prefix);
    scoped_ptr<SandboxDirectoryDatabase> database(iter->second);
    directories_.erase(iter++);
  }
}

ObfuscatedFileUtil::AbstractOriginEnumerator*
ObfuscatedFileUtil::CreateOriginEnumerator() {
  std::vector<SandboxOriginDatabase::OriginRecord> origins;

  InitOriginDatabase(GURL(), false);
  return new ObfuscatedOriginEnumerator(
      origin_database_.get(), file_system_directory_);
}

void ObfuscatedFileUtil::DestroyDirectoryDatabase(
    const GURL& origin,
    const std::string& type_string) {
  // If |type_string| is empty, delete all filesystem types under |origin|.
  const std::string key_prefix = GetDirectoryDatabaseKey(origin, type_string);
  for (DirectoryMap::iterator iter = directories_.lower_bound(key_prefix);
       iter != directories_.end();) {
    if (!base::StartsWith(iter->first, key_prefix,
                          base::CompareCase::SENSITIVE))
      break;
    DCHECK(type_string.empty() || iter->first == key_prefix);
    scoped_ptr<SandboxDirectoryDatabase> database(iter->second);
    directories_.erase(iter++);

    // Continue to destroy databases even if it failed because it doesn't affect
    // the final result.
    database->DestroyDatabase();
  }
}

// static
int64_t ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) {
  return UsageForPath(VirtualPath::BaseName(path).value().size());
}

void ObfuscatedFileUtil::MaybePrepopulateDatabase(
    const std::vector<std::string>& type_strings_to_prepopulate) {
  SandboxPrioritizedOriginDatabase database(file_system_directory_,
                                            env_override_);
  std::string origin_string = database.GetPrimaryOrigin();
  if (origin_string.empty() || !database.HasOriginPath(origin_string))
    return;
  const GURL origin = storage::GetOriginFromIdentifier(origin_string);

  // Prepopulate the directory database(s) if and only if this instance
  // has primary origin and the directory database is already there.
  for (size_t i = 0; i < type_strings_to_prepopulate.size(); ++i) {
    const std::string type_string = type_strings_to_prepopulate[i];
    // Only handles known types.
    if (!ContainsKey(known_type_strings_, type_string))
      continue;
    base::File::Error error = base::File::FILE_ERROR_FAILED;
    base::FilePath path = GetDirectoryForOriginAndType(
        origin, type_string, false, &error);
    if (error != base::File::FILE_OK)
      continue;
    scoped_ptr<SandboxDirectoryDatabase> db(
        new SandboxDirectoryDatabase(path, env_override_));
    if (db->Init(SandboxDirectoryDatabase::FAIL_ON_CORRUPTION)) {
      directories_[GetDirectoryDatabaseKey(origin, type_string)] = db.release();
      MarkUsed();
      // Don't populate more than one database, as it may rather hurt
      // performance.
      break;
    }
  }
}

base::FilePath ObfuscatedFileUtil::GetDirectoryForURL(
    const FileSystemURL& url,
    bool create,
    base::File::Error* error_code) {
  return GetDirectoryForOriginAndType(
      url.origin(), CallGetTypeStringForURL(url), create, error_code);
}

std::string ObfuscatedFileUtil::CallGetTypeStringForURL(
    const FileSystemURL& url) {
  DCHECK(!get_type_string_for_url_.is_null());
  return get_type_string_for_url_.Run(url);
}

base::File::Error ObfuscatedFileUtil::GetFileInfoInternal(
    SandboxDirectoryDatabase* db,
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    FileId file_id,
    FileInfo* local_info,
    base::File::Info* file_info,
    base::FilePath* platform_file_path) {
  DCHECK(db);
  DCHECK(context);
  DCHECK(file_info);
  DCHECK(platform_file_path);

  if (!db->GetFileInfo(file_id, local_info)) {
    NOTREACHED();
    return base::File::FILE_ERROR_FAILED;
  }

  if (local_info->is_directory()) {
    file_info->size = 0;
    file_info->is_directory = true;
    file_info->is_symbolic_link = false;
    file_info->last_modified = local_info->modification_time;
    *platform_file_path = base::FilePath();
    // We don't fill in ctime or atime.
    return base::File::FILE_OK;
  }
  if (local_info->data_path.empty())
    return base::File::FILE_ERROR_INVALID_OPERATION;
  base::FilePath local_path = DataPathToLocalPath(url, local_info->data_path);
  base::File::Error error = NativeFileUtil::GetFileInfo(
      local_path, file_info);
  // We should not follow symbolic links in sandboxed file system.
  if (base::IsLink(local_path)) {
    LOG(WARNING) << "Found a symbolic file.";
    error = base::File::FILE_ERROR_NOT_FOUND;
  }
  if (error == base::File::FILE_OK) {
    *platform_file_path = local_path;
  } else if (error == base::File::FILE_ERROR_NOT_FOUND) {
    LOG(WARNING) << "Lost a backing file.";
    InvalidateUsageCache(context, url.origin(), url.type());
    if (!db->RemoveFileInfo(file_id))
      return base::File::FILE_ERROR_FAILED;
  }
  return error;
}

base::File ObfuscatedFileUtil::CreateAndOpenFile(
    FileSystemOperationContext* context,
    const FileSystemURL& dest_url,
    FileInfo* dest_file_info, int file_flags) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true);

  base::FilePath root, dest_local_path;
  base::File::Error error = GenerateNewLocalPath(db, context, dest_url, &root,
                                                 &dest_local_path);
  if (error != base::File::FILE_OK)
    return base::File(error);

  if (base::PathExists(dest_local_path)) {
    if (!base::DeleteFile(dest_local_path, false /* recursive */))
      return base::File(base::File::FILE_ERROR_FAILED);
    LOG(WARNING) << "A stray file detected";
    InvalidateUsageCache(context, dest_url.origin(), dest_url.type());
  }

  base::File file = NativeFileUtil::CreateOrOpen(dest_local_path, file_flags);
  if (!file.IsValid())
    return file;

  if (!file.created()) {
    file.Close();
    base::DeleteFile(dest_local_path, false /* recursive */);
    return base::File(base::File::FILE_ERROR_FAILED);
  }

  error = CommitCreateFile(root, dest_local_path, db, dest_file_info);
  if (error != base::File::FILE_OK) {
    file.Close();
    base::DeleteFile(dest_local_path, false /* recursive */);
    return base::File(error);
  }

  return file;
}

base::File::Error ObfuscatedFileUtil::CreateFile(
    FileSystemOperationContext* context,
    const base::FilePath& src_file_path,
    const FileSystemURL& dest_url,
    FileInfo* dest_file_info) {
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true);

  base::FilePath root, dest_local_path;
  base::File::Error error = GenerateNewLocalPath(db, context, dest_url, &root,
                                                 &dest_local_path);
  if (error != base::File::FILE_OK)
    return error;

  bool created = false;
  if (src_file_path.empty()) {
    if (base::PathExists(dest_local_path)) {
      if (!base::DeleteFile(dest_local_path, false /* recursive */))
        return base::File::FILE_ERROR_FAILED;
      LOG(WARNING) << "A stray file detected";
      InvalidateUsageCache(context, dest_url.origin(), dest_url.type());
    }

    error = NativeFileUtil::EnsureFileExists(dest_local_path, &created);
  } else {
    error = NativeFileUtil::CopyOrMoveFile(
        src_file_path,
        dest_local_path,
        FileSystemOperation::OPTION_NONE,
        storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
                                                              true /* copy */));
    created = true;
  }
  if (error != base::File::FILE_OK)
    return error;
  if (!created)
    return base::File::FILE_ERROR_FAILED;

  return CommitCreateFile(root, dest_local_path, db, dest_file_info);
}

base::File::Error ObfuscatedFileUtil::CommitCreateFile(
    const base::FilePath& root,
    const base::FilePath& local_path,
    SandboxDirectoryDatabase* db,
    FileInfo* dest_file_info) {
  // This removes the root, including the trailing slash, leaving a relative
  // path.
  dest_file_info->data_path = base::FilePath(
      local_path.value().substr(root.value().length() + 1));

  FileId file_id;
  base::File::Error error = db->AddFileInfo(*dest_file_info, &file_id);
  if (error != base::File::FILE_OK)
    return error;

  TouchDirectory(db, dest_file_info->parent_id);
  return base::File::FILE_OK;
}

base::FilePath ObfuscatedFileUtil::DataPathToLocalPath(
    const FileSystemURL& url, const base::FilePath& data_path) {
  base::File::Error error = base::File::FILE_OK;
  base::FilePath root = GetDirectoryForURL(url, false, &error);
  if (error != base::File::FILE_OK)
    return base::FilePath();
  return root.Append(data_path);
}

std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey(
    const GURL& origin, const std::string& type_string) {
  // For isolated origin we just use a type string as a key.
  return storage::GetIdentifierFromOrigin(origin) +
      kDirectoryDatabaseKeySeparator + type_string;
}

// TODO(ericu): How to do the whole validation-without-creation thing?
// We may not have quota even to create the database.
// Ah, in that case don't even get here?
// Still doesn't answer the quota issue, though.
SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase(
    const FileSystemURL& url, bool create) {
  std::string key = GetDirectoryDatabaseKey(
      url.origin(), CallGetTypeStringForURL(url));
  if (key.empty())
    return NULL;

  DirectoryMap::iterator iter = directories_.find(key);
  if (iter != directories_.end()) {
    MarkUsed();
    return iter->second;
  }

  base::File::Error error = base::File::FILE_OK;
  base::FilePath path = GetDirectoryForURL(url, create, &error);
  if (error != base::File::FILE_OK) {
    LOG(WARNING) << "Failed to get origin+type directory: "
                 << url.DebugString() << " error:" << error;
    return NULL;
  }
  MarkUsed();
  SandboxDirectoryDatabase* database =
      new SandboxDirectoryDatabase(path, env_override_);
  directories_[key] = database;
  return database;
}

base::FilePath ObfuscatedFileUtil::GetDirectoryForOrigin(
    const GURL& origin, bool create, base::File::Error* error_code) {
  if (!InitOriginDatabase(origin, create)) {
    if (error_code) {
      *error_code = create ?
          base::File::FILE_ERROR_FAILED :
          base::File::FILE_ERROR_NOT_FOUND;
    }
    return base::FilePath();
  }
  base::FilePath directory_name;
  std::string id = storage::GetIdentifierFromOrigin(origin);

  bool exists_in_db = origin_database_->HasOriginPath(id);
  if (!exists_in_db && !create) {
    if (error_code)
      *error_code = base::File::FILE_ERROR_NOT_FOUND;
    return base::FilePath();
  }
  if (!origin_database_->GetPathForOrigin(id, &directory_name)) {
    if (error_code)
      *error_code = base::File::FILE_ERROR_FAILED;
    return base::FilePath();
  }

  base::FilePath path = file_system_directory_.Append(directory_name);
  bool exists_in_fs = base::DirectoryExists(path);
  if (!exists_in_db && exists_in_fs) {
    if (!base::DeleteFile(path, true)) {
      if (error_code)
        *error_code = base::File::FILE_ERROR_FAILED;
      return base::FilePath();
    }
    exists_in_fs = false;
  }

  if (!exists_in_fs) {
    if (!create || !base::CreateDirectory(path)) {
      if (error_code)
        *error_code = create ?
            base::File::FILE_ERROR_FAILED :
            base::File::FILE_ERROR_NOT_FOUND;
      return base::FilePath();
    }
  }

  if (error_code)
    *error_code = base::File::FILE_OK;

  return path;
}

void ObfuscatedFileUtil::InvalidateUsageCache(
    FileSystemOperationContext* context,
    const GURL& origin,
    FileSystemType type) {
  if (sandbox_delegate_)
    sandbox_delegate_->InvalidateUsageCache(origin, type);
}

void ObfuscatedFileUtil::MarkUsed() {
  if (!timer_)
    timer_.reset(new TimedTaskHelper(file_task_runner_.get()));

  if (timer_->IsRunning()) {
    timer_->Reset();
  } else {
    timer_->Start(FROM_HERE,
                  base::TimeDelta::FromSeconds(db_flush_delay_seconds_),
                  base::Bind(&ObfuscatedFileUtil::DropDatabases,
                             base::Unretained(this)));
  }
}

void ObfuscatedFileUtil::DropDatabases() {
  origin_database_.reset();
  STLDeleteContainerPairSecondPointers(
      directories_.begin(), directories_.end());
  directories_.clear();
  timer_.reset();
}

bool ObfuscatedFileUtil::InitOriginDatabase(const GURL& origin_hint,
                                            bool create) {
  if (origin_database_)
    return true;

  if (!create && !base::DirectoryExists(file_system_directory_))
    return false;
  if (!base::CreateDirectory(file_system_directory_)) {
    LOG(WARNING) << "Failed to create FileSystem directory: " <<
        file_system_directory_.value();
    return false;
  }

  SandboxPrioritizedOriginDatabase* prioritized_origin_database =
      new SandboxPrioritizedOriginDatabase(file_system_directory_,
                                           env_override_);
  origin_database_.reset(prioritized_origin_database);

  if (origin_hint.is_empty() || !HasIsolatedStorage(origin_hint))
    return true;

  const std::string isolated_origin_string =
      storage::GetIdentifierFromOrigin(origin_hint);

  // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33.
  base::FilePath isolated_origin_dir = file_system_directory_.Append(
      SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory);
  if (base::DirectoryExists(isolated_origin_dir) &&
      prioritized_origin_database->GetSandboxOriginDatabase()) {
    SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase(
        isolated_origin_string,
        file_system_directory_,
        prioritized_origin_database->GetSandboxOriginDatabase());
  }

  prioritized_origin_database->InitializePrimaryOrigin(
      isolated_origin_string);

  return true;
}

base::File::Error ObfuscatedFileUtil::GenerateNewLocalPath(
    SandboxDirectoryDatabase* db,
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    base::FilePath* root,
    base::FilePath* local_path) {
  DCHECK(local_path);
  int64_t number;
  if (!db || !db->GetNextInteger(&number))
    return base::File::FILE_ERROR_FAILED;

  base::File::Error error = base::File::FILE_OK;
  *root = GetDirectoryForURL(url, false, &error);
  if (error != base::File::FILE_OK)
    return error;

  // We use the third- and fourth-to-last digits as the directory.
  int64_t directory_number = number % 10000 / 100;
  base::FilePath new_local_path = root->AppendASCII(
      base::StringPrintf("%02" PRId64, directory_number));

  error = NativeFileUtil::CreateDirectory(
      new_local_path, false /* exclusive */, false /* recursive */);
  if (error != base::File::FILE_OK)
    return error;

  *local_path =
      new_local_path.AppendASCII(base::StringPrintf("%08" PRId64, number));
  return base::File::FILE_OK;
}

base::File ObfuscatedFileUtil::CreateOrOpenInternal(
    FileSystemOperationContext* context,
    const FileSystemURL& url, int file_flags) {
  DCHECK(!(file_flags & (base::File::FLAG_DELETE_ON_CLOSE |
        base::File::FLAG_HIDDEN | base::File::FLAG_EXCLUSIVE_READ |
        base::File::FLAG_EXCLUSIVE_WRITE)));
  SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
  if (!db)
    return base::File(base::File::FILE_ERROR_FAILED);
  FileId file_id;
  if (!db->GetFileWithPath(url.path(), &file_id)) {
    // The file doesn't exist.
    if (!(file_flags & (base::File::FLAG_CREATE |
        base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_ALWAYS))) {
      return base::File(base::File::FILE_ERROR_NOT_FOUND);
    }
    FileId parent_id;
    if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id))
      return base::File(base::File::FILE_ERROR_NOT_FOUND);
    FileInfo file_info;
    InitFileInfo(&file_info, parent_id,
                 VirtualPath::BaseName(url.path()).value());

    int64_t growth = UsageForPath(file_info.name.size());
    if (!AllocateQuota(context, growth))
      return base::File(base::File::FILE_ERROR_NO_SPACE);
    base::File file = CreateAndOpenFile(context, url, &file_info, file_flags);
    if (file.IsValid()) {
      UpdateUsage(context, url, growth);
      context->change_observers()->Notify(
          &FileChangeObserver::OnCreateFile, base::MakeTuple(url));
    }
    return file;
  }

  if (file_flags & base::File::FLAG_CREATE)
    return base::File(base::File::FILE_ERROR_EXISTS);

  base::File::Info platform_file_info;
  base::FilePath local_path;
  FileInfo file_info;
  base::File::Error error = GetFileInfoInternal(
      db, context, url, file_id, &file_info, &platform_file_info, &local_path);
  if (error != base::File::FILE_OK)
    return base::File(error);
  if (file_info.is_directory())
    return base::File(base::File::FILE_ERROR_NOT_A_FILE);

  int64_t delta = 0;
  if (file_flags & (base::File::FLAG_CREATE_ALWAYS |
                    base::File::FLAG_OPEN_TRUNCATED)) {
    // The file exists and we're truncating.
    delta = -platform_file_info.size;
    AllocateQuota(context, delta);
  }

  base::File file = NativeFileUtil::CreateOrOpen(local_path, file_flags);
  if (!file.IsValid()) {
    error = file.error_details();
    if (error == base::File::FILE_ERROR_NOT_FOUND) {
      // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker.
      // TODO(tzik): Delete database entry after ensuring the file lost.
      InvalidateUsageCache(context, url.origin(), url.type());
      LOG(WARNING) << "Lost a backing file.";
      return base::File(base::File::FILE_ERROR_FAILED);
    }
    return file;
  }

  // If truncating we need to update the usage.
  if (delta) {
    UpdateUsage(context, url, delta);
    context->change_observers()->Notify(
        &FileChangeObserver::OnModifyFile, base::MakeTuple(url));
  }
  return file;
}

bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) {
  return special_storage_policy_.get() &&
      special_storage_policy_->HasIsolatedStorage(origin);
}

}  // namespace storage
