// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/url_loader_resource.h"

#include "base/logging.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_url_loader.h"
#include "ppapi/proxy/dispatch_reply_message.h"
#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/url_request_info_resource.h"
#include "ppapi/proxy/url_response_info_resource.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/url_response_info_data.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/resource_creation_api.h"

using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_URLLoader_API;
using ppapi::thunk::PPB_URLRequestInfo_API;

#ifdef _MSC_VER
// Do not warn about use of std::copy with raw pointers.
#pragma warning(disable : 4996)
#endif

namespace ppapi {
namespace proxy {

URLLoaderResource::URLLoaderResource(Connection connection,
                                     PP_Instance instance)
    : PluginResource(connection, instance),
      mode_(MODE_WAITING_TO_OPEN),
      status_callback_(NULL),
      bytes_sent_(0),
      total_bytes_to_be_sent_(-1),
      bytes_received_(0),
      total_bytes_to_be_received_(-1),
      user_buffer_(NULL),
      user_buffer_size_(0),
      done_status_(PP_OK_COMPLETIONPENDING),
      is_streaming_to_file_(false),
      is_asynchronous_load_suspended_(false) {
  SendCreate(RENDERER, PpapiHostMsg_URLLoader_Create());
}

URLLoaderResource::URLLoaderResource(Connection connection,
                                     PP_Instance instance,
                                     int pending_main_document_loader_id,
                                     const ppapi::URLResponseInfoData& data)
    : PluginResource(connection, instance),
      mode_(MODE_OPENING),
      status_callback_(NULL),
      bytes_sent_(0),
      total_bytes_to_be_sent_(-1),
      bytes_received_(0),
      total_bytes_to_be_received_(-1),
      user_buffer_(NULL),
      user_buffer_size_(0),
      done_status_(PP_OK_COMPLETIONPENDING),
      is_streaming_to_file_(false),
      is_asynchronous_load_suspended_(false) {
  AttachToPendingHost(RENDERER, pending_main_document_loader_id);
  SaveResponseInfo(data);
}

URLLoaderResource::~URLLoaderResource() {
}

PPB_URLLoader_API* URLLoaderResource::AsPPB_URLLoader_API() {
  return this;
}

int32_t URLLoaderResource::Open(PP_Resource request_id,
                                scoped_refptr<TrackedCallback> callback) {
  EnterResourceNoLock<PPB_URLRequestInfo_API> enter_request(request_id, true);
  if (enter_request.failed()) {
    Log(PP_LOGLEVEL_ERROR,
        "PPB_URLLoader.Open: invalid request resource ID. (Hint to C++ wrapper"
        " users: use the ResourceRequest constructor that takes an instance or"
        " else the request will be null.)");
    return PP_ERROR_BADARGUMENT;
  }
  return Open(enter_request.object()->GetData(), 0, callback);
}

int32_t URLLoaderResource::Open(
    const ::ppapi::URLRequestInfoData& request_data,
    int requestor_pid,
    scoped_refptr<TrackedCallback> callback) {
  int32_t rv = ValidateCallback(callback);
  if (rv != PP_OK)
    return rv;
  if (mode_ != MODE_WAITING_TO_OPEN)
    return PP_ERROR_INPROGRESS;

  request_data_ = request_data;

  mode_ = MODE_OPENING;
  is_asynchronous_load_suspended_ = false;

  RegisterCallback(callback);
  Post(RENDERER, PpapiHostMsg_URLLoader_Open(request_data));
  return PP_OK_COMPLETIONPENDING;
}

int32_t URLLoaderResource::FollowRedirect(
    scoped_refptr<TrackedCallback> callback) {
  int32_t rv = ValidateCallback(callback);
  if (rv != PP_OK)
    return rv;
  if (mode_ != MODE_OPENING)
    return PP_ERROR_INPROGRESS;

  SetDefersLoading(false);  // Allow the redirect to continue.
  RegisterCallback(callback);
  return PP_OK_COMPLETIONPENDING;
}

PP_Bool URLLoaderResource::GetUploadProgress(int64_t* bytes_sent,
                                              int64_t* total_bytes_to_be_sent) {
  if (!request_data_.record_upload_progress) {
    *bytes_sent = 0;
    *total_bytes_to_be_sent = 0;
    return PP_FALSE;
  }
  *bytes_sent = bytes_sent_;
  *total_bytes_to_be_sent = total_bytes_to_be_sent_;
  return PP_TRUE;
}

PP_Bool URLLoaderResource::GetDownloadProgress(
    int64_t* bytes_received,
    int64_t* total_bytes_to_be_received) {
  if (!request_data_.record_download_progress) {
    *bytes_received = 0;
    *total_bytes_to_be_received = 0;
    return PP_FALSE;
  }
  *bytes_received = bytes_received_;
  *total_bytes_to_be_received = total_bytes_to_be_received_;
  return PP_TRUE;
}

PP_Resource URLLoaderResource::GetResponseInfo() {
  if (response_info_.get())
    return response_info_->GetReference();
  return 0;
}

int32_t URLLoaderResource::ReadResponseBody(
    void* buffer,
    int32_t bytes_to_read,
    scoped_refptr<TrackedCallback> callback) {
  int32_t rv = ValidateCallback(callback);
  if (rv != PP_OK)
    return rv;
  if (!response_info_.get())
    return PP_ERROR_FAILED;

  // Fail if we have a valid file ref.
  // ReadResponseBody() is for reading to a user-provided buffer.
  if (response_info_->data().body_as_file_ref.IsValid())
    return PP_ERROR_FAILED;

  if (bytes_to_read <= 0 || !buffer)
    return PP_ERROR_BADARGUMENT;

  user_buffer_ = static_cast<char*>(buffer);
  user_buffer_size_ = bytes_to_read;

  if (!buffer_.empty())
    return FillUserBuffer();

  // We may have already reached EOF.
  if (done_status_ != PP_OK_COMPLETIONPENDING) {
    user_buffer_ = NULL;
    user_buffer_size_ = 0;
    return done_status_;
  }

  RegisterCallback(callback);
  return PP_OK_COMPLETIONPENDING;
}

int32_t URLLoaderResource::FinishStreamingToFile(
    scoped_refptr<TrackedCallback> callback) {
  int32_t rv = ValidateCallback(callback);
  if (rv != PP_OK)
    return rv;
  if (!response_info_.get())
    return PP_ERROR_FAILED;

  // Fail if we do not have a valid file ref.
  if (!response_info_->data().body_as_file_ref.IsValid())
    return PP_ERROR_FAILED;

  // We may have already reached EOF.
  if (done_status_ != PP_OK_COMPLETIONPENDING)
    return done_status_;

  is_streaming_to_file_ = true;
  if (is_asynchronous_load_suspended_)
    SetDefersLoading(false);

  // Wait for didFinishLoading / didFail.
  RegisterCallback(callback);
  return PP_OK_COMPLETIONPENDING;
}

void URLLoaderResource::Close() {
  mode_ = MODE_LOAD_COMPLETE;
  done_status_ = PP_ERROR_ABORTED;

  Post(RENDERER, PpapiHostMsg_URLLoader_Close());

  // Abort the callbacks, the plugin doesn't want to be called back after this.
  // TODO(brettw) this should fix bug 69457, mark it fixed. ============
  if (TrackedCallback::IsPending(pending_callback_))
    pending_callback_->PostAbort();
}

void URLLoaderResource::GrantUniversalAccess() {
  Post(RENDERER, PpapiHostMsg_URLLoader_GrantUniversalAccess());
}

void URLLoaderResource::RegisterStatusCallback(
    PP_URLLoaderTrusted_StatusCallback callback) {
  status_callback_ = callback;
}

void URLLoaderResource::OnReplyReceived(
    const ResourceMessageReplyParams& params,
    const IPC::Message& msg) {
  PPAPI_BEGIN_MESSAGE_MAP(URLLoaderResource, msg)
    case PpapiPluginMsg_URLLoader_SendData::ID:
      // Special message, manually dispatch since we don't want the automatic
      // unpickling.
      OnPluginMsgSendData(params, msg);
      break;

    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_URLLoader_ReceivedResponse,
        OnPluginMsgReceivedResponse)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_URLLoader_FinishedLoading,
        OnPluginMsgFinishedLoading)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_URLLoader_UpdateProgress,
        OnPluginMsgUpdateProgress)
  PPAPI_END_MESSAGE_MAP()
}

