15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/proxy/file_mapping_resource.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task_runner_util.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/c/pp_errors.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/shared_impl/tracked_callback.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/shared_impl/var.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/thunk/enter.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/thunk/ppb_file_io_api.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace ppapi { 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace proxy { 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileMappingResource::FileMappingResource(Connection connection, 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Instance instance) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : PluginResource(connection, instance) { 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileMappingResource::~FileMappingResource() { 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)thunk::PPB_FileMapping_API* FileMappingResource::AsPPB_FileMapping_API() { 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return this; 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int32_t FileMappingResource::Map(PP_Instance /* instance */, 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Resource file_io, 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t length, 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t protection, 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t flags, 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t offset, 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void** address, 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thunk::EnterResourceNoLock<thunk::PPB_FileIO_API> enter(file_io, true); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (enter.failed()) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOResource* file_io_resource = 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<FileIOResource*>(enter.object()); 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<FileIOResource::FileHolder> file_holder = 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) file_io_resource->file_holder(); 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!FileIOResource::FileHolder::IsValid(file_holder)) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (length < 0 || offset < 0 || 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !base::IsValueInRangeForNumericType<off_t>(offset)) { 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::IsValueInRangeForNumericType<size_t>(length)) { 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_NOMEMORY; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Ensure any bits we don't recognize are zero. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (protection & 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags & 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~(PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE | 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_FILEMAPFLAG_FIXED)) { 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Ensure at least one of SHARED and PRIVATE is set. 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!(flags & (PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE))) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Ensure at most one of SHARED and PRIVATE is set. 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((flags & PP_FILEMAPFLAG_SHARED) && 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (flags & PP_FILEMAPFLAG_PRIVATE)) { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!address) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Callback<MapResult()> map_cb( 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&FileMappingResource::DoMapBlocking, file_holder, *address, 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) length, protection, flags, offset)); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (callback->is_blocking()) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The plugin could release its reference to this instance when we release 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the proxy lock below. 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<FileMappingResource> protect(this); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MapResult map_result; 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Release the proxy lock while making a potentially slow file call. 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProxyAutoUnlock unlock; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) map_result = map_cb.Run(); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnMapCompleted(address, length, callback, map_result); 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return map_result.result; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::PostTaskAndReplyWithResult( 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(), 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) map_cb, 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted, 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(address), 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) length, 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int32_t FileMappingResource::Unmap(PP_Instance /* instance */, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const void* address, 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t length, 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!address) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::IsValueInRangeForNumericType<size_t>(length)) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Callback<int32_t()> unmap_cb( 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&FileMappingResource::DoUnmapBlocking, address, length)); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (callback->is_blocking()) { 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Release the proxy lock while making a potentially slow file call. 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProxyAutoUnlock unlock; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return unmap_cb.Run(); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::PostTaskAndReplyWithResult( 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(), 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unmap_cb, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int64_t FileMappingResource::GetMapPageSize(PP_Instance /* instance */) { 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DoGetMapPageSize(); 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileMappingResource::OnMapCompleted( 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void** mapped_address_out_param, 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t length, 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback, 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MapResult& map_result) { 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (callback->aborted()) { 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (map_result.result == PP_OK) { 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the Map operation was successful, we need to Unmap to avoid leaks. 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The plugin won't get the address, so doesn't have a chance to do the 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Unmap. 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner()->PostTask( 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(base::IgnoreResult(&FileMappingResource::DoUnmapBlocking), 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) map_result.address, 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) length)); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (map_result.result == PP_OK) 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *mapped_address_out_param = map_result.address; 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!callback->is_blocking()) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback->Run(map_result.result); 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace proxy 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace ppapi 161