// 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 "content/browser/fileapi/fileapi_message_filter.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/streams/stream_registry.h"
#include "content/common/fileapi/file_system_messages.h"
#include "content/common/fileapi/webblob_messages.h"
#include "content/public/browser/user_metrics.h"
#include "ipc/ipc_platform_file.h"
#include "net/base/mime_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
#include "webkit/browser/blob/blob_storage_context.h"
#include "webkit/browser/blob/blob_storage_host.h"
#include "webkit/browser/fileapi/file_observers.h"
#include "webkit/browser/fileapi/file_permission_policy.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/isolated_context.h"
#include "webkit/browser/quota/quota_manager.h"
#include "webkit/common/blob/blob_data.h"
#include "webkit/common/blob/shareable_file_reference.h"
#include "webkit/common/fileapi/directory_entry.h"
#include "webkit/common/fileapi/file_system_info.h"
#include "webkit/common/fileapi/file_system_types.h"
#include "webkit/common/fileapi/file_system_util.h"

#if defined(ENABLE_PLUGINS)
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#endif  // defined(ENABLE_PLUGINS)

using fileapi::FileSystemFileUtil;
using fileapi::FileSystemBackend;
using fileapi::FileSystemOperation;
using fileapi::FileSystemURL;
using fileapi::FileUpdateObserver;
using fileapi::UpdateObserverList;
using webkit_blob::BlobData;
using webkit_blob::BlobStorageContext;
using webkit_blob::BlobStorageHost;

namespace content {

namespace {

void RevokeFilePermission(int child_id, const base::FilePath& path) {
  ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
    child_id, path);
}

}  // namespace

FileAPIMessageFilter::FileAPIMessageFilter(
    int process_id,
    net::URLRequestContextGetter* request_context_getter,
    fileapi::FileSystemContext* file_system_context,
    ChromeBlobStorageContext* blob_storage_context,
    StreamContext* stream_context)
    : process_id_(process_id),
      context_(file_system_context),
      security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
      request_context_getter_(request_context_getter),
      request_context_(NULL),
      blob_storage_context_(blob_storage_context),
      stream_context_(stream_context) {
  DCHECK(context_);
  DCHECK(request_context_getter_.get());
  DCHECK(blob_storage_context);
  DCHECK(stream_context);
}

FileAPIMessageFilter::FileAPIMessageFilter(
    int process_id,
    net::URLRequestContext* request_context,
    fileapi::FileSystemContext* file_system_context,
    ChromeBlobStorageContext* blob_storage_context,
    StreamContext* stream_context)
    : process_id_(process_id),
      context_(file_system_context),
      security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
      request_context_(request_context),
      blob_storage_context_(blob_storage_context),
      stream_context_(stream_context) {
  DCHECK(context_);
  DCHECK(request_context_);
  DCHECK(blob_storage_context);
  DCHECK(stream_context);
}

void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (request_context_getter_.get()) {
    DCHECK(!request_context_);
    request_context_ = request_context_getter_->GetURLRequestContext();
    request_context_getter_ = NULL;
    DCHECK(request_context_);
  }

  blob_storage_host_.reset(
      new BlobStorageHost(blob_storage_context_->context()));

  operation_runner_ = context_->CreateFileSystemOperationRunner();
}

void FileAPIMessageFilter::OnChannelClosing() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  // Unregister all the blob and stream URLs that are previously registered in
  // this process.
  blob_storage_host_.reset();
  for (base::hash_set<std::string>::const_iterator iter = stream_urls_.begin();
       iter != stream_urls_.end(); ++iter) {
    stream_context_->registry()->UnregisterStream(GURL(*iter));
  }

  in_transit_snapshot_files_.clear();

  // Close all files that are previously OpenFile()'ed in this process.
  if (!on_close_callbacks_.IsEmpty()) {
    DLOG(INFO)
        << "File API: Renderer process shut down before NotifyCloseFile"
        << " for " << on_close_callbacks_.size() << " files opened in PPAPI";
  }

  for (OnCloseCallbackMap::iterator itr(&on_close_callbacks_);
       !itr.IsAtEnd(); itr.Advance()) {
    const base::Closure* callback = itr.GetCurrentValue();
    DCHECK(callback);
    if (!callback->is_null())
      callback->Run();
  }

  on_close_callbacks_.Clear();
  operation_runner_.reset();
  operations_.clear();
}

