// 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 "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_info.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.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"

namespace content {

PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
                                               PP_Instance instance,
                                               PP_Resource resource)
    : ResourceHost(host->GetPpapiHost(), instance, resource),
      proxy_service_(NULL),
      is_allowed_(false),
      waiting_for_ui_thread_data_(true),
      weak_factory_(this) {
  int render_process_id(0), render_view_id(0);
  host->GetRenderViewIDsForInstance(instance,
                                    &render_process_id,
                                    &render_view_id);
  BrowserThread::PostTaskAndReplyWithResult(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&GetUIThreadDataOnUIThread,
                 render_process_id,
                 render_view_id,
                 host->external_plugin()),
      base::Bind(&PepperNetworkProxyHost::DidGetUIThreadData,
                 weak_factory_.GetWeakPtr()));
}

PepperNetworkProxyHost::~PepperNetworkProxyHost() {
  while (!pending_requests_.empty()) {
    // If the proxy_service_ is NULL, we shouldn't have any outstanding
    // requests.
    DCHECK(proxy_service_);
    net::ProxyService::PacRequest* request = pending_requests_.front();
    proxy_service_->CancelPacRequest(request);
    pending_requests_.pop();
  }
}

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

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

// static
PepperNetworkProxyHost::UIThreadData
PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
                                                  int render_view_id,
                                                  bool is_external_plugin) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  PepperNetworkProxyHost::UIThreadData result;
  RenderProcessHost* render_process_host =
      RenderProcessHost::FromID(render_process_id);
  if (render_process_host && render_process_host->GetBrowserContext()) {
    result.context_getter = render_process_host->GetBrowserContext()->
        GetRequestContextForRenderProcess(render_process_id);
  }

  RenderViewHost* render_view_host =
      RenderViewHost::FromID(render_process_id, render_view_id);
  if (render_view_host) {
    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_view_host);
  }
  return result;
}

void PepperNetworkProxyHost::DidGetUIThreadData(
    const UIThreadData& ui_thread_data) {
  is_allowed_ = ui_thread_data.is_allowed;
  if (ui_thread_data.context_getter.get() &&
      ui_thread_data.context_getter->GetURLRequestContext()) {
    proxy_service_ =
        ui_thread_data.context_getter->GetURLRequestContext()->proxy_service();
  }
  waiting_for_ui_thread_data_ = false;
  if (!proxy_service_) {
    DLOG_IF(WARNING, proxy_service_)
        << "Failed to find a ProxyService for Pepper plugin.";
  }
  TryToSendUnsentRequests();
}

int32_t PepperNetworkProxyHost::OnResourceMessageReceived(
    const IPC::Message& msg,
    ppapi::host::HostMessageContext* context) {
  IPC_BEGIN_MESSAGE_MAP(PepperNetworkProxyHost, msg)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_NetworkProxy_GetProxyForURL, OnMsgGetProxyForURL)
  IPC_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 (!proxy_service_) {
      SendFailureReply(PP_ERROR_FAILED, request.reply_context);
    } else if (!is_allowed_) {
      SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
    } else {
      // Everything looks valid, so try to resolve the proxy.
      net::ProxyInfo* proxy_info = new net::ProxyInfo;
      net::ProxyService::PacRequest* pending_request = NULL;
      base::Callback<void (int)> callback =
          base::Bind(&PepperNetworkProxyHost::OnResolveProxyCompleted,
                     weak_factory_.GetWeakPtr(),
                     request.reply_context,
                     base::Owned(proxy_info));
      int result = proxy_service_->ResolveProxy(request.url,
                                                proxy_info,
                                                callback,
                                                &pending_request,
                                                net::BoundNetLog());
      pending_requests_.push(pending_request);
      // If it was handled synchronously, we must run the callback now;
      // proxy_service_ won't run it for us in this case.
      if (result != net::ERR_IO_PENDING)
        callback.Run(result);
    }
    unsent_requests_.pop();
  }
}

void PepperNetworkProxyHost::OnResolveProxyCompleted(
    ppapi::host::ReplyMessageContext context,
    net::ProxyInfo* proxy_info,
    int result) {
  pending_requests_.pop();

  if (result != net::OK) {
    // Currently, the only proxy-specific error we could get is
    // MANDATORY_PROXY_CONFIGURATION_FAILED. There's really no action a plugin
    // can take in this case, so there's no need to distinguish it from other
    // failures.
    context.params.set_result(PP_ERROR_FAILED);
  }
  host()->SendReply(context,
                    PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(
                        proxy_info->ToPacString()));
}

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