void URLLoaderResource::OnPluginMsgReceivedResponse(
    const ResourceMessageReplyParams& params,
    const URLResponseInfoData& data) {
  SaveResponseInfo(data);
  RunCallback(PP_OK);
}

void URLLoaderResource::OnPluginMsgSendData(
    const ResourceMessageReplyParams& params,
    const IPC::Message& message) {
  PickleIterator iter(message);
  const char* data;
  int data_length;
  if (!iter.ReadData(&data, &data_length)) {
    NOTREACHED() << "Expecting data";
    return;
  }

  mode_ = MODE_STREAMING_DATA;
  buffer_.insert(buffer_.end(), data, data + data_length);

  // To avoid letting the network stack download an entire stream all at once,
  // defer loading when we have enough buffer.
  // Check for this before we run the callback, even though that could move
  // data out of the buffer. Doing anything after the callback is unsafe.
  DCHECK(request_data_.prefetch_buffer_lower_threshold <
         request_data_.prefetch_buffer_upper_threshold);
  if (!is_streaming_to_file_ &&
      !is_asynchronous_load_suspended_ &&
      (buffer_.size() >= static_cast<size_t>(
          request_data_.prefetch_buffer_upper_threshold))) {
    DVLOG(1) << "Suspending async load - buffer size: " << buffer_.size();
    SetDefersLoading(true);
  }

  if (user_buffer_)
    RunCallback(FillUserBuffer());
  else
    DCHECK(!TrackedCallback::IsPending(pending_callback_));
}

