OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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> | |
8 | |
9 #include "base/bind.h" | |
7 #include "ppapi/c/pp_errors.h" | 10 #include "ppapi/c/pp_errors.h" |
8 #include "ppapi/c/ppb_file_ref.h" | 11 #include "ppapi/c/ppb_file_ref.h" |
9 #include "ppapi/c/private/ppb_proxy_private.h" | 12 #include "ppapi/c/private/ppb_proxy_private.h" |
10 #include "ppapi/proxy/enter_proxy.h" | 13 #include "ppapi/proxy/enter_proxy.h" |
11 #include "ppapi/proxy/host_dispatcher.h" | 14 #include "ppapi/proxy/host_dispatcher.h" |
12 #include "ppapi/proxy/plugin_dispatcher.h" | 15 #include "ppapi/proxy/plugin_dispatcher.h" |
13 #include "ppapi/proxy/ppapi_messages.h" | 16 #include "ppapi/proxy/ppapi_messages.h" |
14 #include "ppapi/proxy/serialized_var.h" | 17 #include "ppapi/proxy/serialized_var.h" |
15 #include "ppapi/shared_impl/file_ref_impl.h" | 18 #include "ppapi/shared_impl/file_ref_impl.h" |
16 #include "ppapi/thunk/resource_creation_api.h" | 19 #include "ppapi/thunk/resource_creation_api.h" |
(...skipping 16 matching lines...) Expand all Loading... | |
33 virtual PP_Resource GetParent() OVERRIDE; | 36 virtual PP_Resource GetParent() OVERRIDE; |
34 virtual int32_t MakeDirectory(PP_Bool make_ancestors, | 37 virtual int32_t MakeDirectory(PP_Bool make_ancestors, |
35 PP_CompletionCallback callback) OVERRIDE; | 38 PP_CompletionCallback callback) OVERRIDE; |
36 virtual int32_t Touch(PP_Time last_access_time, | 39 virtual int32_t Touch(PP_Time last_access_time, |
37 PP_Time last_modified_time, | 40 PP_Time last_modified_time, |
38 PP_CompletionCallback callback) OVERRIDE; | 41 PP_CompletionCallback callback) OVERRIDE; |
39 virtual int32_t Delete(PP_CompletionCallback callback) OVERRIDE; | 42 virtual int32_t Delete(PP_CompletionCallback callback) OVERRIDE; |
40 virtual int32_t Rename(PP_Resource new_file_ref, | 43 virtual int32_t Rename(PP_Resource new_file_ref, |
41 PP_CompletionCallback callback) OVERRIDE; | 44 PP_CompletionCallback callback) OVERRIDE; |
42 | 45 |
46 // Executes the pending callback with the given ID. See pending_callbacks_. | |
47 void ExecuteCallback(int callback_id, int32_t result); | |
48 | |
43 private: | 49 private: |
44 PluginDispatcher* GetDispatcher() const { | 50 PluginDispatcher* GetDispatcher() const { |
45 return PluginDispatcher::GetForResource(this); | 51 return PluginDispatcher::GetForResource(this); |
46 } | 52 } |
47 | 53 |
54 // Adds a callback to the list and returns its ID. Returns 0 if the callback | |
55 // is invalid. | |
56 int SendCallback(PP_CompletionCallback callback); | |
57 | |
58 // This class can have any number of out-standing requests with completion | |
59 // callbacks, in contrast to most resources which have one possible pending | |
60 // callback pending (like a Flush callback). | |
61 // | |
62 // To keep track of them, assign integer IDs to the callbacks, which is how | |
63 // the callback will be identified when it's passed to the host and then | |
64 // back here. | |
65 int next_callback_id_; | |
viettrungluu
2011/10/17 17:11:03
Seems bad that things will fail when this wraps, w
brettw
2011/10/17 19:49:20
I added a loop to check for duplicates.
| |
66 typedef std::map<int, PP_CompletionCallback> PendingCallbackMap; | |
67 PendingCallbackMap pending_callbacks_; | |
68 | |
48 DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); | 69 DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); |
49 }; | 70 }; |
50 | 71 |
51 FileRef::FileRef(const PPB_FileRef_CreateInfo& info) | 72 FileRef::FileRef(const PPB_FileRef_CreateInfo& info) |
52 : FileRefImpl(FileRefImpl::InitAsProxy(), info) { | 73 : FileRefImpl(FileRefImpl::InitAsProxy(), info), |
74 next_callback_id_(1) { | |
53 } | 75 } |
54 | 76 |
55 FileRef::~FileRef() { | 77 FileRef::~FileRef() { |
78 // Abort all pending callbacks. Do this by posting a task to avoid reentering | |
79 // the plugin's Release() call that probably deleted this object. | |
80 for (PendingCallbackMap::iterator i = pending_callbacks_.begin(); | |
81 i != pending_callbacks_.end(); ++i) { | |
82 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
83 i->second.func, i->second.user_data, | |
84 static_cast<int32_t>(PP_ERROR_ABORTED))); | |
85 } | |
56 } | 86 } |
57 | 87 |
58 PP_Resource FileRef::GetParent() { | 88 PP_Resource FileRef::GetParent() { |
59 PPB_FileRef_CreateInfo create_info; | 89 PPB_FileRef_CreateInfo create_info; |
60 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent( | 90 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent( |
61 INTERFACE_ID_PPB_FILE_REF, host_resource(), &create_info)); | 91 INTERFACE_ID_PPB_FILE_REF, host_resource(), &create_info)); |
62 return PPB_FileRef_Proxy::DeserializeFileRef(create_info); | 92 return PPB_FileRef_Proxy::DeserializeFileRef(create_info); |
63 } | 93 } |
64 | 94 |
65 int32_t FileRef::MakeDirectory(PP_Bool make_ancestors, | 95 int32_t FileRef::MakeDirectory(PP_Bool make_ancestors, |
66 PP_CompletionCallback callback) { | 96 PP_CompletionCallback callback) { |
97 int callback_id = SendCallback(callback); | |
98 if (!callback_id) | |
99 return PP_ERROR_BADARGUMENT; | |
100 | |
67 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory( | 101 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory( |
68 INTERFACE_ID_PPB_FILE_REF, host_resource(), make_ancestors, | 102 INTERFACE_ID_PPB_FILE_REF, host_resource(), make_ancestors, callback_id)); |
69 GetDispatcher()->callback_tracker().SendCallback(callback))); | |
70 return PP_OK_COMPLETIONPENDING; | 103 return PP_OK_COMPLETIONPENDING; |
71 } | 104 } |
72 | 105 |
73 int32_t FileRef::Touch(PP_Time last_access_time, | 106 int32_t FileRef::Touch(PP_Time last_access_time, |
74 PP_Time last_modified_time, | 107 PP_Time last_modified_time, |
75 PP_CompletionCallback callback) { | 108 PP_CompletionCallback callback) { |
109 int callback_id = SendCallback(callback); | |
110 if (!callback_id) | |
111 return PP_ERROR_BADARGUMENT; | |
112 | |
76 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch( | 113 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch( |
77 INTERFACE_ID_PPB_FILE_REF, host_resource(), | 114 INTERFACE_ID_PPB_FILE_REF, host_resource(), |
78 last_access_time, last_modified_time, | 115 last_access_time, last_modified_time, callback_id)); |
79 GetDispatcher()->callback_tracker().SendCallback(callback))); | |
80 return PP_OK_COMPLETIONPENDING; | 116 return PP_OK_COMPLETIONPENDING; |
81 } | 117 } |
82 | 118 |
83 int32_t FileRef::Delete(PP_CompletionCallback callback) { | 119 int32_t FileRef::Delete(PP_CompletionCallback callback) { |
120 int callback_id = SendCallback(callback); | |
121 if (!callback_id) | |
122 return PP_ERROR_BADARGUMENT; | |
123 | |
84 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete( | 124 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete( |
85 INTERFACE_ID_PPB_FILE_REF, host_resource(), | 125 INTERFACE_ID_PPB_FILE_REF, host_resource(), callback_id)); |
86 GetDispatcher()->callback_tracker().SendCallback(callback))); | |
87 return PP_OK_COMPLETIONPENDING; | 126 return PP_OK_COMPLETIONPENDING; |
88 } | 127 } |
89 | 128 |
90 int32_t FileRef::Rename(PP_Resource new_file_ref, | 129 int32_t FileRef::Rename(PP_Resource new_file_ref, |
91 PP_CompletionCallback callback) { | 130 PP_CompletionCallback callback) { |
131 int callback_id = SendCallback(callback); | |
132 if (!callback_id) | |
133 return PP_ERROR_BADARGUMENT; | |
134 | |
92 Resource* new_file_ref_object = | 135 Resource* new_file_ref_object = |
93 PluginResourceTracker::GetInstance()->GetResource(new_file_ref); | 136 PluginResourceTracker::GetInstance()->GetResource(new_file_ref); |
94 if (!new_file_ref_object || | 137 if (!new_file_ref_object || |
95 new_file_ref_object->host_resource().instance() != pp_instance()) | 138 new_file_ref_object->host_resource().instance() != pp_instance()) |
96 return PP_ERROR_BADRESOURCE; | 139 return PP_ERROR_BADRESOURCE; |
97 | 140 |
98 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename( | 141 GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename( |
99 INTERFACE_ID_PPB_FILE_REF, host_resource(), | 142 INTERFACE_ID_PPB_FILE_REF, host_resource(), |
100 new_file_ref_object->host_resource(), | 143 new_file_ref_object->host_resource(), callback_id)); |
101 GetDispatcher()->callback_tracker().SendCallback(callback))); | |
102 return PP_OK_COMPLETIONPENDING; | 144 return PP_OK_COMPLETIONPENDING; |
103 } | 145 } |
104 | 146 |
147 void FileRef::ExecuteCallback(int callback_id, int32_t result) { | |
148 PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id); | |
149 if (found == pending_callbacks_.end()) | |
150 return; | |
viettrungluu
2011/10/17 17:11:03
Is this really an expected case? Should it ever be
brettw
2011/10/17 19:49:20
I think this happens a bunch, I added a comment.
| |
151 | |
152 // Executing the callback may mutate the callback list. | |
153 PP_CompletionCallback callback = found->second; | |
154 pending_callbacks_.erase(found); | |
155 PP_RunCompletionCallback(&callback, result); | |
156 } | |
157 | |
158 int FileRef::SendCallback(PP_CompletionCallback callback) { | |
159 if (!callback.func) | |
160 return 0; | |
161 pending_callbacks_[next_callback_id_] = callback; | |
162 return next_callback_id_++; | |
163 } | |
164 | |
105 PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher) | 165 PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher) |
106 : InterfaceProxy(dispatcher) { | 166 : InterfaceProxy(dispatcher), |
167 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
107 } | 168 } |
108 | 169 |
109 PPB_FileRef_Proxy::~PPB_FileRef_Proxy() { | 170 PPB_FileRef_Proxy::~PPB_FileRef_Proxy() { |
110 } | 171 } |
111 | 172 |
112 // static | 173 // static |
113 PP_Resource PPB_FileRef_Proxy::CreateProxyResource(PP_Resource file_system, | 174 PP_Resource PPB_FileRef_Proxy::CreateProxyResource(PP_Resource file_system, |
114 const char* path) { | 175 const char* path) { |
115 Resource* file_system_object = | 176 Resource* file_system_object = |
116 PluginResourceTracker::GetInstance()->GetResource(file_system); | 177 PluginResourceTracker::GetInstance()->GetResource(file_system); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 | 231 |
171 void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource, | 232 void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource, |
172 PPB_FileRef_CreateInfo* result) { | 233 PPB_FileRef_CreateInfo* result) { |
173 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); | 234 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); |
174 if (enter.succeeded()) | 235 if (enter.succeeded()) |
175 SerializeFileRef(enter.object()->GetParent(), result); | 236 SerializeFileRef(enter.object()->GetParent(), result); |
176 } | 237 } |
177 | 238 |
178 void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource, | 239 void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource, |
179 PP_Bool make_ancestors, | 240 PP_Bool make_ancestors, |
180 uint32_t serialized_callback) { | 241 int callback_id) { |
181 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); | 242 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( |
182 if (enter.failed()) | 243 host_resource, callback_factory_, |
183 return; | 244 &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); |
184 PP_CompletionCallback callback = ReceiveCallback(serialized_callback); | 245 if (enter.succeeded()) { |
185 int32_t result = enter.object()->MakeDirectory(make_ancestors, callback); | 246 enter.SetResult(enter.object()->MakeDirectory(make_ancestors, |
186 if (result != PP_OK_COMPLETIONPENDING) | 247 enter.callback())); |
187 PP_RunCompletionCallback(&callback, result); | 248 } |
188 } | 249 } |
189 | 250 |
190 void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource, | 251 void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource, |
191 PP_Time last_access, | 252 PP_Time last_access, |
192 PP_Time last_modified, | 253 PP_Time last_modified, |
193 uint32_t serialized_callback) { | 254 int callback_id) { |
194 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); | 255 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( |
195 if (enter.failed()) | 256 host_resource, callback_factory_, |
196 return; | 257 &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); |
197 PP_CompletionCallback callback = ReceiveCallback(serialized_callback); | 258 if (enter.succeeded()) { |
198 int32_t result = enter.object()->Touch(last_access, last_modified, callback); | 259 enter.SetResult(enter.object()->Touch(last_access, last_modified, |
199 if (result != PP_OK_COMPLETIONPENDING) | 260 enter.callback())); |
200 PP_RunCompletionCallback(&callback, result); | 261 } |
201 } | 262 } |
202 | 263 |
203 void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource, | 264 void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource, |
204 uint32_t serialized_callback) { | 265 int callback_id) { |
205 EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); | 266 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( |
206 if (enter.failed()) | 267 host_resource, callback_factory_, |
207 return; | 268 &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); |
208 PP_CompletionCallback callback = ReceiveCallback(serialized_callback); | 269 if (enter.succeeded()) |
209 int32_t result = enter.object()->Delete(callback); | 270 enter.SetResult(enter.object()->Delete(enter.callback())); |
210 if (result != PP_OK_COMPLETIONPENDING) | |
211 PP_RunCompletionCallback(&callback, result); | |
212 } | 271 } |
213 | 272 |
214 void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref, | 273 void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref, |
215 const HostResource& new_file_ref, | 274 const HostResource& new_file_ref, |
216 uint32_t serialized_callback) { | 275 int callback_id) { |
217 EnterHostFromHostResource<PPB_FileRef_API> enter(file_ref); | 276 EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( |
218 if (enter.failed()) | 277 file_ref, callback_factory_, |
219 return; | 278 &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id); |
220 PP_CompletionCallback callback = ReceiveCallback(serialized_callback); | 279 if (enter.succeeded()) { |
221 int32_t result = enter.object()->Rename(new_file_ref.host_resource(), | 280 enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(), |
222 callback); | 281 enter.callback())); |
223 if (result != PP_OK_COMPLETIONPENDING) | 282 } |
224 PP_RunCompletionCallback(&callback, result); | 283 } |
284 | |
285 void PPB_FileRef_Proxy::OnMsgCallbackComplete( | |
286 const HostResource& host_resource, | |
287 int callback_id, | |
288 int32_t result) { | |
289 // Forward the callback info to the plugin resource. | |
290 EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); | |
291 if (enter.succeeded()) | |
292 static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); | |
293 } | |
294 | |
295 void PPB_FileRef_Proxy::OnCallbackCompleteInHost( | |
296 int32_t result, | |
297 const HostResource& host_resource, | |
298 int callback_id) { | |
299 // Execute OnMsgCallbackComplete in the plugin process. | |
300 Send(new PpapiMsg_PPBFileRef_CallbackComplete( | |
301 INTERFACE_ID_PPB_FILE_REF, host_resource, callback_id, result)); | |
225 } | 302 } |
226 | 303 |
227 } // namespace proxy | 304 } // namespace proxy |
228 } // namespace ppapi | 305 } // namespace ppapi |
OLD | NEW |