// Copyright 2015 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/navigation_resource_throttle.h"

#include <memory>

#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/navigation_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/common/referrer.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory.h"
#include "ui/base/page_transition_types.h"

namespace content {

namespace {

// Used in unit tests to make UI thread checks succeed even if there is no
// NavigationHandle.
bool g_ui_checks_always_succeed = false;

// Used in unit tests to transfer all navigations.
bool g_force_transfer = false;

typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
    UIChecksPerformedCallback;

void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
                               NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(result.action(), NavigationThrottle::DEFER);
  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                          base::BindOnce(callback, result));
}

// Returns the NavigationHandle to use for a navigation in the frame specified
// by |render_process_id| and |render_frame_host_id|. If not found, |callback|
// will be invoked to cancel the request.
//
// Note: in unit test |callback| may be invoked with a value of proceed if no
// handle is found. This happens when
// NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing is
// called with a value of true.
NavigationHandleImpl* FindNavigationHandle(
    int render_process_id,
    int render_frame_host_id,
    const UIChecksPerformedCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (g_ui_checks_always_succeed) {
    SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
    return nullptr;
  }

  RenderFrameHostImpl* render_frame_host =
      RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
  if (!render_frame_host) {
    SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
    return nullptr;
  }

  NavigationHandleImpl* navigation_handle =
      render_frame_host->navigation_handle();
  if (!navigation_handle) {
    SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
    return nullptr;
  }
  return navigation_handle;
}

void CheckWillStartRequestOnUIThread(
    UIChecksPerformedCallback callback,
    int render_process_id,
    int render_frame_host_id,
    const std::string& method,
    const scoped_refptr<content::ResourceRequestBody>& resource_request_body,
    const Referrer& sanitized_referrer,
    bool has_user_gesture,
    ui::PageTransition transition,
    bool is_external_protocol,
    RequestContextType request_context_type,
    blink::WebMixedContentContextType mixed_content_context_type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  NavigationHandleImpl* navigation_handle =
      FindNavigationHandle(render_process_id, render_frame_host_id, callback);
  if (!navigation_handle)
    return;

  navigation_handle->WillStartRequest(
      method, resource_request_body, sanitized_referrer, has_user_gesture,
      transition, is_external_protocol, request_context_type,
      mixed_content_context_type,
      base::Bind(&SendCheckResultToIOThread, callback));
}

void CheckWillRedirectRequestOnUIThread(
    UIChecksPerformedCallback callback,
    int render_process_id,
    int render_frame_host_id,
    const GURL& new_url,
    const std::string& new_method,
    const GURL& new_referrer_url,
    bool new_is_external_protocol,
    scoped_refptr<net::HttpResponseHeaders> headers,
    net::HttpResponseInfo::ConnectionInfo connection_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  NavigationHandleImpl* navigation_handle =
      FindNavigationHandle(render_process_id, render_frame_host_id, callback);
  if (!navigation_handle)
    return;

  GURL new_validated_url(new_url);
  RenderProcessHost::FromID(render_process_id)
      ->FilterURL(false, &new_validated_url);
  navigation_handle->WillRedirectRequest(
      new_validated_url, new_method, new_referrer_url, new_is_external_protocol,
      headers, connection_info, nullptr,
      base::Bind(&SendCheckResultToIOThread, callback));
}

void WillProcessResponseOnUIThread(
    UIChecksPerformedCallback callback,
    int render_process_id,
    int render_frame_host_id,
    scoped_refptr<net::HttpResponseHeaders> headers,
    net::HttpResponseInfo::ConnectionInfo connection_info,
    const SSLStatus& ssl_status,
    const GlobalRequestID& request_id,
    bool should_replace_current_entry,
    bool is_download,
    bool is_stream,
    const base::Closure& transfer_callback,
    std::unique_ptr<NavigationData> navigation_data) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (g_force_transfer) {
    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, transfer_callback);
  }

  NavigationHandleImpl* navigation_handle =
      FindNavigationHandle(render_process_id, render_frame_host_id, callback);
  if (!navigation_handle)
    return;

  if (navigation_data)
    navigation_handle->set_navigation_data(std::move(navigation_data));

  RenderFrameHostImpl* render_frame_host =
      RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
  DCHECK(render_frame_host);
  navigation_handle->WillProcessResponse(
      render_frame_host, headers, connection_info, ssl_status, request_id,
      should_replace_current_entry, is_download, is_stream, transfer_callback,
      base::Bind(&SendCheckResultToIOThread, callback));
}

}  // namespace

