diff options
author | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-01 20:37:21 +0000 |
---|---|---|
committer | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-01 20:37:21 +0000 |
commit | 12e9913cd1d7c2c4b3aa49ed006b33b1b1fa5515 (patch) | |
tree | 33135f3eb6a4176210de966c4f31f7e81dfec509 /content | |
parent | ef452a2612cc3d1567fb54c2ac444cbaf8adcd5f (diff) | |
download | chromium_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')
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(¬ify_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; |