root/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_factory_
  2. GetFileSystemURL
  3. GetExternalFilePath
  4. GetFileSystemContext
  5. DidFinish
  6. MakeDirectory
  7. Touch
  8. Delete
  9. Rename
  10. Query
  11. GetMetadataComplete
  12. ReadDirectoryEntries
  13. ReadDirectoryComplete
  14. GetAbsolutePath
  15. CanRead
  16. CanWrite
  17. CanCreate
  18. CanReadWrite

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

#include "content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h"

#include <string>

#include "base/callback.h"
#include "base/file_util.h"
#include "base/files/file_util_proxy.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/escape.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_file_info.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/ppb_file_ref.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/shared_impl/file_ref_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
#include "ppapi/shared_impl/time_conversion.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_file_ref_api.h"
#include "ppapi/thunk/ppb_file_system_api.h"
#include "webkit/browser/fileapi/file_system_operation.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/common/fileapi/file_system_util.h"

using ppapi::host::PpapiHost;
using ppapi::host::ResourceHost;

namespace content {

PepperInternalFileRefBackend::PepperInternalFileRefBackend(
    PpapiHost* host,
    int render_process_id,
    base::WeakPtr<PepperFileSystemBrowserHost> fs_host,
    const std::string& path) : host_(host),
                               render_process_id_(render_process_id),
                               fs_host_(fs_host),
                               fs_type_(fs_host->GetType()),
                               path_(path),
                               weak_factory_(this) {
  ppapi::NormalizeInternalPath(&path_);
}

PepperInternalFileRefBackend::~PepperInternalFileRefBackend() {
}

fileapi::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
  if (!fs_url_.is_valid() && fs_host_.get() && fs_host_->IsOpened()) {
    GURL fs_path = fs_host_->GetRootUrl().Resolve(
        net::EscapePath(path_.substr(1)));
    scoped_refptr<fileapi::FileSystemContext> fs_context =
        GetFileSystemContext();
    if (fs_context.get())
      fs_url_ = fs_context->CrackURL(fs_path);
  }
  return fs_url_;
}

base::FilePath PepperInternalFileRefBackend::GetExternalFilePath() const {
  return base::FilePath();
}

scoped_refptr<fileapi::FileSystemContext>
PepperInternalFileRefBackend::GetFileSystemContext() const {
  if (!fs_host_.get())
    return NULL;
  return fs_host_->GetFileSystemContext();
}

void PepperInternalFileRefBackend::DidFinish(
    ppapi::host::ReplyMessageContext context,
    const IPC::Message& msg,
    base::File::Error error) {
  context.params.set_result(ppapi::FileErrorToPepperError(error));
  host_->SendReply(context, msg);
}

