// 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/renderer/fetchers/resource_fetcher_impl.h"

#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLLoader.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"

using base::TimeDelta;
using blink::WebFrame;
using blink::WebHTTPBody;
using blink::WebSecurityPolicy;
using blink::WebURLError;
using blink::WebURLLoader;
using blink::WebURLRequest;
using blink::WebURLResponse;

namespace content {

// static
ResourceFetcher* ResourceFetcher::Create(const GURL& url) {
  return new ResourceFetcherImpl(url);
}

ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url)
    : request_(url),
      completed_(false) {
}

ResourceFetcherImpl::~ResourceFetcherImpl() {
  if (!completed_ && loader_)
    loader_->cancel();
}

void ResourceFetcherImpl::SetMethod(const std::string& method) {
  DCHECK(!request_.isNull());
  DCHECK(!loader_);

  request_.setHTTPMethod(blink::WebString::fromUTF8(method));
}

void ResourceFetcherImpl::SetBody(const std::string& body) {
  DCHECK(!request_.isNull());
  DCHECK(!loader_);

  WebHTTPBody web_http_body;
  web_http_body.initialize();
  web_http_body.appendData(blink::WebData(body));
  request_.setHTTPBody(web_http_body);
}

void ResourceFetcherImpl::SetHeader(const std::string& header,
                                    const std::string& value) {
  DCHECK(!request_.isNull());
  DCHECK(!loader_);

  if (LowerCaseEqualsASCII(header, "referer")) {
    blink::WebString referrer = WebSecurityPolicy::generateReferrerHeader(
        blink::WebReferrerPolicyDefault,
        request_.url(),
        blink::WebString::fromUTF8(value));
    request_.setHTTPReferrer(referrer, blink::WebReferrerPolicyDefault);
  } else {
    request_.setHTTPHeaderField(blink::WebString::fromUTF8(header),
                                blink::WebString::fromUTF8(value));
  }
}

void ResourceFetcherImpl::Start(WebFrame* frame,
                                WebURLRequest::RequestContext request_context,
                                WebURLRequest::FrameType frame_type,
                                const Callback& callback) {
  DCHECK(!loader_);
  DCHECK(!request_.isNull());
  DCHECK(callback_.is_null());
  DCHECK(!completed_);
  if (!request_.httpBody().isNull())
    DCHECK_NE("GET", request_.httpMethod().utf8()) << "GETs can't have bodies.";

  callback_ = callback;

  request_.setRequestContext(request_context);
  request_.setFrameType(frame_type);
  request_.setFirstPartyForCookies(frame->document().firstPartyForCookies());
  frame->dispatchWillSendRequest(request_);
  loader_.reset(blink::Platform::current()->createURLLoader());
  loader_->loadAsynchronously(request_, this);

  // No need to hold on to the request.
  request_.reset();
}

void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) {
  DCHECK(loader_);
  DCHECK(!completed_);

  timeout_timer_.Start(FROM_HERE, timeout, this,
                       &ResourceFetcherImpl::TimeoutFired);
}

void ResourceFetcherImpl::RunCallback(const WebURLResponse& response,
                                      const std::string& data) {
  completed_ = true;
  timeout_timer_.Stop();
  if (callback_.is_null())
    return;

  // Take a reference to the callback as running the callback may lead to our
  // destruction.
  Callback callback = callback_;
  callback.Run(response, data);
}

void ResourceFetcherImpl::TimeoutFired() {
  DCHECK(!completed_);
  loader_->cancel();
  RunCallback(WebURLResponse(), std::string());
}

/////////////////////////////////////////////////////////////////////////////
// WebURLLoaderClient methods

void ResourceFetcherImpl::willSendRequest(
    WebURLLoader* loader, WebURLRequest& new_request,
    const WebURLResponse& redirect_response) {
}

void ResourceFetcherImpl::didSendData(
    WebURLLoader* loader, unsigned long long bytes_sent,
    unsigned long long total_bytes_to_be_sent) {
}

void ResourceFetcherImpl::didReceiveResponse(
    WebURLLoader* loader, const WebURLResponse& response) {
  DCHECK(!completed_);
  response_ = response;
}

void ResourceFetcherImpl::didReceiveData(
    WebURLLoader* loader, const char* data, int data_length,
    int encoded_data_length) {
  DCHECK(!completed_);
  DCHECK(data_length > 0);

  data_.append(data, data_length);
}

void ResourceFetcherImpl::didReceiveCachedMetadata(
    WebURLLoader* loader, const char* data, int data_length) {
  DCHECK(!completed_);
  DCHECK(data_length > 0);

  metadata_.assign(data, data_length);
}

void ResourceFetcherImpl::didFinishLoading(
    WebURLLoader* loader, double finishTime,
    int64_t total_encoded_data_length) {
  DCHECK(!completed_);

  RunCallback(response_, data_);
}

void ResourceFetcherImpl::didFail(WebURLLoader* loader,
                                  const WebURLError& error) {
  DCHECK(!completed_);

  // Go ahead and tell our delegate that we're done.
  RunCallback(WebURLResponse(), std::string());
}

}  // namespace content
