// Copyright (c) 2011 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 "net/proxy_resolution/proxy_resolver_winhttp.h"

#include <windows.h>
#include <winhttp.h>

#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "starboard/types.h"
#include "url/gurl.h"

using base::TimeDelta;
using base::TimeTicks;

namespace net {
namespace {

static void FreeInfo(WINHTTP_PROXY_INFO* info) {
  if (info->lpszProxy)
    GlobalFree(info->lpszProxy);
  if (info->lpszProxyBypass)
    GlobalFree(info->lpszProxyBypass);
}

static Error WinHttpErrorToNetError(DWORD win_http_error) {
  switch (win_http_error) {
    case ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR:
    case ERROR_WINHTTP_INTERNAL_ERROR:
    case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE:
      return ERR_FAILED;
    case ERROR_WINHTTP_LOGIN_FAILURE:
      return ERR_PROXY_AUTH_UNSUPPORTED;
    case ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT:
      return ERR_PAC_SCRIPT_FAILED;
    case ERROR_WINHTTP_INVALID_URL:
    case ERROR_WINHTTP_OPERATION_CANCELLED:
    case ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT:
    case ERROR_WINHTTP_UNRECOGNIZED_SCHEME:
      return ERR_PAC_STATUS_NOT_OK;
    case ERROR_NOT_ENOUGH_MEMORY:
      return ERR_INSUFFICIENT_RESOURCES;
    default:
      return ERR_FAILED;
  }
}

class ProxyResolverWinHttp : public ProxyResolver {
 public:
  ProxyResolverWinHttp(const scoped_refptr<PacFileData>& script_data);
  ~ProxyResolverWinHttp() override;

  // ProxyResolver implementation:
  int GetProxyForURL(const GURL& url,
                     ProxyInfo* results,
                     CompletionOnceCallback /*callback*/,
                     std::unique_ptr<Request>* /*request*/,
                     const NetLogWithSource& /*net_log*/) override;

 private:
  bool OpenWinHttpSession();
  void CloseWinHttpSession();

  // Proxy configuration is cached on the session handle.
  HINTERNET session_handle_;

  const GURL pac_url_;

