15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/files/file.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/content_export.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_interrupt_reasons.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "crypto/sha2.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SecureHash;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// File being downloaded and saved to disk. This is a base class
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for DownloadFile and SaveFile, which keep more state information.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CONTENT_EXPORT BaseFile {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be constructed on any thread.  All other routines (including
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destruction) must occur on the FILE thread.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BaseFile(const base::FilePath& full_path,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const GURL& source_url,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const GURL& referrer_url,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           int64 received_bytes,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           bool calculate_hash,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const std::string& hash_state,
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           base::File file,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const net::BoundNetLog& bound_net_log);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BaseFile();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns DOWNLOAD_INTERRUPT_REASON_NONE on success, or a
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DownloadInterruptReason on failure.  |default_directory| specifies the
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directory to create the temporary file in if |full_path()| is empty. If
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |default_directory| and |full_path()| are empty, then a temporary file will
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be created in the default download location as determined by
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ContentBrowserClient.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadInterruptReason Initialize(const base::FilePath& default_directory);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write a new chunk of data to the file. Returns a DownloadInterruptReason
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indicating the result of the operation.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rename the download file. Returns a DownloadInterruptReason indicating the
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // result of the operation. A return code of NONE indicates that the rename
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // was successful. After a failure, the full_path() and in_progress() can be
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // used to determine the last known filename and whether the file is available
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // for writing or retrying the rename.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual DownloadInterruptReason Rename(const base::FilePath& full_path);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Detach the file so it is not deleted on destruction.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Detach();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort the download and automatically close the file.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicate that the download has finished. No new data will be received.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Finish();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Set the client guid which will be used to identify the app to the
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // system AV scanning function. Should be called before
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // AnnotateWithSourceInformation() to take effect.
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void SetClientGuid(const std::string& guid);
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Informs the OS that this file came from the internet. Returns a
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DownloadInterruptReason indicating the result of the operation.
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Note: SetClientGuid() should be called before this function on
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Windows to ensure the correct app client ID is available.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadInterruptReason AnnotateWithSourceInformation();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns the last known path to the download file. Can be empty if there's
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // no file.
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const base::FilePath& full_path() const { return full_path_; }
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns true if the file is open. If true, the file can be written to or
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // renamed.
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool in_progress() const { return file_.IsValid(); }
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns the number of bytes in the file pointed to by full_path().
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 bytes_so_far() const { return bytes_so_far_; }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fills |hash| with the hash digest for the file.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if digest is successfully calculated.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetHash(std::string* hash);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current (intermediate) state of the hash as a byte string.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string GetHashState();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the given hash is considered empty.  An empty hash is
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a string of size crypto::kSHA256Length that contains only zeros (initial
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // value for the hash).
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool IsEmptyHash(const std::string& hash);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string DebugString() const;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class BaseFileTest;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Creates and opens the file_ if it is NULL.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadInterruptReason Open();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Closes and resets file_.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Resets file_.
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void ClearFile();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Platform specific method that moves a file to a new path and adjusts the
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // security descriptor / permissions on the file to match the defaults for the
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // new directory.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadInterruptReason MoveFileAndAdjustPermissions(
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& new_path);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Split out from CurrentSpeed to enable testing.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 CurrentSpeedAtTime(base::TimeTicks current_time) const;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on through, converting to a |DownloadInterruptReason|.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadInterruptReason LogNetError(const char* operation, net::Error error);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log the system error in |os_error| and converts it into a
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |DownloadInterruptReason|.
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DownloadInterruptReason LogSystemError(const char* operation,
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                         logging::SystemErrorCode os_error);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |os_error| and |reason|.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns |reason|.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadInterruptReason LogInterruptReason(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* operation, int os_error,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DownloadInterruptReason reason);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const unsigned char kEmptySha256Hash[crypto::kSHA256Length];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Full path to the file including the file name.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath full_path_;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Source URL for the file being downloaded.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL source_url_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The URL where the download was initiated.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL referrer_url_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string client_guid_;
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // OS file for writing
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::File file_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Amount of data received up so far, in bytes.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 bytes_so_far_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start time for calculating speed.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks start_tick_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates if hash should be calculated for the file.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool calculate_hash_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to calculate hash for the file when calculate_hash_
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is set.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<crypto::SecureHash> secure_hash_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  unsigned char sha256_hash_[crypto::kSHA256Length];
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates that this class no longer owns the associated file, and so
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // won't delete it on destruction.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool detached_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::BoundNetLog bound_net_log_;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BaseFile);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
190