void URLLoaderResource::OnPluginMsgFinishedLoading(
    const ResourceMessageReplyParams& params,
    int32_t result) {
  mode_ = MODE_LOAD_COMPLETE;
  done_status_ = result;
  user_buffer_ = NULL;
  user_buffer_size_ = 0;

  // If the client hasn't called any function that takes a callback since
  // the initial call to Open, or called ReadResponseBody and got a
  // synchronous return, then the callback will be NULL.
  if (TrackedCallback::IsPending(pending_callback_))
    RunCallback(done_status_);
}

void URLLoaderResource::OnPluginMsgUpdateProgress(
    const ResourceMessageReplyParams& params,
    int64_t bytes_sent,
    int64_t total_bytes_to_be_sent,
    int64_t bytes_received,
    int64_t total_bytes_to_be_received) {
  bytes_sent_ = bytes_sent;
  total_bytes_to_be_sent_ = total_bytes_to_be_sent;
  bytes_received_ = bytes_received;
  total_bytes_to_be_received_ = total_bytes_to_be_received;

  if (status_callback_)
    status_callback_(pp_instance(), pp_resource(),
                     bytes_sent_, total_bytes_to_be_sent_,
                     bytes_received_, total_bytes_to_be_received_);
}

void URLLoaderResource::SetDefersLoading(bool defers_loading) {
  Post(RENDERER, PpapiHostMsg_URLLoader_SetDeferLoading(defers_loading));
}

int32_t URLLoaderResource::ValidateCallback(
    scoped_refptr<TrackedCallback> callback) {
  DCHECK(callback.get());
  if (TrackedCallback::IsPending(pending_callback_))
    return PP_ERROR_INPROGRESS;
  return PP_OK;
}

void URLLoaderResource::RegisterCallback(
    scoped_refptr<TrackedCallback> callback) {
  DCHECK(!TrackedCallback::IsPending(pending_callback_));
  pending_callback_ = callback;
}

void URLLoaderResource::RunCallback(int32_t result) {
  // This may be null when this is a main document loader.
  if (!pending_callback_.get())
    return;

  // If |user_buffer_| was set as part of registering a callback, the paths
  // which trigger that callack must have cleared it since the callback is now
  // free to delete it.
  DCHECK(!user_buffer_);

  // As a second line of defense, clear the |user_buffer_| in case the
  // callbacks get called in an unexpected order.
  user_buffer_ = NULL;
  user_buffer_size_ = 0;
  pending_callback_->Run(result);
}

void URLLoaderResource::SaveResponseInfo(const URLResponseInfoData& data) {
  // Create a proxy resource for the the file ref host resource if needed.
  PP_Resource body_as_file_ref = 0;
  if (data.body_as_file_ref.IsValid()) {
    body_as_file_ref = FileRefResource::CreateFileRef(connection(),
                                                      pp_instance(),
                                                      data.body_as_file_ref);
  }
  response_info_ = new URLResponseInfoResource(
      connection(), pp_instance(), data, body_as_file_ref);
}

size_t URLLoaderResource::FillUserBuffer() {
  DCHECK(user_buffer_);
  DCHECK(user_buffer_size_);

  size_t bytes_to_copy = std::min(buffer_.size(), user_buffer_size_);
  std::copy(buffer_.begin(), buffer_.begin() + bytes_to_copy, user_buffer_);
  buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_copy);

  // If the buffer is getting too empty, resume asynchronous loading.
  if (is_asynchronous_load_suspended_ &&
      buffer_.size() <= static_cast<size_t>(
          request_data_.prefetch_buffer_lower_threshold)) {
    DVLOG(1) << "Resuming async load - buffer size: " << buffer_.size();
    SetDefersLoading(false);
  }

  // Reset for next time.
  user_buffer_ = NULL;
  user_buffer_size_ = 0;
  return bytes_to_copy;
}

}  // namespace proxy
}  // namespace ppapi
