1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/file_mapping_resource.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/task_runner_util.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/shared_impl/tracked_callback.h"
12 #include "ppapi/shared_impl/var.h"
13 #include "ppapi/thunk/enter.h"
14 #include "ppapi/thunk/ppb_file_io_api.h"
19 FileMappingResource::FileMappingResource(Connection connection
,
21 : PluginResource(connection
, instance
) {
24 FileMappingResource::~FileMappingResource() {
27 thunk::PPB_FileMapping_API
* FileMappingResource::AsPPB_FileMapping_API() {
31 int32_t FileMappingResource::Map(PP_Instance
/* instance */,
38 scoped_refptr
<TrackedCallback
> callback
) {
39 thunk::EnterResourceNoLock
<thunk::PPB_FileIO_API
> enter(file_io
, true);
41 return PP_ERROR_BADARGUMENT
;
42 FileIOResource
* file_io_resource
=
43 static_cast<FileIOResource
*>(enter
.object());
44 scoped_refptr
<FileIOResource::FileHolder
> file_holder
=
45 file_io_resource
->file_holder();
46 if (!FileIOResource::FileHolder::IsValid(file_holder
))
47 return PP_ERROR_FAILED
;
48 if (length
< 0 || offset
< 0 ||
49 !base::IsValueInRangeForNumericType
<off_t
>(offset
)) {
50 return PP_ERROR_BADARGUMENT
;
52 if (!base::IsValueInRangeForNumericType
<size_t>(length
)) {
53 return PP_ERROR_NOMEMORY
;
56 // Ensure any bits we don't recognize are zero.
58 ~(PP_FILEMAPPROTECTION_READ
| PP_FILEMAPPROTECTION_WRITE
)) {
59 return PP_ERROR_BADARGUMENT
;
62 ~(PP_FILEMAPFLAG_SHARED
| PP_FILEMAPFLAG_PRIVATE
|
63 PP_FILEMAPFLAG_FIXED
)) {
64 return PP_ERROR_BADARGUMENT
;
66 // Ensure at least one of SHARED and PRIVATE is set.
67 if (!(flags
& (PP_FILEMAPFLAG_SHARED
| PP_FILEMAPFLAG_PRIVATE
)))
68 return PP_ERROR_BADARGUMENT
;
69 // Ensure at most one of SHARED and PRIVATE is set.
70 if ((flags
& PP_FILEMAPFLAG_SHARED
) &&
71 (flags
& PP_FILEMAPFLAG_PRIVATE
)) {
72 return PP_ERROR_BADARGUMENT
;
75 return PP_ERROR_BADARGUMENT
;
77 base::Callback
<MapResult()> map_cb(
78 base::Bind(&FileMappingResource::DoMapBlocking
, file_holder
, *address
,
79 length
, protection
, flags
, offset
));
80 if (callback
->is_blocking()) {
81 // The plugin could release its reference to this instance when we release
82 // the proxy lock below.
83 scoped_refptr
<FileMappingResource
> protect(this);
86 // Release the proxy lock while making a potentially slow file call.
87 ProxyAutoUnlock unlock
;
88 map_result
= map_cb
.Run();
90 OnMapCompleted(address
, length
, callback
, map_result
);
91 return map_result
.result
;
93 base::PostTaskAndReplyWithResult(
94 PpapiGlobals::Get()->GetFileTaskRunner(),
97 RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted
,
99 base::Unretained(address
),
102 return PP_OK_COMPLETIONPENDING
;
106 int32_t FileMappingResource::Unmap(PP_Instance
/* instance */,
109 scoped_refptr
<TrackedCallback
> callback
) {
111 return PP_ERROR_BADARGUMENT
;
112 if (!base::IsValueInRangeForNumericType
<size_t>(length
))
113 return PP_ERROR_BADARGUMENT
;
115 base::Callback
<int32_t()> unmap_cb(
116 base::Bind(&FileMappingResource::DoUnmapBlocking
, address
, length
));
117 if (callback
->is_blocking()) {
118 // Release the proxy lock while making a potentially slow file call.
119 ProxyAutoUnlock unlock
;
120 return unmap_cb
.Run();
122 base::PostTaskAndReplyWithResult(
123 PpapiGlobals::Get()->GetFileTaskRunner(),
126 RunWhileLocked(Bind(&TrackedCallback::Run
, callback
)));
127 return PP_OK_COMPLETIONPENDING
;
131 int64_t FileMappingResource::GetMapPageSize(PP_Instance
/* instance */) {
132 return DoGetMapPageSize();
135 void FileMappingResource::OnMapCompleted(
136 void** mapped_address_out_param
,
138 scoped_refptr
<TrackedCallback
> callback
,
139 const MapResult
& map_result
) {
140 if (callback
->aborted()) {
141 if (map_result
.result
== PP_OK
) {
142 // If the Map operation was successful, we need to Unmap to avoid leaks.
143 // The plugin won't get the address, so doesn't have a chance to do the
145 PpapiGlobals::Get()->GetFileTaskRunner()->PostTask(
147 base::Bind(base::IgnoreResult(&FileMappingResource::DoUnmapBlocking
),
153 if (map_result
.result
== PP_OK
)
154 *mapped_address_out_param
= map_result
.address
;
155 if (!callback
->is_blocking())
156 callback
->Run(map_result
.result
);