summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-01 20:37:21 +0000
committercsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-01 20:37:21 +0000
commit12e9913cd1d7c2c4b3aa49ed006b33b1b1fa5515 (patch)
tree33135f3eb6a4176210de966c4f31f7e81dfec509 /content
parentef452a2612cc3d1567fb54c2ac444cbaf8adcd5f (diff)
downloadchromium_src-12e9913cd1d7c2c4b3aa49ed006b33b1b1fa5515.zip
chromium_src-12e9913cd1d7c2c4b3aa49ed006b33b1b1fa5515.tar.gz
chromium_src-12e9913cd1d7c2c4b3aa49ed006b33b1b1fa5515.tar.bz2
Revert 232440 "Pepper: Move FileIO host from renderer to browser."
Broke the Linux ASAN Test (2) bot. > Pepper: Move FileIO host from renderer to browser. > > This change is large because it moves QuotaFileIO and PepperFileIOHost all at > once to the browser process. Some code in the refactored PepperFileIOHost is > moved from what's provided in FileAPIMessageFilter. > > Tested locally with Bastion, From Dust, and Angry Bots. > > TBR=jschuh > BUG=246396 > > Review URL: https://codereview.chromium.org/33053002 TBR=teravest@chromium.org Review URL: https://codereview.chromium.org/51213008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232460 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/fileapi/fileapi_message_filter.cc133
-rw-r--r--content/browser/fileapi/fileapi_message_filter.h18
-rw-r--r--content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc5
-rw-r--r--content/browser/renderer_host/pepper/pepper_file_io_host.cc592
-rw-r--r--content/browser/renderer_host/pepper/pepper_file_ref_host.cc11
-rw-r--r--content/browser/renderer_host/pepper/pepper_file_ref_host.h1
-rw-r--r--content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc8
-rw-r--r--content/browser/renderer_host/render_message_filter.cc30
-rw-r--r--content/browser/renderer_host/render_message_filter.h3
-rw-r--r--content/child/fileapi/file_system_dispatcher.cc17
-rw-r--r--content/child/fileapi/file_system_dispatcher.h10
-rw-r--r--content/common/fileapi/file_system_messages.h18
-rw-r--r--content/common/view_messages.h12
-rw-r--r--content/content_browser.gypi4
-rw-r--r--content/content_renderer.gypi4
-rw-r--r--content/content_tests.gypi2
-rw-r--r--content/public/renderer/content_renderer_client.cc5
-rw-r--r--content/public/renderer/content_renderer_client.h6
-rw-r--r--content/renderer/pepper/content_renderer_pepper_host_factory.cc4
-rw-r--r--content/renderer/pepper/pepper_file_io_host.cc493
-rw-r--r--content/renderer/pepper/pepper_file_io_host.h (renamed from content/browser/renderer_host/pepper/pepper_file_io_host.h)81
-rw-r--r--content/renderer/pepper/quota_file_io.cc (renamed from content/browser/renderer_host/pepper/quota_file_io.cc)4
-rw-r--r--content/renderer/pepper/quota_file_io.h (renamed from content/browser/renderer_host/pepper/quota_file_io.h)8
-rw-r--r--content/renderer/pepper/quota_file_io_unittest.cc (renamed from content/browser/renderer_host/pepper/quota_file_io_unittest.cc)4
24 files changed, 810 insertions, 663 deletions
diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc
index 20607d3..99439b7 100644
--- a/content/browser/fileapi/fileapi_message_filter.cc
+++ b/content/browser/fileapi/fileapi_message_filter.cc
@@ -34,6 +34,7 @@
#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"
@@ -41,10 +42,17 @@
#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;
@@ -126,6 +134,22 @@ void FileAPIMessageFilter::OnChannelClosing() {
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();
}
@@ -156,10 +180,16 @@ bool FileAPIMessageFilter::OnMessageReceived(
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)
@@ -466,6 +496,84 @@ void FileAPIMessageFilter::OnCancel(
}
}
+#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);
@@ -707,6 +815,31 @@ void FileAPIMessageFilter::DidReadDirectory(
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,
diff --git a/content/browser/fileapi/fileapi_message_filter.h b/content/browser/fileapi/fileapi_message_filter.h
index d734e85..85e2ad2 100644
--- a/content/browser/fileapi/fileapi_message_filter.h
+++ b/content/browser/fileapi/fileapi_message_filter.h
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/files/file_util_proxy.h"
+#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "base/platform_file.h"
@@ -121,6 +122,12 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const base::Time& last_access_time,
const base::Time& last_modified_time);
void OnCancel(int request_id, int request_to_cancel);
+#if defined(ENABLE_PLUGINS)
+ void OnOpenPepperFile(int request_id, const GURL& path, int pp_open_flags);
+#endif // defined(ENABLE_PLUGINS)
+ void OnNotifyCloseFile(int file_open_id);
+ void OnWillUpdate(const GURL& path);
+ void OnDidUpdate(const GURL& path, int64 delta);
void OnSyncGetPlatformPath(const GURL& path,
base::FilePath* platform_path);
void OnCreateSnapshotFile(int request_id,
@@ -171,6 +178,12 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
base::PlatformFileError result,
const std::vector<fileapi::DirectoryEntry>& entries,
bool has_more);
+ void DidOpenFile(int request_id,
+ quota::QuotaLimitType quota_policy,
+ base::PlatformFileError result,
+ base::PlatformFile file,
+ const base::Closure& on_close_callback,
+ base::ProcessHandle peer_handle);
void DidWrite(int request_id,
base::PlatformFileError result,
int64 bytes,
@@ -239,6 +252,11 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
std::map<int, scoped_refptr<webkit_blob::ShareableFileReference> >
in_transit_snapshot_files_;
+ // Keep track of file system file opened by OpenFile() in this process.
+ // Need to close all of them when the renderer process dies.
+ typedef IDMap<base::Closure, IDMapOwnPointer> OnCloseCallbackMap;
+ OnCloseCallbackMap on_close_callbacks_;
+
DISALLOW_COPY_AND_ASSIGN(FileAPIMessageFilter);
};
diff --git a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
index afa5396..39e778d 100644
--- a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
+++ b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -6,7 +6,6 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h"
-#include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
@@ -68,10 +67,6 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
// Public interfaces.
switch (message.type()) {
- case PpapiHostMsg_FileIO_Create::ID: {
- return scoped_ptr<ResourceHost>(new PepperFileIOHost(
- host_, instance, params.pp_resource()));
- }
case PpapiHostMsg_FileSystem_Create::ID: {
PP_FileSystemType file_system_type;
if (!ppapi::UnpackMessage<PpapiHostMsg_FileSystem_Create>(message,
diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
deleted file mode 100644
index c95fdf6..0000000
--- a/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ /dev/null
@@ -1,592 +0,0 @@
-// 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_file_io_host.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/files/file_util_proxy.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
-#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
-#include "content/browser/renderer_host/pepper/quota_file_io.h"
-#include "content/common/fileapi/file_system_messages.h"
-#include "content/common/sandbox_util.h"
-#include "content/common/view_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/common/content_client.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/ppb_file_io.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_type_conversion.h"
-#include "ppapi/shared_impl/time_conversion.h"
-#include "webkit/browser/fileapi/file_observers.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-namespace content {
-
-using ppapi::FileIOStateManager;
-using ppapi::PPTimeToTime;
-
-namespace {
-
-int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
- // On the plugin side, some callbacks expect a parameter that means different
- // things depending on whether it is negative or not. We translate for those
- // callbacks here.
- return pp_error == PP_OK ? byte_number : pp_error;
-}
-
-class QuotaFileIODelegate : public QuotaFileIO::Delegate {
- public:
- QuotaFileIODelegate(scoped_refptr<fileapi::FileSystemContext> context,
- int render_process_id)
- : context_(context),
- weak_factory_(this) { }
- virtual ~QuotaFileIODelegate() {}
-
- virtual void QueryAvailableSpace(
- const GURL& origin,
- quota::StorageType type,
- const AvailableSpaceCallback& callback) OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- quota::QuotaManagerProxy* quota_manager_proxy =
- context_->quota_manager_proxy();
- DCHECK(quota_manager_proxy);
- if (!quota_manager_proxy) {
- callback.Run(0);
- return;
- }
- quota::QuotaManager* qm = quota_manager_proxy->quota_manager();
- DCHECK(qm);
- if (!qm) {
- callback.Run(0);
- return;
- }
- qm->GetUsageAndQuotaForWebApps(
- origin,
- type,
- base::Bind(&QuotaFileIODelegate::GotUsageAndQuotaForWebApps,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void GotUsageAndQuotaForWebApps(const AvailableSpaceCallback& callback,
- quota::QuotaStatusCode code,
- int64 usage,
- int64 quota) {
- if (code == quota::kQuotaStatusOk)
- callback.Run(std::max(static_cast<int64>(0), quota - usage));
- else
- callback.Run(0);
- }
-
- virtual void WillUpdateFile(const GURL& file_path) OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- fileapi::FileSystemURL url(context_->CrackURL(file_path));
- if (!url.is_valid())
- return;
- const fileapi::UpdateObserverList* observers =
- context_->GetUpdateObservers(url.type());
- if (!observers)
- return;
- observers->Notify(&fileapi::FileUpdateObserver::OnStartUpdate,
- MakeTuple(url));
- }
- virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- fileapi::FileSystemURL url(context_->CrackURL(file_path));
- if (!url.is_valid())
- return;
- const fileapi::UpdateObserverList* observers =
- context_->GetUpdateObservers(url.type());
- if (!observers)
- return;
- observers->Notify(&fileapi::FileUpdateObserver::OnUpdate,
- MakeTuple(url, delta));
- observers->Notify(&fileapi::FileUpdateObserver::OnEndUpdate,
- MakeTuple(url));
- }
- virtual scoped_refptr<base::MessageLoopProxy>
- GetFileThreadMessageLoopProxy() OVERRIDE {
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE);
- }
- private:
- scoped_refptr<fileapi::FileSystemContext> context_;
- base::WeakPtrFactory<QuotaFileIODelegate> weak_factory_;
-};
-
-bool GetUIThreadStuffForInternalFileSystems(
- int render_process_id,
- base::ProcessId* resolved_render_process_id,
- scoped_refptr<fileapi::FileSystemContext>* file_system_context) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
- if (!host)
- return false;
- *resolved_render_process_id = base::GetProcId(host->GetHandle());
- StoragePartition* storage_partition = host->GetStoragePartition();
- if (!storage_partition)
- return false;
- *file_system_context = storage_partition->GetFileSystemContext();
- return true;
-}
-
-base::ProcessId GetResolvedRenderProcessId(int render_process_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
- if (!host)
- return base::kNullProcessId;
- return base::GetProcId(host->GetHandle());
-}
-
-bool GetPluginAllowedToCallRequestOSFileHandle(int render_process_id,
- const GURL& document_url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ContentBrowserClient* client = GetContentClient()->browser();
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
- return client->IsPluginAllowedToCallRequestOSFileHandle(
- host->GetBrowserContext(), document_url);
-}
-
-} // namespace
-
-PepperFileIOHost::PepperFileIOHost(BrowserPpapiHostImpl* host,
- PP_Instance instance,
- PP_Resource resource)
- : ResourceHost(host->GetPpapiHost(), instance, resource),
- browser_ppapi_host_(host),
- render_process_host_(NULL),
- file_(base::kInvalidPlatformFileValue),
- file_system_type_(PP_FILESYSTEMTYPE_INVALID),
- quota_policy_(quota::kQuotaLimitTypeUnknown),
- open_flags_(0),
- weak_factory_(this) {
- int unused;
- if (!host->GetRenderViewIDsForInstance(instance,
- &render_process_id_,
- &unused)) {
- render_process_id_ = -1;
- }
- file_message_loop_ = BrowserThread::GetMessageLoopProxyForThread(
- BrowserThread::FILE);
-}
-
-PepperFileIOHost::~PepperFileIOHost() {
- OnHostMsgClose(NULL);
-}
-
-int32_t PepperFileIOHost::OnResourceMessageReceived(
- const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) {
- IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
- OnHostMsgOpen)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
- OnHostMsgTouch)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
- OnHostMsgWrite)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
- OnHostMsgSetLength)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
- OnHostMsgFlush)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close,
- OnHostMsgClose)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle,
- OnHostMsgRequestOSFileHandle)
- IPC_END_MESSAGE_MAP()
- return PP_ERROR_FAILED;
-}
-
-int32_t PepperFileIOHost::OnHostMsgOpen(
- ppapi::host::HostMessageContext* context,
- PP_Resource file_ref_resource,
- int32_t open_flags) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, false);
- if (rv != PP_OK)
- return rv;
-
- int platform_file_flags = 0;
- if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
- &platform_file_flags))
- return PP_ERROR_BADARGUMENT;
-
- ppapi::host::ResourceHost* resource_host =
- host()->GetResourceHost(file_ref_resource);
- if (!resource_host || !resource_host->IsFileRefHost())
- return PP_ERROR_BADRESOURCE;
- PepperFileRefHost* file_ref_host =
- static_cast<PepperFileRefHost*>(resource_host);
- if (file_ref_host->GetFileSystemType() == PP_FILESYSTEMTYPE_INVALID)
- return PP_ERROR_FAILED;
-
- open_flags_ = open_flags;
- file_system_type_ = file_ref_host->GetFileSystemType();
- file_system_url_ = file_ref_host->GetFileSystemURL();
-
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
- if (!file_system_url_.is_valid())
- return PP_ERROR_BADARGUMENT;
- if (!CanOpenFileSystemURLWithPepperFlags(open_flags,
- render_process_id_,
- file_system_url_))
- return PP_ERROR_NOACCESS;
-
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&GetUIThreadStuffForInternalFileSystems,
- render_process_id_,
- &resolved_render_process_id_,
- &file_system_context_),
- base::Bind(&PepperFileIOHost::GotUIThreadStuffForInternalFileSystems,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext(),
- platform_file_flags));
- } else {
- base::FilePath path = file_ref_host->GetExternalFilePath();
- if (!CanOpenWithPepperFlags(open_flags, render_process_id_, path))
- return PP_ERROR_NOACCESS;
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&GetResolvedRenderProcessId, render_process_id_),
- base::Bind(&PepperFileIOHost::GotResolvedRenderProcessId,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext(),
- path,
- platform_file_flags));
- }
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-void PepperFileIOHost::GotUIThreadStuffForInternalFileSystems(
- ppapi::host::ReplyMessageContext reply_context,
- int platform_file_flags,
- bool ok) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!ok || !file_system_context_.get()) {
- reply_context.params.set_result(PP_ERROR_FAILED);
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
- return;
- }
-
- if (!file_system_context_->GetFileSystemBackend(file_system_url_.type())) {
- reply_context.params.set_result(PP_ERROR_FAILED);
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
- return;
- }
- quota_policy_ = quota::kQuotaLimitTypeUnknown;
- quota::QuotaManagerProxy* quota_manager_proxy =
- file_system_context_->quota_manager_proxy();
- CHECK(quota_manager_proxy);
- CHECK(quota_manager_proxy->quota_manager());
- if (quota_manager_proxy->quota_manager()->IsStorageUnlimited(
- file_system_url_.origin(),
- fileapi::FileSystemTypeToQuotaStorageType(file_system_url_.type())))
- quota_policy_ = quota::kQuotaLimitTypeUnlimited;
- else
- quota_policy_ = quota::kQuotaLimitTypeLimited;
- file_system_operation_runner_ =
- file_system_context_->CreateFileSystemOperationRunner();
- file_system_operation_runner_->OpenFile(
- file_system_url_,
- platform_file_flags,
- base::Bind(&PepperFileIOHost::DidOpenInternalFile,
- weak_factory_.GetWeakPtr(),
- reply_context));
-}
-
-void PepperFileIOHost::DidOpenInternalFile(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError result,
- base::PlatformFile file,
- const base::Closure& on_close_callback) {
- if (result == base::PLATFORM_FILE_OK)
- on_close_callback_ = on_close_callback;
- ExecutePlatformOpenFileCallback(
- reply_context, result, base::PassPlatformFile(&file), true);
-}
-
-void PepperFileIOHost::GotResolvedRenderProcessId(
- ppapi::host::ReplyMessageContext reply_context,
- base::FilePath path,
- int platform_file_flags,
- base::ProcessId resolved_render_process_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- resolved_render_process_id_ = resolved_render_process_id;
- base::FileUtilProxy::CreateOrOpen(
- file_message_loop_,
- path,
- platform_file_flags,
- base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
- weak_factory_.GetWeakPtr(),
- reply_context));
-}
-
-int32_t PepperFileIOHost::OnHostMsgTouch(
- ppapi::host::HostMessageContext* context,
- PP_Time last_access_time,
- PP_Time last_modified_time) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- base::FileUtilProxy::StatusCallback cb =
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext());
-
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
- // We use FileSystemOperationRunner here instead of working on the
- // opened file because it may not have been opened with enough
- // permissions for this operation. See http://crbug.com/313426 for
- // details.
- file_system_operation_runner_->TouchFile(
- file_system_url_,
- PPTimeToTime(last_access_time),
- PPTimeToTime(last_modified_time),
- cb);
- } else {
- if (!base::FileUtilProxy::Touch(
- file_message_loop_,
- file_,
- PPTimeToTime(last_access_time),
- PPTimeToTime(last_modified_time),
- cb))
- return PP_ERROR_FAILED;
- }
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgWrite(
- ppapi::host::HostMessageContext* context,
- int64_t offset,
- const std::string& buffer) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_WRITE, true);
- if (rv != PP_OK)
- return rv;
-
- QuotaFileIO::WriteCallback cb =
- base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext());
-
- if (quota_file_io_) {
- if (!quota_file_io_->Write(offset, buffer.c_str(), buffer.size(), cb))
- return PP_ERROR_FAILED;
- } else {
- if (!base::FileUtilProxy::Write(
- file_message_loop_,
- file_,
- offset,
- buffer.c_str(),
- buffer.size(),
- cb))
- return PP_ERROR_FAILED;
- }
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgSetLength(
- ppapi::host::HostMessageContext* context,
- int64_t length) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- base::FileUtilProxy::StatusCallback cb =
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext());
-
- // TODO(teravest): Use QuotaFileIO::SetLength here.
- // The previous implementation did not use it in the renderer, so I'll
- // do it in a follow-up change.
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
- // We use FileSystemOperationRunner here instead of working on the
- // opened file because it may not have been opened with enough
- // permissions for this operation. See http://crbug.com/313426 for
- // details.
- file_system_operation_runner_->Truncate(file_system_url_, length, cb);
- } else {
- if (!base::FileUtilProxy::Truncate(file_message_loop_, file_, length, cb))
- return PP_ERROR_FAILED;
- }
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgFlush(
- ppapi::host::HostMessageContext* context) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (!base::FileUtilProxy::Flush(
- file_message_loop_,
- file_,
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgClose(
- ppapi::host::HostMessageContext* context) {
- if (file_ != base::kInvalidPlatformFileValue) {
- base::FileUtilProxy::Close(
- file_message_loop_,
- file_,
- base::Bind(&PepperFileIOHost::DidCloseFile,
- weak_factory_.GetWeakPtr()));
- file_ = base::kInvalidPlatformFileValue;
- quota_file_io_.reset();
- }
- return PP_OK;
-}
-
-void PepperFileIOHost::DidCloseFile(base::PlatformFileError error) {
- // Silently ignore if we fail to close the file.
- if (!on_close_callback_.is_null()) {
- on_close_callback_.Run();
- on_close_callback_.Reset();
- }
-}
-
-int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
- ppapi::host::HostMessageContext* context) {
- if (open_flags_ != PP_FILEOPENFLAG_READ &&
- quota_policy_ != quota::kQuotaLimitTypeUnlimited)
- return PP_ERROR_FAILED;
-
- GURL document_url =
- browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&GetPluginAllowedToCallRequestOSFileHandle,
- render_process_id_,
- document_url),
- base::Bind(&PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext()));
- return PP_OK_COMPLETIONPENDING;
-}
-
-void PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle(
- ppapi::host::ReplyMessageContext reply_context,
- bool plugin_allowed) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!browser_ppapi_host_->external_plugin() ||
- host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE) ||
- plugin_allowed) {
- if (!AddFileToReplyContext(open_flags_, &reply_context))
- reply_context.params.set_result(PP_ERROR_FAILED);
- } else {
- reply_context.params.set_result(PP_ERROR_NOACCESS);
- }
- host()->SendReply(reply_context,
- PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
-}
-
-void PepperFileIOHost::ExecutePlatformGeneralCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code) {
- reply_context.params.set_result(
- ppapi::PlatformFileErrorToPepperError(error_code));
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
- state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformOpenFileCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- base::PassPlatformFile file,
- bool unused_created) {
- int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
- if (pp_error == PP_OK)
- state_manager_.SetOpenSucceed();
-
- DCHECK(file_ == base::kInvalidPlatformFileValue);
- file_ = file.ReleaseValue();
-
- DCHECK(!quota_file_io_.get());
- if (file_ != base::kInvalidPlatformFileValue) {
- if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
- file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) {
- quota_file_io_.reset(new QuotaFileIO(
- new QuotaFileIODelegate(file_system_context_, render_process_id_),
- file_, file_system_url_.ToGURL(), file_system_type_));
- }
- int32_t flags_to_send = open_flags_;
- if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) {
- // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
- // the plugin can't write and so bypass our quota checks.
- flags_to_send =
- open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
- }
- if (!AddFileToReplyContext(flags_to_send, &reply_context))
- pp_error = PP_ERROR_FAILED;
- }
- reply_context.params.set_result(pp_error);
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
- state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformWriteCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- int bytes_written) {
- // On the plugin side, the callback expects a parameter with different meaning
- // depends on whether is negative or not. It is the result here. We translate
- // for the callback.
- int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
- reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
- state_manager_.SetOperationFinished();
-}
-
-bool PepperFileIOHost::AddFileToReplyContext(
- int32_t open_flags,
- ppapi::host::ReplyMessageContext* reply_context) const {
- base::ProcessId plugin_process_id;
- if (browser_ppapi_host_->in_process()) {
- plugin_process_id = resolved_render_process_id_;
- } else {
- plugin_process_id = base::GetProcId(
- browser_ppapi_host_->GetPluginProcessHandle());
- }
- IPC::PlatformFileForTransit transit_file = BrokerGetFileHandleForProcess(
- file_, plugin_process_id, false);
- if (transit_file == IPC::InvalidPlatformFileForTransit())
- return false;
- ppapi::proxy::SerializedHandle file_handle;
- file_handle.set_file_handle(transit_file, open_flags);
- reply_context->params.AppendHandle(file_handle);
- return true;
-}
-
-} // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_file_ref_host.cc b/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
index 2f27521..f0fbbd1 100644
--- a/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
@@ -53,14 +53,15 @@ PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
return;
}
- if (!fs_resource_host->IsFileSystemHost()) {
+ PepperFileSystemBrowserHost* fs_host = NULL;
+ if (fs_resource_host->IsFileSystemHost())
+ fs_host = static_cast<PepperFileSystemBrowserHost*>(fs_resource_host);
+ if (fs_host == NULL) {
DLOG(ERROR) << "Filesystem PP_Resource is not PepperFileSystemBrowserHost";
return;
}
- PepperFileSystemBrowserHost* file_system_host =
- static_cast<PepperFileSystemBrowserHost*>(fs_resource_host);
- fs_type_ = file_system_host->GetType();
+ fs_type_ = fs_host->GetType();
if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
(fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY) &&
(fs_type_ != PP_FILESYSTEMTYPE_ISOLATED)) {
@@ -71,7 +72,7 @@ PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
backend_.reset(new PepperInternalFileRefBackend(
host->GetPpapiHost(),
render_process_id,
- file_system_host->AsWeakPtr(),
+ base::AsWeakPtr(fs_host),
path));
}
diff --git a/content/browser/renderer_host/pepper/pepper_file_ref_host.h b/content/browser/renderer_host/pepper/pepper_file_ref_host.h
index 2ef43a7..c0c8ece 100644
--- a/content/browser/renderer_host/pepper/pepper_file_ref_host.h
+++ b/content/browser/renderer_host/pepper/pepper_file_ref_host.h
@@ -18,6 +18,7 @@
#include "webkit/browser/fileapi/file_system_url.h"
namespace content {
+
class PepperFileRefHost;
// Internal and external filesystems have very different codepaths for
diff --git a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index 02692b9..923ee684 100644
--- a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -26,10 +26,12 @@ namespace {
scoped_refptr<fileapi::FileSystemContext>
GetFileSystemContextFromRenderId(int render_process_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
- if (!host)
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id);
+ if (!render_process_host)
return NULL;
- StoragePartition* storage_partition = host->GetStoragePartition();
+ StoragePartition* storage_partition =
+ render_process_host->GetStoragePartition();
if (!storage_partition)
return NULL;
return storage_partition->GetFileSystemContext();
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 0906f66..f926ff6 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -389,6 +389,7 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnDidDeleteOutOfProcessPepperInstance)
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
OnOpenChannelToPpapiBroker)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenPepperFile, OnAsyncOpenPepperFile)
#endif
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
render_widget_helper_->DidReceiveBackingStoreMsg(message))
@@ -439,6 +440,8 @@ base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
return audio_manager_->GetMessageLoop().get();
#endif
+ if (message.type() == ViewHostMsg_AsyncOpenPepperFile::ID)
+ return BrowserThread::GetBlockingPool();
return NULL;
}
@@ -985,6 +988,33 @@ void RenderMessageFilter::OnKeygenOnWorkerThread(
Send(reply_msg);
}
+void RenderMessageFilter::OnAsyncOpenPepperFile(int routing_id,
+ const base::FilePath& path,
+ int pp_open_flags) {
+ int platform_file_flags = 0;
+ if (!CanOpenWithPepperFlags(pp_open_flags, render_process_id_, path) ||
+ !ppapi::PepperFileOpenFlagsToPlatformFileFlags(
+ pp_open_flags, &platform_file_flags)) {
+ DLOG(ERROR) <<
+ "Bad pp_open_flags in ViewMsgHost_AsyncOpenPepperFile message: " <<
+ pp_open_flags;
+ RecordAction(UserMetricsAction("BadMessageTerminate_AOF"));
+ BadMessageReceived();
+ return;
+ }
+
+ base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
+ base::PlatformFile file = base::CreatePlatformFile(
+ path, platform_file_flags, NULL, &error_code);
+ IPC::PlatformFileForTransit file_for_transit =
+ file != base::kInvalidPlatformFileValue ?
+ IPC::GetFileHandleForProcess(file, PeerHandle(), true) :
+ IPC::InvalidPlatformFileForTransit();
+
+ Send(new ViewMsg_AsyncOpenPepperFile_ACK(
+ routing_id, error_code, file_for_transit));
+}
+
void RenderMessageFilter::OnMediaLogEvents(
const std::vector<media::MediaLogEvent>& events) {
if (media_internals_)
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 528f9a5..d0a4386 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -224,6 +224,9 @@ class RenderMessageFilter : public BrowserMessageFilter {
const std::string& challenge_string,
const GURL& url,
IPC::Message* reply_msg);
+ void OnAsyncOpenPepperFile(int routing_id,
+ const base::FilePath& path,
+ int pp_open_flags);
void OnMediaLogEvents(const std::vector<media::MediaLogEvent>&);
// Check the policy for getting cookies. Gets the cookies if allowed.
diff --git a/content/child/fileapi/file_system_dispatcher.cc b/content/child/fileapi/file_system_dispatcher.cc
index 8810c03..f982247 100644
--- a/content/child/fileapi/file_system_dispatcher.cc
+++ b/content/child/fileapi/file_system_dispatcher.cc
@@ -351,6 +351,23 @@ void FileSystemDispatcher::TouchFile(
request_id, path, last_access_time, last_modified_time));
}
+void FileSystemDispatcher::OpenPepperFile(
+ const GURL& file_path,
+ int pp_open_flags,
+ const OpenFileCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int request_id = dispatchers_.Add(
+ CallbackDispatcher::Create(success_callback, error_callback));
+ ChildThread::current()->Send(
+ new FileSystemHostMsg_OpenPepperFile(
+ request_id, file_path, pp_open_flags));
+}
+
+void FileSystemDispatcher::NotifyCloseFile(int file_open_id) {
+ ChildThread::current()->Send(
+ new FileSystemHostMsg_NotifyCloseFile(file_open_id));
+}
+
void FileSystemDispatcher::CreateSnapshotFile(
const GURL& file_path,
const CreateSnapshotFileCallback& success_callback,
diff --git a/content/child/fileapi/file_system_dispatcher.h b/content/child/fileapi/file_system_dispatcher.h
index 55bb299..9cdeb75 100644
--- a/content/child/fileapi/file_system_dispatcher.h
+++ b/content/child/fileapi/file_system_dispatcher.h
@@ -126,6 +126,16 @@ class FileSystemDispatcher : public IPC::Listener {
const base::Time& last_modified_time,
const StatusCallback& callback);
+ // This returns a raw open PlatformFile, unlike the above, which are
+ // self-contained operations.
+ void OpenPepperFile(const GURL& file_path,
+ int pp_open_flags,
+ const OpenFileCallback& success_callback,
+ const StatusCallback& error_callback);
+ // This must be paired with OpenFile, and called after finished using the
+ // raw PlatformFile returned from OpenFile.
+ void NotifyCloseFile(int file_open_id);
+
// The caller must send FileSystemHostMsg_DidReceiveSnapshot message
// with |request_id| passed to |success_callback| after the snapshot file
// is successfully received.
diff --git a/content/common/fileapi/file_system_messages.h b/content/common/fileapi/file_system_messages.h
index 727c6de..e0af3a0 100644
--- a/content/common/fileapi/file_system_messages.h
+++ b/content/common/fileapi/file_system_messages.h
@@ -164,6 +164,16 @@ IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CancelWrite,
int /* request id */,
int /* id of request to cancel */)
+// Pepper's OpenFile message.
+IPC_MESSAGE_CONTROL3(FileSystemHostMsg_OpenPepperFile,
+ int /* request id */,
+ GURL /* file path */,
+ int /* pp_open_flags */)
+
+// Pepper's NotifyCloseFile message.
+IPC_MESSAGE_CONTROL1(FileSystemHostMsg_NotifyCloseFile,
+ int /* file_open_id */)
+
// WebFileSystem::createSnapshotFileAndReadMetadata() message.
IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CreateSnapshotFile,
int /* request_id */,
@@ -179,3 +189,11 @@ IPC_MESSAGE_CONTROL1(FileSystemHostMsg_DidReceiveSnapshotFile,
IPC_SYNC_MESSAGE_CONTROL1_1(FileSystemHostMsg_SyncGetPlatformPath,
GURL /* file path */,
base::FilePath /* platform_path */)
+
+// Pre- and post-update notifications for ppapi implementation.
+IPC_MESSAGE_CONTROL1(FileSystemHostMsg_WillUpdate,
+ GURL /* file_path */)
+
+IPC_MESSAGE_CONTROL2(FileSystemHostMsg_DidUpdate,
+ GURL /* file_path */,
+ int64 /* delta */)
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 4f6c165..356d33f 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1231,6 +1231,11 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetActive,
// Sent when the worker has started.
IPC_MESSAGE_ROUTED0(ViewMsg_WorkerCreated)
+// The response to ViewHostMsg_AsyncOpenPepperFile.
+IPC_MESSAGE_ROUTED2(ViewMsg_AsyncOpenPepperFile_ACK,
+ base::PlatformFileError /* error_code */,
+ IPC::PlatformFileForTransit /* file descriptor */)
+
// Tells the renderer that the network state has changed and that
// window.navigator.onLine should be updated for all WebViews.
IPC_MESSAGE_CONTROL1(ViewMsg_NetworkStateChanged,
@@ -1925,6 +1930,13 @@ IPC_MESSAGE_CONTROL2(ViewHostMsg_OpenChannelToPpapiBroker,
int /* routing_id */,
base::FilePath /* path */)
+// Opens a Pepper file asynchronously. The response returns a file descriptor
+// and an error code from base/platform_file.h.
+IPC_MESSAGE_CONTROL3(ViewHostMsg_AsyncOpenPepperFile,
+ int /* routing_id */,
+ base::FilePath /* file path */,
+ int /* pp_open_flags */)
+
// A renderer sends this to the browser process when it wants to access a PPAPI
// broker. In contrast to ViewHostMsg_OpenChannelToPpapiBroker, this is called
// for every connection.
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index f5141f6..e9d7315 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -943,8 +943,6 @@
'browser/renderer_host/pepper/pepper_browser_font_singleton_host.h',
'browser/renderer_host/pepper/pepper_external_file_ref_backend.cc',
'browser/renderer_host/pepper/pepper_external_file_ref_backend.h',
- 'browser/renderer_host/pepper/pepper_file_io_host.cc',
- 'browser/renderer_host/pepper/pepper_file_io_host.h',
'browser/renderer_host/pepper/pepper_file_ref_host.cc',
'browser/renderer_host/pepper/pepper_file_ref_host.h',
'browser/renderer_host/pepper/pepper_file_system_browser_host.cc',
@@ -987,8 +985,6 @@
'browser/renderer_host/pepper/pepper_truetype_font_list_win.cc',
'browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc',
'browser/renderer_host/pepper/pepper_udp_socket_message_filter.h',
- 'browser/renderer_host/pepper/quota_file_io.cc',
- 'browser/renderer_host/pepper/quota_file_io.h',
'browser/renderer_host/pepper/ssl_context_helper.cc',
'browser/renderer_host/pepper/ssl_context_helper.h',
'browser/renderer_host/popup_menu_helper_mac.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index d037896..1e72a81 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -307,6 +307,8 @@
'renderer/pepper/pepper_device_enumeration_host_helper.h',
'renderer/pepper/pepper_file_chooser_host.cc',
'renderer/pepper/pepper_file_chooser_host.h',
+ 'renderer/pepper/pepper_file_io_host.cc',
+ 'renderer/pepper/pepper_file_io_host.h',
'renderer/pepper/pepper_file_ref_renderer_host.cc',
'renderer/pepper/pepper_file_ref_renderer_host.h',
'renderer/pepper/pepper_file_system_host.cc',
@@ -378,6 +380,8 @@
'renderer/pepper/ppb_video_decoder_impl.h',
'renderer/pepper/ppb_widget_impl.cc',
'renderer/pepper/ppb_widget_impl.h',
+ 'renderer/pepper/quota_file_io.cc',
+ 'renderer/pepper/quota_file_io.h',
'renderer/pepper/renderer_ppapi_host_impl.cc',
'renderer/pepper/renderer_ppapi_host_impl.h',
'renderer/pepper/renderer_restrict_dispatch_group.h',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index e8253d6..6fe6c5d 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -442,7 +442,6 @@
'browser/renderer_host/pepper/browser_ppapi_host_test.h',
'browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc',
'browser/renderer_host/pepper/pepper_printing_host_unittest.cc',
- 'browser/renderer_host/pepper/quota_file_io_unittest.cc',
'browser/renderer_host/render_view_host_unittest.cc',
'browser/renderer_host/render_widget_host_unittest.cc',
'browser/renderer_host/render_widget_host_view_aura_unittest.cc',
@@ -535,6 +534,7 @@
'renderer/pepper/host_var_tracker_unittest.cc',
'renderer/pepper/mock_resource.h',
'renderer/pepper/pepper_broker_unittest.cc',
+ 'renderer/pepper/quota_file_io_unittest.cc',
'renderer/pepper/v8_var_converter_unittest.cc',
'renderer/render_thread_impl_unittest.cc',
'renderer/render_view_impl_unittest.cc',
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 97cc600..fbbe343 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -168,6 +168,11 @@ bool ContentRendererClient::IsExternalPepperPlugin(
return false;
}
+bool ContentRendererClient::IsPluginAllowedToCallRequestOSFileHandle(
+ WebKit::WebPluginContainer* container) {
+ return false;
+}
+
bool ContentRendererClient::AllowBrowserPlugin(
WebKit::WebPluginContainer* container) {
return false;
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index e1a9041..86b7e31 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -239,6 +239,12 @@ class CONTENT_EXPORT ContentRendererClient {
// startup steps).
virtual bool IsExternalPepperPlugin(const std::string& module_name);
+ // Returns true if plugin living in the container can use
+ // pp::FileIO::RequestOSFileHandle.
+ // TODO(teravest): Remove this when FileIO is moved to the browser.
+ virtual bool IsPluginAllowedToCallRequestOSFileHandle(
+ WebKit::WebPluginContainer* container);
+
// Returns whether BrowserPlugin should be allowed within the |container|.
virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container);
diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index 5a58054..0b59503 100644
--- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -10,6 +10,7 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/pepper_audio_input_host.h"
#include "content/renderer/pepper/pepper_file_chooser_host.h"
+#include "content/renderer/pepper/pepper_file_io_host.h"
#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
#include "content/renderer/pepper/pepper_file_system_host.h"
#include "content/renderer/pepper/pepper_graphics_2d_host.h"
@@ -72,6 +73,9 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
// Public interfaces.
switch (message.type()) {
+ case PpapiHostMsg_FileIO_Create::ID:
+ return scoped_ptr<ResourceHost>(new PepperFileIOHost(
+ host_, instance, params.pp_resource()));
case PpapiHostMsg_FileRef_CreateInternal::ID: {
PP_Resource file_system;
std::string internal_path;
diff --git a/content/renderer/pepper/pepper_file_io_host.cc b/content/renderer/pepper/pepper_file_io_host.cc
new file mode 100644
index 0000000..f505313
--- /dev/null
+++ b/content/renderer/pepper/pepper_file_io_host.cc
@@ -0,0 +1,493 @@
+// 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/renderer/pepper/pepper_file_io_host.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/files/file_util_proxy.h"
+#include "content/child/child_thread.h"
+#include "content/child/fileapi/file_system_dispatcher.h"
+#include "content/child/quota_dispatcher.h"
+#include "content/common/fileapi/file_system_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
+#include "content/renderer/pepper/quota_file_io.h"
+#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
+#include "content/renderer/render_thread_impl.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_io.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_type_conversion.h"
+#include "ppapi/shared_impl/time_conversion.h"
+#include "ppapi/thunk/enter.h"
+#include "third_party/WebKit/public/web/WebPluginContainer.h"
+
+namespace content {
+
+using ppapi::FileIOStateManager;
+using ppapi::PPTimeToTime;
+using ppapi::host::ReplyMessageContext;
+using ppapi::thunk::EnterResourceNoLock;
+
+namespace {
+
+typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback;
+
+int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
+ // On the plugin side, some callbacks expect a parameter that means different
+ // things depending on whether is negative or not. We translate for those
+ // callbacks here.
+ return pp_error == PP_OK ? byte_number : pp_error;
+}
+
+class QuotaCallbackTranslator : public QuotaDispatcher::Callback {
+ public:
+ typedef QuotaFileIO::Delegate::AvailableSpaceCallback PluginCallback;
+ explicit QuotaCallbackTranslator(const PluginCallback& cb) : callback_(cb) {}
+ virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
+ callback_.Run(std::max(static_cast<int64>(0), quota - usage));
+ }
+ virtual void DidGrantStorageQuota(int64 granted_quota) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
+ callback_.Run(0);
+ }
+ private:
+ PluginCallback callback_;
+};
+
+class QuotaFileIODelegate : public QuotaFileIO::Delegate {
+ public:
+ QuotaFileIODelegate() {}
+ virtual ~QuotaFileIODelegate() {}
+
+ virtual void QueryAvailableSpace(
+ const GURL& origin,
+ quota::StorageType type,
+ const AvailableSpaceCallback& callback) OVERRIDE {
+ ChildThread::current()->quota_dispatcher()->QueryStorageUsageAndQuota(
+ origin, type, new QuotaCallbackTranslator(callback));
+ }
+ virtual void WillUpdateFile(const GURL& file_path) OVERRIDE {
+ ChildThread::current()->Send(new FileSystemHostMsg_WillUpdate(file_path));
+ }
+ virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE {
+ ChildThread::current()->Send(new FileSystemHostMsg_DidUpdate(
+ file_path, delta));
+ }
+ virtual scoped_refptr<base::MessageLoopProxy>
+ GetFileThreadMessageLoopProxy() OVERRIDE {
+ return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy();
+ }
+};
+
+typedef base::Callback<
+ void (base::PlatformFileError error,
+ base::PassPlatformFile file,
+ quota::QuotaLimitType quota_policy,
+ const PepperFileIOHost::NotifyCloseFileCallback& close_file_callback)>
+ AsyncOpenFileSystemURLCallback;
+
+void DoNotifyCloseFile(int file_open_id, base::PlatformFileError error) {
+ ChildThread::current()->file_system_dispatcher()->NotifyCloseFile(
+ file_open_id);
+}
+
+void DidOpenFileSystemURL(const AsyncOpenFileSystemURLCallback& callback,
+ base::PlatformFile file,
+ int file_open_id,
+ quota::QuotaLimitType quota_policy) {
+ callback.Run(base::PLATFORM_FILE_OK,
+ base::PassPlatformFile(&file),
+ quota_policy,
+ base::Bind(&DoNotifyCloseFile, file_open_id));
+ // Make sure we won't leak file handle if the requester has died.
+ if (file != base::kInvalidPlatformFileValue) {
+ base::FileUtilProxy::Close(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file,
+ base::Bind(&DoNotifyCloseFile, file_open_id));
+ }
+}
+
+void DidFailOpenFileSystemURL(const AsyncOpenFileSystemURLCallback& callback,
+ base::PlatformFileError error_code) {
+ base::PlatformFile invalid_file = base::kInvalidPlatformFileValue;
+ callback.Run(error_code,
+ base::PassPlatformFile(&invalid_file),
+ quota::kQuotaLimitTypeUnknown,
+ PepperFileIOHost::NotifyCloseFileCallback());
+}
+
+} // namespace
+
+PepperFileIOHost::PepperFileIOHost(RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ renderer_ppapi_host_(host),
+ file_(base::kInvalidPlatformFileValue),
+ file_system_type_(PP_FILESYSTEMTYPE_INVALID),
+ quota_policy_(quota::kQuotaLimitTypeUnknown),
+ open_flags_(0),
+ routing_id_(RenderThreadImpl::current()->GenerateRoutingID()),
+ weak_factory_(this) {
+ ChildThread::current()->AddRoute(routing_id_, this);
+}
+
+PepperFileIOHost::~PepperFileIOHost() {
+ OnHostMsgClose(NULL);
+ ChildThread::current()->RemoveRoute(routing_id_);
+}
+
+int32_t PepperFileIOHost::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
+ OnHostMsgOpen)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
+ OnHostMsgTouch)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
+ OnHostMsgWrite)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
+ OnHostMsgSetLength)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
+ OnHostMsgFlush)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close,
+ OnHostMsgClose)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle,
+ OnHostMsgRequestOSFileHandle)
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+bool PepperFileIOHost::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
+ IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenPepperFile_ACK, OnAsyncFileOpened)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PepperFileIOHost::OnAsyncFileOpened(
+ base::PlatformFileError error_code,
+ IPC::PlatformFileForTransit file_for_transit) {
+ DCHECK(!pending_open_callback_.is_null());
+ base::PlatformFile file =
+ IPC::PlatformFileForTransitToPlatformFile(file_for_transit);
+ if (!pending_open_callback_.is_null())
+ pending_open_callback_.Run(error_code, base::PassPlatformFile(&file));
+
+ // Make sure we won't leak file handle if the requester has died.
+ if (file != base::kInvalidPlatformFileValue) {
+ base::FileUtilProxy::Close(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file,
+ base::FileUtilProxy::StatusCallback());
+ }
+ pending_open_callback_.Reset();
+}
+
+int32_t PepperFileIOHost::OnHostMsgOpen(
+ ppapi::host::HostMessageContext* context,
+ PP_Resource file_ref_resource,
+ int32_t open_flags) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, false);
+ if (rv != PP_OK)
+ return rv;
+
+ if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags, NULL))
+ return PP_ERROR_BADARGUMENT;
+
+ ppapi::host::ResourceHost* resource_host =
+ renderer_ppapi_host_->GetPpapiHost()->GetResourceHost(file_ref_resource);
+ if (!resource_host || !resource_host->IsFileRefHost())
+ return PP_ERROR_BADRESOURCE;
+
+ PepperFileRefRendererHost* file_ref_host =
+ static_cast<PepperFileRefRendererHost*>(resource_host);
+ if (file_ref_host->GetFileSystemType() == PP_FILESYSTEMTYPE_INVALID)
+ return PP_ERROR_FAILED;
+
+ open_flags_ = open_flags;
+ file_system_type_ = file_ref_host->GetFileSystemType();
+
+ if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+ file_system_url_ = file_ref_host->GetFileSystemURL();
+ FileSystemDispatcher* file_system_dispatcher =
+ ChildThread::current()->file_system_dispatcher();
+
+ AsyncOpenFileSystemURLCallback callback = base::Bind(
+ &PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext());
+ file_system_dispatcher->OpenPepperFile(
+ file_system_url_, open_flags,
+ base::Bind(&DidOpenFileSystemURL, callback),
+ base::Bind(&DidFailOpenFileSystemURL, callback));
+ } else {
+ pending_open_callback_ =
+ base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext());
+ RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile(
+ routing_id_,
+ file_ref_host->GetExternalFilePath(),
+ open_flags_));
+ }
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgTouch(
+ ppapi::host::HostMessageContext* context,
+ PP_Time last_access_time,
+ PP_Time last_modified_time) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+ FileSystemDispatcher* file_system_dispatcher =
+ ChildThread::current()->file_system_dispatcher();
+ file_system_dispatcher->TouchFile(
+ file_system_url_,
+ PPTimeToTime(last_access_time),
+ PPTimeToTime(last_modified_time),
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext()));
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+ }
+
+ // TODO(nhiroki): fix a failure of FileIO.Touch for an external filesystem on
+ // Mac and Linux due to sandbox restrictions (http://crbug.com/101128).
+ if (!base::FileUtilProxy::Touch(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file_,
+ PPTimeToTime(last_access_time),
+ PPTimeToTime(last_modified_time),
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgWrite(
+ ppapi::host::HostMessageContext* context,
+ int64_t offset,
+ const std::string& buffer) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_WRITE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ if (quota_file_io_) {
+ if (!quota_file_io_->Write(
+ offset, buffer.c_str(), buffer.size(),
+ base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+ } else {
+ if (!base::FileUtilProxy::Write(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file_,
+ offset,
+ buffer.c_str(),
+ buffer.size(),
+ base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+ }
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgSetLength(
+ ppapi::host::HostMessageContext* context,
+ int64_t length) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+ FileSystemDispatcher* file_system_dispatcher =
+ ChildThread::current()->file_system_dispatcher();
+ file_system_dispatcher->Truncate(
+ file_system_url_, length, NULL,
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext()));
+ } else {
+ // TODO(nhiroki): fix a failure of FileIO.SetLength for an external
+ // filesystem on Mac due to sandbox restrictions (http://crbug.com/156077).
+ if (!base::FileUtilProxy::Truncate(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file_,
+ length,
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+ }
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgFlush(
+ ppapi::host::HostMessageContext* context) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ if (!base::FileUtilProxy::Flush(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file_,
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgClose(
+ ppapi::host::HostMessageContext* context) {
+ if (file_ != base::kInvalidPlatformFileValue) {
+ base::FileUtilProxy::Close(
+ RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
+ file_,
+ base::ResetAndReturn(&notify_close_file_callback_));
+ file_ = base::kInvalidPlatformFileValue;
+ quota_file_io_.reset();
+ }
+ return PP_OK;
+}
+
+int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
+ ppapi::host::HostMessageContext* context) {
+ if (open_flags_ != PP_FILEOPENFLAG_READ &&
+ quota_policy_ != quota::kQuotaLimitTypeUnlimited)
+ return PP_ERROR_FAILED;
+
+ // Whitelist to make it privately accessible.
+ if (!host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE) &&
+ !GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle(
+ renderer_ppapi_host_->GetContainerForInstance(pp_instance())))
+ return PP_ERROR_NOACCESS;
+
+ IPC::PlatformFileForTransit file =
+ renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
+ if (file == IPC::InvalidPlatformFileForTransit())
+ return PP_ERROR_FAILED;
+ ppapi::host::ReplyMessageContext reply_context =
+ context->MakeReplyMessageContext();
+ ppapi::proxy::SerializedHandle file_handle;
+ file_handle.set_file_handle(file, open_flags_);
+ reply_context.params.AppendHandle(file_handle);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperFileIOHost::ExecutePlatformGeneralCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code) {
+ reply_context.params.set_result(
+ ppapi::PlatformFileErrorToPepperError(error_code));
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
+ state_manager_.SetOperationFinished();
+}
+
+void PepperFileIOHost::ExecutePlatformOpenFileCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ base::PassPlatformFile file) {
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
+ if (pp_error == PP_OK)
+ state_manager_.SetOpenSucceed();
+
+ DCHECK(file_ == base::kInvalidPlatformFileValue);
+ file_ = file.ReleaseValue();
+
+ DCHECK(!quota_file_io_.get());
+ if (file_ != base::kInvalidPlatformFileValue) {
+ if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
+ file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) {
+ quota_file_io_.reset(new QuotaFileIO(
+ new QuotaFileIODelegate, file_, file_system_url_, file_system_type_));
+ }
+
+ IPC::PlatformFileForTransit file_for_transit =
+ renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
+ if (!(file_for_transit == IPC::InvalidPlatformFileForTransit())) {
+ // Send the file descriptor to the plugin process. This is used in the
+ // plugin for any file operations that can be done there.
+ int32_t flags_to_send = open_flags_;
+ if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) {
+ // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
+ // the plugin can't write and so bypass our quota checks.
+ flags_to_send =
+ open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
+ }
+ ppapi::proxy::SerializedHandle file_handle;
+ file_handle.set_file_handle(file_for_transit, flags_to_send);
+ reply_context.params.AppendHandle(file_handle);
+ }
+ }
+
+ reply_context.params.set_result(pp_error);
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
+ state_manager_.SetOperationFinished();
+}
+
+void PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ base::PassPlatformFile file,
+ quota::QuotaLimitType quota_policy,
+ const PepperFileIOHost::NotifyCloseFileCallback& callback) {
+ if (error_code == base::PLATFORM_FILE_OK)
+ notify_close_file_callback_ = callback;
+ quota_policy_ = quota_policy;
+ ExecutePlatformOpenFileCallback(reply_context, error_code, file);
+}
+
+void PepperFileIOHost::ExecutePlatformWriteCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ int bytes_written) {
+ // On the plugin side, the callback expects a parameter with different meaning
+ // depends on whether is negative or not. It is the result here. We translate
+ // for the callback.
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
+ reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
+ state_manager_.SetOperationFinished();
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.h b/content/renderer/pepper/pepper_file_io_host.h
index a5fa538..95f1d72 100644
--- a/content/browser/renderer_host/pepper/pepper_file_io_host.h
+++ b/content/renderer/pepper/pepper_file_io_host.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/platform_file.h"
-#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_platform_file.h"
#include "ppapi/c/pp_file_info.h"
@@ -20,8 +20,6 @@
#include "ppapi/host/resource_host.h"
#include "ppapi/shared_impl/file_io_state_manager.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
#include "webkit/common/quota/quota_types.h"
using ppapi::host::ReplyMessageContext;
@@ -30,12 +28,13 @@ namespace content {
class QuotaFileIO;
class PepperFileIOHost : public ppapi::host::ResourceHost,
- public base::SupportsWeakPtr<PepperFileIOHost> {
+ public base::SupportsWeakPtr<PepperFileIOHost>,
+ public IPC::Listener {
public:
typedef base::Callback<void (base::PlatformFileError)>
NotifyCloseFileCallback;
- PepperFileIOHost(BrowserPpapiHostImpl* host,
+ PepperFileIOHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
virtual ~PepperFileIOHost();
@@ -44,7 +43,15 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
virtual int32_t OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) OVERRIDE;
+
private:
+ // IPC::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ void OnAsyncFileOpened(
+ base::PlatformFileError error_code,
+ IPC::PlatformFileForTransit file_for_transit);
+
int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
PP_Resource file_ref_resource,
int32_t open_flags);
@@ -58,13 +65,10 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
int64_t length);
int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context);
int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context);
+ // Private API.
int32_t OnHostMsgRequestOSFileHandle(
ppapi::host::HostMessageContext* context);
- void GotPluginAllowedToCallRequestOSFileHandle(
- ppapi::host::ReplyMessageContext reply_context,
- bool plugin_allowed);
-
// Callback handlers. These mostly convert the PlatformFileError to the
// PP_Error code and send back the reply. Note that the argument
// ReplyMessageContext is copied so that we have a closure containing all
@@ -73,40 +77,24 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
base::PlatformFileError error_code);
void ExecutePlatformOpenFileCallback(ReplyMessageContext reply_context,
base::PlatformFileError error_code,
- base::PassPlatformFile file,
- bool unused_created);
+ base::PassPlatformFile file);
+ void ExecutePlatformOpenFileSystemURLCallback(
+ ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ base::PassPlatformFile file,
+ quota::QuotaLimitType quota_policy,
+ const NotifyCloseFileCallback& callback);
+ void ExecutePlatformQueryCallback(ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ const base::PlatformFileInfo& file_info);
+ void ExecutePlatformReadCallback(ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ const char* data, int bytes_read);
void ExecutePlatformWriteCallback(ReplyMessageContext reply_context,
base::PlatformFileError error_code,
int bytes_written);
- void GotUIThreadStuffForInternalFileSystems(
- ReplyMessageContext reply_context,
- int platform_file_flags,
- bool ok);
- void DidOpenInternalFile(
- ReplyMessageContext reply_context,
- base::PlatformFileError result,
- base::PlatformFile file,
- const base::Closure& on_close_callback);
- void GotResolvedRenderProcessId(
- ReplyMessageContext reply_context,
- base::FilePath path,
- int platform_file_flags,
- base::ProcessId resolved_render_process_id);
-
- void DidCloseFile(base::PlatformFileError error);
-
- // Adds file_ to |reply_context| with the specified |open_flags|.
- bool AddFileToReplyContext(
- int32_t open_flags,
- ppapi::host::ReplyMessageContext* reply_context) const;
-
- BrowserPpapiHostImpl* browser_ppapi_host_;
-
- RenderProcessHost* render_process_host_;
- int render_process_id_;
- base::ProcessId resolved_render_process_id_;
-
+ RendererPpapiHost* renderer_ppapi_host_;
base::PlatformFile file_;
// The file system type specified in the Open() call. This will be
@@ -115,14 +103,14 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
PP_FileSystemType file_system_type_;
// Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
- scoped_ptr<fileapi::FileSystemOperationRunner> file_system_operation_runner_;
- fileapi::FileSystemURL file_system_url_;
- base::Closure on_close_callback_;
+ GURL file_system_url_;
// Used to check if we can pass file handle to plugins.
quota::QuotaLimitType quota_policy_;
+ // Callback function for notifying when the file handle is closed.
+ NotifyCloseFileCallback notify_close_file_callback_;
+
// Pointer to a QuotaFileIO instance, which is valid only while a file
// of type PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY} is opened.
scoped_ptr<QuotaFileIO> quota_file_io_;
@@ -131,7 +119,10 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
ppapi::FileIOStateManager state_manager_;
- scoped_refptr<base::MessageLoopProxy> file_message_loop_;
+ int routing_id_;
+
+ base::Callback<void(base::PlatformFileError, base::PassPlatformFile)>
+ pending_open_callback_;
base::WeakPtrFactory<PepperFileIOHost> weak_factory_;
diff --git a/content/browser/renderer_host/pepper/quota_file_io.cc b/content/renderer/pepper/quota_file_io.cc
index 0768574..af87432f 100644
--- a/content/browser/renderer_host/pepper/quota_file_io.cc
+++ b/content/renderer/pepper/quota_file_io.cc
@@ -1,8 +1,8 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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/renderer_host/pepper/quota_file_io.h"
+#include "content/renderer/pepper/quota_file_io.h"
#include <algorithm>
diff --git a/content/browser/renderer_host/pepper/quota_file_io.h b/content/renderer/pepper/quota_file_io.h
index 54229b8..e1ec4c1 100644
--- a/content/browser/renderer_host/pepper/quota_file_io.h
+++ b/content/renderer/pepper/quota_file_io.h
@@ -1,9 +1,9 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_FILE_IO_H_
-#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_FILE_IO_H_
+#ifndef CONTENT_RENDERER_PEPPER_QUOTA_FILE_IO_H_
+#define CONTENT_RENDERER_PEPPER_QUOTA_FILE_IO_H_
#include <deque>
@@ -124,4 +124,4 @@ class QuotaFileIO {
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_FILE_IO_H_
+#endif // CONTENT_RENDERER_PEPPER_QUOTA_FILE_IO_H_
diff --git a/content/browser/renderer_host/pepper/quota_file_io_unittest.cc b/content/renderer/pepper/quota_file_io_unittest.cc
index bcc08d3..f1d7a59 100644
--- a/content/browser/renderer_host/pepper/quota_file_io_unittest.cc
+++ b/content/renderer/pepper/quota_file_io_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -13,7 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/platform_file.h"
-#include "content/browser/renderer_host/pepper/quota_file_io.h"
+#include "content/renderer/pepper/quota_file_io.h"
#include "content/test/ppapi_unittest.h"
using base::MessageLoopProxy;