// 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/download/save_file_resource_handler.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/download/save_file_manager.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_status.h"

namespace content {

SaveFileResourceHandler::SaveFileResourceHandler(net::URLRequest* request,
                                                 SaveItemId save_item_id,
                                                 SavePackageId save_package_id,
                                                 int render_process_host_id,
                                                 int render_frame_routing_id,
                                                 const GURL& url,
                                                 SaveFileManager* manager)
    : ResourceHandler(request),
      save_item_id_(save_item_id),
      save_package_id_(save_package_id),
      render_process_id_(render_process_host_id),
      render_frame_routing_id_(render_frame_routing_id),
      url_(url),
      content_length_(0),
      save_manager_(manager) {}

SaveFileResourceHandler::~SaveFileResourceHandler() {
}

bool SaveFileResourceHandler::OnRequestRedirected(
    const net::RedirectInfo& redirect_info,
    ResourceResponse* response,
    bool* defer) {
  final_url_ = redirect_info.new_url;
  return true;
}

bool SaveFileResourceHandler::OnResponseStarted(ResourceResponse* response,
                                                bool* defer) {
  // |save_manager_| consumes (deletes):
  SaveFileCreateInfo* info = new SaveFileCreateInfo(
      url_, final_url_, save_item_id_, save_package_id_, render_process_id_,
      render_frame_routing_id_, GetRequestID(), content_disposition_,
      content_length_);
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&SaveFileManager::StartSave, save_manager_, info));
  return true;
}

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

bool SaveFileResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                         int* buf_size,
                                         int min_size) {
  DCHECK(buf && buf_size);
  if (!read_buffer_.get()) {
    *buf_size = min_size < 0 ? kReadBufSize : min_size;
    read_buffer_ = new net::IOBuffer(*buf_size);
  }
  *buf = read_buffer_.get();
  return true;
}

bool SaveFileResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
  DCHECK(read_buffer_.get());
  // We are passing ownership of this buffer to the save file manager.
  scoped_refptr<net::IOBuffer> buffer;
  read_buffer_.swap(buffer);
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&SaveFileManager::UpdateSaveProgress, save_manager_,
                 save_item_id_, base::RetainedRef(buffer), bytes_read));
  return true;
}

void SaveFileResourceHandler::OnResponseCompleted(
    const net::URLRequestStatus& status,
    const std::string& security_info,
    bool* defer) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&SaveFileManager::SaveFinished, save_manager_, save_item_id_,
                 save_package_id_,
                 status.is_success() && !status.is_io_pending()));
  read_buffer_ = NULL;
}

void SaveFileResourceHandler::OnDataDownloaded(int bytes_downloaded) {
  NOTREACHED();
}

void SaveFileResourceHandler::set_content_length(
    const std::string& content_length) {
  base::StringToInt64(content_length, &content_length_);
}

}  // namespace content
