Avi Drissman | 8ba1bad | 2022-09-13 19:22:36 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 5 | #ifndef COMPONENTS_WINHTTP_NETWORK_FETCHER_H_ |
| 6 | #define COMPONENTS_WINHTTP_NETWORK_FETCHER_H_ |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 7 | |
Sorin Jianu | 40b6bd0 | 2024-01-11 00:25:04 | [diff] [blame] | 8 | #include <windows.h> |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 9 | |
Takuto Ikuta | c8d6b16f | 2024-04-15 16:59:19 | [diff] [blame] | 10 | #include <stdint.h> |
| 11 | |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 12 | #include <memory> |
S. Ganesh | e0267975 | 2024-06-05 21:41:44 | [diff] [blame] | 13 | #include <optional> |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 14 | #include <string> |
Lei Zhang | 69278837 | 2023-11-08 19:37:28 | [diff] [blame] | 15 | #include <string_view> |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 16 | #include <vector> |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 17 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 18 | #include "base/containers/flat_map.h" |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 19 | #include "base/files/file.h" |
| 20 | #include "base/files/file_path.h" |
Sorin Jianu | 92a26c9 | 2022-10-19 17:07:20 | [diff] [blame] | 21 | #include "base/functional/callback.h" |
Sorin Jianu | 622be9c | 2024-02-15 00:17:42 | [diff] [blame] | 22 | #include "base/memory/ref_counted.h" |
Sorin Jianu | 0c01aed | 2020-03-10 14:42:33 | [diff] [blame] | 23 | #include "base/memory/scoped_refptr.h" |
Sorin Jianu | ed72242 | 2020-05-29 19:17:14 | [diff] [blame] | 24 | #include "base/sequence_checker.h" |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 25 | #include "components/winhttp/proxy_configuration.h" |
| 26 | #include "components/winhttp/scoped_hinternet.h" |
S. Ganesh | e0267975 | 2024-06-05 21:41:44 | [diff] [blame] | 27 | #include "components/winhttp/scoped_winttp_proxy_info.h" |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 28 | #include "url/gurl.h" |
| 29 | |
| 30 | namespace base { |
Sorin Jianu | 6092b8c1 | 2023-02-01 17:40:05 | [diff] [blame] | 31 | class SequencedTaskRunner; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 32 | } |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 33 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 34 | namespace winhttp { |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 35 | |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 36 | // Implements a network fetcher in terms of WinHTTP. The class is ref-counted |
Sorin Jianu | 6092b8c1 | 2023-02-01 17:40:05 | [diff] [blame] | 37 | // as it is accessed from the main sequence and the worker threads in WinHTTP. |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 38 | class NetworkFetcher : public base::RefCountedThreadSafe<NetworkFetcher> { |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 39 | public: |
Sebastien Lalancette | e26adaec | 2022-01-05 15:32:46 | [diff] [blame] | 40 | using FetchCompleteCallback = base::OnceCallback<void(int response_code)>; |
Sorin Jianu | 520cfc0 | 2019-03-04 23:49:29 | [diff] [blame] | 41 | using FetchStartedCallback = |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 42 | base::OnceCallback<void(int response_code, int64_t content_length)>; |
| 43 | using FetchProgressCallback = base::RepeatingCallback<void(int64_t current)>; |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 44 | |
Sorin Jianu | 622be9c | 2024-02-15 00:17:42 | [diff] [blame] | 45 | NetworkFetcher(scoped_refptr<SharedHInternet> session_handle, |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 46 | scoped_refptr<ProxyConfiguration> proxy_configuration); |
| 47 | NetworkFetcher(const NetworkFetcher&) = delete; |
| 48 | NetworkFetcher& operator=(const NetworkFetcher&) = delete; |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 49 | |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 50 | void Close(); |
| 51 | |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 52 | void PostRequest( |
| 53 | const GURL& url, |
| 54 | const std::string& post_data, |
Sorin Jianu | c2e9139 | 2020-06-18 01:05:30 | [diff] [blame] | 55 | const std::string& content_type, |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 56 | const base::flat_map<std::string, std::string>& post_additional_headers, |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 57 | FetchStartedCallback fetch_started_callback, |
Sorin Jianu | 520cfc0 | 2019-03-04 23:49:29 | [diff] [blame] | 58 | FetchProgressCallback fetch_progress_callback, |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 59 | FetchCompleteCallback fetch_complete_callback); |
Sorin Jianu | ed72242 | 2020-05-29 19:17:14 | [diff] [blame] | 60 | |
| 61 | // Downloads the content of the |url| to a file identified by |file_path|. |
| 62 | // The content is written to the file as it is being retrieved from the |
Joshua Pawlicki | bb0a3f5c | 2023-09-20 01:08:36 | [diff] [blame] | 63 | // network. Returns a closure that can be run to cancel the download. |
| 64 | base::OnceClosure DownloadToFile( |
| 65 | const GURL& url, |
| 66 | const base::FilePath& file_path, |
| 67 | FetchStartedCallback fetch_started_callback, |
| 68 | FetchProgressCallback fetch_progress_callback, |
| 69 | FetchCompleteCallback fetch_complete_callback); |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 70 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 71 | HRESULT QueryHeaderString(const std::wstring& name, |
| 72 | std::wstring* value) const; |
| 73 | HRESULT QueryHeaderInt(const std::wstring& name, int* value) const; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 74 | std::string GetResponseBody() const; |
| 75 | HRESULT GetNetError() const; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 76 | base::FilePath GetFilePath() const; |
Sorin Jianu | ed72242 | 2020-05-29 19:17:14 | [diff] [blame] | 77 | |
| 78 | // Returns the number of bytes retrieved from the network. This may be |
| 79 | // different than the content length if an error occurred. |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 80 | int64_t GetContentSize() const; |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 81 | |
| 82 | private: |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 83 | friend class base::RefCountedThreadSafe<NetworkFetcher>; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 84 | using WriteDataCallback = base::RepeatingCallback<void()>; |
| 85 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 86 | ~NetworkFetcher(); |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 87 | |
| 88 | static void __stdcall WinHttpStatusCallback(HINTERNET handle, |
| 89 | DWORD_PTR context, |
| 90 | DWORD status, |
| 91 | void* info, |
| 92 | DWORD info_len); |
| 93 | |
Sorin Jianu | 92a26c9 | 2022-10-19 17:07:20 | [diff] [blame] | 94 | // Invoked by the last WinHTTPstatus status callback. |
| 95 | void HandleClosing(); |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 96 | |
Sorin Jianu | 92a26c9 | 2022-10-19 17:07:20 | [diff] [blame] | 97 | DWORD_PTR context() const { return reinterpret_cast<DWORD_PTR>(this); } |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 98 | |
| 99 | HRESULT BeginFetch( |
| 100 | const std::string& data, |
S. Ganesh | e0267975 | 2024-06-05 21:41:44 | [diff] [blame] | 101 | const base::flat_map<std::string, std::string>& additional_headers); |
| 102 | std::optional<ScopedWinHttpProxyInfo> GetProxyForUrl(); |
| 103 | void ContinueFetch( |
| 104 | const std::string& data, |
| 105 | base::flat_map<std::string, std::string> additional_headers, |
| 106 | std::optional<ScopedWinHttpProxyInfo> winhttp_proxy_info); |
| 107 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 108 | ScopedHInternet Connect(); |
| 109 | ScopedHInternet OpenRequest(); |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 110 | HRESULT SendRequest(const std::string& data); |
| 111 | void SendRequestComplete(); |
| 112 | HRESULT ReceiveResponse(); |
Sorin Jianu | 617e779 | 2020-05-30 00:53:53 | [diff] [blame] | 113 | void HeadersAvailable(); |
| 114 | HRESULT ReadData(); |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 115 | void ReadDataComplete(size_t num_bytes_read); |
Sorin Jianu | 92a26c9 | 2022-10-19 17:07:20 | [diff] [blame] | 116 | void RequestError(DWORD error); |
Sorin Jianu | 660bfa8 | 2020-05-31 15:28:56 | [diff] [blame] | 117 | void CompleteFetch(); |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 118 | |
| 119 | void WriteDataToMemory(); |
| 120 | void WriteDataToFile(); |
| 121 | bool WriteDataToFileBlocking(); |
| 122 | void WriteDataToFileComplete(bool is_eof); |
| 123 | |
Sorin Jianu | ed72242 | 2020-05-29 19:17:14 | [diff] [blame] | 124 | SEQUENCE_CHECKER(sequence_checker_); |
Sorin Jianu | 6092b8c1 | 2023-02-01 17:40:05 | [diff] [blame] | 125 | scoped_refptr<base::SequencedTaskRunner> main_task_runner_; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 126 | |
Sorin Jianu | 622be9c | 2024-02-15 00:17:42 | [diff] [blame] | 127 | scoped_refptr<SharedHInternet> session_handle_; |
Maciek Kumorek | 1d1e5c2 | 2020-07-25 22:49:39 | [diff] [blame] | 128 | scoped_refptr<ProxyConfiguration> proxy_configuration_; |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 129 | ScopedHInternet connect_handle_; |
| 130 | ScopedHInternet request_handle_; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 131 | |
| 132 | // Keeps an outstanding reference count on itself as long as there is a |
| 133 | // valid request handle and the context for the handle is set to this |
| 134 | // instance. |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 135 | scoped_refptr<NetworkFetcher> self_; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 136 | |
| 137 | GURL url_; |
| 138 | bool is_https_ = false; |
| 139 | std::string host_; |
| 140 | int port_ = 0; |
| 141 | std::string path_for_request_; |
| 142 | |
Lei Zhang | 69278837 | 2023-11-08 19:37:28 | [diff] [blame] | 143 | std::wstring_view verb_; |
Xiaoling Bao | 3d98e16 | 2022-11-12 03:32:18 | [diff] [blame] | 144 | std::string request_data_; |
Maciek Kumorek | 50ead5c5c | 2020-07-08 15:10:14 | [diff] [blame] | 145 | // The value of Content-Type header, e.g. "application/json". |
| 146 | std::string content_type_; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 147 | WriteDataCallback write_data_callback_; |
| 148 | HRESULT net_error_ = S_OK; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 149 | std::vector<char> read_buffer_; |
Sebastien Lalancette | e26adaec | 2022-01-05 15:32:46 | [diff] [blame] | 150 | int response_code_ = 0; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 151 | std::string post_response_body_; |
| 152 | base::FilePath file_path_; |
| 153 | base::File file_; |
| 154 | int64_t content_size_ = 0; |
| 155 | |
| 156 | FetchStartedCallback fetch_started_callback_; |
Sorin Jianu | 520cfc0 | 2019-03-04 23:49:29 | [diff] [blame] | 157 | FetchProgressCallback fetch_progress_callback_; |
Sorin Jianu | bf44a91 | 2019-03-02 01:35:01 | [diff] [blame] | 158 | FetchCompleteCallback fetch_complete_callback_; |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 159 | }; |
| 160 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 161 | } // namespace winhttp |
Sorin Jianu | 95fb33d | 2019-02-21 16:59:33 | [diff] [blame] | 162 | |
Roger Tawa | c0a1b9c | 2021-09-23 23:34:04 | [diff] [blame] | 163 | #endif // COMPONENTS_WINHTTP_NETWORK_FETCHER_H_ |