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