base::TaskRunner* FileAPIMessageFilter::OverrideTaskRunnerForMessage(
    const IPC::Message& message) {
  if (message.type() == FileSystemHostMsg_SyncGetPlatformPath::ID)
    return context_->default_file_task_runner();
  return NULL;
}

bool FileAPIMessageFilter::OnMessageReceived(
    const IPC::Message& message, bool* message_was_ok) {
  *message_was_ok = true;
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP_EX(FileAPIMessageFilter, message, *message_was_ok)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_OpenFileSystem, OnOpenFileSystem)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_ResolveURL, OnResolveURL)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_DeleteFileSystem, OnDeleteFileSystem)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Move, OnMove)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Copy, OnCopy)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Remove, OnRemove)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadMetadata, OnReadMetadata)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Create, OnCreate)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Exists, OnExists)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadDirectory, OnReadDirectory)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Write, OnWrite)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_WriteDeprecated, OnWriteDeprecated)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_Truncate, OnTruncate)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_TouchFile, OnTouchFile)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_CancelWrite, OnCancel)
#if defined(ENABLE_PLUGINS)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_OpenPepperFile, OnOpenPepperFile)
#endif  // defined(ENABLE_PLUGINS)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_NotifyCloseFile, OnNotifyCloseFile)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_CreateSnapshotFile,
                        OnCreateSnapshotFile)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidReceiveSnapshotFile,
                        OnDidReceiveSnapshotFile)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_WillUpdate, OnWillUpdate)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidUpdate, OnDidUpdate)
    IPC_MESSAGE_HANDLER(FileSystemHostMsg_SyncGetPlatformPath,
                        OnSyncGetPlatformPath)
    IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuilding, OnStartBuildingBlob)
    IPC_MESSAGE_HANDLER(BlobHostMsg_AppendBlobDataItem,
                        OnAppendBlobDataItemToBlob)
    IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory,
                        OnAppendSharedMemoryToBlob)
    IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuilding, OnFinishBuildingBlob)
    IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount,
                        OnIncrementBlobRefCount)
    IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount,
                        OnDecrementBlobRefCount)
    IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL,
                        OnRegisterPublicBlobURL)
    IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL)
    IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedRegisterBlobURL,
                        OnDeprecatedRegisterBlobURL)
    IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedRevokeBlobURL,
                        OnDeprecatedRevokeBlobURL)
    IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedCloneBlobURL,
                        OnDeprecatedCloneBlobURL)
    IPC_MESSAGE_HANDLER(StreamHostMsg_StartBuilding, OnStartBuildingStream)
    IPC_MESSAGE_HANDLER(StreamHostMsg_AppendBlobDataItem,
                        OnAppendBlobDataItemToStream)
    IPC_MESSAGE_HANDLER(StreamHostMsg_SyncAppendSharedMemory,
                        OnAppendSharedMemoryToStream)
    IPC_MESSAGE_HANDLER(StreamHostMsg_FinishBuilding, OnFinishBuildingStream)
    IPC_MESSAGE_HANDLER(StreamHostMsg_AbortBuilding, OnAbortBuildingStream)
    IPC_MESSAGE_HANDLER(StreamHostMsg_Clone, OnCloneStream)
    IPC_MESSAGE_HANDLER(StreamHostMsg_Remove, OnRemoveStream)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP_EX()
  return handled;
}

FileAPIMessageFilter::~FileAPIMessageFilter() {}

void FileAPIMessageFilter::BadMessageReceived() {
  RecordAction(UserMetricsAction("BadMessageTerminate_FAMF"));
  BrowserMessageFilter::BadMessageReceived();
}

void FileAPIMessageFilter::OnOpenFileSystem(int request_id,
                                            const GURL& origin_url,
                                            fileapi::FileSystemType type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (type == fileapi::kFileSystemTypeTemporary) {
    RecordAction(UserMetricsAction("OpenFileSystemTemporary"));
  } else if (type == fileapi::kFileSystemTypePersistent) {
    RecordAction(UserMetricsAction("OpenFileSystemPersistent"));
  }
  fileapi::OpenFileSystemMode mode =
      fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT;
  context_->OpenFileSystem(origin_url, type, mode, base::Bind(
      &FileAPIMessageFilter::DidOpenFileSystem, this, request_id));
}

