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
3 // found in the LICENSE file.
5 #include "ppapi/proxy/ppb_url_loader_proxy.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "build/build_config.h"
14 #include "ppapi/c/pp_completion_callback.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/pp_resource.h"
17 #include "ppapi/c/ppb_url_loader.h"
18 #include "ppapi/c/private/ppb_proxy_private.h"
19 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
20 #include "ppapi/proxy/enter_proxy.h"
21 #include "ppapi/proxy/host_dispatcher.h"
22 #include "ppapi/proxy/plugin_dispatcher.h"
23 #include "ppapi/proxy/plugin_resource_tracker.h"
24 #include "ppapi/proxy/ppapi_messages.h"
25 #include "ppapi/proxy/ppb_file_ref_proxy.h"
26 #include "ppapi/shared_impl/scoped_pp_resource.h"
27 #include "ppapi/shared_impl/tracked_callback.h"
28 #include "ppapi/thunk/enter.h"
29 #include "ppapi/thunk/ppb_url_loader_api.h"
30 #include "ppapi/thunk/ppb_url_request_info_api.h"
31 #include "ppapi/thunk/resource_creation_api.h"
32 #include "ppapi/thunk/thunk.h"
38 using ppapi::thunk::EnterResourceNoLock
;
39 using ppapi::thunk::PPB_URLLoader_API
;
40 using ppapi::thunk::ResourceCreationAPI
;
47 // The maximum size we'll read into the plugin without being explicitly
48 // asked for a larger buffer.
49 const int32_t kMaxReadBufferSize
= 16777216; // 16MB
52 // Called in the renderer when the byte counts have changed. We send a message
53 // to the plugin to synchronize its counts so it can respond to status polls
55 void UpdateResourceLoadStatus(PP_Instance pp_instance
,
56 PP_Resource pp_resource
,
58 int64 total_bytes_to_be_sent
,
60 int64 total_bytes_to_be_received
) {
61 Dispatcher
* dispatcher
= HostDispatcher::GetForInstance(pp_instance
);
65 PPBURLLoader_UpdateProgress_Params params
;
66 params
.instance
= pp_instance
;
67 params
.resource
.SetHostResource(pp_instance
, pp_resource
);
68 params
.bytes_sent
= bytes_sent
;
69 params
.total_bytes_to_be_sent
= total_bytes_to_be_sent
;
70 params
.bytes_received
= bytes_received
;
71 params
.total_bytes_to_be_received
= total_bytes_to_be_received
;
72 dispatcher
->Send(new PpapiMsg_PPBURLLoader_UpdateProgress(
73 API_ID_PPB_URL_LOADER
, params
));
75 #endif // !defined(OS_NACL)
77 InterfaceProxy
* CreateURLLoaderProxy(Dispatcher
* dispatcher
) {
78 return new PPB_URLLoader_Proxy(dispatcher
);
83 // URLLoader -------------------------------------------------------------------
85 class URLLoader
: public Resource
, public PPB_URLLoader_API
{
87 URLLoader(const HostResource
& resource
);
90 // Resource overrides.
91 virtual PPB_URLLoader_API
* AsPPB_URLLoader_API() OVERRIDE
;
93 // PPB_URLLoader_API implementation.
94 virtual int32_t Open(PP_Resource request_id
,
95 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
96 virtual int32_t Open(const URLRequestInfoData
& data
,
98 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
99 virtual int32_t FollowRedirect(
100 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
101 virtual PP_Bool
GetUploadProgress(int64_t* bytes_sent
,
102 int64_t* total_bytes_to_be_sent
) OVERRIDE
;
103 virtual PP_Bool
GetDownloadProgress(
104 int64_t* bytes_received
,
105 int64_t* total_bytes_to_be_received
) OVERRIDE
;
106 virtual PP_Resource
GetResponseInfo() OVERRIDE
;
107 virtual int32_t ReadResponseBody(
109 int32_t bytes_to_read
,
110 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
111 virtual int32_t FinishStreamingToFile(
112 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
113 virtual void Close() OVERRIDE
;
114 virtual void GrantUniversalAccess() OVERRIDE
;
115 virtual void SetStatusCallback(
116 PP_URLLoaderTrusted_StatusCallback cb
) OVERRIDE
;
117 virtual bool GetResponseInfoData(URLResponseInfoData
* data
) OVERRIDE
;
119 // Called when the browser has new up/download progress to report.
120 void UpdateProgress(const PPBURLLoader_UpdateProgress_Params
& params
);
122 // Called when the browser responds to our ReadResponseBody request.
123 void ReadResponseBodyAck(int32_t result
, const char* data
);
125 // Called when any callback other than the read callback has been executed.
126 void CallbackComplete(int32_t result
);
129 // Reads the give bytes out of the buffer_, placing them in the given output
130 // buffer, and removes the bytes from the buffer.
132 // The size must be not more than the current size of the buffer.
133 void PopBuffer(void* output_buffer
, int32_t output_size
);
135 PluginDispatcher
* GetDispatcher() const {
136 return PluginDispatcher::GetForResource(this);
139 // Initialized to -1. Will be set to nonnegative values by the UpdateProgress
140 // message when the values are known.
142 int64_t total_bytes_to_be_sent_
;
143 int64_t bytes_received_
;
144 int64_t total_bytes_to_be_received_
;
146 // Current completion callback for the current phase of loading. We have only
147 // one thing (open, follow redirect, read, etc.) outstanding at once.
148 scoped_refptr
<TrackedCallback
> current_callback_
;
150 // When an asynchronous read is pending, this will contain the buffer to put
151 // the data. The current_callback_ will identify the read callback.
152 void* current_read_buffer_
;
153 int32_t current_read_buffer_size_
;
155 // A buffer of all the data that's been sent to us from the host that we
156 // have yet to send out to the plugin.
157 std::deque
<char> buffer_
;
159 // Cached copy of the response info. When nonzero, we're holding a reference
161 PP_Resource response_info_
;
164 DISALLOW_COPY_AND_ASSIGN(URLLoader
);
167 URLLoader::URLLoader(const HostResource
& resource
)
168 : Resource(OBJECT_IS_PROXY
, resource
),
170 total_bytes_to_be_sent_(-1),
172 total_bytes_to_be_received_(-1),
173 current_read_buffer_(NULL
),
174 current_read_buffer_size_(0),
178 URLLoader::~URLLoader() {
180 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(response_info_
);
183 PPB_URLLoader_API
* URLLoader::AsPPB_URLLoader_API() {
187 int32_t URLLoader::Open(PP_Resource request_id
,
188 scoped_refptr
<TrackedCallback
> callback
) {
189 EnterResourceNoLock
<thunk::PPB_URLRequestInfo_API
> enter(request_id
, true);
190 if (enter
.failed()) {
191 Log(PP_LOGLEVEL_ERROR
, "PPB_URLLoader.Open: The URL you're requesting is "
192 " on a different security origin than your plugin. To request "
193 " cross-origin resources, see "
194 " PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS.");
195 return PP_ERROR_BADRESOURCE
;
197 return Open(enter
.object()->GetData(), 0, callback
);
200 int32_t URLLoader::Open(const URLRequestInfoData
& data
,
202 scoped_refptr
<TrackedCallback
> callback
) {
203 DCHECK_EQ(0, requestor_pid
); // Used in-process only.
205 if (TrackedCallback::IsPending(current_callback_
))
206 return PP_ERROR_INPROGRESS
;
208 current_callback_
= callback
;
210 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Open(
211 API_ID_PPB_URL_LOADER
, host_resource(), data
));
212 return PP_OK_COMPLETIONPENDING
;
215 int32_t URLLoader::FollowRedirect(scoped_refptr
<TrackedCallback
> callback
) {
216 if (TrackedCallback::IsPending(current_callback_
))
217 return PP_ERROR_INPROGRESS
;
219 current_callback_
= callback
;
221 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect(
222 API_ID_PPB_URL_LOADER
, host_resource()));
223 return PP_OK_COMPLETIONPENDING
;
226 PP_Bool
URLLoader::GetUploadProgress(int64_t* bytes_sent
,
227 int64_t* total_bytes_to_be_sent
) {
228 if (bytes_sent_
== -1) {
230 *total_bytes_to_be_sent
= 0;
233 *bytes_sent
= bytes_sent_
;
234 *total_bytes_to_be_sent
= total_bytes_to_be_sent_
;
238 PP_Bool
URLLoader::GetDownloadProgress(
239 int64_t* bytes_received
,
240 int64_t* total_bytes_to_be_received
) {
241 if (bytes_received_
== -1) {
243 *total_bytes_to_be_received
= 0;
246 *bytes_received
= bytes_received_
;
247 *total_bytes_to_be_received
= total_bytes_to_be_received_
;
251 PP_Resource
URLLoader::GetResponseInfo() {
252 if (!response_info_
) {
253 bool success
= false;
254 URLResponseInfoData data
;
255 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo(
256 API_ID_PPB_URL_LOADER
, host_resource(), &success
, &data
));
260 // Create a proxy resource for the the file ref host resource if needed.
261 PP_Resource body_as_file_ref
= 0;
262 if (!data
.body_as_file_ref
.resource
.is_null()) {
264 PPB_FileRef_Proxy::DeserializeFileRef(data
.body_as_file_ref
);
267 // Assumes ownership of body_as_file_ref.
268 thunk::EnterResourceCreationNoLock
enter(pp_instance());
269 response_info_
= enter
.functions()->CreateURLResponseInfo(
270 pp_instance(), data
, body_as_file_ref
);
273 // The caller expects to get a ref, and we want to keep holding ours.
274 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(response_info_
);
275 return response_info_
;
278 int32_t URLLoader::ReadResponseBody(void* buffer
,
279 int32_t bytes_to_read
,
280 scoped_refptr
<TrackedCallback
> callback
) {
281 if (!buffer
|| bytes_to_read
<= 0)
282 return PP_ERROR_BADARGUMENT
; // Must specify an output buffer.
283 if (TrackedCallback::IsPending(current_callback_
))
284 return PP_ERROR_INPROGRESS
; // Can only have one request pending.
286 if (buffer_
.size()) {
287 // Special case: we've already buffered some data that we can synchronously
288 // return to the caller. Do so without making IPCs.
289 int32_t bytes_to_return
=
290 std::min(bytes_to_read
, static_cast<int32_t>(buffer_
.size()));
291 PopBuffer(buffer
, bytes_to_return
);
292 return bytes_to_return
;
295 current_callback_
= callback
;
296 current_read_buffer_
= buffer
;
297 current_read_buffer_size_
= bytes_to_read
;
299 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
300 API_ID_PPB_URL_LOADER
, host_resource(), bytes_to_read
));
301 return PP_OK_COMPLETIONPENDING
;
304 int32_t URLLoader::FinishStreamingToFile(
305 scoped_refptr
<TrackedCallback
> callback
) {
306 if (TrackedCallback::IsPending(current_callback_
))
307 return PP_ERROR_INPROGRESS
;
309 current_callback_
= callback
;
311 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile(
312 API_ID_PPB_URL_LOADER
, host_resource()));
313 return PP_OK_COMPLETIONPENDING
;
316 void URLLoader::Close() {
317 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Close(
318 API_ID_PPB_URL_LOADER
, host_resource()));
321 void URLLoader::GrantUniversalAccess() {
322 GetDispatcher()->Send(
323 new PpapiHostMsg_PPBURLLoader_GrantUniversalAccess(
324 API_ID_PPB_URL_LOADER
, host_resource()));
327 void URLLoader::SetStatusCallback(
328 PP_URLLoaderTrusted_StatusCallback cb
) {
329 // Not implemented in the proxied version, this is for implementing the
330 // proxy itself in the host.
333 bool URLLoader::GetResponseInfoData(URLResponseInfoData
* data
) {
334 // Not implemented in the proxied version, this is for implementing the
335 // proxy itself in the host.
339 void URLLoader::UpdateProgress(
340 const PPBURLLoader_UpdateProgress_Params
& params
) {
341 bytes_sent_
= params
.bytes_sent
;
342 total_bytes_to_be_sent_
= params
.total_bytes_to_be_sent
;
343 bytes_received_
= params
.bytes_received
;
344 total_bytes_to_be_received_
= params
.total_bytes_to_be_received
;
347 void URLLoader::ReadResponseBodyAck(int32 result
, const char* data
) {
348 if (!TrackedCallback::IsPending(current_callback_
) || !current_read_buffer_
) {
354 DCHECK_EQ(0U, buffer_
.size());
356 int32_t bytes_to_return
= std::min(current_read_buffer_size_
, result
);
358 data
+ bytes_to_return
,
359 static_cast<char*>(current_read_buffer_
));
361 if (result
> bytes_to_return
) {
362 // Save what remains to be copied when ReadResponseBody is called again.
363 buffer_
.insert(buffer_
.end(),
364 data
+ bytes_to_return
,
368 result
= bytes_to_return
;
371 current_callback_
->Run(result
);
374 void URLLoader::CallbackComplete(int32_t result
) {
375 current_callback_
->Run(result
);
378 void URLLoader::PopBuffer(void* output_buffer
, int32_t output_size
) {
379 CHECK(output_size
<= static_cast<int32_t>(buffer_
.size()));
380 std::copy(buffer_
.begin(),
381 buffer_
.begin() + output_size
,
382 static_cast<char*>(output_buffer
));
383 buffer_
.erase(buffer_
.begin(),
384 buffer_
.begin() + output_size
);
387 // PPB_URLLoader_Proxy ---------------------------------------------------------
389 PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher
* dispatcher
)
390 : InterfaceProxy(dispatcher
),
391 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
394 PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() {
398 PP_Resource
PPB_URLLoader_Proxy::TrackPluginResource(
399 const HostResource
& url_loader_resource
) {
400 return (new URLLoader(url_loader_resource
))->GetReference();
404 const InterfaceProxy::Info
* PPB_URLLoader_Proxy::GetTrustedInfo() {
405 static const Info info
= {
406 thunk::GetPPB_URLLoaderTrusted_0_3_Thunk(),
407 PPB_URLLOADERTRUSTED_INTERFACE_0_3
,
408 API_ID_NONE
, // URL_LOADER is the canonical one.
410 &CreateURLLoaderProxy
416 PP_Resource
PPB_URLLoader_Proxy::CreateProxyResource(PP_Instance pp_instance
) {
417 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(pp_instance
);
422 dispatcher
->Send(new PpapiHostMsg_PPBURLLoader_Create(
423 API_ID_PPB_URL_LOADER
, pp_instance
, &result
));
424 if (result
.is_null())
426 return PPB_URLLoader_Proxy::TrackPluginResource(result
);
429 bool PPB_URLLoader_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
431 IPC_BEGIN_MESSAGE_MAP(PPB_URLLoader_Proxy
, msg
)
432 #if !defined(OS_NACL)
433 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Create
,
435 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Open
,
437 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FollowRedirect
,
439 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetResponseInfo
,
440 OnMsgGetResponseInfo
)
441 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_ReadResponseBody
,
442 OnMsgReadResponseBody
)
443 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile
,
444 OnMsgFinishStreamingToFile
)
445 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Close
,
447 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GrantUniversalAccess
,
448 OnMsgGrantUniversalAccess
)
449 #endif // !defined(OS_NACL)
451 IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_UpdateProgress
,
453 IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack
,
454 OnMsgReadResponseBodyAck
)
455 IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_CallbackComplete
,
456 OnMsgCallbackComplete
)
457 IPC_MESSAGE_UNHANDLED(handled
= false)
458 IPC_END_MESSAGE_MAP()
459 // TODO(brettw) handle bad messages!
463 #if !defined(OS_NACL)
464 void PPB_URLLoader_Proxy::PrepareURLLoaderForSendingToPlugin(
465 PP_Resource resource
) {
466 // So the plugin can query load status, we need to register our status
467 // callback before sending any URLLoader to the plugin.
468 EnterResourceNoLock
<PPB_URLLoader_API
> enter(resource
, false);
469 if (enter
.succeeded())
470 enter
.object()->SetStatusCallback(&UpdateResourceLoadStatus
);
472 NOTREACHED(); // Only called internally, resource should be valid.
475 void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance
,
476 HostResource
* result
) {
477 thunk::EnterResourceCreation
enter(instance
);
478 if (enter
.succeeded()) {
479 result
->SetHostResource(instance
,
480 enter
.functions()->CreateURLLoader(instance
));
481 PrepareURLLoaderForSendingToPlugin(result
->host_resource());
485 void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource
& loader
,
486 const URLRequestInfoData
& data
) {
487 int peer_pid
= dispatcher()->channel()->peer_pid();
489 EnterHostFromHostResourceForceCallback
<PPB_URLLoader_API
> enter(
490 loader
, callback_factory_
, &PPB_URLLoader_Proxy::OnCallback
, loader
);
491 enter
.SetResult(enter
.object()->Open(data
, peer_pid
, enter
.callback()));
492 // TODO(brettw) bug 73236 register for the status callbacks.
495 void PPB_URLLoader_Proxy::OnMsgFollowRedirect(
496 const HostResource
& loader
) {
497 EnterHostFromHostResourceForceCallback
<PPB_URLLoader_API
> enter(
498 loader
, callback_factory_
, &PPB_URLLoader_Proxy::OnCallback
, loader
);
499 if (enter
.succeeded())
500 enter
.SetResult(enter
.object()->FollowRedirect(enter
.callback()));
503 void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(const HostResource
& loader
,
505 URLResponseInfoData
* result
) {
506 EnterHostFromHostResource
<PPB_URLLoader_API
> enter(loader
);
507 if (enter
.succeeded())
508 *success
= enter
.object()->GetResponseInfoData(result
);
513 void PPB_URLLoader_Proxy::OnMsgReadResponseBody(
514 const HostResource
& loader
,
515 int32_t bytes_to_read
) {
516 // The plugin could be sending us malicious messages, don't accept negative
518 if (bytes_to_read
< 0) {
519 // TODO(brettw) kill plugin.
523 // Read more than requested if there are bytes available for synchronous
524 // reading. This prevents us from getting too far behind due to IPC message
525 // latency. Any extra data will get buffered in the plugin.
526 int32_t synchronously_available_bytes
=
527 static_cast<HostDispatcher
*>(dispatcher())->ppb_proxy()->
528 GetURLLoaderBufferedBytes(loader
.host_resource());
529 if (bytes_to_read
< kMaxReadBufferSize
) {
530 // Grow the amount to read so we read ahead synchronously, if possible.
532 std::max(bytes_to_read
,
533 std::min(synchronously_available_bytes
, kMaxReadBufferSize
));
536 // This heap object will get deleted by the callback handler.
537 // TODO(brettw) this will be leaked if the plugin closes the resource!
538 // (Also including the plugin unloading and having the resource implicitly
539 // destroyed. Depending on the cleanup ordering, we may not need the weak
541 IPC::Message
* message
=
542 new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack(API_ID_PPB_URL_LOADER
);
543 IPC::ParamTraits
<HostResource
>::Write(message
, loader
);
545 char* ptr
= message
->BeginWriteData(bytes_to_read
);
547 // TODO(brettw) have a way to check for out-of-memory.
550 EnterHostFromHostResourceForceCallback
<PPB_URLLoader_API
> enter(
551 loader
, callback_factory_
, &PPB_URLLoader_Proxy::OnReadCallback
, message
);
552 if (enter
.succeeded()) {
553 enter
.SetResult(enter
.object()->ReadResponseBody(ptr
, bytes_to_read
,
558 void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile(
559 const HostResource
& loader
) {
560 EnterHostFromHostResourceForceCallback
<PPB_URLLoader_API
> enter(
561 loader
, callback_factory_
, &PPB_URLLoader_Proxy::OnCallback
, loader
);
562 if (enter
.succeeded())
563 enter
.SetResult(enter
.object()->FinishStreamingToFile(enter
.callback()));;
566 void PPB_URLLoader_Proxy::OnMsgClose(const HostResource
& loader
) {
567 EnterHostFromHostResource
<PPB_URLLoader_API
> enter(loader
);
568 if (enter
.succeeded())
569 enter
.object()->Close();
572 void PPB_URLLoader_Proxy::OnMsgGrantUniversalAccess(
573 const HostResource
& loader
) {
574 EnterHostFromHostResource
<PPB_URLLoader_API
> enter(loader
);
575 if (enter
.succeeded())
576 enter
.object()->GrantUniversalAccess();
578 #endif // !defined(OS_NACL)
580 // Called in the Plugin.
581 void PPB_URLLoader_Proxy::OnMsgUpdateProgress(
582 const PPBURLLoader_UpdateProgress_Params
& params
) {
583 EnterPluginFromHostResource
<PPB_URLLoader_API
> enter(params
.resource
);
584 if (enter
.succeeded())
585 static_cast<URLLoader
*>(enter
.object())->UpdateProgress(params
);
588 // Called in the Plugin.
589 void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck(
590 const IPC::Message
& message
) {
591 PickleIterator
iter(message
);
593 HostResource host_resource
;
594 if (!IPC::ParamTraits
<HostResource
>::Read(&message
, &iter
, &host_resource
)) {
595 NOTREACHED() << "Expecting HostResource";
601 if (!iter
.ReadData(&data
, &data_len
)) {
602 NOTREACHED() << "Expecting data";
607 if (!iter
.ReadInt(&result
)) {
608 NOTREACHED() << "Expecting result";
612 DCHECK(result
< 0 || result
== data_len
);
614 EnterPluginFromHostResource
<PPB_URLLoader_API
> enter(host_resource
);
615 if (enter
.succeeded())
616 static_cast<URLLoader
*>(enter
.object())->ReadResponseBodyAck(result
, data
);
619 // Called in the plugin.
620 void PPB_URLLoader_Proxy::OnMsgCallbackComplete(
621 const HostResource
& host_resource
,
623 EnterPluginFromHostResource
<PPB_URLLoader_API
> enter(host_resource
);
624 if (enter
.succeeded())
625 static_cast<URLLoader
*>(enter
.object())->CallbackComplete(result
);
628 #if !defined(OS_NACL)
629 void PPB_URLLoader_Proxy::OnReadCallback(int32_t result
,
630 IPC::Message
* message
) {
631 int32_t bytes_read
= 0;
633 bytes_read
= result
; // Positive results indicate bytes read.
635 message
->TrimWriteData(bytes_read
);
636 message
->WriteInt(result
);
638 dispatcher()->Send(message
);
641 void PPB_URLLoader_Proxy::OnCallback(int32_t result
,
642 const HostResource
& resource
) {
643 dispatcher()->Send(new PpapiMsg_PPBURLLoader_CallbackComplete(
644 API_ID_PPB_URL_LOADER
, resource
, result
));
646 #endif // !defined(OS_NACL)