190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/proxy/url_loader_resource.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/c/pp_completion_callback.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/c/ppb_url_loader.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/proxy/dispatch_reply_message.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ppapi/proxy/file_ref_resource.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/proxy/url_request_info_resource.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/proxy/url_response_info_resource.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/shared_impl/url_response_info_data.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/thunk/enter.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ppapi/thunk/resource_creation_api.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using ppapi::thunk::EnterResourceNoLock;
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using ppapi::thunk::PPB_URLLoader_API;
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using ppapi::thunk::PPB_URLRequestInfo_API;
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifdef _MSC_VER
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Do not warn about use of std::copy with raw pointers.
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#pragma warning(disable : 4996)
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ppapi {
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace proxy {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)URLLoaderResource::URLLoaderResource(Connection connection,
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     PP_Instance instance)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : PluginResource(connection, instance),
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      mode_(MODE_WAITING_TO_OPEN),
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      status_callback_(NULL),
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bytes_sent_(0),
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      total_bytes_to_be_sent_(-1),
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bytes_received_(0),
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      total_bytes_to_be_received_(-1),
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      user_buffer_(NULL),
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      user_buffer_size_(0),
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      done_status_(PP_OK_COMPLETIONPENDING),
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      is_streaming_to_file_(false),
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      is_asynchronous_load_suspended_(false) {
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SendCreate(RENDERER, PpapiHostMsg_URLLoader_Create());
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)URLLoaderResource::URLLoaderResource(Connection connection,
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     PP_Instance instance,
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     int pending_main_document_loader_id,
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     const ppapi::URLResponseInfoData& data)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : PluginResource(connection, instance),
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      mode_(MODE_OPENING),
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      status_callback_(NULL),
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bytes_sent_(0),
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      total_bytes_to_be_sent_(-1),
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bytes_received_(0),
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      total_bytes_to_be_received_(-1),
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      user_buffer_(NULL),
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      user_buffer_size_(0),
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      done_status_(PP_OK_COMPLETIONPENDING),
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      is_streaming_to_file_(false),
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      is_asynchronous_load_suspended_(false) {
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  AttachToPendingHost(RENDERER, pending_main_document_loader_id);
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SaveResponseInfo(data);
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)URLLoaderResource::~URLLoaderResource() {
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PPB_URLLoader_API* URLLoaderResource::AsPPB_URLLoader_API() {
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return this;
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int32_t URLLoaderResource::Open(PP_Resource request_id,
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                scoped_refptr<TrackedCallback> callback) {
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EnterResourceNoLock<PPB_URLRequestInfo_API> enter_request(request_id, true);
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (enter_request.failed()) {
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Log(PP_LOGLEVEL_ERROR,
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        "PPB_URLLoader.Open: invalid request resource ID. (Hint to C++ wrapper"
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        " users: use the ResourceRequest constructor that takes an instance or"
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        " else the request will be null.)");
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_BADARGUMENT;
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Open(enter_request.object()->GetData(), 0, callback);
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int32_t URLLoaderResource::Open(
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ::ppapi::URLRequestInfoData& request_data,
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int requestor_pid,
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int32_t rv = ValidateCallback(callback);
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (rv != PP_OK)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return rv;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (mode_ != MODE_WAITING_TO_OPEN)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  request_data_ = request_data;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mode_ = MODE_OPENING;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  is_asynchronous_load_suspended_ = false;
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RegisterCallback(callback);
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Post(RENDERER, PpapiHostMsg_URLLoader_Open(request_data));
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int32_t URLLoaderResource::FollowRedirect(
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int32_t rv = ValidateCallback(callback);
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (rv != PP_OK)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return rv;
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (mode_ != MODE_OPENING)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetDefersLoading(false);  // Allow the redirect to continue.
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RegisterCallback(callback);
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PP_Bool URLLoaderResource::GetUploadProgress(int64_t* bytes_sent,
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                              int64_t* total_bytes_to_be_sent) {
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!request_data_.record_upload_progress) {
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *bytes_sent = 0;
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *total_bytes_to_be_sent = 0;
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_FALSE;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *bytes_sent = bytes_sent_;
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *total_bytes_to_be_sent = total_bytes_to_be_sent_;
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_TRUE;
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PP_Bool URLLoaderResource::GetDownloadProgress(
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int64_t* bytes_received,
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int64_t* total_bytes_to_be_received) {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!request_data_.record_download_progress) {
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *bytes_received = 0;
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *total_bytes_to_be_received = 0;
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_FALSE;
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *bytes_received = bytes_received_;
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *total_bytes_to_be_received = total_bytes_to_be_received_;
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_TRUE;
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PP_Resource URLLoaderResource::GetResponseInfo() {
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (response_info_.get())
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return response_info_->GetReference();
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 0;
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int32_t URLLoaderResource::ReadResponseBody(
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    void* buffer,
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int32_t bytes_to_read,
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int32_t rv = ValidateCallback(callback);
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (rv != PP_OK)
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return rv;
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!response_info_.get())
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_FAILED;
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Fail if we have a valid file ref.
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // ReadResponseBody() is for reading to a user-provided buffer.
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (response_info_->data().body_as_file_ref.IsValid())
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return PP_ERROR_FAILED;
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (bytes_to_read <= 0 || !buffer)
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_BADARGUMENT;
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_ = static_cast<char*>(buffer);
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_size_ = bytes_to_read;
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!buffer_.empty())
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return FillUserBuffer();
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // We may have already reached EOF.
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (done_status_ != PP_OK_COMPLETIONPENDING) {
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    user_buffer_ = NULL;
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    user_buffer_size_ = 0;
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return done_status_;
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RegisterCallback(callback);
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int32_t URLLoaderResource::FinishStreamingToFile(
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int32_t rv = ValidateCallback(callback);
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (rv != PP_OK)
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return rv;
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!response_info_.get())
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return PP_ERROR_FAILED;
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Fail if we do not have a valid file ref.
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!response_info_->data().body_as_file_ref.IsValid())
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_FAILED;
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // We may have already reached EOF.
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (done_status_ != PP_OK_COMPLETIONPENDING)
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return done_status_;
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  is_streaming_to_file_ = true;
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_asynchronous_load_suspended_)
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetDefersLoading(false);
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Wait for didFinishLoading / didFail.
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RegisterCallback(callback);
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::Close() {
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mode_ = MODE_LOAD_COMPLETE;
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  done_status_ = PP_ERROR_ABORTED;
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Post(RENDERER, PpapiHostMsg_URLLoader_Close());
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Abort the callbacks, the plugin doesn't want to be called back after this.
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(brettw) this should fix bug 69457, mark it fixed. ============
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (TrackedCallback::IsPending(pending_callback_))
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    pending_callback_->PostAbort();
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::GrantUniversalAccess() {
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Post(RENDERER, PpapiHostMsg_URLLoader_GrantUniversalAccess());
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::RegisterStatusCallback(
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PP_URLLoaderTrusted_StatusCallback callback) {
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  status_callback_ = callback;
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::OnReplyReceived(
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ResourceMessageReplyParams& params,
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const IPC::Message& msg) {
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(URLLoaderResource, msg)
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case PpapiPluginMsg_URLLoader_SendData::ID:
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Special message, manually dispatch since we don't want the automatic
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // unpickling.
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      OnPluginMsgSendData(params, msg);
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        PpapiPluginMsg_URLLoader_ReceivedResponse,
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        OnPluginMsgReceivedResponse)
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        PpapiPluginMsg_URLLoader_FinishedLoading,
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        OnPluginMsgFinishedLoading)
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        PpapiPluginMsg_URLLoader_UpdateProgress,
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        OnPluginMsgUpdateProgress)
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::OnPluginMsgReceivedResponse(
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ResourceMessageReplyParams& params,
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const URLResponseInfoData& data) {
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SaveResponseInfo(data);
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunCallback(PP_OK);
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::OnPluginMsgSendData(
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ResourceMessageReplyParams& params,
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const IPC::Message& message) {
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PickleIterator iter(message);
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char* data;
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int data_length;
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!iter.ReadData(&data, &data_length)) {
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NOTREACHED() << "Expecting data";
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mode_ = MODE_STREAMING_DATA;
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  buffer_.insert(buffer_.end(), data, data + data_length);
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To avoid letting the network stack download an entire stream all at once,
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // defer loading when we have enough buffer.
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check for this before we run the callback, even though that could move
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // data out of the buffer. Doing anything after the callback is unsafe.
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(request_data_.prefetch_buffer_lower_threshold <
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         request_data_.prefetch_buffer_upper_threshold);
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!is_streaming_to_file_ &&
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !is_asynchronous_load_suspended_ &&
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      (buffer_.size() >= static_cast<size_t>(
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          request_data_.prefetch_buffer_upper_threshold))) {
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DVLOG(1) << "Suspending async load - buffer size: " << buffer_.size();
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetDefersLoading(true);
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (user_buffer_)
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RunCallback(FillUserBuffer());
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(!TrackedCallback::IsPending(pending_callback_));
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::OnPluginMsgFinishedLoading(
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ResourceMessageReplyParams& params,
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int32_t result) {
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mode_ = MODE_LOAD_COMPLETE;
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  done_status_ = result;
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_ = NULL;
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_size_ = 0;
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If the client hasn't called any function that takes a callback since
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the initial call to Open, or called ReadResponseBody and got a
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // synchronous return, then the callback will be NULL.
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (TrackedCallback::IsPending(pending_callback_))
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RunCallback(done_status_);
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::OnPluginMsgUpdateProgress(
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ResourceMessageReplyParams& params,
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int64_t bytes_sent,
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int64_t total_bytes_to_be_sent,
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int64_t bytes_received,
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int64_t total_bytes_to_be_received) {
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bytes_sent_ = bytes_sent;
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  total_bytes_to_be_sent_ = total_bytes_to_be_sent;
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bytes_received_ = bytes_received;
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  total_bytes_to_be_received_ = total_bytes_to_be_received;
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status_callback_)
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    status_callback_(pp_instance(), pp_resource(),
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     bytes_sent_, total_bytes_to_be_sent_,
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     bytes_received_, total_bytes_to_be_received_);
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::SetDefersLoading(bool defers_loading) {
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Post(RENDERER, PpapiHostMsg_URLLoader_SetDeferLoading(defers_loading));
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int32_t URLLoaderResource::ValidateCallback(
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(callback.get());
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (TrackedCallback::IsPending(pending_callback_))
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_OK;
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::RegisterCallback(
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!TrackedCallback::IsPending(pending_callback_));
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pending_callback_ = callback;
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::RunCallback(int32_t result) {
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This may be null when this is a main document loader.
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!pending_callback_.get())
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If |user_buffer_| was set as part of registering a callback, the paths
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // which trigger that callack must have cleared it since the callback is now
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free to delete it.
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!user_buffer_);
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // As a second line of defense, clear the |user_buffer_| in case the
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // callbacks get called in an unexpected order.
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_ = NULL;
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_size_ = 0;
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pending_callback_->Run(result);
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void URLLoaderResource::SaveResponseInfo(const URLResponseInfoData& data) {
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create a proxy resource for the the file ref host resource if needed.
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PP_Resource body_as_file_ref = 0;
368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (data.body_as_file_ref.IsValid()) {
369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    body_as_file_ref = FileRefResource::CreateFileRef(connection(),
370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                      pp_instance(),
371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                      data.body_as_file_ref);
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  response_info_ = new URLResponseInfoResource(
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      connection(), pp_instance(), data, body_as_file_ref);
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t URLLoaderResource::FillUserBuffer() {
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(user_buffer_);
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(user_buffer_size_);
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t bytes_to_copy = std::min(buffer_.size(), user_buffer_size_);
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::copy(buffer_.begin(), buffer_.begin() + bytes_to_copy, user_buffer_);
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_copy);
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If the buffer is getting too empty, resume asynchronous loading.
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_asynchronous_load_suspended_ &&
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      buffer_.size() <= static_cast<size_t>(
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          request_data_.prefetch_buffer_lower_threshold)) {
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DVLOG(1) << "Resuming async load - buffer size: " << buffer_.size();
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetDefersLoading(false);
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reset for next time.
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_ = NULL;
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  user_buffer_size_ = 0;
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return bytes_to_copy;
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace proxy
400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}  // namespace ppapi
401