void FileAPIMessageFilter::OnResolveURL(
    int request_id,
    const GURL& filesystem_url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(filesystem_url));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  context_->ResolveURL(url, base::Bind(
      &FileAPIMessageFilter::DidResolveURL, this, request_id));
}

void FileAPIMessageFilter::OnDeleteFileSystem(
    int request_id,
    const GURL& origin_url,
    fileapi::FileSystemType type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  context_->DeleteFileSystem(origin_url, type, base::Bind(
      &FileAPIMessageFilter::DidDeleteFileSystem, this, request_id));
}

void FileAPIMessageFilter::OnMove(
    int request_id, const GURL& src_path, const GURL& dest_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL src_url(context_->CrackURL(src_path));
  FileSystemURL dest_url(context_->CrackURL(dest_path));
  if (!ValidateFileSystemURL(request_id, src_url) ||
      !ValidateFileSystemURL(request_id, dest_url)) {
    return;
  }
  if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
      !security_policy_->CanDeleteFileSystemFile(process_id_, src_url) ||
      !security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->Move(
      src_url, dest_url,
      fileapi::FileSystemOperation::OPTION_NONE,
      base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}

void FileAPIMessageFilter::OnCopy(
    int request_id, const GURL& src_path, const GURL& dest_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL src_url(context_->CrackURL(src_path));
  FileSystemURL dest_url(context_->CrackURL(dest_path));
  if (!ValidateFileSystemURL(request_id, src_url) ||
      !ValidateFileSystemURL(request_id, dest_url)) {
    return;
  }
  if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
      !security_policy_->CanCopyIntoFileSystemFile(process_id_, dest_url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->Copy(
      src_url, dest_url,
      fileapi::FileSystemOperation::OPTION_NONE,
      fileapi::FileSystemOperationRunner::CopyProgressCallback(),
      base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}

void FileAPIMessageFilter::OnRemove(
    int request_id, const GURL& path, bool recursive) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanDeleteFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->Remove(
      url, recursive,
      base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}

void FileAPIMessageFilter::OnReadMetadata(
    int request_id, const GURL& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->GetMetadata(
      url, base::Bind(&FileAPIMessageFilter::DidGetMetadata, this, request_id));
}

void FileAPIMessageFilter::OnCreate(
    int request_id, const GURL& path, bool exclusive,
    bool is_directory, bool recursive) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  if (is_directory) {
    operations_[request_id] = operation_runner()->CreateDirectory(
        url, exclusive, recursive,
        base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
  } else {
    operations_[request_id] = operation_runner()->CreateFile(
        url, exclusive,
        base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
  }
}

void FileAPIMessageFilter::OnExists(
    int request_id, const GURL& path, bool is_directory) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  if (is_directory) {
    operations_[request_id] = operation_runner()->DirectoryExists(
        url,
        base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
  } else {
    operations_[request_id] = operation_runner()->FileExists(
        url,
        base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
  }
}

void FileAPIMessageFilter::OnReadDirectory(
    int request_id, const GURL& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->ReadDirectory(
      url, base::Bind(&FileAPIMessageFilter::DidReadDirectory,
                      this, request_id));
}

void FileAPIMessageFilter::OnWriteDeprecated(
    int request_id,
    const GURL& path,
    const GURL& blob_url,
    int64 offset) {
  std::string uuid =
      blob_storage_context_->context()->LookupUuidFromDeprecatedURL(blob_url);
  OnWrite(request_id, path, uuid, offset);
}

void FileAPIMessageFilter::OnWrite(
    int request_id,
    const GURL& path,
    const std::string& blob_uuid,
    int64 offset) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (!request_context_) {
    // We can't write w/o a request context, trying to do so will crash.
    NOTREACHED();
    return;
  }

  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  scoped_ptr<webkit_blob::BlobDataHandle> blob =
      blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid);

  operations_[request_id] = operation_runner()->Write(
      request_context_, url, blob.Pass(), offset,
      base::Bind(&FileAPIMessageFilter::DidWrite, this, request_id));
}

void FileAPIMessageFilter::OnTruncate(
    int request_id,
    const GURL& path,
    int64 length) {
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->Truncate(
      url, length,
      base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}

void FileAPIMessageFilter::OnTouchFile(
    int request_id,
    const GURL& path,
    const base::Time& last_access_time,
    const base::Time& last_modified_time) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->TouchFile(
      url, last_access_time, last_modified_time,
      base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}

void FileAPIMessageFilter::OnCancel(
    int request_id,
    int request_id_to_cancel) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  OperationsMap::iterator found = operations_.find(request_id_to_cancel);
  if (found != operations_.end()) {
    // The cancel will eventually send both the write failure and the cancel
    // success.
    operation_runner()->Cancel(
        found->second,
        base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
  } else {
    // The write already finished; report that we failed to stop it.
    Send(new FileSystemMsg_DidFail(
        request_id, base::PLATFORM_FILE_ERROR_INVALID_OPERATION));
  }
}

#if defined(ENABLE_PLUGINS)
void FileAPIMessageFilter::OnOpenPepperFile(
    int request_id, const GURL& path, int pp_open_flags) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FileSystemURL url(context_->CrackURL(path));
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!CanOpenFileSystemURLWithPepperFlags(pp_open_flags, process_id_, url)) {
    Send(new FileSystemMsg_DidFail(
        request_id, base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  quota::QuotaLimitType quota_policy = quota::kQuotaLimitTypeUnknown;
  quota::QuotaManagerProxy* quota_manager_proxy =
      context_->quota_manager_proxy();
  CHECK(quota_manager_proxy);
  CHECK(quota_manager_proxy->quota_manager());

  if (quota_manager_proxy->quota_manager()->IsStorageUnlimited(
          url.origin(), FileSystemTypeToQuotaStorageType(url.type()))) {
    quota_policy = quota::kQuotaLimitTypeUnlimited;
  } else {
    quota_policy = quota::kQuotaLimitTypeLimited;
  }

  int platform_file_flags = 0;
  if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(pp_open_flags,
                                                     &platform_file_flags)) {
    // |pp_open_flags| should have already been checked in PepperFileIOHost.
    NOTREACHED() << "Open file request with invalid pp_open_flags ignored.";
  }

  operations_[request_id] = operation_runner()->OpenFile(
      url, platform_file_flags, PeerHandle(),
      base::Bind(&FileAPIMessageFilter::DidOpenFile, this, request_id,
                 quota_policy));
}
#endif  // defined(ENABLE_PLUGINS)

void FileAPIMessageFilter::OnNotifyCloseFile(int file_open_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  // Remove |file_open_id| from the map of |on_close_callback|s.
  // It must only be called for a ID that is successfully opened and enrolled in
  // DidOpenFile.
  base::Closure* on_close_callback = on_close_callbacks_.Lookup(file_open_id);
  if (on_close_callback && !on_close_callback->is_null()) {
    on_close_callback->Run();
    on_close_callbacks_.Remove(file_open_id);
  }
}

void FileAPIMessageFilter::OnWillUpdate(const GURL& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!url.is_valid())
    return;
  const UpdateObserverList* observers =
      context_->GetUpdateObservers(url.type());
  if (!observers)
    return;
  observers->Notify(&FileUpdateObserver::OnStartUpdate, MakeTuple(url));
}

void FileAPIMessageFilter::OnDidUpdate(const GURL& path, int64 delta) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));
  if (!url.is_valid())
    return;
  const UpdateObserverList* observers =
      context_->GetUpdateObservers(url.type());
  if (!observers)
    return;
  observers->Notify(&FileUpdateObserver::OnUpdate, MakeTuple(url, delta));
  observers->Notify(&FileUpdateObserver::OnEndUpdate, MakeTuple(url));
}

