12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/files/file.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/child_process_security_policy_impl.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_ppapi_host.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_constants.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_platform_file.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/host/dispatch_host_message.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/host/host_message_context.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/host/ppapi_host.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/file_path.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/file_type_conversion.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool CanRead(int process_id, const base::FilePath& path) {
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(process_id,
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                                                    path);
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CanCreateReadWrite(int process_id, const base::FilePath& path) {
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ChildProcessSecurityPolicyImpl::GetInstance()->CanCreateReadWriteFile(
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      process_id, path);
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PepperFlashFileMessageFilter::PepperFlashFileMessageFilter(
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PP_Instance instance,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserPpapiHost* host)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : plugin_process_handle_(host->GetPluginProcessHandle()) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int unused;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host->GetRenderFrameIDsForInstance(instance, &render_process_id_, &unused);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath profile_data_directory = host->GetProfileDataDirectory();
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string plugin_name = host->GetPluginName();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_data_directory.empty() || plugin_name.empty()) {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // These are used to construct the path. If they are not set it means we
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // will construct a bad path and could provide access to the wrong files.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // In this case, |plugin_data_directory_| will remain unset and
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |ValidateAndConvertPepperFilePath| will fail.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    plugin_data_directory_ = GetDataDirName(profile_data_directory).Append(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::FilePath::FromUTF8Unsafe(plugin_name));
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
63a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochPepperFlashFileMessageFilter::~PepperFlashFileMessageFilter() {}
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath PepperFlashFileMessageFilter::GetDataDirName(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& profile_path) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return profile_path.Append(kPepperDataDirname);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<base::TaskRunner>
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PepperFlashFileMessageFilter::OverrideTaskRunnerForMessage(
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const IPC::Message& msg) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The blocking pool provides a pool of threads to run file
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // operations, instead of a single thread which might require
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // queuing time.  Since these messages are synchronous as sent from
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the plugin, the sending thread cannot send a new message until
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this one returns, so there is no need to sequence tasks here.  If
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the plugin has multiple threads, it cannot make assumptions about
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ordering of IPC message sends, so it cannot make assumptions
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // about ordering of operations caused by those IPC messages.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return scoped_refptr<base::TaskRunner>(BrowserThread::GetBlockingPool());
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnResourceMessageReceived(
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const IPC::Message& msg,
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ppapi::host::HostMessageContext* context) {
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(PepperFlashFileMessageFilter, msg)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashFile_OpenFile,
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnOpenFile)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashFile_RenameFile,
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnRenameFile)
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashFile_DeleteFileOrDir,
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnDeleteFileOrDir)
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashFile_CreateDir,
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnCreateDir)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashFile_QueryFile,
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnQueryFile)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashFile_GetDirContents,
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnGetDirContents)
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        PpapiHostMsg_FlashFile_CreateTemporaryFile, OnCreateTemporaryFile)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_ERROR_FAILED;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnOpenFile(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& path,
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int pp_open_flags) {
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::FilePath full_path = ValidateAndConvertPepperFilePath(
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      path, base::Bind(&CanOpenWithPepperFlags, pp_open_flags));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (full_path.empty()) {
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int platform_file_flags = 0;
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(pp_open_flags,
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                                     &platform_file_flags)) {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::File::FILE_ERROR_FAILED;
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::File file(full_path, platform_file_flags);
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!file.IsValid()) {
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return ppapi::FileErrorToPepperError(file.error_details());
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure we didn't try to open a directory: directory fd shouldn't be
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // passed to untrusted processes because they open security holes.
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::File::Info info;
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!file.GetInfo(&info) || info.is_directory) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // When in doubt, throw it out.
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  IPC::PlatformFileForTransit transit_file =
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      IPC::TakeFileHandleForProcess(file.Pass(), plugin_process_handle_);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context =
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      context->MakeReplyMessageContext();
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  reply_context.params.AppendHandle(ppapi::proxy::SerializedHandle(
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ppapi::proxy::SerializedHandle::FILE, transit_file));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendReply(reply_context, IPC::Message());
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnRenameFile(
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& from_path,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& to_path) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath from_full_path = ValidateAndConvertPepperFilePath(
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      from_path, base::Bind(&CanCreateReadWrite));
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath to_full_path = ValidateAndConvertPepperFilePath(
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      to_path, base::Bind(&CanCreateReadWrite));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (from_full_path.empty() || to_full_path.empty()) {
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool result = base::Move(from_full_path, to_full_path);
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ppapi::FileErrorToPepperError(
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      result ? base::File::FILE_OK : base::File::FILE_ERROR_ACCESS_DENIED);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnDeleteFileOrDir(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& path,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool recursive) {
167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FilePath full_path =
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ValidateAndConvertPepperFilePath(path, base::Bind(&CanCreateReadWrite));
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (full_path.empty()) {
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool result = base::DeleteFile(full_path, recursive);
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ppapi::FileErrorToPepperError(
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      result ? base::File::FILE_OK : base::File::FILE_ERROR_ACCESS_DENIED);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnCreateDir(
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& path) {
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FilePath full_path =
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ValidateAndConvertPepperFilePath(path, base::Bind(&CanCreateReadWrite));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (full_path.empty()) {
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool result = base::CreateDirectory(full_path);
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ppapi::FileErrorToPepperError(
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      result ? base::File::FILE_OK : base::File::FILE_ERROR_ACCESS_DENIED);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnQueryFile(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& path) {
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FilePath full_path =
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ValidateAndConvertPepperFilePath(path, base::Bind(&CanRead));
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (full_path.empty()) {
197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Info info;
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool result = base::GetFileInfo(full_path, &info);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context->reply_msg = PpapiPluginMsg_FlashFile_QueryFileReply(info);
203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ppapi::FileErrorToPepperError(
204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      result ? base::File::FILE_OK : base::File::FILE_ERROR_ACCESS_DENIED);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnGetDirContents(
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& path) {
210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FilePath full_path =
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ValidateAndConvertPepperFilePath(path, base::Bind(&CanRead));
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (full_path.empty()) {
213a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi::DirContents contents;
217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FileEnumerator enumerator(full_path,
218a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                  false,
219a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                  base::FileEnumerator::FILES |
220a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      base::FileEnumerator::DIRECTORIES |
221a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      base::FileEnumerator::INCLUDE_DOT_DOT);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!enumerator.Next().empty()) {
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FileEnumerator::FileInfo info = enumerator.GetInfo();
225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ppapi::DirEntry entry = {info.GetName(), info.IsDirectory()};
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    contents.push_back(entry);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context->reply_msg = PpapiPluginMsg_FlashFile_GetDirContentsReply(contents);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t PepperFlashFileMessageFilter::OnCreateTemporaryFile(
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context) {
235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ppapi::PepperFilePath dir_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                 base::FilePath());
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath validated_dir_path = ValidateAndConvertPepperFilePath(
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      dir_path, base::Bind(&CanCreateReadWrite));
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (validated_dir_path.empty() ||
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      (!base::DirectoryExists(validated_dir_path) &&
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       !base::CreateDirectory(validated_dir_path))) {
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_ACCESS_DENIED);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file_path;
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::CreateTemporaryFileInDir(validated_dir_path, &file_path)) {
247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return ppapi::FileErrorToPepperError(base::File::FILE_ERROR_FAILED);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::File file(file_path,
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ |
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      base::File::FLAG_DELETE_ON_CLOSE);
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!file.IsValid())
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return ppapi::FileErrorToPepperError(file.error_details());
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  IPC::PlatformFileForTransit transit_file =
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      IPC::TakeFileHandleForProcess(file.Pass(), plugin_process_handle_);
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context =
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      context->MakeReplyMessageContext();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  reply_context.params.AppendHandle(ppapi::proxy::SerializedHandle(
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ppapi::proxy::SerializedHandle::FILE, transit_file));
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendReply(reply_context, IPC::Message());
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath PepperFlashFileMessageFilter::ValidateAndConvertPepperFilePath(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::PepperFilePath& pepper_path,
270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const CheckPermissionsCallback& check_permissions_callback) const {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file_path;  // Empty path returned on error.
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (pepper_path.domain()) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ppapi::PepperFilePath::DOMAIN_ABSOLUTE:
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (pepper_path.path().IsAbsolute() &&
275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          check_permissions_callback.Run(render_process_id_,
276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         pepper_path.path()))
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_path = pepper_path.path();
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL:
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // This filter provides the module name portion of the path to prevent
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // plugins from accessing each other's data.
282a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      if (!plugin_data_directory_.empty() && !pepper_path.path().IsAbsolute() &&
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !pepper_path.path().ReferencesParent())
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_path = plugin_data_directory_.Append(pepper_path.path());
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return file_path;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
294