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

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/proxy_resolution/proxy_info.h"
#include "services/network/public/mojom/network_context.mojom.h"

namespace content {

ResolveProxyMsgHelper::ResolveProxyMsgHelper(int render_process_host_id)
    : BrowserMessageFilter(ViewMsgStart),
      render_process_host_id_(render_process_host_id),
      binding_(this) {}

void ResolveProxyMsgHelper::OverrideThreadForMessage(
    const IPC::Message& message,
    BrowserThread::ID* thread) {
  if (message.type() == ViewHostMsg_ResolveProxy::ID)
    *thread = BrowserThread::UI;
}

bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(ResolveProxyMsgHelper, message)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void ResolveProxyMsgHelper::OnResolveProxy(const GURL& url,
                                           IPC::Message* reply_msg) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Enqueue the pending request.
  pending_requests_.push_back(PendingRequest(url, reply_msg));

  // If nothing is in progress, start.
  if (!binding_.is_bound()) {
    DCHECK_EQ(1u, pending_requests_.size());
    StartPendingRequest();
  }
}

ResolveProxyMsgHelper::~ResolveProxyMsgHelper() {
  DCHECK(!owned_self_);
  DCHECK(!binding_.is_bound());
}

void ResolveProxyMsgHelper::StartPendingRequest() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!binding_.is_bound());
  DCHECK(!pending_requests_.empty());

  // Start the request.
  network::mojom::ProxyLookupClientPtr proxy_lookup_client;
  binding_.Bind(mojo::MakeRequest(&proxy_lookup_client));
  binding_.set_connection_error_handler(
      base::BindOnce(&ResolveProxyMsgHelper::OnProxyLookupComplete,
                     base::Unretained(this), net::ERR_ABORTED, base::nullopt));
  owned_self_ = this;
  if (!SendRequestToNetworkService(pending_requests_.front().url,
                                   std::move(proxy_lookup_client))) {
    OnProxyLookupComplete(net::ERR_FAILED, base::nullopt);
  }
}

bool ResolveProxyMsgHelper::SendRequestToNetworkService(
    const GURL& url,
    network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  RenderProcessHost* render_process_host =
      RenderProcessHost::FromID(render_process_host_id_);
  // Fail the request if there's no such RenderProcessHost;
  if (!render_process_host)
    return false;
  render_process_host->GetStoragePartition()
      ->GetNetworkContext()
      ->LookUpProxyForURL(url, std::move(proxy_lookup_client));
  return true;
}

void ResolveProxyMsgHelper::OnProxyLookupComplete(
    int32_t net_error,
    const base::Optional<net::ProxyInfo>& proxy_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!pending_requests_.empty());

  binding_.Close();

  // Need to keep |this| alive until the end of this method, and then release
  // this reference. StartPendingRequest(), if called, will grab other
  // reference, and a reference may be owned by the IO thread or by other
  // posted tasks, so |this| may or may not be deleted at the end of this
  // method.
  scoped_refptr<ResolveProxyMsgHelper> owned_self = std::move(owned_self_);

  // If all references except |owned_self| have been released, then there's
  // nothing waiting for pending requests to complete. So just exit this method,
  // which will release the last reference, destroying |this|.
  if (HasOneRef())
    return;

  // Clear the current (completed) request.
  PendingRequest completed_req = std::move(pending_requests_.front());
  pending_requests_.pop_front();

  ViewHostMsg_ResolveProxy::WriteReplyParams(
      completed_req.reply_msg.get(), !!proxy_info,
      proxy_info ? proxy_info->ToPacString() : std::string());
  Send(completed_req.reply_msg.release());

  // Start the next request.
  if (!pending_requests_.empty())
    StartPendingRequest();
}

ResolveProxyMsgHelper::PendingRequest::PendingRequest(const GURL& url,
                                                      IPC::Message* reply_msg)
    : url(url), reply_msg(reply_msg) {}

ResolveProxyMsgHelper::PendingRequest::PendingRequest(
    PendingRequest&& pending_request) noexcept = default;

ResolveProxyMsgHelper::PendingRequest::~PendingRequest() noexcept = default;

ResolveProxyMsgHelper::PendingRequest& ResolveProxyMsgHelper::PendingRequest::
operator=(PendingRequest&& pending_request) noexcept = default;

}  // namespace content