void FileAPIMessageFilter::OnSyncGetPlatformPath(
    const GURL& path, base::FilePath* platform_path) {
  SyncGetPlatformPath(context_, process_id_, path, platform_path);
}

void FileAPIMessageFilter::OnCreateSnapshotFile(
    int request_id, const GURL& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  FileSystemURL url(context_->CrackURL(path));

  // Make sure if this file can be read by the renderer as this is
  // called when the renderer is about to create a new File object
  // (for reading the file).
  if (!ValidateFileSystemURL(request_id, url))
    return;
  if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
    Send(new FileSystemMsg_DidFail(request_id,
                                   base::PLATFORM_FILE_ERROR_SECURITY));
    return;
  }

  operations_[request_id] = operation_runner()->CreateSnapshotFile(
      url,
      base::Bind(&FileAPIMessageFilter::DidCreateSnapshot,
                 this, request_id, url));
}

void FileAPIMessageFilter::OnDidReceiveSnapshotFile(int request_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  in_transit_snapshot_files_.erase(request_id);
}

void FileAPIMessageFilter::OnStartBuildingBlob(const std::string& uuid) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  ignore_result(blob_storage_host_->StartBuildingBlob(uuid));
}

void FileAPIMessageFilter::OnAppendBlobDataItemToBlob(
    const std::string& uuid, const BlobData::Item& item) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (item.type() == BlobData::Item::TYPE_FILE_FILESYSTEM) {
    FileSystemURL filesystem_url(context_->CrackURL(item.filesystem_url()));
    if (!FileSystemURLIsValid(context_, filesystem_url) ||
        !security_policy_->CanReadFileSystemFile(process_id_, filesystem_url)) {
      ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
      return;
    }
  }
  if (item.type() == BlobData::Item::TYPE_FILE &&
      !security_policy_->CanReadFile(process_id_, item.path())) {
    ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
    return;
  }
  if (item.length() == 0) {
    BadMessageReceived();
    return;
  }
  ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item));
}

