1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef PDF_PPAPI_MIGRATION_URL_LOADER_H_ 6 #define PDF_PPAPI_MIGRATION_URL_LOADER_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <string> 13 14 #include "base/callback.h" 15 #include "base/containers/circular_deque.h" 16 #include "base/containers/span.h" 17 #include "base/memory/weak_ptr.h" 18 #include "pdf/ppapi_migration/callback.h" 19 #include "ppapi/cpp/instance_handle.h" 20 #include "ppapi/cpp/url_loader.h" 21 #include "third_party/blink/public/web/web_associated_url_loader_client.h" 22 23 namespace blink { 24 class WebAssociatedURLLoader; 25 class WebString; 26 class WebURL; 27 class WebURLRequest; 28 struct WebAssociatedURLLoaderOptions; 29 } // namespace blink 30 31 namespace net { 32 class SiteForCookies; 33 } // namespace net 34 35 namespace chrome_pdf { 36 37 // Properties for making a URL request. 38 struct UrlRequest final { 39 UrlRequest(); 40 UrlRequest(const UrlRequest& other); 41 UrlRequest(UrlRequest&& other) noexcept; 42 UrlRequest& operator=(const UrlRequest& other); 43 UrlRequest& operator=(UrlRequest&& other) noexcept; 44 ~UrlRequest(); 45 46 // Request URL. 47 std::string url; 48 49 // HTTP method. 50 std::string method; 51 52 // Whether to ignore redirects. By default, redirects are followed 53 // automatically. 54 bool ignore_redirects = false; 55 56 // Custom referrer URL. 57 std::string custom_referrer_url; 58 59 // HTTP headers as a single string of `\n`-delimited key-value pairs. 60 std::string headers; 61 62 // Request body. 63 std::string body; 64 65 // Thresholds for throttling filling of the loader's internal buffer. Filling 66 // will stop after exceeding the upper threshold, and resume after dropping 67 // below the lower threshold. 68 // 69 // Default values taken from `ppapi/shared_impl/url_request_info_data.cc`. The 70 // PDF viewer never changes the defaults in production, so these fields mostly 71 // exist for testing purposes. 72 size_t buffer_lower_threshold = 50 * 1000 * 1000; 73 size_t buffer_upper_threshold = 100 * 1000 * 1000; 74 }; 75 76 // Properties returned from a URL request. Does not include the response body. 77 struct UrlResponse final { 78 UrlResponse(); 79 UrlResponse(const UrlResponse& other); 80 UrlResponse(UrlResponse&& other) noexcept; 81 UrlResponse& operator=(const UrlResponse& other); 82 UrlResponse& operator=(UrlResponse&& other) noexcept; 83 ~UrlResponse(); 84 85 // HTTP status code. 86 int32_t status_code = 0; 87 88 // HTTP headers as a single string of `\n`-delimited key-value pairs. 89 std::string headers; 90 }; 91 92 // Abstraction for a Blink or Pepper URL loader. 93 class UrlLoader { 94 public: 95 UrlLoader(const UrlLoader&) = delete; 96 UrlLoader& operator=(const UrlLoader&) = delete; 97 virtual ~UrlLoader(); 98 99 // Tries to grant the loader the capability to make unrestricted cross-origin 100 // requests ("universal access," in `blink::SecurityOrigin` terms). Must be 101 // called before `Open()`. 102 virtual void GrantUniversalAccess() = 0; 103 104 // Mimic `pp::URLLoader`: 105 virtual void Open(const UrlRequest& request, ResultCallback callback) = 0; 106 virtual void ReadResponseBody(base::span<char> buffer, 107 ResultCallback callback) = 0; 108 virtual void Close() = 0; 109 110 // Returns the URL response (not including the body). Only valid after 111 // `Open()` completes. response()112 const UrlResponse& response() const { return response_; } 113 114 protected: 115 UrlLoader(); 116 mutable_response()117 UrlResponse& mutable_response() { return response_; } 118 119 private: 120 UrlResponse response_; 121 }; 122 123 // A Blink URL loader. This implementation tries to emulate a combination of 124 // `content::PepperURLLoaderHost` and `ppapi::proxy::URLLoaderResource`. 125 class BlinkUrlLoader final : public UrlLoader, 126 public blink::WebAssociatedURLLoaderClient { 127 public: 128 // Client interface required by `BlinkUrlLoader`. Instances should be passed 129 // using weak pointers, as the loader can be shared, and may outlive the 130 // client. 131 class Client { 132 public: 133 // Returns `true` if the client is still usable. The client may require 134 // resources that can become unavailable, such as a local frame. Rather than 135 // handling missing resources separately for each method, callers can just 136 // verify validity once, before making any other calls. 137 virtual bool IsValid() const = 0; 138 139 // Completes `partial_url` using the current document. 140 virtual blink::WebURL CompleteURL( 141 const blink::WebString& partial_url) const = 0; 142 143 // Gets the site-for-cookies for the current document. 144 virtual net::SiteForCookies SiteForCookies() const = 0; 145 146 // Sets the referrer on `request` to `referrer_url` using the current frame. 147 virtual void SetReferrerForRequest(blink::WebURLRequest& request, 148 const blink::WebURL& referrer_url) = 0; 149 150 // Returns a new `blink::WebAssociatedURLLoader` from the current frame. 151 virtual std::unique_ptr<blink::WebAssociatedURLLoader> 152 CreateAssociatedURLLoader( 153 const blink::WebAssociatedURLLoaderOptions& options) = 0; 154 155 protected: 156 ~Client() = default; 157 }; 158 159 explicit BlinkUrlLoader(base::WeakPtr<Client> client); 160 BlinkUrlLoader(const BlinkUrlLoader&) = delete; 161 BlinkUrlLoader& operator=(const BlinkUrlLoader&) = delete; 162 ~BlinkUrlLoader() override; 163 164 // UrlLoader: 165 void GrantUniversalAccess() override; 166 void Open(const UrlRequest& request, ResultCallback callback) override; 167 void ReadResponseBody(base::span<char> buffer, 168 ResultCallback callback) override; 169 void Close() override; 170 171 // blink::WebAssociatedURLLoaderClient: 172 bool WillFollowRedirect( 173 const blink::WebURL& new_url, 174 const blink::WebURLResponse& redirect_response) override; 175 void DidSendData(uint64_t bytes_sent, 176 uint64_t total_bytes_to_be_sent) override; 177 void DidReceiveResponse(const blink::WebURLResponse& response) override; 178 void DidDownloadData(uint64_t data_length) override; 179 void DidReceiveData(const char* data, int data_length) override; 180 void DidFinishLoading() override; 181 void DidFail(const blink::WebURLError& error) override; 182 183 private: 184 enum class LoadingState { 185 // Before calling `Open()`. 186 kWaitingToOpen, 187 188 // After calling `Open()`, but before `DidReceiveResponse()` or `DidFail()`. 189 kOpening, 190 191 // After `DidReceiveResponse()`, but before `DidFinishLoading()` or 192 // `DidFail()`. Zero or more calls allowed to `DidReceiveData()`. 193 kStreamingData, 194 195 // After `DidFinishLoading()` or `DidFail()`, or forced by `Close()`. 196 // Details about how the load completed are in `complete_result_`. 197 kLoadComplete, 198 }; 199 200 // Aborts the load with `result`. Runs callback if pending. 201 void AbortLoad(int32_t result); 202 203 // Runs callback for `ReadResponseBody()` if pending. 204 void RunReadCallback(); 205 206 void SetLoadComplete(int32_t result); 207 208 base::WeakPtr<Client> client_; 209 bool grant_universal_access_ = false; 210 211 LoadingState state_ = LoadingState::kWaitingToOpen; 212 int32_t complete_result_ = 0; 213 214 std::unique_ptr<blink::WebAssociatedURLLoader> blink_loader_; 215 216 bool ignore_redirects_ = false; 217 ResultCallback open_callback_; 218 219 // Thresholds control buffer throttling, as defined in `UrlRequest`. 220 size_t buffer_lower_threshold_ = 0; 221 size_t buffer_upper_threshold_ = 0; 222 bool deferring_loading_ = false; 223 base::circular_deque<char> buffer_; 224 225 ResultCallback read_callback_; 226 base::span<char> client_buffer_; 227 }; 228 229 // A Pepper URL loader. 230 class PepperUrlLoader final : public UrlLoader { 231 public: 232 explicit PepperUrlLoader(pp::InstanceHandle plugin_instance); 233 PepperUrlLoader(const PepperUrlLoader&) = delete; 234 PepperUrlLoader& operator=(const PepperUrlLoader&) = delete; 235 ~PepperUrlLoader() override; 236 237 // UrlLoader: 238 void GrantUniversalAccess() override; 239 void Open(const UrlRequest& request, ResultCallback callback) override; 240 void ReadResponseBody(base::span<char> buffer, 241 ResultCallback callback) override; 242 void Close() override; 243 244 private: 245 void DidOpen(ResultCallback callback, int32_t result); 246 247 pp::InstanceHandle plugin_instance_; 248 pp::URLLoader pepper_loader_; 249 250 base::WeakPtrFactory<PepperUrlLoader> weak_factory_{this}; 251 }; 252 253 } // namespace chrome_pdf 254 255 #endif // PDF_PPAPI_MIGRATION_URL_LOADER_H_ 256