1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_H_
#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_H_
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/http/http_transaction.h"
#include "net/shared_dictionary/shared_dictionary_getter.h"
#include "net/socket/next_proto.h"
class GURL;
namespace net {
class SharedDictionary;
class SourceStream;
struct LoadTimingInternalInfo;
struct TransportInfo;
// A `HttpTransaction` that decodes shared dictionary compression.
// If the `LOAD_CAN_USE_SHARED_DICTIONARY` flag is not set in the `request`'s
// `load_flags`, this class delegates all function calls to the underlying
// transaction.
// Otherwise, this class registers a callback with the underlying transaction
// that will be called just before the request is sent to the network. When this
// callback is called, this class tries to get a registered dictionary from the
// `shared_dictionary_manager`. If a matching dictionary is found, and the
// "content-encoding" header of the response from the server is "dcb" or "dcz",
// this class will decode the response body using a `BrotliSourceStream` or
// `ZstdSourceStream` with the dictionary.
class NET_EXPORT SharedDictionaryNetworkTransaction : public HttpTransaction {
public:
SharedDictionaryNetworkTransaction(
std::unique_ptr<HttpTransaction> network_transaction,
bool enable_shared_zstd);
SharedDictionaryNetworkTransaction(
const SharedDictionaryNetworkTransaction&) = delete;
SharedDictionaryNetworkTransaction& operator=(
const SharedDictionaryNetworkTransaction&) = delete;
~SharedDictionaryNetworkTransaction() override;
// HttpTransaction methods:
int Start(const HttpRequestInfo* request,
CompletionOnceCallback callback,
const NetLogWithSource& net_log) override;
int RestartIgnoringLastError(CompletionOnceCallback callback) override;
int RestartWithCertificate(scoped_refptr<X509Certificate> client_cert,
scoped_refptr<SSLPrivateKey> client_private_key,
CompletionOnceCallback callback) override;
int RestartWithAuth(const AuthCredentials& credentials,
CompletionOnceCallback callback) override;
bool IsReadyToRestartForAuth() override;
int Read(IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback) override;
void StopCaching() override;
int64_t GetTotalReceivedBytes() const override;
int64_t GetTotalSentBytes() const override;
int64_t GetReceivedBodyBytes() const override;
void DoneReading() override;
const HttpResponseInfo* GetResponseInfo() const override;
LoadState GetLoadState() const override;
bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
void PopulateLoadTimingInternalInfo(
LoadTimingInternalInfo* load_timing_internal_info) const override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) const override;
void PopulateNetErrorDetails(NetErrorDetails* details) const override;
void SetPriority(RequestPriority priority) override;
void SetWebSocketHandshakeStreamCreateHelper(
WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
void SetConnectedCallback(const ConnectedCallback& callback) override;
void SetRequestHeadersCallback(RequestHeadersCallback callback) override;
void SetResponseHeadersCallback(ResponseHeadersCallback callback) override;
void SetEarlyResponseHeadersCallback(
ResponseHeadersCallback callback) override;
void SetModifyRequestHeadersCallback(
base::RepeatingCallback<void(HttpRequestHeaders*)> callback) override;
void SetIsSharedDictionaryReadAllowedCallback(
base::RepeatingCallback<bool()> callback) override;
ConnectionAttempts GetConnectionAttempts() const override;
void CloseConnectionOnDestruction() override;
bool IsMdlMatchForMetrics() const override;
private:
enum class DictionaryStatus {
kNoDictionary,
kReading,
kFinished,
kFailed,
};
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class SharedDictionaryEncodingType {
kNotUsed = 0,
kSharedBrotli = 1,
kSharedZstd = 2,
kMaxValue = kSharedZstd,
};
class PendingReadTask {
public:
PendingReadTask(IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback);
PendingReadTask(const PendingReadTask&) = delete;
PendingReadTask& operator=(const PendingReadTask&) = delete;
~PendingReadTask();
scoped_refptr<IOBuffer> buf;
int buf_len;
CompletionOnceCallback callback;
};
SharedDictionaryEncodingType ParseSharedDictionaryEncodingType(
const HttpResponseHeaders& headers);
void OnStartCompleted(CompletionOnceCallback callback, int result);
void ModifyRequestHeaders(const GURL& request_url,
HttpRequestHeaders* request_headers);
void OnReadSharedDictionary(base::Time read_start_time, int result);
int OnConnected(const TransportInfo& info, CompletionOnceCallback callback);
const bool enable_shared_zstd_;
scoped_refptr<SharedDictionary> shared_dictionary_;
// The Structured Field sf-binary hash of sha256 of dictionary calculated when
// sending a HTTP request.
std::string dictionary_hash_base64_;
DictionaryStatus dictionary_status_ = DictionaryStatus::kNoDictionary;
SharedDictionaryEncodingType shared_dictionary_encoding_type_ =
SharedDictionaryEncodingType::kNotUsed;
std::unique_ptr<PendingReadTask> pending_read_task_;
base::RepeatingCallback<bool()> is_shared_dictionary_read_allowed_callback_;
// The network side transaction.
std::unique_ptr<HttpTransaction> network_transaction_;
std::unique_ptr<SourceStream> shared_compression_stream_;
// This is set only when a shared dictionary is used for decoding the body.
std::unique_ptr<HttpResponseInfo> shared_dictionary_used_response_info_;
ConnectedCallback connected_callback_;
bool cert_is_issued_by_known_root_ = false;
NextProto negotiated_protocol_ = NextProto::kProtoUnknown;
base::RepeatingCallback<scoped_refptr<SharedDictionary>()>
shared_dictionary_getter_;
base::WeakPtrFactory<SharedDictionaryNetworkTransaction> weak_factory_{this};
};
} // namespace net
#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_H_
|