Chromium Code Reviews| 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 |