OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/ppb_file_ref_proxy.h" | 5 #include "ppapi/proxy/ppb_file_ref_proxy.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "ppapi/c/pp_errors.h" | 10 #include "ppapi/c/pp_errors.h" |
(...skipping 29 matching lines...) Expand all Loading... | |
40 virtual PP_Resource GetParent() OVERRIDE; | 40 virtual PP_Resource GetParent() OVERRIDE; |
41 virtual int32_t MakeDirectory( | 41 virtual int32_t MakeDirectory( |
42 PP_Bool make_ancestors, | 42 PP_Bool make_ancestors, |
43 scoped_refptr<TrackedCallback> callback) OVERRIDE; | 43 scoped_refptr<TrackedCallback> callback) OVERRIDE; |
44 virtual int32_t Touch(PP_Time last_access_time, | 44 virtual int32_t Touch(PP_Time last_access_time, |
45 PP_Time last_modified_time, | 45 PP_Time last_modified_time, |
46 scoped_refptr<TrackedCallback> callback) OVERRIDE; | 46 scoped_refptr<TrackedCallback> callback) OVERRIDE; |
47 virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE; | 47 virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE; |
48 virtual int32_t Rename(PP_Resource new_file_ref, | 48 virtual int32_t Rename(PP_Resource new_file_ref, |
49 scoped_refptr<TrackedCallback> callback) OVERRIDE; | 49 scoped_refptr<TrackedCallback> callback) OVERRIDE; |
50 virtual int32_t Query(PP_FileInfo* info, | |
51 scoped_refptr<TrackedCallback> callback) OVERRIDE; | |
50 virtual PP_Var GetAbsolutePath() OVERRIDE; | 52 virtual PP_Var GetAbsolutePath() OVERRIDE; |
51 | 53 |
52 // Executes the pending callback with the given ID. See pending_callbacks_. | 54 // Executes the pending callback with the given ID. See pending_callbacks_. |
53 void ExecuteCallback(int callback_id, int32_t result); | 55 void ExecuteCallback(int callback_id, int32_t result); |
56 void SetFileInfo(int callback_id, const PP_FileInfo& info); | |
54 | 57 |
55 private: | 58 private: |
56 PluginDispatcher* GetDispatcher() const { | 59 PluginDispatcher* GetDispatcher() const { |
57 return PluginDispatcher::GetForResource(this); | 60 return PluginDispatcher::GetForResource(this); |
58 } | 61 } |
59 | 62 |
60 // Adds a callback to the list and returns its ID. | 63 // Adds a callback to the list and returns its ID. |
61 int SendCallback(scoped_refptr<TrackedCallback> callback); | 64 int SendCallback(scoped_refptr<TrackedCallback> callback); |
62 | 65 |
63 // This class can have any number of out-standing requests with completion | 66 // This class can have any number of out-standing requests with completion |
64 // callbacks, in contrast to most resources which have one possible pending | 67 // callbacks, in contrast to most resources which have one possible pending |
65 // callback pending (like a Flush callback). | 68 // callback pending (like a Flush callback). |
66 // | 69 // |
67 // To keep track of them, assign integer IDs to the callbacks, which is how | 70 // To keep track of them, assign integer IDs to the callbacks, which is how |
68 // the callback will be identified when it's passed to the host and then | 71 // the callback will be identified when it's passed to the host and then |
69 // back here. Use unsigned so that overflow is well-defined. | 72 // back here. Use unsigned so that overflow is well-defined. |
70 unsigned int next_callback_id_; | 73 unsigned int next_callback_id_; |
71 typedef std::map<unsigned int, | 74 typedef std::map<unsigned int, |
72 scoped_refptr<TrackedCallback> > PendingCallbackMap; | 75 scoped_refptr<TrackedCallback> > PendingCallbackMap; |
73 PendingCallbackMap pending_callbacks_; | 76 PendingCallbackMap pending_callbacks_; |
74 | 77 |
78 // Used to keep pointers to PP_FileInfo instances that are written before | |
79 // callbacks are invoked. The id of a pending file info will match that of | |
80 // the corresponding callback. | |
81 typedef std::map<unsigned int, PP_FileInfo*> PendingFileInfoMap; | |
82 PendingFileInfoMap pending_file_infos_; | |
83 | |
75 DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); | 84 DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); |
76 }; | 85 }; |
77 | 86 |
78 FileRef::FileRef(const PPB_FileRef_CreateInfo& info) | 87 FileRef::FileRef(const PPB_FileRef_CreateInfo& info) |
79 : PPB_FileRef_Shared(OBJECT_IS_PROXY, info), | 88 : PPB_FileRef_Shared(OBJECT_IS_PROXY, info), |
80 next_callback_id_(0u) { | 89 next_callback_id_(0u) { |
81 } | 90 } |
82 | 91 |
83 FileRef::~FileRef() { | 92 FileRef::~FileRef() { |
84 // The callbacks map should have been cleared by LastPluginRefWasDeleted. | 93 // The callbacks map should have been cleared by LastPluginRefWasDeleted. |
85 DCHECK(pending_callbacks_.empty()); | 94 DCHECK(pending_callbacks_.empty()); |
95 DCHECK(pending_file_infos_.empty()); | |
86 } | 96 } |
87 | 97 |
88 void FileRef::LastPluginRefWasDeleted() { | 98 void FileRef::LastPluginRefWasDeleted() { |
89 // The callback tracker will abort our callbacks for us. | 99 // The callback tracker will abort our callbacks for us. |
90 pending_callbacks_.clear(); | 100 pending_callbacks_.clear(); |
101 pending_file_infos_.clear(); | |
91 } | 102 } |
92 | 103 |
93 PP_Resource FileRef::GetParent() { | 104 PP_Resource FileRef::GetParent() { |
94 PPB_FileRef_CreateInfo create_info; | 105 PPB_FileRef_CreateInfo create_info; |
95 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent( | 106 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent( |
96 API_ID_PPB_FILE_REF, host_resource(), &create_info)); | 107 API_ID_PPB_FILE_REF, host_resource(), &create_info)); |
97 return PPB_FileRef_Proxy::DeserializeFileRef(create_info); | 108 return PPB_FileRef_Proxy::DeserializeFileRef(create_info); |
98 } | 109 } |
99 | 110 |
100 int32_t FileRef::MakeDirectory(PP_Bool make_ancestors, | 111 int32_t FileRef::MakeDirectory(PP_Bool make_ancestors, |
(...skipping 26 matching lines...) Expand all Loading... | |
127 if (!new_file_ref_object || | 138 if (!new_file_ref_object || |
128 new_file_ref_object->host_resource().instance() != pp_instance()) | 139 new_file_ref_object->host_resource().instance() != pp_instance()) |
129 return PP_ERROR_BADRESOURCE; | 140 return PP_ERROR_BADRESOURCE; |
130 | 141 |
131 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename( | 142 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename( |
132 API_ID_PPB_FILE_REF, host_resource(), | 143 API_ID_PPB_FILE_REF, host_resource(), |
133 new_file_ref_object->host_resource(), SendCallback(callback))); | 144 new_file_ref_object->host_resource(), SendCallback(callback))); |
134 return PP_OK_COMPLETIONPENDING; | 145 return PP_OK_COMPLETIONPENDING; |
135 } | 146 } |
136 | 147 |
148 int32_t FileRef::Query(PP_FileInfo* info, | |
149 scoped_refptr<TrackedCallback> callback) { | |
150 // Store the pending file info id. | |
151 int id = SendCallback(callback); | |
152 pending_file_infos_[id] = info; | |
153 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Query( | |
154 API_ID_PPB_FILE_REF, host_resource(), id)); | |
155 return PP_OK_COMPLETIONPENDING; | |
156 } | |
157 | |
137 PP_Var FileRef::GetAbsolutePath() { | 158 PP_Var FileRef::GetAbsolutePath() { |
138 ReceiveSerializedVarReturnValue result; | 159 ReceiveSerializedVarReturnValue result; |
139 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath( | 160 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath( |
140 API_ID_PPB_FILE_REF, host_resource(), &result)); | 161 API_ID_PPB_FILE_REF, host_resource(), &result)); |
141 return result.Return(GetDispatcher()); | 162 return result.Return(GetDispatcher()); |
142 } | 163 } |
143 | 164 |
144 void FileRef::ExecuteCallback(int callback_id, int32_t result) { | 165 void FileRef::ExecuteCallback(int callback_id, int32_t result) { |
145 PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id); | 166 PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id); |
146 if (found == pending_callbacks_.end()) { | 167 if (found == pending_callbacks_.end()) { |
147 // This will happen when the plugin deletes its resource with a pending | 168 // This will happen when the plugin deletes its resource with a pending |
148 // callback. The callback will be locally issued with an ABORTED call while | 169 // callback. The callback will be locally issued with an ABORTED call while |
149 // the operation may still be pending in the renderer. | 170 // the operation may still be pending in the renderer. |
150 return; | 171 return; |
151 } | 172 } |
152 | 173 |
153 // Executing the callback may mutate the callback list. | 174 // Executing the callback may mutate the callback list. |
154 scoped_refptr<TrackedCallback> callback = found->second; | 175 scoped_refptr<TrackedCallback> callback = found->second; |
155 pending_callbacks_.erase(found); | 176 pending_callbacks_.erase(found); |
156 callback->Run(result); | 177 callback->Run(result); |
157 } | 178 } |
158 | 179 |
180 void FileRef::SetFileInfo(int callback_id, const PP_FileInfo& info) { | |
181 PendingFileInfoMap::iterator found = pending_file_infos_.find(callback_id); | |
182 if (found == pending_file_infos_.end()) | |
183 return; | |
184 PP_FileInfo* target_info = found->second; | |
185 *target_info = info; | |
186 pending_file_infos_.erase(found); | |
187 } | |
188 | |
159 int FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) { | 189 int FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) { |
160 // In extreme cases the IDs may wrap around, so avoid duplicates. | 190 // In extreme cases the IDs may wrap around, so avoid duplicates. |
161 while (pending_callbacks_.count(next_callback_id_)) | 191 while (pending_callbacks_.count(next_callback_id_)) |
162 ++next_callback_id_; | 192 ++next_callback_id_; |
163 | 193 |
164 pending_callbacks_[next_callback_id_] = callback; | 194 pending_callbacks_[next_callback_id_] = callback; |
165 return next_callback_id_++; | 195 return next_callback_id_++; |
166 } | 196 } |
167 | 197 |
168 PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher) | 198 PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher) |
(...skipping 24 matching lines...) Expand all Loading... | |
193 bool handled = true; | 223 bool handled = true; |
194 IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Proxy, msg) | 224 IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Proxy, msg) |
195 #if !defined(OS_NACL) | 225 #if !defined(OS_NACL) |
196 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Create, OnMsgCreate) | 226 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Create, OnMsgCreate) |
197 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetParent, OnMsgGetParent) | 227 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetParent, OnMsgGetParent) |
198 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_MakeDirectory, | 228 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_MakeDirectory, |
199 OnMsgMakeDirectory) | 229 OnMsgMakeDirectory) |
200 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Touch, OnMsgTouch) | 230 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Touch, OnMsgTouch) |
201 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Delete, OnMsgDelete) | 231 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Delete, OnMsgDelete) |
202 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Rename, OnMsgRename) | 232 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Rename, OnMsgRename) |
233 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Query, OnMsgQuery) | |
203 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetAbsolutePath, | 234 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetAbsolutePath, |
204 OnMsgGetAbsolutePath) | 235 OnMsgGetAbsolutePath) |
205 #endif // !defined(OS_NACL) | 236 #endif // !defined(OS_NACL) |
206 | 237 |
207 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_CallbackComplete, | 238 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_CallbackComplete, |
208 OnMsgCallbackComplete) | 239 OnMsgCallbackComplete) |
240 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_QueryCallbackComplete, | |
241 OnMsgQueryCallbackComplete) | |
209 IPC_MESSAGE_UNHANDLED(handled = false) | 242 IPC_MESSAGE_UNHANDLED(handled = false) |
210 IPC_END_MESSAGE_MAP() | 243 IPC_END_MESSAGE_MAP() |
211 return handled; | 244 return handled; |
212 } | 245 } |
213 | 246 |
214 // static | 247 // static |
215 void PPB_FileRef_Proxy::SerializeFileRef(PP_Resource file_ref, | 248 void PPB_FileRef_Proxy::SerializeFileRef(PP_Resource file_ref, |
216 PPB_FileRef_CreateInfo* result) { | 249 PPB_FileRef_CreateInfo* result) { |
217 EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, false); | 250 EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, false); |
218 if (enter.succeeded()) | 251 if (enter.succeeded()) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 int callback_id) { | 320 int callback_id) { |
288 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( | 321 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( |
289 file_ref, callback_factory_, | 322 file_ref, callback_factory_, |
290 &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id); | 323 &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id); |
291 if (enter.succeeded()) { | 324 if (enter.succeeded()) { |
292 enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(), | 325 enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(), |
293 enter.callback())); | 326 enter.callback())); |
294 } | 327 } |
295 } | 328 } |
296 | 329 |
330 void PPB_FileRef_Proxy::OnMsgQuery(const HostResource& file_ref, | |
331 int callback_id) { | |
332 PP_FileInfo* info = new PP_FileInfo(); | |
333 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( | |
334 file_ref, callback_factory_, | |
335 &PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost, file_ref, | |
336 base::Owned(info), callback_id); | |
yzshen1
2013/03/21 22:02:05
I thought you will need to change your OnQueryCall
| |
337 if (enter.succeeded()) | |
338 enter.SetResult(enter.object()->Query(info, enter.callback())); | |
339 } | |
340 | |
297 void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource, | 341 void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource, |
298 SerializedVarReturnValue result) { | 342 SerializedVarReturnValue result) { |
299 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); | 343 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); |
300 if (enter.succeeded()) | 344 if (enter.succeeded()) |
301 result.Return(dispatcher(), enter.object()->GetAbsolutePath()); | 345 result.Return(dispatcher(), enter.object()->GetAbsolutePath()); |
302 } | 346 } |
303 #endif // !defined(OS_NACL) | 347 #endif // !defined(OS_NACL) |
304 | 348 |
305 void PPB_FileRef_Proxy::OnMsgCallbackComplete( | 349 void PPB_FileRef_Proxy::OnMsgCallbackComplete( |
306 const HostResource& host_resource, | 350 const HostResource& host_resource, |
307 int callback_id, | 351 int callback_id, |
308 int32_t result) { | 352 int32_t result) { |
309 // Forward the callback info to the plugin resource. | 353 // Forward the callback info to the plugin resource. |
310 EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); | 354 EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); |
311 if (enter.succeeded()) | 355 if (enter.succeeded()) |
312 static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); | 356 static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); |
313 } | 357 } |
314 | 358 |
359 void PPB_FileRef_Proxy::OnMsgQueryCallbackComplete( | |
360 const HostResource& host_resource, | |
361 const PP_FileInfo& info, | |
362 int callback_id, | |
363 int32_t result) { | |
364 EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); | |
365 if (enter.succeeded()) { | |
366 // Set the FileInfo output parameter. | |
367 static_cast<FileRef*>(enter.object())->SetFileInfo(callback_id, info); | |
368 static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); | |
369 } | |
370 } | |
371 | |
315 #if !defined(OS_NACL) | 372 #if !defined(OS_NACL) |
316 void PPB_FileRef_Proxy::OnCallbackCompleteInHost( | 373 void PPB_FileRef_Proxy::OnCallbackCompleteInHost( |
317 int32_t result, | 374 int32_t result, |
318 const HostResource& host_resource, | 375 const HostResource& host_resource, |
319 int callback_id) { | 376 int callback_id) { |
320 // Execute OnMsgCallbackComplete in the plugin process. | 377 // Execute OnMsgCallbackComplete in the plugin process. |
321 Send(new PpapiMsg_PPBFileRef_CallbackComplete( | 378 Send(new PpapiMsg_PPBFileRef_CallbackComplete( |
322 API_ID_PPB_FILE_REF, host_resource, callback_id, result)); | 379 API_ID_PPB_FILE_REF, host_resource, callback_id, result)); |
323 } | 380 } |
381 | |
382 void PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost( | |
383 int32_t result, | |
384 const HostResource& host_resource, | |
385 PP_FileInfo* info, | |
386 int callback_id) { | |
387 if (result == PP_OK) { | |
388 Send(new PpapiMsg_PPBFileRef_QueryCallbackComplete( | |
389 API_ID_PPB_FILE_REF, host_resource, *info, callback_id, result)); | |
390 } else { | |
391 PP_FileInfo tmp_info; | |
392 memset(&tmp_info, 0, sizeof(tmp_info)); | |
393 Send(new PpapiMsg_PPBFileRef_QueryCallbackComplete( | |
394 API_ID_PPB_FILE_REF, host_resource, tmp_info, callback_id, result)); | |
395 } | |
396 } | |
324 #endif // !defined(OS_NACL) | 397 #endif // !defined(OS_NACL) |
325 | 398 |
326 } // namespace proxy | 399 } // namespace proxy |
327 } // namespace ppapi | 400 } // namespace ppapi |
OLD | NEW |