void FileAPIMessageFilter::OnAppendSharedMemoryToBlob(
    const std::string& uuid,
    base::SharedMemoryHandle handle,
    size_t buffer_size) {
  DCHECK(base::SharedMemory::IsHandleValid(handle));
  if (!buffer_size) {
    BadMessageReceived();
    return;
  }
#if defined(OS_WIN)
  base::SharedMemory shared_memory(handle, true, PeerHandle());
#else
  base::SharedMemory shared_memory(handle, true);
#endif
  if (!shared_memory.Map(buffer_size)) {
    ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
    return;
  }

  BlobData::Item item;
  item.SetToSharedBytes(static_cast<char*>(shared_memory.memory()),
                        buffer_size);
  ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item));
}

void FileAPIMessageFilter::OnFinishBuildingBlob(
    const std::string& uuid, const std::string& content_type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  ignore_result(blob_storage_host_->FinishBuildingBlob(uuid, content_type));
  // TODO(michaeln): check return values once blink has migrated, crbug/174200
}

void FileAPIMessageFilter::OnIncrementBlobRefCount(const std::string& uuid) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  ignore_result(blob_storage_host_->IncrementBlobRefCount(uuid));
}

void FileAPIMessageFilter::OnDecrementBlobRefCount(const std::string& uuid) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  ignore_result(blob_storage_host_->DecrementBlobRefCount(uuid));
}

void FileAPIMessageFilter::OnRegisterPublicBlobURL(
    const GURL& public_url, const std::string& uuid) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  ignore_result(blob_storage_host_->RegisterPublicBlobURL(public_url, uuid));
}

void FileAPIMessageFilter::OnRevokePublicBlobURL(const GURL& public_url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  ignore_result(blob_storage_host_->RevokePublicBlobURL(public_url));
}

void FileAPIMessageFilter::OnDeprecatedRegisterBlobURL(
    const GURL& url, const std::string& uuid) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  blob_storage_host_->DeprecatedRegisterBlobURL(url, uuid);
}

void FileAPIMessageFilter::OnDeprecatedCloneBlobURL(
    const GURL& url, const GURL& src_url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  blob_storage_host_->DeprecatedCloneBlobURL(url, src_url);
}

void FileAPIMessageFilter::OnDeprecatedRevokeBlobURL(const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  blob_storage_host_->DeprecatedRevokeBlobURL(url);
}

void FileAPIMessageFilter::OnStartBuildingStream(
    const GURL& url, const std::string& content_type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  // Only an internal Blob URL is expected here. See the BlobURL of the Blink.
  if (!StartsWithASCII(
          url.path(), "blobinternal%3A///", true /* case_sensitive */)) {
    NOTREACHED() << "Malformed Stream URL: " << url.spec();
    BadMessageReceived();
    return;
  }
  // Use an empty security origin for now. Stream accepts a security origin
  // but how it's handled is not fixed yet.
  new Stream(stream_context_->registry(),
             NULL /* write_observer */,
             url);
  stream_urls_.insert(url.spec());
}

