Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
|
teravest
2014/01/23 21:40:58
boring nit: 2014 :(
dmichael (off chromium)
2014/01/24 20:02:50
Done.
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ppapi/proxy/file_mapping_resource.h" | |
| 6 | |
| 7 #if defined(OS_POSIX) | |
|
teravest
2014/01/23 21:40:58
It would be cool if there was an abstraction you c
dmichael (off chromium)
2014/01/24 20:02:50
Yeah... I had already considered it, and was thin
| |
| 8 #include <stdio.h> | |
| 9 #include <sys/mman.h> | |
| 10 #include <unistd.h> | |
| 11 #endif | |
| 12 | |
| 13 #include <limits> | |
| 14 | |
| 15 #include "base/bind.h" | |
| 16 #include "base/numerics/safe_conversions.h" | |
| 17 #include "base/task_runner_util.h" | |
| 18 #include "ppapi/shared_impl/tracked_callback.h" | |
| 19 #include "ppapi/shared_impl/var.h" | |
| 20 #include "ppapi/thunk/enter.h" | |
| 21 #include "ppapi/thunk/ppb_file_io_api.h" | |
| 22 | |
| 23 namespace ppapi { | |
| 24 namespace proxy { | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 int32_t ErrnoToPPError(int error_code) { | |
| 29 switch (error_code) { | |
| 30 case EACCES: | |
| 31 return PP_ERROR_NOACCESS; | |
| 32 case EAGAIN: | |
| 33 return PP_ERROR_NOMEMORY; | |
| 34 case EINVAL: | |
| 35 return PP_ERROR_BADARGUMENT; | |
| 36 case ENFILE: | |
| 37 case ENOMEM: | |
| 38 return PP_ERROR_NOMEMORY; | |
| 39 default: | |
| 40 return PP_ERROR_FAILED; | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 } | |
| 45 | |
| 46 FileMappingResource::FileMappingResource(Connection connection, | |
| 47 PP_Instance instance) | |
| 48 : PluginResource(connection, instance) { | |
| 49 } | |
| 50 | |
| 51 FileMappingResource::~FileMappingResource() { | |
| 52 } | |
| 53 | |
| 54 thunk::PPB_FileMapping_API* FileMappingResource::AsPPB_FileMapping_API() { | |
| 55 return this; | |
| 56 } | |
| 57 | |
| 58 int32_t FileMappingResource::Map(PP_Instance /* instance */, | |
| 59 PP_Resource file_io, | |
| 60 int64_t length, | |
| 61 uint32_t map_protection, | |
| 62 uint32_t map_flags, | |
| 63 int64_t offset, | |
| 64 void** address, | |
| 65 scoped_refptr<TrackedCallback> callback) { | |
| 66 thunk::EnterResourceNoLock<thunk::PPB_FileIO_API> enter(file_io, true); | |
| 67 if (enter.failed()) | |
| 68 return PP_ERROR_BADARGUMENT; | |
| 69 FileIOResource* file_io_resource = | |
| 70 static_cast<FileIOResource*>(enter.object()); | |
| 71 scoped_refptr<FileIOResource::FileHandleHolder> file_handle = | |
| 72 file_io_resource->file_handle(); | |
| 73 if (!FileIOResource::FileHandleHolder::IsValid(file_handle)) | |
| 74 return PP_ERROR_BADARGUMENT; | |
|
bbudge
2014/01/23 23:01:03
Kind of a gray area, but this could also be PP_ERR
dmichael (off chromium)
2014/01/24 20:02:50
I think of PP_ERROR_FAILED as a more generic, "we
bbudge
2014/01/24 21:41:21
In retrospect, we should probably have defined a P
dmichael (off chromium)
2014/01/24 22:05:13
Okay, I'm convinced. Done.
| |
| 75 if (length < 0 || offset < 0) | |
| 76 return PP_ERROR_BADARGUMENT; | |
| 77 if (!base::IsValueInRangeForNumericType<size_t>(length)) | |
| 78 return PP_ERROR_NOMEMORY; | |
|
teravest
2014/01/23 21:40:58
I'd argue that this should be BADARGUMENT. But eit
dmichael (off chromium)
2014/01/24 20:02:50
This is for platform consistency. On 64-bit, value
| |
| 79 if (!base::IsValueInRangeForNumericType<off_t>(offset)) | |
| 80 return PP_ERROR_BADARGUMENT; | |
| 81 | |
| 82 // Ensure no bits that we don't recognize are set. | |
| 83 if (map_protection & | |
| 84 ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) { | |
| 85 return PP_ERROR_BADARGUMENT; | |
| 86 } | |
| 87 if (map_flags & | |
| 88 ~(PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE | | |
| 89 PP_FILEMAPFLAG_FIXED)) { | |
| 90 return PP_ERROR_BADARGUMENT; | |
| 91 } | |
| 92 // Ensure at least one of SHARED and PRIVATE is set. | |
| 93 if (!(map_flags & (PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE))) | |
| 94 return PP_ERROR_BADARGUMENT; | |
| 95 // Ensure at most one of SHARED and PRIVATE is set. | |
| 96 if ((map_flags & PP_FILEMAPFLAG_SHARED) && | |
| 97 (map_flags & PP_FILEMAPFLAG_PRIVATE)) { | |
| 98 return PP_ERROR_BADARGUMENT; | |
| 99 } | |
| 100 if (!address) | |
| 101 return PP_ERROR_BADARGUMENT; | |
| 102 | |
| 103 base::Callback<MapResult()> map_op( | |
|
bbudge
2014/01/24 21:41:21
Maybe a better name is map_task or map_cb?
Same fo
| |
| 104 base::Bind(&FileMappingResource::DoMap, file_handle, *address, length, | |
| 105 map_protection, map_flags, offset)); | |
| 106 if (callback->is_blocking()) { | |
| 107 // The plugin could release its reference to this instance when we release | |
| 108 // the proxy lock below. | |
| 109 scoped_refptr<FileMappingResource> protect(this); | |
| 110 MapResult map_result; | |
| 111 { | |
| 112 // Release the proxy lock while making a potentially slow file call. | |
| 113 ProxyAutoUnlock unlock; | |
| 114 map_result = map_op.Run(); | |
| 115 } | |
| 116 OnMapCompleted(address, callback, map_result); | |
| 117 return map_result.result; | |
| 118 } else { | |
| 119 base::PostTaskAndReplyWithResult( | |
| 120 PpapiGlobals::Get()->GetFileTaskRunner(), | |
| 121 FROM_HERE, | |
| 122 map_op, | |
| 123 RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted, | |
| 124 this, | |
| 125 base::Unretained(address), | |
| 126 callback))); | |
| 127 return PP_OK_COMPLETIONPENDING; | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 int32_t FileMappingResource::Unmap(PP_Instance /* instance */, | |
| 132 const void* address, | |
| 133 int64_t length, | |
| 134 scoped_refptr<TrackedCallback> callback) { | |
| 135 if (!address) | |
| 136 return PP_ERROR_BADARGUMENT; | |
| 137 if (!base::IsValueInRangeForNumericType<size_t>(length)) | |
| 138 return PP_ERROR_BADARGUMENT; | |
| 139 | |
| 140 base::Callback<int32_t()> unmap_op( | |
| 141 base::Bind(&FileMappingResource::DoUnmap, address, length)); | |
| 142 if (callback->is_blocking()) { | |
| 143 // Release the proxy lock while making a potentially slow file call. | |
| 144 ProxyAutoUnlock unlock; | |
| 145 return unmap_op.Run(); | |
| 146 } else { | |
| 147 base::PostTaskAndReplyWithResult( | |
| 148 PpapiGlobals::Get()->GetFileTaskRunner(), | |
| 149 FROM_HERE, | |
| 150 unmap_op, | |
| 151 RunWhileLocked(Bind(&TrackedCallback::Run, callback))); | |
| 152 return PP_OK_COMPLETIONPENDING; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 int64_t FileMappingResource::GetMapPageSize(PP_Instance /* instance */) { | |
| 157 // TODO(dmichael): It might be better to port sys_info_posix.cc to NaCl and | |
| 158 // call Sysinfo::VMAllocationGranularity. | |
| 159 #if defined(OS_POSIX) | |
| 160 return getpagesize(); | |
| 161 #else // defined(OS_POSIX) | |
| 162 NOTREACHED(); | |
|
bbudge
2014/01/23 23:01:03
NOTIMPLEMENTED()?
dmichael (off chromium)
2014/01/24 20:02:50
Oops, the other Windows functions just return PP_E
bbudge
2014/01/24 21:41:21
No big deal.
| |
| 163 return 0; | |
| 164 #endif | |
| 165 } | |
| 166 | |
| 167 // static | |
| 168 FileMappingResource::MapResult FileMappingResource::DoMap( | |
| 169 scoped_refptr<FileIOResource::FileHandleHolder> handle, | |
| 170 void* address_hint, | |
| 171 int64_t length, | |
| 172 uint32_t map_protection, | |
| 173 uint32_t map_flags, | |
| 174 int64_t offset) { | |
| 175 #if defined(OS_POSIX) | |
| 176 int prot_for_mmap = 0; | |
| 177 if (map_protection & PP_FILEMAPPROTECTION_READ) | |
| 178 prot_for_mmap |= PROT_READ; | |
| 179 if (map_protection & PP_FILEMAPPROTECTION_WRITE) | |
| 180 prot_for_mmap |= PROT_WRITE; | |
| 181 if (prot_for_mmap == 0) | |
| 182 prot_for_mmap = PROT_NONE; | |
| 183 | |
| 184 int flags_for_mmap = 0; | |
| 185 if (map_flags & PP_FILEMAPFLAG_SHARED) | |
| 186 flags_for_mmap |= MAP_SHARED; | |
| 187 if (map_flags & PP_FILEMAPFLAG_PRIVATE) | |
| 188 flags_for_mmap |= MAP_PRIVATE; | |
| 189 if (map_flags & PP_FILEMAPFLAG_FIXED) | |
| 190 flags_for_mmap |= MAP_FIXED; | |
| 191 | |
| 192 MapResult map_result; | |
| 193 map_result.address = | |
| 194 mmap(address_hint, | |
| 195 static_cast<size_t>(length), | |
| 196 prot_for_mmap, | |
| 197 flags_for_mmap, | |
| 198 handle->raw_handle(), | |
| 199 static_cast<off_t>(offset)); | |
| 200 if (map_result.address != MAP_FAILED) | |
| 201 map_result.result = PP_OK; | |
| 202 else | |
| 203 map_result.result = ErrnoToPPError(errno); | |
|
bbudge
2014/01/23 23:01:03
nit: Seems like you could access this inside Errno
dmichael (off chromium)
2014/01/24 20:02:50
Yeah... I thought about that, but I already hate
bbudge
2014/01/24 21:41:21
OK
| |
| 204 return map_result; | |
| 205 #else // defined(OS_POSIX) | |
| 206 // TODO(dmichael): Implement for Windows (crbug.com/83774). | |
| 207 MapResult map_result; | |
| 208 map_result.result = PP_ERROR_NOTSUPPORTED; | |
| 209 return map_result; | |
| 210 #endif | |
| 211 } | |
| 212 | |
| 213 void FileMappingResource::OnMapCompleted( | |
| 214 void** mapped_address_out_param, | |
| 215 scoped_refptr<TrackedCallback> callback, | |
| 216 const MapResult& map_result) { | |
| 217 // TODO(dmichael): If the callback is aborted, should we unmap? | |
|
teravest
2014/01/23 21:40:58
I think we should unmap when the callback is abort
dmichael (off chromium)
2014/01/24 20:02:50
Good point... they do get a PP_ERROR_ABORTED callb
| |
| 218 if (callback->aborted()) | |
| 219 return; | |
| 220 if (map_result.result == 0) | |
|
bbudge
2014/01/23 23:01:03
Since this is logically a PP_Error, PP_OK?
dmichael (off chromium)
2014/01/24 20:02:50
Done.
| |
| 221 *mapped_address_out_param = map_result.address; | |
| 222 if (!callback->is_blocking()) | |
| 223 callback->Run(map_result.result); | |
| 224 } | |
| 225 | |
| 226 // static | |
| 227 int32_t FileMappingResource::DoUnmap(const void* address, int64_t length) { | |
| 228 #if defined(OS_POSIX) | |
| 229 int result = munmap(const_cast<void*>(address), static_cast<size_t>(length)); | |
| 230 if (result) | |
| 231 return ErrnoToPPError(errno); | |
| 232 return PP_OK; | |
| 233 #else | |
| 234 // TODO(dmichael): Implement for Windows (crbug.com/83774). | |
| 235 return PP_ERROR_NOTSUPPORTED; | |
| 236 #endif | |
| 237 } | |
| 238 | |
| 239 } // namespace proxy | |
| 240 } // namespace ppapi | |
| OLD | NEW |