  DISALLOW_COPY_AND_ASSIGN(ProxyResolverWinHttp);
};

ProxyResolverWinHttp::ProxyResolverWinHttp(
    const scoped_refptr<PacFileData>& script_data)
    : session_handle_(NULL),
      pac_url_(script_data->type() == PacFileData::TYPE_AUTO_DETECT
                   ? GURL("http://wpad/wpad.dat")
                   : script_data->url()) {}

ProxyResolverWinHttp::~ProxyResolverWinHttp() {
  CloseWinHttpSession();
}

int ProxyResolverWinHttp::GetProxyForURL(const GURL& query_url,
                                         ProxyInfo* results,
                                         CompletionOnceCallback /*callback*/,
                                         std::unique_ptr<Request>* /*request*/,
                                         const NetLogWithSource& /*net_log*/) {
  // If we don't have a WinHTTP session, then create a new one.
  if (!session_handle_ && !OpenWinHttpSession())
    return ERR_FAILED;

  // Windows' system resolver does not support WebSocket URLs in proxy.pac. This
  // was tested in version 10.0.16299, and is also implied by the description of
  // the ERROR_WINHTTP_UNRECOGNIZED_SCHEME error code in the Microsoft
  // documentation at
  // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpgetproxyforurl.
  // See https://crbug.com/862121.
  GURL mutable_query_url = query_url;
  if (query_url.SchemeIsWSOrWSS()) {
    GURL::Replacements replacements;
    replacements.SetSchemeStr(query_url.SchemeIsCryptographic() ? "https"
                                                                : "http");
    mutable_query_url = query_url.ReplaceComponents(replacements);
  }

  // If we have been given an empty PAC url, then use auto-detection.
  //
  // NOTE: We just use DNS-based auto-detection here like Firefox.  We do this
  // to avoid WinHTTP's auto-detection code, which while more featureful (it
  // supports DHCP based auto-detection) also appears to have issues.
  //
  WINHTTP_AUTOPROXY_OPTIONS options = {0};
  options.fAutoLogonIfChallenged = FALSE;
  options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
  base::string16 pac_url16 = base::ASCIIToUTF16(pac_url_.spec());
  options.lpszAutoConfigUrl = pac_url16.c_str();

  WINHTTP_PROXY_INFO info = {0};
  DCHECK(session_handle_);

  // Per http://msdn.microsoft.com/en-us/library/aa383153(VS.85).aspx, it is
  // necessary to first try resolving with fAutoLogonIfChallenged set to false.
  // Otherwise, we fail over to trying it with a value of true.  This way we
  // get good performance in the case where WinHTTP uses an out-of-process
  // resolver.  This is important for Vista and Win2k3.
  BOOL ok = WinHttpGetProxyForUrl(
      session_handle_, base::ASCIIToUTF16(mutable_query_url.spec()).c_str(),
      &options, &info);
  if (!ok) {
    if (ERROR_WINHTTP_LOGIN_FAILURE == GetLastError()) {
      options.fAutoLogonIfChallenged = TRUE;
      ok = WinHttpGetProxyForUrl(
          session_handle_, base::ASCIIToUTF16(mutable_query_url.spec()).c_str(),
          &options, &info);
    }
    if (!ok) {
      DWORD error = GetLastError();
      // If we got here because of RPC timeout during out of process PAC
      // resolution, no further requests on this session are going to work.
      if (ERROR_WINHTTP_TIMEOUT == error ||
          ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR == error) {
        CloseWinHttpSession();
      }
      return WinHttpErrorToNetError(error);
    }
  }

  int rv = OK;

  switch (info.dwAccessType) {
    case WINHTTP_ACCESS_TYPE_NO_PROXY:
      results->UseDirect();
      break;
    case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
      // According to MSDN:
      //
      // The proxy server list contains one or more of the following strings
      // separated by semicolons or whitespace.
      //
      // ([<scheme>=][<scheme>"://"]<server>[":"<port>])
      //
      // Based on this description, ProxyInfo::UseNamedProxy() isn't
      // going to handle all the variations (in particular <scheme>=).
      //
      // However in practice, it seems that WinHTTP is simply returning
      // things like "foopy1:80;foopy2:80". It strips out the non-HTTP
      // proxy types, and stops the list when PAC encounters a "DIRECT".
      // So UseNamedProxy() should work OK.
      results->UseNamedProxy(base::UTF16ToASCII(info.lpszProxy));
      break;
    default:
      NOTREACHED();
      rv = ERR_FAILED;
  }

  FreeInfo(&info);
  return rv;
}

bool ProxyResolverWinHttp::OpenWinHttpSession() {
  DCHECK(!session_handle_);
  session_handle_ = WinHttpOpen(NULL,
                                WINHTTP_ACCESS_TYPE_NO_PROXY,
                                WINHTTP_NO_PROXY_NAME,
                                WINHTTP_NO_PROXY_BYPASS,
                                0);
  if (!session_handle_)
    return false;

  // Since this session handle will never be used for WinHTTP connections,
  // these timeouts don't really mean much individually.  However, WinHTTP's
  // out of process PAC resolution will use a combined (sum of all timeouts)
  // value to wait for an RPC reply.
  BOOL rv = WinHttpSetTimeouts(session_handle_, 10000, 10000, 5000, 5000);
  DCHECK(rv);

  return true;
}

void ProxyResolverWinHttp::CloseWinHttpSession() {
  if (session_handle_) {
    WinHttpCloseHandle(session_handle_);
    session_handle_ = NULL;
  }
}

}  // namespace

ProxyResolverFactoryWinHttp::ProxyResolverFactoryWinHttp()
    : ProxyResolverFactory(false /*expects_pac_bytes*/) {
}

int ProxyResolverFactoryWinHttp::CreateProxyResolver(
    const scoped_refptr<PacFileData>& pac_script,
    std::unique_ptr<ProxyResolver>* resolver,
    CompletionOnceCallback callback,
    std::unique_ptr<Request>* request) {
  resolver->reset(new ProxyResolverWinHttp(pac_script));
  return OK;
}

}  // namespace net