void FileAPIMessageFilter::OnAppendBlobDataItemToStream(
    const GURL& url, const BlobData::Item& item) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  scoped_refptr<Stream> stream(GetStreamForURL(url));
  // Stream instances may be deleted on error. Just abort if there's no Stream
  // instance for |url| in the registry.
  if (!stream.get())
    return;

  // Data for stream is delivered as TYPE_BYTES item.
  if (item.type() != BlobData::Item::TYPE_BYTES) {
    BadMessageReceived();
    return;
  }
  stream->AddData(item.bytes(), item.length());
}

void FileAPIMessageFilter::OnAppendSharedMemoryToStream(
    const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) {
  DCHECK(base::SharedMemory::IsHandleValid(handle));
  if (!buffer_size) {
    BadMessageReceived();
    return;
  }
#if defined(OS_WIN)
  base::SharedMemory shared_memory(handle, true, PeerHandle());
#else
  base::SharedMemory shared_memory(handle, true);
#endif
  if (!shared_memory.Map(buffer_size)) {
    OnRemoveStream(url);
    return;
  }

  scoped_refptr<Stream> stream(GetStreamForURL(url));
  if (!stream.get())
    return;

  stream->AddData(static_cast<char*>(shared_memory.memory()), buffer_size);
}

void FileAPIMessageFilter::OnFinishBuildingStream(const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  scoped_refptr<Stream> stream(GetStreamForURL(url));
  if (stream.get())
    stream->Finalize();
}

void FileAPIMessageFilter::OnAbortBuildingStream(const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  scoped_refptr<Stream> stream(GetStreamForURL(url));
  if (stream.get())
    stream->Abort();
}

void FileAPIMessageFilter::OnCloneStream(
    const GURL& url, const GURL& src_url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  // Abort if there's no Stream instance for |src_url| (source Stream which
  // we're going to make |url| point to) in the registry.
  if (!GetStreamForURL(src_url))
    return;

  stream_context_->registry()->CloneStream(url, src_url);
  stream_urls_.insert(url.spec());
}

void FileAPIMessageFilter::OnRemoveStream(const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!GetStreamForURL(url).get())
    return;

  stream_context_->registry()->UnregisterStream(url);
  stream_urls_.erase(url.spec());
}

void FileAPIMessageFilter::DidFinish(int request_id,
                                     base::PlatformFileError result) {
  if (result == base::PLATFORM_FILE_OK)
    Send(new FileSystemMsg_DidSucceed(request_id));
  else
    Send(new FileSystemMsg_DidFail(request_id, result));
  operations_.erase(request_id);
}

void FileAPIMessageFilter::DidGetMetadata(
    int request_id,
    base::PlatformFileError result,
    const base::PlatformFileInfo& info) {
  if (result == base::PLATFORM_FILE_OK)
    Send(new FileSystemMsg_DidReadMetadata(request_id, info));
  else
    Send(new FileSystemMsg_DidFail(request_id, result));
  operations_.erase(request_id);
}

void FileAPIMessageFilter::DidReadDirectory(
    int request_id,
    base::PlatformFileError result,
    const std::vector<fileapi::DirectoryEntry>& entries,
    bool has_more) {
  if (result == base::PLATFORM_FILE_OK)
    Send(new FileSystemMsg_DidReadDirectory(request_id, entries, has_more));
  else
    Send(new FileSystemMsg_DidFail(request_id, result));
  operations_.erase(request_id);
}

void FileAPIMessageFilter::DidOpenFile(int request_id,
                                       quota::QuotaLimitType quota_policy,
                                       base::PlatformFileError result,
                                       base::PlatformFile file,
                                       const base::Closure& on_close_callback,
                                       base::ProcessHandle peer_handle) {
  if (result == base::PLATFORM_FILE_OK) {
    IPC::PlatformFileForTransit file_for_transit =
        file != base::kInvalidPlatformFileValue ?
            IPC::GetFileHandleForProcess(file, peer_handle, true) :
            IPC::InvalidPlatformFileForTransit();
    int file_open_id = on_close_callbacks_.Add(
        new base::Closure(on_close_callback));

    Send(new FileSystemMsg_DidOpenFile(request_id,
                                       file_for_transit,
                                       file_open_id,
                                       quota_policy));
  } else {
    Send(new FileSystemMsg_DidFail(request_id,
                                   result));
  }
  operations_.erase(request_id);
}

