1 // Copyright 2018 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 COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_PARAMETERS_H_ 6 #define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_PARAMETERS_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/callback.h" 16 #include "base/macros.h" 17 #include "base/optional.h" 18 #include "components/download/public/common/download_interrupt_reasons.h" 19 #include "components/download/public/common/download_save_info.h" 20 #include "components/download/public/common/download_source.h" 21 #include "net/traffic_annotation/network_traffic_annotation.h" 22 #include "net/url_request/referrer_policy.h" 23 #include "services/network/public/cpp/resource_request_body.h" 24 #include "services/network/public/mojom/fetch_api.mojom-shared.h" 25 #include "storage/browser/blob/blob_data_handle.h" 26 #include "url/gurl.h" 27 #include "url/origin.h" 28 29 namespace download { 30 31 class DownloadItem; 32 33 // Pass an instance of DownloadUrlParameters to DownloadManager::DownloadUrl() 34 // to download the content at |url|. All parameters with setters are optional. 35 // |referrer| and |referrer_encoding| are the referrer for the download. If 36 // |prefer_cache| is true, then if the response to |url| is in the HTTP cache it 37 // will be used without revalidation. If |post_id| is non-negative, then it 38 // identifies the post transaction used to originally retrieve the |url| 39 // resource - it also requires |prefer_cache| to be |true| since re-post'ing is 40 // not done. |save_info| specifies where the downloaded file should be saved, 41 // and whether the user should be prompted about the download. If not null, 42 // |callback| will be called when the download starts, or if an error occurs 43 // that prevents a download item from being created. We send a pointer to 44 // content::ResourceContext instead of the usual reference so that a copy of the 45 // object isn't made. 46 47 class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { 48 public: 49 // An OnStartedCallback is invoked when a response is available for the 50 // download request. For new downloads, this callback is invoked after the 51 // OnDownloadCreated notification is issued by the DownloadManager. If the 52 // download fails, then the DownloadInterruptReason parameter will indicate 53 // the failure. 54 // 55 // DownloadItem* may be nullptr if no DownloadItem was created. DownloadItems 56 // are not created when a resource throttle or a resource handler blocks the 57 // download request. I.e. the download triggered a warning of some sort and 58 // the user chose to not to proceed with the download as a result. 59 typedef base::OnceCallback<void(DownloadItem*, DownloadInterruptReason)> 60 OnStartedCallback; 61 62 typedef std::pair<std::string, std::string> RequestHeadersNameValuePair; 63 typedef std::vector<RequestHeadersNameValuePair> RequestHeadersType; 64 65 using BlobStorageContextGetter = 66 base::OnceCallback<storage::BlobStorageContext*()>; 67 using UploadProgressCallback = 68 base::RepeatingCallback<void(uint64_t bytes_uploaded)>; 69 70 // Constructs a download not associated with a frame. 71 // 72 // It is not safe to have downloads not associated with a frame and 73 // this should only be done in a limited set of cases where the download URL 74 // has been previously vetted. A download that's initiated without 75 // associating it with a frame don't receive the same security checks 76 // as a request that's associated with one. Hence, downloads that are not 77 // associated with a frame should only be made for URLs that are either 78 // trusted or URLs that have previously been successfully issued using a 79 // non-privileged frame. 80 DownloadUrlParameters( 81 const GURL& url, 82 const net::NetworkTrafficAnnotationTag& traffic_annotation); 83 84 DownloadUrlParameters( 85 const GURL& url, 86 int render_process_host_id, 87 int render_frame_host_routing_id, 88 const net::NetworkTrafficAnnotationTag& traffic_annotation); 89 90 ~DownloadUrlParameters(); 91 92 // Should be set to true if the download was initiated by a script or a web 93 // page. I.e. if the download request cannot be attributed to an explicit user 94 // request for a download, then set this value to true. set_content_initiated(bool content_initiated)95 void set_content_initiated(bool content_initiated) { 96 content_initiated_ = content_initiated; 97 } add_request_header(const std::string & name,const std::string & value)98 void add_request_header(const std::string& name, const std::string& value) { 99 request_headers_.push_back(make_pair(name, value)); 100 } 101 102 // HTTP Referrer, referrer policy and encoding. set_referrer(const GURL & referrer)103 void set_referrer(const GURL& referrer) { referrer_ = referrer; } set_referrer_policy(net::ReferrerPolicy referrer_policy)104 void set_referrer_policy(net::ReferrerPolicy referrer_policy) { 105 referrer_policy_ = referrer_policy; 106 } set_referrer_encoding(const std::string & referrer_encoding)107 void set_referrer_encoding(const std::string& referrer_encoding) { 108 referrer_encoding_ = referrer_encoding; 109 } 110 111 // The origin of the context which initiated the request. See 112 // net::URLRequest::initiator(). set_initiator(const base::Optional<url::Origin> & initiator)113 void set_initiator(const base::Optional<url::Origin>& initiator) { 114 initiator_ = initiator; 115 } 116 117 // If this is a request for resuming an HTTP/S download, |last_modified| 118 // should be the value of the last seen Last-Modified response header. set_last_modified(const std::string & last_modified)119 void set_last_modified(const std::string& last_modified) { 120 last_modified_ = last_modified; 121 } 122 123 // If this is a request for resuming an HTTP/S download, |etag| should be the 124 // last seen Etag response header. set_etag(const std::string & etag)125 void set_etag(const std::string& etag) { etag_ = etag; } 126 127 // If the "If-Range" header is used in a partial request. set_use_if_range(bool use_if_range)128 void set_use_if_range(bool use_if_range) { use_if_range_ = use_if_range; } 129 130 // HTTP method to use. set_method(const std::string & method)131 void set_method(const std::string& method) { method_ = method; } 132 133 // Body of the HTTP POST request. set_post_body(scoped_refptr<network::ResourceRequestBody> post_body)134 void set_post_body(scoped_refptr<network::ResourceRequestBody> post_body) { 135 post_body_ = post_body; 136 } 137 138 // The blob storage context to be used for uploading blobs, if any. set_blob_storage_context_getter(BlobStorageContextGetter blob_getter)139 void set_blob_storage_context_getter(BlobStorageContextGetter blob_getter) { 140 blob_storage_context_getter_ = std::move(blob_getter); 141 } 142 143 // If |prefer_cache| is true and the response to |url| is in the HTTP cache, 144 // it will be used without validation. If |method| is POST, then |post_id_| 145 // shoud be set via |set_post_id()| below to the identifier of the POST 146 // transaction used to originally retrieve the resource. set_prefer_cache(bool prefer_cache)147 void set_prefer_cache(bool prefer_cache) { prefer_cache_ = prefer_cache; } 148 149 // See set_prefer_cache() above. set_post_id(int64_t post_id)150 void set_post_id(int64_t post_id) { post_id_ = post_id; } 151 152 // See OnStartedCallback above. set_callback(OnStartedCallback callback)153 void set_callback(OnStartedCallback callback) { 154 callback_ = std::move(callback); 155 } 156 157 // If not empty, specifies the full target path for the download. This value 158 // overrides the filename suggested by a Content-Disposition headers. It 159 // should only be set for programmatic downloads where the caller can verify 160 // the safety of the filename and the resulting download. set_file_path(const base::FilePath & file_path)161 void set_file_path(const base::FilePath& file_path) { 162 save_info_.file_path = file_path; 163 } 164 165 // Suggested filename for the download. The suggestion can be overridden by 166 // either a Content-Disposition response header or a |file_path|. set_suggested_name(const base::string16 & suggested_name)167 void set_suggested_name(const base::string16& suggested_name) { 168 save_info_.suggested_name = suggested_name; 169 } 170 171 // If |offset| is non-zero, then a byte range request will be issued to fetch 172 // the range of bytes starting at |offset|. set_offset(int64_t offset)173 void set_offset(int64_t offset) { save_info_.offset = offset; } 174 175 // Sets the offset to start writing to the file. If set, The data received 176 // before |file_offset| are discarded or are used for validation purpose. set_file_offset(int64_t file_offset)177 void set_file_offset(int64_t file_offset) { 178 save_info_.file_offset = file_offset; 179 } 180 181 // If |offset| is non-zero, then |hash_of_partial_file| contains the raw 182 // SHA-256 hash of the first |offset| bytes of the target file. Only 183 // meaningful if a partial file exists and is identified by either the 184 // |file_path()| or |file()|. set_hash_of_partial_file(const std::string & hash_of_partial_file)185 void set_hash_of_partial_file(const std::string& hash_of_partial_file) { 186 save_info_.hash_of_partial_file = hash_of_partial_file; 187 } 188 189 // If |offset| is non-zero, then |hash_state| indicates the SHA-256 hash state 190 // of the first |offset| bytes of the target file. In this case, the prefix 191 // hash will be ignored since the |hash_state| is assumed to be correct if 192 // provided. set_hash_state(std::unique_ptr<crypto::SecureHash> hash_state)193 void set_hash_state(std::unique_ptr<crypto::SecureHash> hash_state) { 194 save_info_.hash_state = std::move(hash_state); 195 } 196 197 // If |prompt| is true, then the user will be prompted for a filename. Ignored 198 // if |file_path| is non-empty. set_prompt(bool prompt)199 void set_prompt(bool prompt) { save_info_.prompt_for_save_location = prompt; } set_file(base::File file)200 void set_file(base::File file) { save_info_.file = std::move(file); } set_do_not_prompt_for_login(bool do_not_prompt)201 void set_do_not_prompt_for_login(bool do_not_prompt) { 202 do_not_prompt_for_login_ = do_not_prompt; 203 } 204 205 // If |cross_origin_redirects| is kFollow, we will follow cross origin 206 // redirects while downloading. If it is kManual, then we'll attempt to 207 // navigate to the URL or cancel the download. If it is kError, then we will 208 // fail the download (kFail). set_cross_origin_redirects(network::mojom::RedirectMode cross_origin_redirects)209 void set_cross_origin_redirects( 210 network::mojom::RedirectMode cross_origin_redirects) { 211 cross_origin_redirects_ = cross_origin_redirects; 212 } 213 214 // Sets whether to download the response body even if the server returns 215 // non-successful HTTP response code, like "HTTP NOT FOUND". set_fetch_error_body(bool fetch_error_body)216 void set_fetch_error_body(bool fetch_error_body) { 217 fetch_error_body_ = fetch_error_body; 218 } 219 220 // A transient download will not be shown in the UI, and will not prompt 221 // to user for target file path determination. Transient download should be 222 // cleared properly through DownloadManager to avoid the database and 223 // in-memory DownloadItem objects accumulated for the user. set_transient(bool transient)224 void set_transient(bool transient) { transient_ = transient; } 225 226 // Sets the optional guid for the download, the guid serves as the unique 227 // identitfier for the download item. If no guid is provided, download 228 // system will automatically generate one. set_guid(const std::string & guid)229 void set_guid(const std::string& guid) { guid_ = guid; } 230 231 // For downloads originating from custom tabs, this records the origin 232 // of the custom tab. set_request_origin(const std::string & origin)233 void set_request_origin(const std::string& origin) { 234 request_origin_ = origin; 235 } 236 237 // Sets the download source, which will be used in metrics recording. set_download_source(DownloadSource download_source)238 void set_download_source(DownloadSource download_source) { 239 download_source_ = download_source; 240 } 241 242 // Sets the callback to run if there are upload progress updates. set_upload_progress_callback(const UploadProgressCallback & upload_callback)243 void set_upload_progress_callback( 244 const UploadProgressCallback& upload_callback) { 245 upload_callback_ = upload_callback; 246 } 247 248 // Sets whether the download will require safety checks for its URL chain and 249 // downloaded content. set_require_safety_checks(bool require_safety_checks)250 void set_require_safety_checks(bool require_safety_checks) { 251 require_safety_checks_ = require_safety_checks; 252 } 253 callback()254 OnStartedCallback& callback() { return callback_; } content_initiated()255 bool content_initiated() const { return content_initiated_; } last_modified()256 const std::string& last_modified() const { return last_modified_; } etag()257 const std::string& etag() const { return etag_; } use_if_range()258 bool use_if_range() const { return use_if_range_; } method()259 const std::string& method() const { return method_; } post_body()260 scoped_refptr<network::ResourceRequestBody> post_body() { return post_body_; } post_id()261 int64_t post_id() const { return post_id_; } prefer_cache()262 bool prefer_cache() const { return prefer_cache_; } referrer()263 const GURL& referrer() const { return referrer_; } referrer_policy()264 net::ReferrerPolicy referrer_policy() const { return referrer_policy_; } referrer_encoding()265 const std::string& referrer_encoding() const { return referrer_encoding_; } initiator()266 const base::Optional<url::Origin>& initiator() const { return initiator_; } request_origin()267 const std::string& request_origin() const { return request_origin_; } get_blob_storage_context_getter()268 BlobStorageContextGetter get_blob_storage_context_getter() { 269 return std::move(blob_storage_context_getter_); 270 } 271 272 // These will be -1 if the request is not associated with a frame. See 273 // the constructors for more. render_process_host_id()274 int render_process_host_id() const { return render_process_host_id_; } render_frame_host_routing_id()275 int render_frame_host_routing_id() const { 276 return render_frame_host_routing_id_; 277 } 278 request_headers()279 const RequestHeadersType& request_headers() const { return request_headers_; } file_path()280 const base::FilePath& file_path() const { return save_info_.file_path; } suggested_name()281 const base::string16& suggested_name() const { 282 return save_info_.suggested_name; 283 } offset()284 int64_t offset() const { return save_info_.offset; } hash_of_partial_file()285 const std::string& hash_of_partial_file() const { 286 return save_info_.hash_of_partial_file; 287 } prompt()288 bool prompt() const { return save_info_.prompt_for_save_location; } url()289 const GURL& url() const { return url_; } set_url(GURL url)290 void set_url(GURL url) { url_ = std::move(url); } do_not_prompt_for_login()291 bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; } cross_origin_redirects()292 network::mojom::RedirectMode cross_origin_redirects() const { 293 return cross_origin_redirects_; 294 } fetch_error_body()295 bool fetch_error_body() const { return fetch_error_body_; } is_transient()296 bool is_transient() const { return transient_; } guid()297 std::string guid() const { return guid_; } require_safety_checks()298 bool require_safety_checks() const { return require_safety_checks_; } 299 300 // STATE CHANGING: All save_info_ sub-objects will be in an indeterminate 301 // state following this call. GetSaveInfo()302 DownloadSaveInfo GetSaveInfo() { return std::move(save_info_); } 303 GetNetworkTrafficAnnotation()304 const net::NetworkTrafficAnnotationTag& GetNetworkTrafficAnnotation() { 305 return traffic_annotation_; 306 } 307 download_source()308 DownloadSource download_source() const { return download_source_; } 309 upload_callback()310 const UploadProgressCallback& upload_callback() const { 311 return upload_callback_; 312 } 313 314 private: 315 OnStartedCallback callback_; 316 bool content_initiated_; 317 RequestHeadersType request_headers_; 318 std::string last_modified_; 319 std::string etag_; 320 bool use_if_range_; 321 std::string method_; 322 scoped_refptr<network::ResourceRequestBody> post_body_; 323 BlobStorageContextGetter blob_storage_context_getter_; 324 int64_t post_id_; 325 bool prefer_cache_; 326 GURL referrer_; 327 net::ReferrerPolicy referrer_policy_; 328 base::Optional<url::Origin> initiator_; 329 std::string referrer_encoding_; 330 int render_process_host_id_; 331 int render_frame_host_routing_id_; 332 DownloadSaveInfo save_info_; 333 GURL url_; 334 bool do_not_prompt_for_login_; 335 network::mojom::RedirectMode cross_origin_redirects_; 336 bool fetch_error_body_; 337 bool transient_; 338 std::string guid_; 339 const net::NetworkTrafficAnnotationTag traffic_annotation_; 340 std::string request_origin_; 341 DownloadSource download_source_; 342 UploadProgressCallback upload_callback_; 343 bool require_safety_checks_; 344 345 DISALLOW_COPY_AND_ASSIGN(DownloadUrlParameters); 346 }; 347 348 } // namespace download 349 350 #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_PARAMETERS_H_ 351