NavigationResourceThrottle::NavigationResourceThrottle(
    net::URLRequest* request,
    ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate,
    RequestContextType request_context_type,
    blink::WebMixedContentContextType mixed_content_context_type)
    : request_(request),
      resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate),
      request_context_type_(request_context_type),
      mixed_content_context_type_(mixed_content_context_type),
      in_cross_site_transition_(false),
      on_transfer_done_result_(NavigationThrottle::DEFER),
      weak_ptr_factory_(this) {}

NavigationResourceThrottle::~NavigationResourceThrottle() {}

void NavigationResourceThrottle::WillStartRequest(bool* defer) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  const ResourceRequestInfoImpl* info =
      ResourceRequestInfoImpl::ForRequest(request_);
  if (!info)
    return;

  int render_process_id, render_frame_id;
  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
    return;

  bool is_external_protocol =
      request_->url().is_valid() &&
      !info->GetContext()
           ->GetRequestContext()
           ->job_factory()
           ->IsHandledProtocol(request_->url().scheme());
  UIChecksPerformedCallback callback =
      base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
                 weak_ptr_factory_.GetWeakPtr());
  DCHECK(request_->method() == "POST" || request_->method() == "GET");
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::BindOnce(
          &CheckWillStartRequestOnUIThread, callback, render_process_id,
          render_frame_id, request_->method(), info->body(),
          Referrer::SanitizeForRequest(
              request_->url(),
              Referrer(GURL(request_->referrer()), info->GetReferrerPolicy())),
          info->HasUserGesture(), info->GetPageTransition(),
          is_external_protocol, request_context_type_,
          mixed_content_context_type_));
  *defer = true;
}

void NavigationResourceThrottle::WillRedirectRequest(
    const net::RedirectInfo& redirect_info,
    bool* defer) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
  if (!info)
    return;

  if (redirect_info.new_method != "POST")
    info->ResetBody();

  int render_process_id, render_frame_id;
  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
    return;

  bool new_is_external_protocol =
      request_->url().is_valid() &&
      !info->GetContext()
           ->GetRequestContext()
           ->job_factory()
           ->IsHandledProtocol(request_->url().scheme());
  DCHECK(redirect_info.new_method == "POST" ||
         redirect_info.new_method == "GET");
  UIChecksPerformedCallback callback =
      base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
                 weak_ptr_factory_.GetWeakPtr());

  // Send the redirect info to the NavigationHandle on the UI thread.
  // Note: to avoid threading issues, a copy of the HttpResponseHeaders is sent
  // in lieu of the original.
  scoped_refptr<net::HttpResponseHeaders> response_headers;
  if (request_->response_headers()) {
    response_headers = new net::HttpResponseHeaders(
        request_->response_headers()->raw_headers());
  }

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::BindOnce(&CheckWillRedirectRequestOnUIThread, callback,
                     render_process_id, render_frame_id, redirect_info.new_url,
                     redirect_info.new_method, GURL(redirect_info.new_referrer),
                     new_is_external_protocol, response_headers,
                     request_->response_info().connection_info));
  *defer = true;
}