void FileAPIMessageFilter::DidWrite(int request_id,
                                    base::PlatformFileError result,
                                    int64 bytes,
                                    bool complete) {
  if (result == base::PLATFORM_FILE_OK) {
    Send(new FileSystemMsg_DidWrite(request_id, bytes, complete));
    if (complete)
      operations_.erase(request_id);
  } else {
    Send(new FileSystemMsg_DidFail(request_id, result));
    operations_.erase(request_id);
  }
}

void FileAPIMessageFilter::DidOpenFileSystem(int request_id,
                                             const GURL& root,
                                             const std::string& filesystem_name,
                                             base::PlatformFileError result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (result == base::PLATFORM_FILE_OK) {
    DCHECK(root.is_valid());
    Send(new FileSystemMsg_DidOpenFileSystem(
        request_id, filesystem_name, root));
  } else {
    Send(new FileSystemMsg_DidFail(request_id, result));
  }
  // For OpenFileSystem we do not create a new operation, so no unregister here.
}

void FileAPIMessageFilter::DidResolveURL(int request_id,
                                         base::PlatformFileError result,
                                         const fileapi::FileSystemInfo& info,
                                         const base::FilePath& file_path,
                                         bool is_directory) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (result == base::PLATFORM_FILE_OK) {
    DCHECK(info.root_url.is_valid());
    Send(new FileSystemMsg_DidResolveURL(
        request_id, info, file_path, is_directory));
  } else {
    Send(new FileSystemMsg_DidFail(request_id, result));
  }
  // For ResolveURL we do not create a new operation, so no unregister here.
}

void FileAPIMessageFilter::DidDeleteFileSystem(
    int request_id,
    base::PlatformFileError result) {
  if (result == base::PLATFORM_FILE_OK)
    Send(new FileSystemMsg_DidSucceed(request_id));
  else
    Send(new FileSystemMsg_DidFail(request_id, result));
  // For DeleteFileSystem we do not create a new operation,
  // so no unregister here.
}

void FileAPIMessageFilter::DidCreateSnapshot(
    int request_id,
    const fileapi::FileSystemURL& url,
    base::PlatformFileError result,
    const base::PlatformFileInfo& info,
    const base::FilePath& platform_path,
    const scoped_refptr<webkit_blob::ShareableFileReference>& /* unused */) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  operations_.erase(request_id);

  if (result != base::PLATFORM_FILE_OK) {
    Send(new FileSystemMsg_DidFail(request_id, result));
    return;
  }

  scoped_refptr<webkit_blob::ShareableFileReference> file_ref =
      webkit_blob::ShareableFileReference::Get(platform_path);
  if (!security_policy_->CanReadFile(process_id_, platform_path)) {
    // Give per-file read permission to the snapshot file if it hasn't it yet.
    // In order for the renderer to be able to read the file via File object,
    // it must be granted per-file read permission for the file's platform
    // path. By now, it has already been verified that the renderer has
    // sufficient permissions to read the file, so giving per-file permission
    // here must be safe.
    security_policy_->GrantReadFile(process_id_, platform_path);

    // Revoke all permissions for the file when the last ref of the file
    // is dropped.
    if (!file_ref.get()) {
      // Create a reference for temporary permission handling.
      file_ref = webkit_blob::ShareableFileReference::GetOrCreate(
          platform_path,
          webkit_blob::ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
          context_->default_file_task_runner());
    }
    file_ref->AddFinalReleaseCallback(
        base::Bind(&RevokeFilePermission, process_id_));
  }

  if (file_ref.get()) {
    // This ref is held until OnDidReceiveSnapshotFile is called.
    in_transit_snapshot_files_[request_id] = file_ref;
  }

  // Return the file info and platform_path.
  Send(new FileSystemMsg_DidCreateSnapshotFile(
               request_id, info, platform_path));
}

bool FileAPIMessageFilter::ValidateFileSystemURL(
    int request_id, const fileapi::FileSystemURL& url) {
  if (FileSystemURLIsValid(context_, url))
    return true;
  Send(new FileSystemMsg_DidFail(request_id,
                                 base::PLATFORM_FILE_ERROR_INVALID_URL));
  return false;
}

scoped_refptr<Stream> FileAPIMessageFilter::GetStreamForURL(const GURL& url) {
  return stream_context_->registry()->GetStream(url);
}

}  // namespace content
