#ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
#define CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
#include <map>
#include "base/callback.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/http/http_byte_range.h"
#include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace net_service {
class InputStreamReader;
class InputStream {
public:
virtual ~InputStream() {}
using SkipCallback = base::OnceCallback<void(int64_t )>;
virtual bool Skip(int64_t n,
int64_t* bytes_skipped,
SkipCallback callback) = 0;
using ReadCallback = base::OnceCallback<void(int )>;
virtual bool Read(net::IOBuffer* dest,
int length,
int* bytes_read,
ReadCallback callback) = 0;
};
class ResourceResponse {
public:
virtual ~ResourceResponse() {}
using OpenCallback = base::OnceCallback<void(std::unique_ptr<InputStream>)>;
virtual bool OpenInputStream(int32_t request_id,
const network::ResourceRequest& request,
OpenCallback callback) = 0;
using HeaderMap = std::multimap<std::string, std::string>;
virtual void GetResponseHeaders(int32_t request_id,
int* status_code,
std::string* reason_phrase,
std::string* mime_type,
std::string* charset,
int64_t* content_length,
HeaderMap* extra_headers) = 0;
};
class StreamReaderURLLoader : public network::mojom::URLLoader {
public:
class Delegate : public ResourceResponse {
public:
virtual void OnInputStreamOpenFailed(int32_t request_id,
bool* restarted) = 0;
};
StreamReaderURLLoader(
int32_t request_id,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
mojo::PendingRemote<network::mojom::TrustedHeaderClient> header_client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
std::unique_ptr<Delegate> response_delegate);
StreamReaderURLLoader(const StreamReaderURLLoader&) = delete;
StreamReaderURLLoader& operator=(const StreamReaderURLLoader&) = delete;
~StreamReaderURLLoader() override;
void Start();
void ContinueResponse(bool was_redirected);
void FollowRedirect(
const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
const absl::optional<GURL>& new_url) override;
void SetPriority(net::RequestPriority priority,
int intra_priority_value) override;
void PauseReadingBodyFromNet() override;
void ResumeReadingBodyFromNet() override;
private:
void ContinueWithRequestHeaders(
int32_t result,
const absl::optional<net::HttpRequestHeaders>& headers);
void OnInputStreamOpened(std::unique_ptr<Delegate> returned_delegate,
std::unique_ptr<InputStream> input_stream);
void OnReaderSkipCompleted(int64_t bytes_skipped);
void HeadersComplete(int status_code, int64_t expected_content_length);
void ContinueWithResponseHeaders(
network::mojom::URLResponseHeadPtr pending_response,
int32_t result,
const absl::optional<std::string>& headers,
const absl::optional<GURL>& redirect_url);
void SendBody();
void ReadMore();
void OnDataPipeWritable(MojoResult result);
void OnReaderReadCompleted(int bytes_read);
void RequestComplete(int status_code);
void CleanUp();
bool ParseRange(const net::HttpRequestHeaders& headers);
bool byte_range_valid() const;
const int32_t request_id_;
size_t header_length_ = 0;
int64_t total_bytes_read_ = 0;
net::HttpByteRange byte_range_;
network::ResourceRequest request_;
mojo::Remote<network::mojom::URLLoaderClient> client_;
mojo::Remote<network::mojom::TrustedHeaderClient> header_client_;
const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
std::unique_ptr<Delegate> response_delegate_;
scoped_refptr<InputStreamReader> input_stream_reader_;
mojo::ScopedDataPipeProducerHandle producer_handle_;
scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_;
mojo::SimpleWatcher writable_handle_watcher_;
base::ThreadChecker thread_checker_;
scoped_refptr<base::SequencedTaskRunner> stream_work_task_runner_;
base::OnceClosure open_cancel_callback_;
base::WeakPtrFactory<StreamReaderURLLoader> weak_factory_;
};
}
#endif