void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  const ResourceRequestInfoImpl* info =
      ResourceRequestInfoImpl::ForRequest(request_);
  if (!info)
    return;

  int render_process_id, render_frame_id;
  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
    return;

  // Send a copy of the response headers to the NavigationHandle on the UI
  // thread.
  scoped_refptr<net::HttpResponseHeaders> response_headers;
  if (request_->response_headers()) {
    response_headers = new net::HttpResponseHeaders(
        request_->response_headers()->raw_headers());
  }

  std::unique_ptr<NavigationData> cloned_data;
  if (resource_dispatcher_host_delegate_) {
    // Ask the embedder for a NavigationData instance.
    NavigationData* navigation_data =
        resource_dispatcher_host_delegate_->GetNavigationData(request_);

    // Clone the embedder's NavigationData before moving it to the UI thread.
    if (navigation_data)
      cloned_data = navigation_data->Clone();
  }

  UIChecksPerformedCallback callback =
      base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
                 weak_ptr_factory_.GetWeakPtr());
  base::Closure transfer_callback =
      base::Bind(&NavigationResourceThrottle::InitiateTransfer,
                 weak_ptr_factory_.GetWeakPtr());

  SSLStatus ssl_status;
  if (request_->ssl_info().cert.get()) {
    NavigationResourceHandler::GetSSLStatusForRequest(request_->ssl_info(),
                                                      &ssl_status);
  }

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::BindOnce(&WillProcessResponseOnUIThread, callback,
                     render_process_id, render_frame_id, response_headers,
                     request_->response_info().connection_info, ssl_status,
                     info->GetGlobalRequestID(),
                     info->should_replace_current_entry(), info->IsDownload(),
                     info->is_stream(), transfer_callback,
                     base::Passed(&cloned_data)));
  *defer = true;
}

const char* NavigationResourceThrottle::GetNameForLogging() const {
  return "NavigationResourceThrottle";
}

void NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(
    bool ui_checks_always_succeed) {
  g_ui_checks_always_succeed = ui_checks_always_succeed;
}

void NavigationResourceThrottle::set_force_transfer_for_testing(
    bool force_transfer) {
  g_force_transfer = force_transfer;
}

void NavigationResourceThrottle::OnUIChecksPerformed(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK_NE(NavigationThrottle::DEFER, result.action());
  if (in_cross_site_transition_) {
    on_transfer_done_result_ = result;
    return;
  }

  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
      result.action() == NavigationThrottle::CANCEL) {
    Cancel();
  } else if (result.action() == NavigationThrottle::BLOCK_REQUEST ||
             result.action() ==
                 NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
    CancelWithError(net::ERR_BLOCKED_BY_CLIENT);
  } else if (result.action() == NavigationThrottle::BLOCK_RESPONSE) {
    // TODO(mkwst): If we cancel the main frame request with anything other than
    // 'net::ERR_ABORTED', we'll trigger some special behavior that might not be
    // desirable here (non-POSTs will reload the page, while POST has some logic
    // around reloading to avoid duplicating actions server-side). For the
    // moment, only child frame navigations should be blocked. If we need to
    // block main frame navigations in the future, we'll need to carefully
    // consider the right thing to do here.
    DCHECK(!ResourceRequestInfo::ForRequest(request_)->IsMainFrame());
    CancelWithError(net::ERR_BLOCKED_BY_RESPONSE);
  } else {
    Resume();
  }
}

void NavigationResourceThrottle::InitiateTransfer() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  in_cross_site_transition_ = true;
  ResourceRequestInfoImpl* info =
      ResourceRequestInfoImpl::ForRequest(request_);
  ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(
      info->GetGlobalRequestID(),
      base::Bind(&NavigationResourceThrottle::OnTransferComplete,
                 weak_ptr_factory_.GetWeakPtr()));
}

void NavigationResourceThrottle::OnTransferComplete() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(in_cross_site_transition_);
  in_cross_site_transition_ = false;

  // If the results of the checks on the UI thread are known, unblock the
  // navigation. Otherwise, wait until the callback has executed.
  if (on_transfer_done_result_.action() != NavigationThrottle::DEFER) {
    OnUIChecksPerformed(on_transfer_done_result_);
    on_transfer_done_result_ = NavigationThrottle::DEFER;
  }
}

}  // namespace content