int32_t PepperInternalFileRefBackend::MakeDirectory(
    ppapi::host::ReplyMessageContext reply_context,
    int32_t make_directory_flags) {
  if (!GetFileSystemURL().is_valid())
    return PP_ERROR_FAILED;

  GetFileSystemContext()->operation_runner()->CreateDirectory(
      GetFileSystemURL(),
      !!(make_directory_flags & PP_MAKEDIRECTORYFLAG_EXCLUSIVE),
      !!(make_directory_flags & PP_MAKEDIRECTORYFLAG_WITH_ANCESTORS),
      base::Bind(&PepperInternalFileRefBackend::DidFinish,
                 weak_factory_.GetWeakPtr(),
                 reply_context,
                 PpapiPluginMsg_FileRef_MakeDirectoryReply()));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperInternalFileRefBackend::Touch(
    ppapi::host::ReplyMessageContext reply_context,
    PP_Time last_access_time,
    PP_Time last_modified_time) {
  if (!GetFileSystemURL().is_valid())
    return PP_ERROR_FAILED;

  GetFileSystemContext()->operation_runner()->TouchFile(
      GetFileSystemURL(),
      ppapi::PPTimeToTime(last_access_time),
      ppapi::PPTimeToTime(last_modified_time),
      base::Bind(&PepperInternalFileRefBackend::DidFinish,
                 weak_factory_.GetWeakPtr(),
                 reply_context,
                 PpapiPluginMsg_FileRef_TouchReply()));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperInternalFileRefBackend::Delete(
    ppapi::host::ReplyMessageContext reply_context) {
  if (!GetFileSystemURL().is_valid())
    return PP_ERROR_FAILED;

  GetFileSystemContext()->operation_runner()->Remove(
      GetFileSystemURL(),
      false,
      base::Bind(&PepperInternalFileRefBackend::DidFinish,
                 weak_factory_.GetWeakPtr(),
                 reply_context,
                 PpapiPluginMsg_FileRef_DeleteReply()));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperInternalFileRefBackend::Rename(
    ppapi::host::ReplyMessageContext reply_context,
    PepperFileRefHost* new_file_ref) {
  if (!GetFileSystemURL().is_valid())
    return PP_ERROR_FAILED;

  fileapi::FileSystemURL new_url = new_file_ref->GetFileSystemURL();
  if (!new_url.is_valid())
    return PP_ERROR_FAILED;
  if (!new_url.IsInSameFileSystem(GetFileSystemURL()))
    return PP_ERROR_FAILED;

  GetFileSystemContext()->operation_runner()->Move(
      GetFileSystemURL(),
      new_url,
      fileapi::FileSystemOperation::OPTION_NONE,
      base::Bind(&PepperInternalFileRefBackend::DidFinish,
                 weak_factory_.GetWeakPtr(),
                 reply_context,
                 PpapiPluginMsg_FileRef_RenameReply()));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperInternalFileRefBackend::Query(
    ppapi::host::ReplyMessageContext reply_context) {
  if (!GetFileSystemURL().is_valid())
    return PP_ERROR_FAILED;

  GetFileSystemContext()->operation_runner()->GetMetadata(
      GetFileSystemURL(),
      base::Bind(&PepperInternalFileRefBackend::GetMetadataComplete,
                 weak_factory_.GetWeakPtr(),
                 reply_context));
  return PP_OK_COMPLETIONPENDING;
}

void PepperInternalFileRefBackend::GetMetadataComplete(
    ppapi::host::ReplyMessageContext reply_context,
    base::File::Error error,
    const base::File::Info& file_info) {
  reply_context.params.set_result(ppapi::FileErrorToPepperError(error));

  PP_FileInfo pp_file_info;
  if (error == base::File::FILE_OK)
    ppapi::FileInfoToPepperFileInfo(file_info, fs_type_, &pp_file_info);
  else
    memset(&pp_file_info, 0, sizeof(pp_file_info));

  host_->SendReply(reply_context,
                   PpapiPluginMsg_FileRef_QueryReply(pp_file_info));
}

int32_t PepperInternalFileRefBackend::ReadDirectoryEntries(
    ppapi::host::ReplyMessageContext reply_context) {
  if (!GetFileSystemURL().is_valid())
    return PP_ERROR_FAILED;

  fileapi::FileSystemOperation::FileEntryList* accumulated_file_list
      = new fileapi::FileSystemOperation::FileEntryList;
  GetFileSystemContext()->operation_runner()->ReadDirectory(
      GetFileSystemURL(),
      base::Bind(&PepperInternalFileRefBackend::ReadDirectoryComplete,
                 weak_factory_.GetWeakPtr(),
                 reply_context,
                 base::Owned(accumulated_file_list)));
  return PP_OK_COMPLETIONPENDING;
}

void PepperInternalFileRefBackend::ReadDirectoryComplete(
    ppapi::host::ReplyMessageContext context,
    fileapi::FileSystemOperation::FileEntryList* accumulated_file_list,
    base::File::Error error,
    const fileapi::FileSystemOperation::FileEntryList& file_list,
    bool has_more) {
  accumulated_file_list->insert(accumulated_file_list->end(),
                                file_list.begin(), file_list.end());
  if (has_more)
    return;

  context.params.set_result(ppapi::FileErrorToPepperError(error));

  std::vector<ppapi::FileRefCreateInfo> infos;
  std::vector<PP_FileType> file_types;
  if (error == base::File::FILE_OK && fs_host_.get()) {
    std::string dir_path = path_;
    if (dir_path.empty() || dir_path[dir_path.size() - 1] != '/')
      dir_path += '/';

    for (fileapi::FileSystemOperation::FileEntryList::const_iterator it =
             accumulated_file_list->begin();
         it != accumulated_file_list->end(); ++it) {
      if (it->is_directory)
        file_types.push_back(PP_FILETYPE_DIRECTORY);
      else
        file_types.push_back(PP_FILETYPE_REGULAR);

      ppapi::FileRefCreateInfo info;
      info.file_system_type = fs_type_;
      info.file_system_plugin_resource = fs_host_->pp_resource();
      std::string path =
          dir_path + fileapi::FilePathToString(base::FilePath(it->name));
      info.internal_path = path;
      info.display_name = ppapi::GetNameForInternalFilePath(path);
      infos.push_back(info);
    }
  }

  host_->SendReply(context,
      PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply(infos, file_types));
}

int32_t PepperInternalFileRefBackend::GetAbsolutePath(
    ppapi::host::ReplyMessageContext reply_context) {
  host_->SendReply(reply_context,
      PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperInternalFileRefBackend::CanRead() const {
  fileapi::FileSystemURL url = GetFileSystemURL();
  if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
    return PP_ERROR_FAILED;
  if (!ChildProcessSecurityPolicyImpl::GetInstance()->
          CanReadFileSystemFile(render_process_id_, url)) {
    return PP_ERROR_NOACCESS;
  }
  return PP_OK;
}

int32_t PepperInternalFileRefBackend::CanWrite() const {
  fileapi::FileSystemURL url = GetFileSystemURL();
  if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
    return PP_ERROR_FAILED;
  if (!ChildProcessSecurityPolicyImpl::GetInstance()->
          CanWriteFileSystemFile(render_process_id_, url)) {
    return PP_ERROR_NOACCESS;
  }
  return PP_OK;
}

int32_t PepperInternalFileRefBackend::CanCreate() const {
  fileapi::FileSystemURL url = GetFileSystemURL();
  if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
    return PP_ERROR_FAILED;
  if (!ChildProcessSecurityPolicyImpl::GetInstance()->
          CanCreateFileSystemFile(render_process_id_, url)) {
    return PP_ERROR_NOACCESS;
  }
  return PP_OK;
}

int32_t PepperInternalFileRefBackend::CanReadWrite() const {
  fileapi::FileSystemURL url = GetFileSystemURL();
  if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
    return PP_ERROR_FAILED;
  ChildProcessSecurityPolicyImpl* policy =
      ChildProcessSecurityPolicyImpl::GetInstance();
  if (!policy->CanReadFileSystemFile(render_process_id_, url) ||
      !policy->CanWriteFileSystemFile(render_process_id_, url)) {
    return PP_ERROR_NOACCESS;
  }
  return PP_OK;
}

}  // namespace content

/* [<][>][^][v][top][bottom][index][help] */