| 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..c314650aa85dca2d9d793b21b695c71521566e67 | 
| --- /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 map_protection, | 
| +                                 uint32_t map_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 (map_protection & | 
| +      ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) { | 
| +    return PP_ERROR_BADARGUMENT; | 
| +  } | 
| +  if (map_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 (!(map_flags & (PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE))) | 
| +    return PP_ERROR_BADARGUMENT; | 
| +  // Ensure at most one of SHARED and PRIVATE is set. | 
| +  if ((map_flags & PP_FILEMAPFLAG_SHARED) && | 
| +      (map_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, map_protection, map_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 | 
|  |