#ifndef PDF_LOADER_URL_LOADER_H_
#define PDF_LOADER_URL_LOADER_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "base/containers/circular_deque.h"
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/memory/raw_span.h"
#include "base/memory/weak_ptr.h"
#include "pdf/loader/result_codes.h"
#include "third_party/blink/public/web/web_associated_url_loader_client.h"
namespace blink {
class WebAssociatedURLLoader;
class WebString;
class WebURL;
class WebURLRequest;
struct WebAssociatedURLLoaderOptions;
}
namespace net {
class SiteForCookies;
}
namespace chrome_pdf {
struct UrlRequest final {
UrlRequest();
UrlRequest(const UrlRequest& other);
UrlRequest(UrlRequest&& other) noexcept;
UrlRequest& operator=(const UrlRequest& other);
UrlRequest& operator=(UrlRequest&& other) noexcept;
~UrlRequest();
std::string url;
std::string method;
bool ignore_redirects = false;
std::string custom_referrer_url;
std::string headers;
std::string body;
size_t buffer_lower_threshold = 50 * 1000 * 1000;
size_t buffer_upper_threshold = 100 * 1000 * 1000;
};
struct UrlResponse final {
UrlResponse();
UrlResponse(const UrlResponse& other);
UrlResponse(UrlResponse&& other) noexcept;
UrlResponse& operator=(const UrlResponse& other);
UrlResponse& operator=(UrlResponse&& other) noexcept;
~UrlResponse();
int32_t status_code = 0;
std::string headers;
};
class UrlLoader final : public blink::WebAssociatedURLLoaderClient {
public:
using OpenCallback = base::OnceCallback<void(Result)>;
class Client {
public:
virtual bool IsValid() const = 0;
virtual blink::WebURL CompleteURL(
const blink::WebString& partial_url) const = 0;
virtual net::SiteForCookies SiteForCookies() const = 0;
virtual void SetReferrerForRequest(blink::WebURLRequest& request,
const blink::WebURL& referrer_url) = 0;
virtual std::unique_ptr<blink::WebAssociatedURLLoader>
CreateAssociatedURLLoader(
const blink::WebAssociatedURLLoaderOptions& options) = 0;
protected:
~Client() = default;
};
explicit UrlLoader(base::WeakPtr<Client> client);
UrlLoader(const UrlLoader&) = delete;
UrlLoader& operator=(const UrlLoader&) = delete;
~UrlLoader() override;
void Open(const UrlRequest& request, OpenCallback callback);
void ReadResponseBody(base::span<uint8_t> buffer,
base::OnceCallback<void(int)> callback);
void Close();
const UrlResponse& response() const { return response_; }
bool WillFollowRedirect(
const blink::WebURL& new_url,
const blink::WebURLResponse& redirect_response) override;
void DidSendData(uint64_t bytes_sent,
uint64_t total_bytes_to_be_sent) override;
void DidReceiveResponse(const blink::WebURLResponse& response) override;
void DidDownloadData(uint64_t data_length) override;
void DidReceiveData(base::span<const char> data) override;
void DidFinishLoading() override;
void DidFail(const blink::WebURLError& error) override;
private:
enum class LoadingState {
kWaitingToOpen,
kOpening,
kStreamingData,
kLoadComplete,
};
void AbortLoad(Result result);
void RunReadCallback();
void SetLoadComplete(Result result);
base::WeakPtr<Client> client_;
LoadingState state_ = LoadingState::kWaitingToOpen;
Result complete_result_ = Result::kSuccess;
std::unique_ptr<blink::WebAssociatedURLLoader> blink_loader_;
bool ignore_redirects_ = false;
OpenCallback open_callback_;
UrlResponse response_;
size_t buffer_lower_threshold_ = 0;
size_t buffer_upper_threshold_ = 0;
bool deferring_loading_ = false;
base::circular_deque<uint8_t> buffer_;
base::OnceCallback<void(int)> read_callback_;
base::raw_span<uint8_t> client_buffer_;
};
}
#endif