diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-29 00:49:51 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-29 00:49:51 +0000 |
commit | f54329e5d6a76858c67869e678f9462a964632b7 (patch) | |
tree | 4b92fd9b8111a157a4b66049aedf673c0856dfc9 /ppapi/proxy | |
parent | 0be9392b7cc037c74baa929bc384baf36b0001f3 (diff) | |
download | chromium_src-f54329e5d6a76858c67869e678f9462a964632b7.zip chromium_src-f54329e5d6a76858c67869e678f9462a964632b7.tar.gz chromium_src-f54329e5d6a76858c67869e678f9462a964632b7.tar.bz2 |
PPAPI: Implement PPB_FileMapping on POSIX
BUG=83774
R=bbudge@chromium.org
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=247473
Review URL: https://codereview.chromium.org/69663002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247546 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/file_io_resource.h | 5 | ||||
-rw-r--r-- | ppapi/proxy/file_mapping_resource.cc | 160 | ||||
-rw-r--r-- | ppapi/proxy/file_mapping_resource.h | 77 | ||||
-rw-r--r-- | ppapi/proxy/file_mapping_resource_posix.cc | 89 | ||||
-rw-r--r-- | ppapi/proxy/file_mapping_resource_win.cc | 40 | ||||
-rw-r--r-- | ppapi/proxy/interface_list.cc | 1 | ||||
-rw-r--r-- | ppapi/proxy/ppb_instance_proxy.cc | 4 |
7 files changed, 375 insertions, 1 deletions
diff --git a/ppapi/proxy/file_io_resource.h b/ppapi/proxy/file_io_resource.h index d6465fd..5d58035 100644 --- a/ppapi/proxy/file_io_resource.h +++ b/ppapi/proxy/file_io_resource.h @@ -69,7 +69,6 @@ class PPAPI_PROXY_EXPORT FileIOResource PP_FileHandle* handle, scoped_refptr<TrackedCallback> callback) OVERRIDE; - private: // FileHandleHolder is used to guarantee that file operations will have a // valid FD to operate on, even if they're in a different thread. // If instead we just passed the raw FD, the FD could be closed before the @@ -102,7 +101,11 @@ class PPAPI_PROXY_EXPORT FileIOResource ~FileHandleHolder(); PP_FileHandle raw_handle_; }; + scoped_refptr<FileHandleHolder> file_handle() { + return file_handle_; + } + private: // Class to perform file query operations across multiple threads. class QueryOp : public base::RefCountedThreadSafe<QueryOp> { public: diff --git a/ppapi/proxy/file_mapping_resource.cc b/ppapi/proxy/file_mapping_resource.cc new file mode 100644 index 0000000..5b18dbb --- /dev/null +++ b/ppapi/proxy/file_mapping_resource.cc @@ -0,0 +1,160 @@ +// Copyright 2014 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 "ppapi/proxy/file_mapping_resource.h" + +#include "base/bind.h" +#include "base/numerics/safe_conversions.h" +#include "base/task_runner_util.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/shared_impl/var.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_file_io_api.h" + +namespace ppapi { +namespace proxy { + +FileMappingResource::FileMappingResource(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance) { +} + +FileMappingResource::~FileMappingResource() { +} + +thunk::PPB_FileMapping_API* FileMappingResource::AsPPB_FileMapping_API() { + return this; +} + +int32_t FileMappingResource::Map(PP_Instance /* instance */, + PP_Resource file_io, + int64_t length, + uint32_t protection, + uint32_t flags, + int64_t offset, + void** address, + scoped_refptr<TrackedCallback> callback) { + thunk::EnterResourceNoLock<thunk::PPB_FileIO_API> enter(file_io, true); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + FileIOResource* file_io_resource = + static_cast<FileIOResource*>(enter.object()); + scoped_refptr<FileIOResource::FileHandleHolder> file_handle = + file_io_resource->file_handle(); + if (!FileIOResource::FileHandleHolder::IsValid(file_handle)) + return PP_ERROR_FAILED; + if (length < 0 || offset < 0 || + !base::IsValueInRangeForNumericType<off_t>(offset)) { + return PP_ERROR_BADARGUMENT; + } + if (!base::IsValueInRangeForNumericType<size_t>(length)) { + return PP_ERROR_NOMEMORY; + } + + // Ensure any bits we don't recognize are zero. + if (protection & + ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) { + return PP_ERROR_BADARGUMENT; + } + if (flags & + ~(PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE | + PP_FILEMAPFLAG_FIXED)) { + return PP_ERROR_BADARGUMENT; + } + // Ensure at least one of SHARED and PRIVATE is set. + if (!(flags & (PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE))) + return PP_ERROR_BADARGUMENT; + // Ensure at most one of SHARED and PRIVATE is set. + if ((flags & PP_FILEMAPFLAG_SHARED) && + (flags & PP_FILEMAPFLAG_PRIVATE)) { + return PP_ERROR_BADARGUMENT; + } + if (!address) + return PP_ERROR_BADARGUMENT; + + base::Callback<MapResult()> map_cb( + base::Bind(&FileMappingResource::DoMapBlocking, file_handle, *address, + length, protection, flags, offset)); + if (callback->is_blocking()) { + // The plugin could release its reference to this instance when we release + // the proxy lock below. + scoped_refptr<FileMappingResource> protect(this); + MapResult map_result; + { + // Release the proxy lock while making a potentially slow file call. + ProxyAutoUnlock unlock; + map_result = map_cb.Run(); + } + OnMapCompleted(address, length, callback, map_result); + return map_result.result; + } else { + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(), + FROM_HERE, + map_cb, + RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted, + this, + base::Unretained(address), + length, + callback))); + return PP_OK_COMPLETIONPENDING; + } +} + +int32_t FileMappingResource::Unmap(PP_Instance /* instance */, + const void* address, + int64_t length, + scoped_refptr<TrackedCallback> callback) { + if (!address) + return PP_ERROR_BADARGUMENT; + if (!base::IsValueInRangeForNumericType<size_t>(length)) + return PP_ERROR_BADARGUMENT; + + base::Callback<int32_t()> unmap_cb( + base::Bind(&FileMappingResource::DoUnmapBlocking, address, length)); + if (callback->is_blocking()) { + // Release the proxy lock while making a potentially slow file call. + ProxyAutoUnlock unlock; + return unmap_cb.Run(); + } else { + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(), + FROM_HERE, + unmap_cb, + RunWhileLocked(Bind(&TrackedCallback::Run, callback))); + return PP_OK_COMPLETIONPENDING; + } +} + +int64_t FileMappingResource::GetMapPageSize(PP_Instance /* instance */) { + return DoGetMapPageSize(); +} + +void FileMappingResource::OnMapCompleted( + void** mapped_address_out_param, + int64_t length, + scoped_refptr<TrackedCallback> callback, + const MapResult& map_result) { + if (callback->aborted()) { + if (map_result.result == PP_OK) { + // If the Map operation was successful, we need to Unmap to avoid leaks. + // The plugin won't get the address, so doesn't have a chance to do the + // Unmap. + PpapiGlobals::Get()->GetFileTaskRunner()->PostTask( + FROM_HERE, + base::Bind(base::IgnoreResult(&FileMappingResource::DoUnmapBlocking), + map_result.address, + length)); + } + return; + } + if (map_result.result == PP_OK) + *mapped_address_out_param = map_result.address; + if (!callback->is_blocking()) + callback->Run(map_result.result); +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/file_mapping_resource.h b/ppapi/proxy/file_mapping_resource.h new file mode 100644 index 0000000..240da21 --- /dev/null +++ b/ppapi/proxy/file_mapping_resource.h @@ -0,0 +1,77 @@ +// Copyright 2014 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 PPAPI_PROXY_FILE_MAPPING_RESOURCE_H_ +#define PPAPI_PROXY_FILE_MAPPING_RESOURCE_H_ + +#include "ppapi/proxy/file_io_resource.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/thunk/ppb_file_mapping_api.h" + +namespace ppapi { +namespace proxy { + +// The proxy-side resource for PPB_FileMapping. +class PPAPI_PROXY_EXPORT FileMappingResource + : public PluginResource, + public thunk::PPB_FileMapping_API { + public: + FileMappingResource(Connection connection, PP_Instance instance); + + private: + virtual ~FileMappingResource(); + + // Resource implementation. + virtual thunk::PPB_FileMapping_API* AsPPB_FileMapping_API() OVERRIDE; + + // PPB_FileMapping_API implementation. + virtual int32_t Map(PP_Instance instance, + PP_Resource file_io, + int64_t length, + uint32_t protection, + uint32_t flags, + int64_t offset, + void** address, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t Unmap(PP_Instance instance, + const void* address, + int64_t length, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int64_t GetMapPageSize(PP_Instance instance) OVERRIDE; + + struct MapResult { + MapResult() : result(PP_ERROR_FAILED), address(NULL) { + } + int32_t result; + void* address; + }; + void OnMapCompleted(void** mapped_address_out_param, + int64_t length, + scoped_refptr<TrackedCallback> callback, + const MapResult& map_result); + + // These functions perform potentially blocking operations so they should not + // be called on the main thread or while we hold the proxy lock. Their + // implementation is platform specific. See file_mapping_resource_posix.cc and + // file_mapping_resource_win.cc. + static MapResult DoMapBlocking( + scoped_refptr<FileIOResource::FileHandleHolder> handle, + void* address_hint, + int64_t length, + uint32_t protection, + uint32_t flags, + int64_t offset); + static int32_t DoUnmapBlocking(const void* address, int64_t length); + // DoGetMapPageSize is platform-specific, but fast enough that we can call it + // on the main thread with the lock. + static int64_t DoGetMapPageSize(); + + DISALLOW_COPY_AND_ASSIGN(FileMappingResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_FILE_MAPPING_RESOURCE_H_ diff --git a/ppapi/proxy/file_mapping_resource_posix.cc b/ppapi/proxy/file_mapping_resource_posix.cc new file mode 100644 index 0000000..b1aff77 --- /dev/null +++ b/ppapi/proxy/file_mapping_resource_posix.cc @@ -0,0 +1,89 @@ +// Copyright 2014 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 "ppapi/proxy/file_mapping_resource.h" + +#include <stdio.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "ppapi/c/pp_errors.h" + +namespace ppapi { +namespace proxy { + +namespace { + +int32_t ErrnoToPPError(int error_code) { + switch (error_code) { + case EACCES: + return PP_ERROR_NOACCESS; + case EAGAIN: + return PP_ERROR_NOMEMORY; + case EINVAL: + return PP_ERROR_BADARGUMENT; + case ENFILE: + case ENOMEM: + return PP_ERROR_NOMEMORY; + default: + return PP_ERROR_FAILED; + } +} + +} // namespace + +// static +FileMappingResource::MapResult FileMappingResource::DoMapBlocking( + scoped_refptr<FileIOResource::FileHandleHolder> handle, + void* address_hint, + int64_t length, + uint32_t map_protection, + uint32_t map_flags, + int64_t offset) { + int prot_for_mmap = 0; + if (map_protection & PP_FILEMAPPROTECTION_READ) + prot_for_mmap |= PROT_READ; + if (map_protection & PP_FILEMAPPROTECTION_WRITE) + prot_for_mmap |= PROT_WRITE; + if (prot_for_mmap == 0) + prot_for_mmap = PROT_NONE; + + int flags_for_mmap = 0; + if (map_flags & PP_FILEMAPFLAG_SHARED) + flags_for_mmap |= MAP_SHARED; + if (map_flags & PP_FILEMAPFLAG_PRIVATE) + flags_for_mmap |= MAP_PRIVATE; + if (map_flags & PP_FILEMAPFLAG_FIXED) + flags_for_mmap |= MAP_FIXED; + + MapResult map_result; + map_result.address = + mmap(address_hint, + static_cast<size_t>(length), + prot_for_mmap, + flags_for_mmap, + handle->raw_handle(), + static_cast<off_t>(offset)); + if (map_result.address != MAP_FAILED) + map_result.result = PP_OK; + else + map_result.result = ErrnoToPPError(errno); + return map_result; +} + +// static +int32_t FileMappingResource::DoUnmapBlocking(const void* address, + int64_t length) { + if (munmap(const_cast<void*>(address), static_cast<size_t>(length))) + return ErrnoToPPError(errno); + return PP_OK; +} + +// static +int64_t FileMappingResource::DoGetMapPageSize() { + return getpagesize(); +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/file_mapping_resource_win.cc b/ppapi/proxy/file_mapping_resource_win.cc new file mode 100644 index 0000000..70c3d20 --- /dev/null +++ b/ppapi/proxy/file_mapping_resource_win.cc @@ -0,0 +1,40 @@ +// Copyright 2014 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 "ppapi/proxy/file_mapping_resource.h" + +#include "ppapi/c/pp_errors.h" + +namespace ppapi { +namespace proxy { + +// static +FileMappingResource::MapResult FileMappingResource::DoMapBlocking( + scoped_refptr<FileIOResource::FileHandleHolder> handle, + void* address_hint, + int64_t length, + uint32_t map_protection, + uint32_t map_flags, + int64_t offset) { + // TODO(dmichael): Implement for Windows (crbug.com/83774). + MapResult map_result; + map_result.result = PP_ERROR_NOTSUPPORTED; + return map_result; +} + +// static +int32_t FileMappingResource::DoUnmapBlocking(const void* address, + int64_t length) { + // TODO(dmichael): Implement for Windows (crbug.com/83774). + return PP_ERROR_NOTSUPPORTED; +} + +// static +int64_t FileMappingResource::DoGetMapPageSize() { + // TODO(dmichael): Implement for Windows (crbug.com/83774). + return 0; +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 4044b27b..79789d7 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -35,6 +35,7 @@ #include "ppapi/c/ppb_console.h" #include "ppapi/c/ppb_core.h" #include "ppapi/c/ppb_file_io.h" +#include "ppapi/c/ppb_file_mapping.h" #include "ppapi/c/ppb_file_ref.h" #include "ppapi/c/ppb_file_system.h" #include "ppapi/c/ppb_fullscreen.h" diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc index 6429f50..80715ad 100644 --- a/ppapi/proxy/ppb_instance_proxy.cc +++ b/ppapi/proxy/ppb_instance_proxy.cc @@ -19,6 +19,7 @@ #include "ppapi/proxy/content_decryptor_private_serializer.h" #include "ppapi/proxy/enter_proxy.h" #include "ppapi/proxy/extensions_common_resource.h" +#include "ppapi/proxy/file_mapping_resource.h" #include "ppapi/proxy/flash_clipboard_resource.h" #include "ppapi/proxy/flash_file_resource.h" #include "ppapi/proxy/flash_fullscreen_resource.h" @@ -363,6 +364,9 @@ Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance, case EXTENSIONS_COMMON_SINGLETON_ID: new_singleton = new ExtensionsCommonResource(connection, instance); break; + case FILE_MAPPING_SINGLETON_ID: + new_singleton = new FileMappingResource(connection, instance); + break; case GAMEPAD_SINGLETON_ID: new_singleton = new GamepadResource(connection, instance); break; |