// Copyright (c) 2013 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/renderer_host/pepper/pepper_network_proxy_host.h"

#include "base/bind.h"
#include "base/task/post_task.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
#include "net/proxy_resolution/proxy_info.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"

namespace content {

namespace {

bool LookUpProxyForURLCallback(
    int render_process_host_id,
    int render_frame_host_id,
    const GURL& url,
    network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
  RenderFrameHost* render_frame_host =
      RenderFrameHost::FromID(render_process_host_id, render_frame_host_id);
  if (!render_frame_host)
    return false;

  SiteInstance* site_instance = render_frame_host->GetSiteInstance();
  StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
      site_instance->GetBrowserContext(), site_instance);

  storage_partition->GetNetworkContext()->LookUpProxyForURL(
      url, std::move(proxy_lookup_client));
  return true;
}

}  // namespace

PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
                                               PP_Instance instance,
                                               PP_Resource resource)
    : ResourceHost(host->GetPpapiHost(), instance, resource),
      render_process_id_(0),
      render_frame_id_(0),
      is_allowed_(false),
      waiting_for_ui_thread_data_(true),
      weak_factory_(this) {
  host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
                                     &render_frame_id_);
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&GetUIThreadDataOnUIThread, render_process_id_,
                     render_frame_id_, host->external_plugin()),
      base::BindOnce(&PepperNetworkProxyHost::DidGetUIThreadData,
                     weak_factory_.GetWeakPtr()));
}

PepperNetworkProxyHost::~PepperNetworkProxyHost() = default;

PepperNetworkProxyHost::UIThreadData::UIThreadData() : is_allowed(false) {}

PepperNetworkProxyHost::UIThreadData::UIThreadData(const UIThreadData& other) =
    default;

PepperNetworkProxyHost::UIThreadData::~UIThreadData() {}

// static
PepperNetworkProxyHost::UIThreadData
PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
                                                  int render_frame_id,
                                                  bool is_external_plugin) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  PepperNetworkProxyHost::UIThreadData result;

  SocketPermissionRequest request(
      content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0);
  result.is_allowed =
      pepper_socket_utils::CanUseSocketAPIs(is_external_plugin,
                                            false /* is_private_api */,
                                            &request,
                                            render_process_id,
                                            render_frame_id);
  return result;
}

void PepperNetworkProxyHost::DidGetUIThreadData(
    const UIThreadData& ui_thread_data) {
  is_allowed_ = ui_thread_data.is_allowed;
  waiting_for_ui_thread_data_ = false;
  TryToSendUnsentRequests();
}

int32_t PepperNetworkProxyHost::OnResourceMessageReceived(
    const IPC::Message& msg,
    ppapi::host::HostMessageContext* context) {
  PPAPI_BEGIN_MESSAGE_MAP(PepperNetworkProxyHost, msg)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_NetworkProxy_GetProxyForURL,
                                      OnMsgGetProxyForURL)
  PPAPI_END_MESSAGE_MAP()
  return PP_ERROR_FAILED;
}

int32_t PepperNetworkProxyHost::OnMsgGetProxyForURL(
    ppapi::host::HostMessageContext* context,
    const std::string& url) {
  GURL gurl(url);
  if (gurl.is_valid()) {
    UnsentRequest request = {gurl, context->MakeReplyMessageContext()};
    unsent_requests_.push(request);
    TryToSendUnsentRequests();
  } else {
    SendFailureReply(PP_ERROR_BADARGUMENT, context->MakeReplyMessageContext());
  }
  return PP_OK_COMPLETIONPENDING;
}

void PepperNetworkProxyHost::TryToSendUnsentRequests() {
  if (waiting_for_ui_thread_data_)
    return;

  while (!unsent_requests_.empty()) {
    const UnsentRequest& request = unsent_requests_.front();
    if (!is_allowed_) {
      SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
    } else {
      // Everything looks valid, so try to resolve the proxy.
      auto lookup_helper = std::make_unique<PepperProxyLookupHelper>();
      PepperProxyLookupHelper::LookUpProxyForURLCallback
          look_up_proxy_for_url_callback = base::BindOnce(
              &LookUpProxyForURLCallback, render_process_id_, render_frame_id_);
      PepperProxyLookupHelper::LookUpCompleteCallback
          look_up_complete_callback =
              base::BindOnce(&PepperNetworkProxyHost::OnResolveProxyCompleted,
                             weak_factory_.GetWeakPtr(), request.reply_context,
                             lookup_helper.get());
      lookup_helper->Start(request.url,
                           std::move(look_up_proxy_for_url_callback),
                           std::move(look_up_complete_callback));
      pending_requests_.insert(std::move(lookup_helper));
    }
    unsent_requests_.pop();
  }
}

void PepperNetworkProxyHost::OnResolveProxyCompleted(
    ppapi::host::ReplyMessageContext context,
    PepperProxyLookupHelper* pending_request,
    base::Optional<net::ProxyInfo> proxy_info) {
  auto it = pending_requests_.find(pending_request);
  DCHECK(it != pending_requests_.end());
  pending_requests_.erase(it);

  std::string pac_string;
  if (!proxy_info) {
    // This can happen in cases of network service crash, shutdown, or when
    // the request fails with ERR_MANDATORY_PROXY_CONFIGURATION_FAILED. There's
    // really no action a plugin can take, so there's no need to distinguish
    // which error occurred.
    context.params.set_result(PP_ERROR_FAILED);
  } else {
    pac_string = proxy_info->ToPacString();
  }
  host()->SendReply(
      context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(pac_string));
}

void PepperNetworkProxyHost::SendFailureReply(
    int32_t error,
    ppapi::host::ReplyMessageContext context) {
  context.params.set_result(error);
  host()->SendReply(
      context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(std::string()));
}

}  // namespace content
