blob: 3596ec8f935e17874895123b40eacc3d29faeb7d [file] [log] [blame]
// Copyright 2020 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.
#ifndef NET_PROXY_RESOLUTION_WIN_WINDOWS_SYSTEM_PROXY_RESOLVER_H_
#define NET_PROXY_RESOLUTION_WIN_WINDOWS_SYSTEM_PROXY_RESOLVER_H_
#include <windows.h>
#include <winhttp.h>
#include <memory>
#include <string>
#include <unordered_map>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "net/base/net_export.h"
#include "net/proxy_resolution/proxy_list.h"
namespace net {
class WindowsSystemProxyResolutionRequest;
class WinHttpAPIWrapper;
// This provides a layer of abstraction between calling code Windows-specific
// code. It is shared between the WindowsSystemProxyResolutionService and
// inflight WinHttp callbacks. Internally, it takes care of all interaction with
// WinHttp. The only time this object is ever access outside of its sequence is
// during the WinHttp callback. For the sake of that callback, this must be
// RefcountedThreadSafe.
class NET_EXPORT WindowsSystemProxyResolver
: public base::RefCountedThreadSafe<WindowsSystemProxyResolver> {
public:
static scoped_refptr<WindowsSystemProxyResolver>
CreateWindowsSystemProxyResolver();
WindowsSystemProxyResolver(const WindowsSystemProxyResolver&) = delete;
WindowsSystemProxyResolver& operator=(const WindowsSystemProxyResolver&) =
delete;
// This will first fetch the current system proxy settings by calling into
// WinHttpGetIEProxyConfigForCurrentUser() and then resolve the proxy using
// those settings as an input into WinHttpGetProxyForUrlEx().
virtual bool GetProxyForUrl(
WindowsSystemProxyResolutionRequest* callback_target,
const std::string& url) WARN_UNUSED_RESULT;
// After calling GetProxyForUrl(), a |callback_target| is saved internally for
// when proxy resolution is complete. When a
// WindowsSystemProxyResolutionRequest wants to avoid receiving a callback,
// it must remove itself from the list of pending callback targets.
virtual void RemovePendingCallbackTarget(
WindowsSystemProxyResolutionRequest* callback_target);
virtual bool HasPendingCallbackTarget(
WindowsSystemProxyResolutionRequest* callback_target) const
WARN_UNUSED_RESULT;
protected:
explicit WindowsSystemProxyResolver(
std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper);
virtual ~WindowsSystemProxyResolver();
private:
friend class base::RefCountedThreadSafe<WindowsSystemProxyResolver>;
friend class WindowsSystemProxyResolverTest;
// Sets up the WinHttp session that will be used throughout the lifetime of
// this object.
bool Initialize();
// These will interact with |pending_callback_target_map_|.
void AddPendingCallbackTarget(
WindowsSystemProxyResolutionRequest* callback_target,
HINTERNET handle);
WindowsSystemProxyResolutionRequest* LookupCallbackTargetFromResolverHandle(
HINTERNET resolver_handle) const;
// This is the callback provided to WinHttp. Once a call to resolve a proxy
// succeeds or errors out, it'll call into here with |context| being a pointer
// to a WindowsSystemProxyResolver that has been kept alive. This callback can
// hit in any thread and will immediately post a task to the right sequence.
static void __stdcall WinHttpStatusCallback(HINTERNET resolver_handle,
DWORD_PTR context,
DWORD status,
void* info,
DWORD info_len);
// Called from WinHttpStatusCallback on the right sequence. This will make
// decisions about what to do from the results of the proxy resolution call.
// Note that the WindowsSystemProxyResolutionRequest that asked for this proxy
// may have decided they no longer need an answer (ex: the request has gone
// away), so this function has to deal with that situation too.
void DoWinHttpStatusCallback(HINTERNET resolver_handle,
DWORD status,
int windows_error);
// On a successful call to WinHttpGetProxyForUrlEx(), this translates WinHttp
// results into Chromium-friendly structures before notifying the right
// WindowsSystemProxyResolutionRequest.
void GetProxyResultForCallbackTarget(
WindowsSystemProxyResolutionRequest* callback_target,
HINTERNET resolver_handle);
// On a failed call to WinHttpGetProxyForUrlEx(), this will notify the right
// WindowsSystemProxyResolutionRequest of the error.
void HandleErrorForCallbackTarget(
WindowsSystemProxyResolutionRequest* callback_target,
int windows_error);
// This is a thin wrapper over WinHttp APIs that may be overridden for
// testing.
std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper_;
// This is the mapping of WindowsSystemProxyResolutionRequest objects that
// called GetProxyForUrl() to the handle that's being used for their proxy
// resolution call. Upon receiving a callback from WinHttp (which includes an
// HINTERNET handle), a reverse lookup here will get the right
// WindowsSystemProxyResolutionRequest to use.
std::unordered_map<WindowsSystemProxyResolutionRequest*, HINTERNET>
pending_callback_target_map_;
SEQUENCE_CHECKER(sequence_checker_);
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
};
} // namespace net
#endif // NET_PROXY_RESOLUTION_WIN_WINDOWS_SYSTEM_PROXY_RESOLVER_H_