OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ | 5 #ifndef CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ |
6 #define CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ | 6 #define CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/files/file.h" | 13 #include "base/files/file.h" |
14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
15 #include "base/gtest_prod_util.h" | 15 #include "base/gtest_prod_util.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/memory/linked_ptr.h" | 18 #include "base/memory/linked_ptr.h" |
19 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
20 #include "base/time/time.h" | 20 #include "base/time/time.h" |
21 #include "content/common/content_export.h" | 21 #include "content/common/content_export.h" |
22 #include "content/public/browser/download_interrupt_reasons.h" | 22 #include "content/public/browser/download_interrupt_reasons.h" |
23 #include "crypto/sha2.h" | 23 #include "crypto/secure_hash.h" |
24 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
25 #include "net/log/net_log.h" | 25 #include "net/log/net_log.h" |
26 #include "url/gurl.h" | 26 #include "url/gurl.h" |
27 | 27 |
28 namespace crypto { | |
29 class SecureHash; | |
30 } | |
31 | |
32 namespace content { | 28 namespace content { |
33 | 29 |
34 // File being downloaded and saved to disk. This is a base class | 30 // File being downloaded and saved to disk. This is a base class |
35 // for DownloadFile and SaveFile, which keep more state information. | 31 // for DownloadFile and SaveFile, which keep more state information. BaseFile |
32 // considers itself the owner of the physical file and will delete it when the | |
33 // BaseFile object is destroyed unless the ownership is revoked via a call to | |
34 // Detach(). | |
36 class CONTENT_EXPORT BaseFile { | 35 class CONTENT_EXPORT BaseFile { |
37 public: | 36 public: |
38 // May be constructed on any thread. All other routines (including | 37 // May be constructed on any thread. All other routines (including |
39 // destruction) must occur on the FILE thread. | 38 // destruction) must occur on the FILE thread. |
40 BaseFile(const base::FilePath& full_path, | 39 BaseFile(const net::BoundNetLog& bound_net_log); |
41 const GURL& source_url, | 40 ~BaseFile(); |
42 const GURL& referrer_url, | |
43 int64_t received_bytes, | |
44 bool calculate_hash, | |
45 const std::string& hash_state, | |
46 base::File file, | |
47 const net::BoundNetLog& bound_net_log); | |
48 virtual ~BaseFile(); | |
49 | 41 |
50 // Returns DOWNLOAD_INTERRUPT_REASON_NONE on success, or a | 42 // Returns DOWNLOAD_INTERRUPT_REASON_NONE on success, or a |
51 // DownloadInterruptReason on failure. |default_directory| specifies the | 43 // DownloadInterruptReason on failure. Upon success, the file at |full_path()| |
52 // directory to create the temporary file in if |full_path()| is empty. If | 44 // is assumed to be owned by the BaseFile. It will be deleted when the |
53 // |default_directory| and |full_path()| are empty, then a temporary file will | 45 // BaseFile object is destroyed unless Detach() is called before destroying |
54 // be created in the default download location as determined by | 46 // the BaseFile instance. |
55 // ContentBrowserClient. | 47 // |
56 DownloadInterruptReason Initialize(const base::FilePath& default_directory); | 48 // |full_path|: Full path to the download file. Can be empty, in which case |
49 // the rules described in |default_directory| will be used to generate a | |
50 // temporary filename. | |
51 // | |
52 // |default_directory|: specifies the directory to create the temporary file | |
53 // in if |full_path| is empty. If |default_directory| and |full_path| are | |
54 // empty, then a temporary file will be created in the default download | |
55 // location as determined by ContentBrowserClient. | |
56 // | |
57 // |file|: The base::File handle to use. If specified, BaseFile will not open | |
58 // a file and will use this handle. The file should be opened for both | |
59 // read and write. Only makes sense if |full_path| is non-empty since it | |
60 // implies that the caller already knows the path to the file. There's no | |
61 // perfect way to come up with a canonical path for a file. So BaseFile | |
62 // will not attempt to determine the |full_path|. | |
63 // | |
64 // |bytes_so_far|: If a file is provided (via |full_path| or |file|), then | |
65 // this argument specifies the size of the file to expect. It is legal for | |
66 // the file to be larger, in which case the file will be truncated down to | |
67 // this size. However, if the file is shorter, then the operation will | |
68 // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. | |
69 // | |
70 // |hash_so_far|: If |bytes_so_far| is non-zero, this specifies the SHA-256 | |
71 // hash of the first |bytes_so_far| bytes of the target file. If | |
72 // specified, BaseFile will read the first |bytes_so_far| of the target | |
73 // file in order to calculate the hash and verify that the file matches. | |
74 // If there's a mismatch, then the operation fails with | |
75 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |hash_state| | |
76 // is also specified. | |
77 // | |
78 // |hash_state|: The partial hash object to use. Only meaningful if there's a | |
79 // preexisting target file and it is non-empty (i.e. bytes_so_far is | |
80 // non-zero). If specified, BaseFile will assume that the bytes up to | |
81 // |bytes_so_far| has been accurately hashed into |hash_state| and will | |
82 // ignore |hash_so_far|. | |
83 DownloadInterruptReason Initialize(const base::FilePath& full_path, | |
84 const base::FilePath& default_directory, | |
85 base::File file, | |
86 int64_t bytes_so_far, | |
87 const std::string& hash_so_far, | |
88 scoped_ptr<crypto::SecureHash> hash_state); | |
57 | 89 |
58 // Write a new chunk of data to the file. Returns a DownloadInterruptReason | 90 // Write a new chunk of data to the file. Returns a DownloadInterruptReason |
59 // indicating the result of the operation. | 91 // indicating the result of the operation. |
60 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len); | 92 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len); |
61 | 93 |
62 // Rename the download file. Returns a DownloadInterruptReason indicating the | 94 // Rename the download file. Returns a DownloadInterruptReason indicating the |
63 // result of the operation. A return code of NONE indicates that the rename | 95 // result of the operation. A return code of NONE indicates that the rename |
64 // was successful. After a failure, the full_path() and in_progress() can be | 96 // was successful. After a failure, the full_path() and in_progress() can be |
65 // used to determine the last known filename and whether the file is available | 97 // used to determine the last known filename and whether the file is available |
66 // for writing or retrying the rename. | 98 // for writing or retrying the rename. Call Finish() to obtain the last known |
67 virtual DownloadInterruptReason Rename(const base::FilePath& full_path); | 99 // hash state. |
100 DownloadInterruptReason Rename(const base::FilePath& full_path); | |
68 | 101 |
69 // Detach the file so it is not deleted on destruction. | 102 // Mark the file as detached. Up until this method is called, BaseFile assumes |
70 virtual void Detach(); | 103 // ownership of the file and hence will delete the file if the BaseFile object |
104 // is destroyed. Calling Detach() causes BaseFile to assume that it no longer | |
105 // owns the file. Detach() can be called at any time. Close() must still be | |
106 // called to close the file if it is open. | |
107 void Detach(); | |
71 | 108 |
72 // Abort the download and automatically close the file. | 109 // Abort the download and automatically close and delete the file. |
73 void Cancel(); | 110 void Cancel(); |
74 | 111 |
75 // Indicate that the download has finished. No new data will be received. | 112 // Indicate that the download has finished. No new data will be received. |
76 void Finish(); | 113 // Returns the SecureHash object representing the state of the hash function |
77 | 114 // at the end of the operation. |
78 // Indicate that the download is being aborted due to an error. This is | 115 scoped_ptr<crypto::SecureHash> Finish(); |
79 // identical to Finish() with the exception that the hash state will not be | |
80 // finalized. | |
81 void FinishWithError(); | |
82 | |
83 // Set the client guid which will be used to identify the app to the | |
84 // system AV scanning function. Should be called before | |
85 // AnnotateWithSourceInformation() to take effect. | |
86 void SetClientGuid(const std::string& guid); | |
87 | 116 |
88 // Informs the OS that this file came from the internet. Returns a | 117 // Informs the OS that this file came from the internet. Returns a |
89 // DownloadInterruptReason indicating the result of the operation. | 118 // DownloadInterruptReason indicating the result of the operation. |
90 // Note: SetClientGuid() should be called before this function on | 119 // |
91 // Windows to ensure the correct app client ID is available. | 120 // |client_guid|: The client GUID which will be used to identify the caller to |
92 DownloadInterruptReason AnnotateWithSourceInformation(); | 121 // the system AV scanning function. |
122 // | |
123 // |source_url| / |referrer_url|: Source and referrer for the network request | |
124 // that originated this download. Will be used to annotate source | |
125 // information and also to determine the relative danger level of the | |
126 // file. | |
127 DownloadInterruptReason AnnotateWithSourceInformation( | |
128 const std::string& client_guid, | |
129 const GURL& source_url, | |
130 const GURL& referrer_url); | |
93 | 131 |
94 // Returns the last known path to the download file. Can be empty if there's | 132 // Returns the last known path to the download file. Can be empty if there's |
95 // no file. | 133 // no file. |
96 const base::FilePath& full_path() const { return full_path_; } | 134 const base::FilePath& full_path() const { return full_path_; } |
97 | 135 |
98 // Returns true if the file is open. If true, the file can be written to or | 136 // Returns true if the file is open. If true, the file can be written to or |
99 // renamed. | 137 // renamed. |
100 bool in_progress() const { return file_.IsValid(); } | 138 bool in_progress() const { return file_.IsValid(); } |
101 | 139 |
102 // Returns the number of bytes in the file pointed to by full_path(). | 140 // Returns the number of bytes in the file pointed to by full_path(). |
103 int64_t bytes_so_far() const { return bytes_so_far_; } | 141 int64_t bytes_so_far() const { return bytes_so_far_; } |
104 | 142 |
105 // Fills |hash| with the hash digest for the file. | 143 std::string DebugString() const; |
106 // Returns true if digest is successfully calculated. | |
107 virtual bool GetHash(std::string* hash); | |
108 | |
109 // Returns the current (intermediate) state of the hash as a byte string. | |
110 virtual std::string GetHashState(); | |
111 | |
112 // Returns true if the given hash is considered empty. An empty hash is | |
113 // a string of size crypto::kSHA256Length that contains only zeros (initial | |
114 // value for the hash). | |
115 static bool IsEmptyHash(const std::string& hash); | |
116 | |
117 virtual std::string DebugString() const; | |
118 | 144 |
119 private: | 145 private: |
120 friend class BaseFileTest; | 146 friend class BaseFileTest; |
121 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash); | 147 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash); |
122 | 148 |
123 // Creates and opens the file_ if it is NULL. | 149 // Creates and opens the file_ if it is NULL. |
124 DownloadInterruptReason Open(); | 150 DownloadInterruptReason Open(const std::string& hash_so_far); |
svaldez
2016/03/09 19:27:33
Add comment about hash_so_far.
asanka
2016/03/10 16:48:08
Done.
| |
125 | 151 |
126 // Closes and resets file_. | 152 // Closes and resets file_. |
127 void Close(); | 153 void Close(); |
128 | 154 |
129 // Resets file_. | 155 // Resets file_. |
130 void ClearFile(); | 156 void ClearFile(); |
131 | 157 |
132 // Platform specific method that moves a file to a new path and adjusts the | 158 // Platform specific method that moves a file to a new path and adjusts the |
133 // security descriptor / permissions on the file to match the defaults for the | 159 // security descriptor / permissions on the file to match the defaults for the |
134 // new directory. | 160 // new directory. |
135 DownloadInterruptReason MoveFileAndAdjustPermissions( | 161 DownloadInterruptReason MoveFileAndAdjustPermissions( |
136 const base::FilePath& new_path); | 162 const base::FilePath& new_path); |
137 | 163 |
138 // Split out from CurrentSpeed to enable testing. | 164 // Split out from CurrentSpeed to enable testing. |
139 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const; | 165 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const; |
140 | 166 |
167 // Verifies that: | |
168 // * Size of the file represented by |file_| is at least |bytes_so_far_|. | |
169 // | |
170 // * If |hash_to_expect| is not empty, then the result of hashing the first | |
171 // |bytes_so_far_| bytes of |file_| matches |hash_to_expect|. | |
172 // | |
173 // If the result is REASON_NONE, then on return |secure_hash_| is valid and | |
174 // is ready to hash bytes from offset |bytes_so_far_| + 1. | |
175 DownloadInterruptReason CalculatePartialHash( | |
176 const std::string& hash_to_expect); | |
177 | |
141 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error | 178 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error |
142 // on through, converting to a |DownloadInterruptReason|. | 179 // on through, converting to a |DownloadInterruptReason|. |
143 DownloadInterruptReason LogNetError(const char* operation, net::Error error); | 180 DownloadInterruptReason LogNetError(const char* operation, net::Error error); |
144 | 181 |
145 // Log the system error in |os_error| and converts it into a | 182 // Log the system error in |os_error| and converts it into a |
146 // |DownloadInterruptReason|. | 183 // |DownloadInterruptReason|. |
147 DownloadInterruptReason LogSystemError(const char* operation, | 184 DownloadInterruptReason LogSystemError(const char* operation, |
148 logging::SystemErrorCode os_error); | 185 logging::SystemErrorCode os_error); |
149 | 186 |
150 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |os_error| and |reason|. | 187 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |os_error| and |reason|. |
151 // Returns |reason|. | 188 // Returns |reason|. |
152 DownloadInterruptReason LogInterruptReason( | 189 DownloadInterruptReason LogInterruptReason( |
153 const char* operation, int os_error, | 190 const char* operation, int os_error, |
154 DownloadInterruptReason reason); | 191 DownloadInterruptReason reason); |
155 | 192 |
156 static const unsigned char kEmptySha256Hash[crypto::kSHA256Length]; | |
157 | |
158 // Full path to the file including the file name. | 193 // Full path to the file including the file name. |
159 base::FilePath full_path_; | 194 base::FilePath full_path_; |
160 | 195 |
161 // Source URL for the file being downloaded. | |
162 GURL source_url_; | |
163 | |
164 // The URL where the download was initiated. | |
165 GURL referrer_url_; | |
166 | |
167 std::string client_guid_; | |
168 | |
169 // OS file for writing | 196 // OS file for writing |
170 base::File file_; | 197 base::File file_; |
171 | 198 |
172 // Amount of data received up so far, in bytes. | 199 // Amount of data received up so far, in bytes. |
173 int64_t bytes_so_far_; | 200 int64_t bytes_so_far_ = 0; |
201 | |
202 // Used to calculate hash for the file when calculate_hash_ is set. | |
203 scoped_ptr<crypto::SecureHash> secure_hash_; | |
174 | 204 |
175 // Start time for calculating speed. | 205 // Start time for calculating speed. |
176 base::TimeTicks start_tick_; | 206 base::TimeTicks start_tick_; |
177 | 207 |
178 // Indicates if hash should be calculated for the file. | |
179 bool calculate_hash_; | |
180 | |
181 // Used to calculate hash for the file when calculate_hash_ | |
182 // is set. | |
183 scoped_ptr<crypto::SecureHash> secure_hash_; | |
184 | |
185 unsigned char sha256_hash_[crypto::kSHA256Length]; | |
186 | |
187 // Indicates that this class no longer owns the associated file, and so | 208 // Indicates that this class no longer owns the associated file, and so |
188 // won't delete it on destruction. | 209 // won't delete it on destruction. |
189 bool detached_; | 210 bool detached_ = false; |
190 | 211 |
191 net::BoundNetLog bound_net_log_; | 212 net::BoundNetLog bound_net_log_; |
192 | 213 |
193 DISALLOW_COPY_AND_ASSIGN(BaseFile); | 214 DISALLOW_COPY_AND_ASSIGN(BaseFile); |
194 }; | 215 }; |
195 | 216 |
196 } // namespace content | 217 } // namespace content |
197 | 218 |
198 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ | 219 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ |
OLD | NEW |