• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ppapi/proxy/file_mapping_resource.h"
6 
7 #include "base/bind.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"
15 
16 namespace ppapi {
17 namespace proxy {
18 
FileMappingResource(Connection connection,PP_Instance instance)19 FileMappingResource::FileMappingResource(Connection connection,
20                                          PP_Instance instance)
21     : PluginResource(connection, instance) {
22 }
23 
~FileMappingResource()24 FileMappingResource::~FileMappingResource() {
25 }
26 
AsPPB_FileMapping_API()27 thunk::PPB_FileMapping_API* FileMappingResource::AsPPB_FileMapping_API() {
28   return this;
29 }
30 
Map(PP_Instance,PP_Resource file_io,int64_t length,uint32_t protection,uint32_t flags,int64_t offset,void ** address,scoped_refptr<TrackedCallback> callback)31 int32_t FileMappingResource::Map(PP_Instance /* instance */,
32                                  PP_Resource file_io,
33                                  int64_t length,
34                                  uint32_t protection,
35                                  uint32_t flags,
36                                  int64_t offset,
37                                  void** address,
38                                  scoped_refptr<TrackedCallback> callback) {
39   thunk::EnterResourceNoLock<thunk::PPB_FileIO_API> enter(file_io, true);
40   if (enter.failed())
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;
51   }
52   if (!base::IsValueInRangeForNumericType<size_t>(length)) {
53     return PP_ERROR_NOMEMORY;
54   }
55 
56   // Ensure any bits we don't recognize are zero.
57   if (protection &
58       ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) {
59     return PP_ERROR_BADARGUMENT;
60   }
61   if (flags &
62       ~(PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE |
63         PP_FILEMAPFLAG_FIXED)) {
64     return PP_ERROR_BADARGUMENT;
65   }
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;
73   }
74   if (!address)
75     return PP_ERROR_BADARGUMENT;
76 
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);
84     MapResult map_result;
85     {
86       // Release the proxy lock while making a potentially slow file call.
87       ProxyAutoUnlock unlock;
88       map_result = map_cb.Run();
89     }
90     OnMapCompleted(address, length, callback, map_result);
91     return map_result.result;
92   } else {
93     base::PostTaskAndReplyWithResult(
94       PpapiGlobals::Get()->GetFileTaskRunner(),
95       FROM_HERE,
96       map_cb,
97       RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted,
98                           this,
99                           base::Unretained(address),
100                           length,
101                           callback)));
102     return PP_OK_COMPLETIONPENDING;
103   }
104 }
105 
Unmap(PP_Instance,const void * address,int64_t length,scoped_refptr<TrackedCallback> callback)106 int32_t FileMappingResource::Unmap(PP_Instance /* instance */,
107                                    const void* address,
108                                    int64_t length,
109                                    scoped_refptr<TrackedCallback> callback) {
110   if (!address)
111     return PP_ERROR_BADARGUMENT;
112   if (!base::IsValueInRangeForNumericType<size_t>(length))
113     return PP_ERROR_BADARGUMENT;
114 
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();
121   } else {
122     base::PostTaskAndReplyWithResult(
123       PpapiGlobals::Get()->GetFileTaskRunner(),
124       FROM_HERE,
125       unmap_cb,
126       RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
127     return PP_OK_COMPLETIONPENDING;
128   }
129 }
130 
GetMapPageSize(PP_Instance)131 int64_t FileMappingResource::GetMapPageSize(PP_Instance /* instance */) {
132   return DoGetMapPageSize();
133 }
134 
OnMapCompleted(void ** mapped_address_out_param,int64_t length,scoped_refptr<TrackedCallback> callback,const MapResult & map_result)135 void FileMappingResource::OnMapCompleted(
136     void** mapped_address_out_param,
137     int64_t length,
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
144       // Unmap.
145       PpapiGlobals::Get()->GetFileTaskRunner()->PostTask(
146           FROM_HERE,
147           base::Bind(base::IgnoreResult(&FileMappingResource::DoUnmapBlocking),
148                      map_result.address,
149                      length));
150     }
151     return;
152   }
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);
157 }
158 
159 }  // namespace proxy
160 }  // namespace ppapi
161