// Copyright (c) 2012 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 "content/browser/loader/sync_resource_handler.h"

#include "base/logging.h"
#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/redirect_info.h"

namespace content {

SyncResourceHandler::SyncResourceHandler(
    net::URLRequest* request,
    IPC::Message* result_message,
    ResourceDispatcherHostImpl* resource_dispatcher_host)
    : ResourceHandler(request),
      read_buffer_(new net::IOBuffer(kReadBufSize)),
      result_message_(result_message),
      rdh_(resource_dispatcher_host),
      total_transfer_size_(0) {
  result_.final_url = request->url();
}

SyncResourceHandler::~SyncResourceHandler() {
  if (result_message_) {
    result_message_->set_reply_error();
    ResourceMessageFilter* filter = GetFilter();
    // If the filter doesn't exist at this point, the process has died and isn't
    // waiting for the result message anymore.
    if (filter)
      filter->Send(result_message_);
  }
}

bool SyncResourceHandler::OnRequestRedirected(
    const net::RedirectInfo& redirect_info,
    ResourceResponse* response,
    bool* defer) {
  if (rdh_->delegate()) {
    rdh_->delegate()->OnRequestRedirected(
        redirect_info.new_url, request(), GetRequestInfo()->GetContext(),
        response);
  }

  NetLogObserver::PopulateResponseInfo(request(), response);
  // TODO(darin): It would be much better if this could live in WebCore, but
  // doing so requires API changes at all levels.  Similar code exists in
  // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
  if (redirect_info.new_url.GetOrigin() != result_.final_url.GetOrigin()) {
    LOG(ERROR) << "Cross origin redirect denied";
    return false;
  }
  result_.final_url = redirect_info.new_url;

  total_transfer_size_ += request()->GetTotalReceivedBytes();
  return true;
}

bool SyncResourceHandler::OnResponseStarted(
    ResourceResponse* response,
    bool* defer) {
  const ResourceRequestInfoImpl* info = GetRequestInfo();
  if (!info->filter())
    return false;

  if (rdh_->delegate()) {
    rdh_->delegate()->OnResponseStarted(request(), info->GetContext(),
                                        response);
  }

  NetLogObserver::PopulateResponseInfo(request(), response);

  // We don't care about copying the status here.
  result_.headers = response->head.headers;
  result_.mime_type = response->head.mime_type;
  result_.charset = response->head.charset;
  result_.download_file_path = response->head.download_file_path;
  result_.request_time = response->head.request_time;
  result_.response_time = response->head.response_time;
  result_.load_timing = response->head.load_timing;
  result_.devtools_info = response->head.devtools_info;
  return true;
}

bool SyncResourceHandler::OnWillStart(const GURL& url, bool* defer) {
  return true;
}

bool SyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                     int* buf_size,
                                     int min_size) {
  DCHECK(min_size == -1);
  *buf = read_buffer_.get();
  *buf_size = kReadBufSize;
  return true;
}

bool SyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
  if (!bytes_read)
    return true;
  result_.data.append(read_buffer_->data(), bytes_read);
  return true;
}

void SyncResourceHandler::OnResponseCompleted(
    const net::URLRequestStatus& status,
    bool* defer) {
  ResourceMessageFilter* filter = GetFilter();
  if (!filter)
    return;

  result_.error_code = status.error();

  int total_transfer_size = request()->GetTotalReceivedBytes();
  result_.encoded_data_length = total_transfer_size_ + total_transfer_size;
  result_.encoded_body_length = request()->GetRawBodyBytes();

  ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_);
  filter->Send(result_message_);
  result_message_ = NULL;
  return;
}

void SyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
  // Sync requests don't involve ResourceMsg_DataDownloaded messages
  // being sent back to renderers as progress is made.
}

}  // namespace content
