Index: ppapi/proxy/file_mapping_resource.cc |
diff --git a/ppapi/proxy/file_mapping_resource.cc b/ppapi/proxy/file_mapping_resource.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f7ecb2793e824f4e8d1e9891f1d87da8b8a7b957 |
--- /dev/null |
+++ b/ppapi/proxy/file_mapping_resource.cc |
@@ -0,0 +1,160 @@ |
+// Copyright (c) 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 |