// 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 "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 = base::as_wcstr(pac_url16);

  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::as_wcstr(base::ASCIIToUTF16(mutable_query_url.spec())), &options,
      &info);
  if (!ok) {
    if (ERROR_WINHTTP_LOGIN_FAILURE == GetLastError()) {
      options.fAutoLogonIfChallenged = TRUE;
      ok = WinHttpGetProxyForUrl(
          session_handle_,
          base::as_wcstr(base::ASCIIToUTF16(mutable_query_url.spec())),
          &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::WideToUTF8(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
