Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: ppapi/proxy/ppb_file_ref_proxy.cc

Issue 10081020: PPAPI: Make blocking completion callbacks work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: export AssertLockHeld Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/ppb_file_io_proxy.cc ('k') | ppapi/proxy/ppb_file_system_proxy.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 20 matching lines...) Expand all
31 class FileRef : public PPB_FileRef_Shared { 31 class FileRef : public PPB_FileRef_Shared {
32 public: 32 public:
33 explicit FileRef(const PPB_FileRef_CreateInfo& info); 33 explicit FileRef(const PPB_FileRef_CreateInfo& info);
34 virtual ~FileRef(); 34 virtual ~FileRef();
35 35
36 // Resource overrides. 36 // Resource overrides.
37 virtual void LastPluginRefWasDeleted() OVERRIDE; 37 virtual void LastPluginRefWasDeleted() OVERRIDE;
38 38
39 // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared). 39 // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared).
40 virtual PP_Resource GetParent() OVERRIDE; 40 virtual PP_Resource GetParent() OVERRIDE;
41 virtual int32_t MakeDirectory(PP_Bool make_ancestors, 41 virtual int32_t MakeDirectory(
42 PP_CompletionCallback callback) OVERRIDE; 42 PP_Bool make_ancestors,
43 scoped_refptr<TrackedCallback> callback) OVERRIDE;
43 virtual int32_t Touch(PP_Time last_access_time, 44 virtual int32_t Touch(PP_Time last_access_time,
44 PP_Time last_modified_time, 45 PP_Time last_modified_time,
45 PP_CompletionCallback callback) OVERRIDE; 46 scoped_refptr<TrackedCallback> callback) OVERRIDE;
46 virtual int32_t Delete(PP_CompletionCallback callback) OVERRIDE; 47 virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE;
47 virtual int32_t Rename(PP_Resource new_file_ref, 48 virtual int32_t Rename(PP_Resource new_file_ref,
48 PP_CompletionCallback callback) OVERRIDE; 49 scoped_refptr<TrackedCallback> callback) OVERRIDE;
49 virtual PP_Var GetAbsolutePath() OVERRIDE; 50 virtual PP_Var GetAbsolutePath() OVERRIDE;
50 51
51 // Executes the pending callback with the given ID. See pending_callbacks_. 52 // Executes the pending callback with the given ID. See pending_callbacks_.
52 void ExecuteCallback(int callback_id, int32_t result); 53 void ExecuteCallback(int callback_id, int32_t result);
53 54
54 private: 55 private:
55 PluginDispatcher* GetDispatcher() const { 56 PluginDispatcher* GetDispatcher() const {
56 return PluginDispatcher::GetForResource(this); 57 return PluginDispatcher::GetForResource(this);
57 } 58 }
58 59
59 // Adds a callback to the list and returns its ID. Returns 0 if the callback 60 // Adds a callback to the list and returns its ID.
60 // is invalid. 61 int SendCallback(scoped_refptr<TrackedCallback> callback);
61 int SendCallback(PP_CompletionCallback callback);
62 62
63 // This class can have any number of out-standing requests with completion 63 // This class can have any number of out-standing requests with completion
64 // callbacks, in contrast to most resources which have one possible pending 64 // callbacks, in contrast to most resources which have one possible pending
65 // callback pending (like a Flush callback). 65 // callback pending (like a Flush callback).
66 // 66 //
67 // To keep track of them, assign integer IDs to the callbacks, which is how 67 // 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 68 // the callback will be identified when it's passed to the host and then
69 // back here. 69 // back here. Use unsigned so that overflow is well-defined.
70 int next_callback_id_; 70 unsigned int next_callback_id_;
71 typedef std::map<int, scoped_refptr<TrackedCallback> > PendingCallbackMap; 71 typedef std::map<unsigned int,
72 scoped_refptr<TrackedCallback> > PendingCallbackMap;
72 PendingCallbackMap pending_callbacks_; 73 PendingCallbackMap pending_callbacks_;
73 74
74 DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); 75 DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef);
75 }; 76 };
76 77
77 FileRef::FileRef(const PPB_FileRef_CreateInfo& info) 78 FileRef::FileRef(const PPB_FileRef_CreateInfo& info)
78 : PPB_FileRef_Shared(OBJECT_IS_PROXY, info), 79 : PPB_FileRef_Shared(OBJECT_IS_PROXY, info),
79 next_callback_id_(1) { 80 next_callback_id_(0u) {
80 } 81 }
81 82
82 FileRef::~FileRef() { 83 FileRef::~FileRef() {
83 // The callbacks map should have been cleared by LastPluginRefWasDeleted. 84 // The callbacks map should have been cleared by LastPluginRefWasDeleted.
84 DCHECK(pending_callbacks_.empty()); 85 DCHECK(pending_callbacks_.empty());
85 } 86 }
86 87
87 void FileRef::LastPluginRefWasDeleted() { 88 void FileRef::LastPluginRefWasDeleted() {
88 // The callback tracker will abort our callbacks for us. 89 // The callback tracker will abort our callbacks for us.
89 pending_callbacks_.clear(); 90 pending_callbacks_.clear();
90 } 91 }
91 92
92 PP_Resource FileRef::GetParent() { 93 PP_Resource FileRef::GetParent() {
93 PPB_FileRef_CreateInfo create_info; 94 PPB_FileRef_CreateInfo create_info;
94 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent( 95 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent(
95 API_ID_PPB_FILE_REF, host_resource(), &create_info)); 96 API_ID_PPB_FILE_REF, host_resource(), &create_info));
96 return PPB_FileRef_Proxy::DeserializeFileRef(create_info); 97 return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
97 } 98 }
98 99
99 int32_t FileRef::MakeDirectory(PP_Bool make_ancestors, 100 int32_t FileRef::MakeDirectory(PP_Bool make_ancestors,
100 PP_CompletionCallback callback) { 101 scoped_refptr<TrackedCallback> callback) {
101 int callback_id = SendCallback(callback);
102 if (!callback_id)
103 return PP_ERROR_BADARGUMENT;
104
105 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory( 102 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory(
106 API_ID_PPB_FILE_REF, host_resource(), make_ancestors, callback_id)); 103 API_ID_PPB_FILE_REF, host_resource(), make_ancestors,
104 SendCallback(callback)));
107 return PP_OK_COMPLETIONPENDING; 105 return PP_OK_COMPLETIONPENDING;
108 } 106 }
109 107
110 int32_t FileRef::Touch(PP_Time last_access_time, 108 int32_t FileRef::Touch(PP_Time last_access_time,
111 PP_Time last_modified_time, 109 PP_Time last_modified_time,
112 PP_CompletionCallback callback) { 110 scoped_refptr<TrackedCallback> callback) {
113 int callback_id = SendCallback(callback);
114 if (!callback_id)
115 return PP_ERROR_BADARGUMENT;
116
117 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch( 111 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch(
118 API_ID_PPB_FILE_REF, host_resource(), 112 API_ID_PPB_FILE_REF, host_resource(), last_access_time,
119 last_access_time, last_modified_time, callback_id)); 113 last_modified_time, SendCallback(callback)));
120 return PP_OK_COMPLETIONPENDING; 114 return PP_OK_COMPLETIONPENDING;
121 } 115 }
122 116
123 int32_t FileRef::Delete(PP_CompletionCallback callback) { 117 int32_t FileRef::Delete(scoped_refptr<TrackedCallback> callback) {
124 int callback_id = SendCallback(callback);
125 if (!callback_id)
126 return PP_ERROR_BADARGUMENT;
127
128 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete( 118 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete(
129 API_ID_PPB_FILE_REF, host_resource(), callback_id)); 119 API_ID_PPB_FILE_REF, host_resource(), SendCallback(callback)));
130 return PP_OK_COMPLETIONPENDING; 120 return PP_OK_COMPLETIONPENDING;
131 } 121 }
132 122
133 int32_t FileRef::Rename(PP_Resource new_file_ref, 123 int32_t FileRef::Rename(PP_Resource new_file_ref,
134 PP_CompletionCallback callback) { 124 scoped_refptr<TrackedCallback> callback) {
135 int callback_id = SendCallback(callback);
136 if (!callback_id)
137 return PP_ERROR_BADARGUMENT;
138
139 Resource* new_file_ref_object = 125 Resource* new_file_ref_object =
140 PpapiGlobals::Get()->GetResourceTracker()->GetResource(new_file_ref); 126 PpapiGlobals::Get()->GetResourceTracker()->GetResource(new_file_ref);
141 if (!new_file_ref_object || 127 if (!new_file_ref_object ||
142 new_file_ref_object->host_resource().instance() != pp_instance()) 128 new_file_ref_object->host_resource().instance() != pp_instance())
143 return PP_ERROR_BADRESOURCE; 129 return PP_ERROR_BADRESOURCE;
144 130
145 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename( 131 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename(
146 API_ID_PPB_FILE_REF, host_resource(), 132 API_ID_PPB_FILE_REF, host_resource(),
147 new_file_ref_object->host_resource(), callback_id)); 133 new_file_ref_object->host_resource(), SendCallback(callback)));
148 return PP_OK_COMPLETIONPENDING; 134 return PP_OK_COMPLETIONPENDING;
149 } 135 }
150 136
151 PP_Var FileRef::GetAbsolutePath() { 137 PP_Var FileRef::GetAbsolutePath() {
152 ReceiveSerializedVarReturnValue result; 138 ReceiveSerializedVarReturnValue result;
153 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath( 139 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath(
154 API_ID_PPB_FILE_REF, host_resource(), &result)); 140 API_ID_PPB_FILE_REF, host_resource(), &result));
155 return result.Return(GetDispatcher()); 141 return result.Return(GetDispatcher());
156 } 142 }
157 143
158 void FileRef::ExecuteCallback(int callback_id, int32_t result) { 144 void FileRef::ExecuteCallback(int callback_id, int32_t result) {
159 PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id); 145 PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id);
160 if (found == pending_callbacks_.end()) { 146 if (found == pending_callbacks_.end()) {
161 // This will happen when the plugin deletes its resource with a pending 147 // This will happen when the plugin deletes its resource with a pending
162 // callback. The callback will be locally issued with an ABORTED call while 148 // callback. The callback will be locally issued with an ABORTED call while
163 // the operation may still be pending in the renderer. 149 // the operation may still be pending in the renderer.
164 return; 150 return;
165 } 151 }
166 152
167 // Executing the callback may mutate the callback list. 153 // Executing the callback may mutate the callback list.
168 scoped_refptr<TrackedCallback> callback = found->second; 154 scoped_refptr<TrackedCallback> callback = found->second;
169 pending_callbacks_.erase(found); 155 pending_callbacks_.erase(found);
170 callback->Run(result); 156 callback->Run(result);
171 } 157 }
172 158
173 int FileRef::SendCallback(PP_CompletionCallback callback) { 159 int FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) {
174 if (!callback.func) 160 // In extreme cases the IDs may wrap around, so avoid duplicates.
175 return 0; 161 while (pending_callbacks_.count(next_callback_id_))
162 ++next_callback_id_;
176 163
177 // In extreme cases the IDs may wrap around, so avoid duplicates. 164 pending_callbacks_[next_callback_id_] = callback;
178 while (pending_callbacks_.find(next_callback_id_) != pending_callbacks_.end())
179 next_callback_id_++;
180
181 pending_callbacks_[next_callback_id_] = new TrackedCallback(this, callback);
182 return next_callback_id_++; 165 return next_callback_id_++;
183 } 166 }
184 167
185 namespace { 168 namespace {
186 169
187 InterfaceProxy* CreateFileRefProxy(Dispatcher* dispatcher) { 170 InterfaceProxy* CreateFileRefProxy(Dispatcher* dispatcher) {
188 return new PPB_FileRef_Proxy(dispatcher); 171 return new PPB_FileRef_Proxy(dispatcher);
189 } 172 }
190 173
191 } // namespace 174 } // namespace
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 int32_t result, 319 int32_t result,
337 const HostResource& host_resource, 320 const HostResource& host_resource,
338 int callback_id) { 321 int callback_id) {
339 // Execute OnMsgCallbackComplete in the plugin process. 322 // Execute OnMsgCallbackComplete in the plugin process.
340 Send(new PpapiMsg_PPBFileRef_CallbackComplete( 323 Send(new PpapiMsg_PPBFileRef_CallbackComplete(
341 API_ID_PPB_FILE_REF, host_resource, callback_id, result)); 324 API_ID_PPB_FILE_REF, host_resource, callback_id, result));
342 } 325 }
343 326
344 } // namespace proxy 327 } // namespace proxy
345 } // namespace ppapi 328 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/ppb_file_io_proxy.cc ('k') | ppapi/proxy/ppb_file_system_proxy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698