proxy_configuration.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/winhttp/proxy_configuration.h"
  5. #include "base/logging.h"
  6. #include "base/memory/scoped_refptr.h"
  7. #include "base/strings/sys_string_conversions.h"
  8. #include "base/win/scoped_handle.h"
  9. #include "base/win/windows_version.h"
  10. #include "components/winhttp/net_util.h"
  11. #include "components/winhttp/proxy_info.h"
  12. #include "components/winhttp/scoped_winttp_proxy_info.h"
  13. #include "url/gurl.h"
  14. namespace winhttp {
  15. ProxyConfiguration::ProxyConfiguration(const ProxyInfo& proxy_info)
  16. : proxy_info_(proxy_info) {}
  17. int ProxyConfiguration::access_type() const {
  18. return DoGetAccessType();
  19. }
  20. int ProxyConfiguration::DoGetAccessType() const {
  21. const bool is_using_named_proxy = !proxy_info_.auto_detect &&
  22. proxy_info_.auto_config_url.empty() &&
  23. !proxy_info_.proxy.empty();
  24. return is_using_named_proxy ? WINHTTP_ACCESS_TYPE_NAMED_PROXY
  25. : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
  26. }
  27. absl::optional<ScopedWinHttpProxyInfo> ProxyConfiguration::GetProxyForUrl(
  28. HINTERNET session_handle,
  29. const GURL& url) const {
  30. return DoGetProxyForUrl(session_handle, url);
  31. }
  32. absl::optional<ScopedWinHttpProxyInfo> ProxyConfiguration::DoGetProxyForUrl(
  33. HINTERNET session_handle,
  34. const GURL& url) const {
  35. // Detect proxy settings using Web Proxy Auto Detection (WPAD).
  36. WINHTTP_AUTOPROXY_OPTIONS auto_proxy_options = {0};
  37. // Per MSDN, setting fAutoLogonIfChallenged to false first may work
  38. // if Windows cached the proxy config.
  39. auto_proxy_options.fAutoLogonIfChallenged = false;
  40. bool try_auto_proxy = false;
  41. if (proxy_info_.auto_detect) {
  42. auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
  43. auto_proxy_options.dwAutoDetectFlags =
  44. WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
  45. try_auto_proxy = true;
  46. }
  47. // PAC Url was specified, let system auto detect given the PAC url.
  48. if (!proxy_info_.auto_config_url.empty()) {
  49. auto_proxy_options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
  50. auto_proxy_options.lpszAutoConfigUrl = proxy_info_.auto_config_url.c_str();
  51. try_auto_proxy = true;
  52. }
  53. // Find the proxy server for the url.
  54. ScopedWinHttpProxyInfo winhttp_proxy_info = {};
  55. if (try_auto_proxy) {
  56. const std::wstring url_str = base::SysUTF8ToWide(url.spec());
  57. bool success = ::WinHttpGetProxyForUrl(session_handle, url_str.c_str(),
  58. &auto_proxy_options,
  59. winhttp_proxy_info.receive());
  60. if (!success && ::GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) {
  61. auto_proxy_options.fAutoLogonIfChallenged = true;
  62. success = ::WinHttpGetProxyForUrl(session_handle, url_str.c_str(),
  63. &auto_proxy_options,
  64. winhttp_proxy_info.receive());
  65. }
  66. if (!success) {
  67. PLOG(ERROR) << "Failed to get proxy for url";
  68. return {};
  69. }
  70. } else {
  71. winhttp_proxy_info.set_proxy(proxy_info_.proxy);
  72. winhttp_proxy_info.set_proxy_bypass(proxy_info_.proxy_bypass);
  73. }
  74. if (!winhttp_proxy_info.IsValid())
  75. return {};
  76. return winhttp_proxy_info;
  77. }
  78. void SetProxyForRequest(
  79. const HINTERNET request_handle,
  80. const absl::optional<ScopedWinHttpProxyInfo>& winhttp_proxy_info) {
  81. // Set the proxy option on the request handle.
  82. if (winhttp_proxy_info.has_value() && winhttp_proxy_info.value().IsValid()) {
  83. const ScopedWinHttpProxyInfo& proxy_info = winhttp_proxy_info.value();
  84. VLOG(1) << "Setting proxy " << proxy_info.proxy();
  85. auto hr = SetOption(request_handle, WINHTTP_OPTION_PROXY,
  86. const_cast<WINHTTP_PROXY_INFO*>(proxy_info.get()));
  87. if (FAILED(hr)) {
  88. PLOG(ERROR) << "Failed to set WINHTTP_OPTION_PROXY: 0x" << std::hex << hr;
  89. }
  90. }
  91. }
  92. int AutoProxyConfiguration::DoGetAccessType() const {
  93. return WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY;
  94. }
  95. absl::optional<ScopedWinHttpProxyInfo> AutoProxyConfiguration::DoGetProxyForUrl(
  96. HINTERNET,
  97. const GURL&) const {
  98. // When using automatic proxy settings, Windows will resolve the proxy
  99. // for us.
  100. DVLOG(3) << "Auto-proxy: skip getting proxy for a url";
  101. return {};
  102. }
  103. } // namespace winhttp