Index: ppapi/proxy/ppb_url_loader_proxy.cc |
=================================================================== |
--- ppapi/proxy/ppb_url_loader_proxy.cc (revision 106763) |
+++ ppapi/proxy/ppb_url_loader_proxy.cc (working copy) |
@@ -111,8 +111,11 @@ |
void UpdateProgress(const PPBURLLoader_UpdateProgress_Params& params); |
// Called when the browser responds to our ReadResponseBody request. |
- void ReadResponseBodyAck(int32 result, const std::string& data); |
+ void ReadResponseBodyAck(int32_t result, const std::string& data); |
+ // Called when any callback other than the read callback has been executed. |
+ void CallbackComplete(int32_t result); |
+ |
private: |
// Reads the give bytes out of the buffer_, placing them in the given output |
// buffer, and removes the bytes from the buffer. |
@@ -131,9 +134,12 @@ |
int64_t bytes_received_; |
int64_t total_bytes_to_be_received_; |
- // When an asynchronous read is pending, this will contain the callback and |
- // the buffer to put the data. |
- PP_CompletionCallback current_read_callback_; |
+ // Current completion callback for the current phase of loading. We have only |
+ // one thing (open, follow redirect, read, etc.) outstanding at once. |
+ PP_CompletionCallback current_callback_; |
+ |
+ // When an asynchronous read is pending, this will contain the buffer to put |
+ // the data. The current_callback_ will identify the read callback. |
void* current_read_buffer_; |
int32_t current_read_buffer_size_; |
@@ -155,7 +161,7 @@ |
total_bytes_to_be_sent_(-1), |
bytes_received_(-1), |
total_bytes_to_be_received_(-1), |
- current_read_callback_(PP_MakeCompletionCallback(NULL, NULL)), |
+ current_callback_(PP_MakeCompletionCallback(NULL, NULL)), |
current_read_buffer_(NULL), |
current_read_buffer_size_(0), |
response_info_(0) { |
@@ -163,11 +169,11 @@ |
URLLoader::~URLLoader() { |
// Always need to fire completion callbacks to prevent a leak in the plugin. |
- if (current_read_callback_.func) { |
+ if (current_callback_.func) { |
// TODO(brettw) the callbacks at this level should be refactored with a |
// more automatic tracking system like we have in the renderer. |
MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
- current_read_callback_.func, current_read_callback_.user_data, |
+ current_callback_.func, current_callback_.user_data, |
static_cast<int32_t>(PP_ERROR_ABORTED))); |
} |
@@ -185,20 +191,28 @@ |
if (enter.failed()) |
return PP_ERROR_BADRESOURCE; |
- // TODO(brettw) http://crbug.com/86279: SendCallback doesn't ensure that |
- // the proper callback semantics happen if the object is deleted. |
+ if (current_callback_.func) |
+ return PP_ERROR_INPROGRESS; |
+ |
+ if (!callback.func) |
+ return PP_ERROR_BLOCKS_MAIN_THREAD; |
+ current_callback_ = callback; |
+ |
GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Open( |
- API_ID_PPB_URL_LOADER, host_resource(), enter.object()->GetData(), |
- GetDispatcher()->callback_tracker().SendCallback(callback))); |
+ API_ID_PPB_URL_LOADER, host_resource(), enter.object()->GetData())); |
return PP_OK_COMPLETIONPENDING; |
} |
int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { |
- // TODO(brettw) http://crbug.com/86279: SendCallback doesn't ensure that |
- // the proper callback semantics happen if the object is deleted. |
+ if (current_callback_.func) |
+ return PP_ERROR_INPROGRESS; |
+ |
+ if (!callback.func) |
+ return PP_ERROR_BLOCKS_MAIN_THREAD; |
+ current_callback_ = callback; |
+ |
GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect( |
- API_ID_PPB_URL_LOADER, host_resource(), |
- GetDispatcher()->callback_tracker().SendCallback(callback))); |
+ API_ID_PPB_URL_LOADER, host_resource())); |
return PP_OK_COMPLETIONPENDING; |
} |
@@ -249,7 +263,7 @@ |
PP_CompletionCallback callback) { |
if (!buffer || bytes_to_read <= 0) |
return PP_ERROR_BADARGUMENT; // Must specify an output buffer. |
- if (current_read_callback_.func) |
+ if (current_callback_.func) |
return PP_ERROR_INPROGRESS; // Can only have one request pending. |
// Currently we don't support sync calls to read. We'll need to revisit |
@@ -264,7 +278,7 @@ |
return bytes_to_read; |
} |
- current_read_callback_ = callback; |
+ current_callback_ = callback; |
current_read_buffer_ = buffer; |
current_read_buffer_size_ = bytes_to_read; |
@@ -274,9 +288,15 @@ |
} |
int32_t URLLoader::FinishStreamingToFile(PP_CompletionCallback callback) { |
+ if (current_callback_.func) |
+ return PP_ERROR_INPROGRESS; |
+ |
+ if (!callback.func) |
+ return PP_ERROR_BLOCKS_MAIN_THREAD; |
+ current_callback_ = callback; |
+ |
GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile( |
- API_ID_PPB_URL_LOADER, host_resource(), |
- GetDispatcher()->callback_tracker().SendCallback(callback))); |
+ API_ID_PPB_URL_LOADER, host_resource())); |
return PP_OK_COMPLETIONPENDING; |
} |
@@ -306,7 +326,7 @@ |
} |
void URLLoader::ReadResponseBodyAck(int32 result, const std::string& data) { |
- if (!current_read_callback_.func || !current_read_buffer_) { |
+ if (!current_callback_.func || !current_read_buffer_) { |
NOTREACHED(); |
return; |
} |
@@ -327,9 +347,13 @@ |
// The plugin should be able to make a new request from their callback, so |
// we have to clear our copy first. |
- PP_RunAndClearCompletionCallback(¤t_read_callback_, result); |
+ PP_RunAndClearCompletionCallback(¤t_callback_, result); |
} |
+void URLLoader::CallbackComplete(int32_t result) { |
+ PP_RunAndClearCompletionCallback(¤t_callback_, result); |
+} |
+ |
void URLLoader::PopBuffer(void* output_buffer, int32_t output_size) { |
CHECK(output_size <= static_cast<int32_t>(buffer_.size())); |
std::copy(buffer_.begin(), |
@@ -439,37 +463,27 @@ |
} |
void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource& loader, |
- const PPB_URLRequestInfo_Data& data, |
- uint32_t serialized_callback) { |
- // Have to be careful to always issue the callback, so don't return early. |
- EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); |
+ const PPB_URLRequestInfo_Data& data) { |
+ EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( |
+ loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); |
thunk::EnterResourceCreation enter_creation(loader.instance()); |
+ if (enter.failed() || enter_creation.failed()) |
+ return; |
- PP_CompletionCallback callback = ReceiveCallback(serialized_callback); |
- |
- int32_t result = PP_ERROR_BADRESOURCE; |
- if (enter.succeeded() && enter_creation.succeeded()) { |
- ScopedPPResource request_resource( |
- ScopedPPResource::PassRef(), |
- enter_creation.functions()->CreateURLRequestInfo(loader.instance(), |
- data)); |
- result = enter.object()->Open(request_resource, callback); |
- } |
- if (result != PP_OK_COMPLETIONPENDING) |
- PP_RunCompletionCallback(&callback, result); |
+ ScopedPPResource request_resource( |
+ ScopedPPResource::PassRef(), |
+ enter_creation.functions()->CreateURLRequestInfo(loader.instance(), |
+ data)); |
+ enter.SetResult(enter.object()->Open(request_resource, enter.callback())); |
// TODO(brettw) bug 73236 register for the status callbacks. |
} |
void PPB_URLLoader_Proxy::OnMsgFollowRedirect( |
- const HostResource& loader, |
- uint32_t serialized_callback) { |
- EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); |
- PP_CompletionCallback callback = ReceiveCallback(serialized_callback); |
- int32_t result = PP_ERROR_BADRESOURCE; |
+ const HostResource& loader) { |
+ EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( |
+ loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); |
if (enter.succeeded()) |
- result = enter.object()->FollowRedirect(callback); |
- if (result != PP_OK_COMPLETIONPENDING) |
- PP_RunCompletionCallback(&callback, result); |
+ enter.SetResult(enter.object()->FollowRedirect(enter.callback())); |
} |
void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(const HostResource& loader, |
@@ -524,15 +538,11 @@ |
} |
void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile( |
- const HostResource& loader, |
- uint32_t serialized_callback) { |
- EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); |
- PP_CompletionCallback callback = ReceiveCallback(serialized_callback); |
- int32_t result = PP_ERROR_BADRESOURCE; |
- if (enter.succeeded()) |
- result = enter.object()->FinishStreamingToFile(callback); |
- if (result != PP_OK_COMPLETIONPENDING) |
- PP_RunCompletionCallback(&callback, result); |
+ const HostResource& loader) { |
+ EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( |
+ loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); |
+ if (enter.failed()) |
+ enter.SetResult(enter.object()->FinishStreamingToFile(enter.callback()));; |
} |
void PPB_URLLoader_Proxy::OnMsgClose(const HostResource& loader) { |
@@ -566,6 +576,15 @@ |
static_cast<URLLoader*>(enter.object())->ReadResponseBodyAck(result, data); |
} |
+// Called in the plugin. |
+void PPB_URLLoader_Proxy::OnMsgCallbackComplete( |
+ const HostResource& host_resource, |
+ int32_t result) { |
+ EnterPluginFromHostResource<PPB_URLLoader_API> enter(host_resource); |
+ if (enter.succeeded()) |
+ static_cast<URLLoader*>(enter.object())->CallbackComplete(result); |
+} |
+ |
void PPB_URLLoader_Proxy::OnReadCallback(int32_t result, |
ReadCallbackInfo* info) { |
int32_t bytes_read = 0; |
@@ -579,5 +598,11 @@ |
delete info; |
} |
+void PPB_URLLoader_Proxy::OnCallback(int32_t result, |
+ const HostResource& resource) { |
+ dispatcher()->Send(new PpapiMsg_PPBURLLoader_CallbackComplete( |
+ API_ID_PPB_URL_LOADER, resource, result)); |
+} |
+ |
} // namespace proxy |
} // namespace ppapi |