| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_IMPL_H_ |
| #define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_IMPL_H_ |
| |
| #include <string> |
| |
| #include "base/basictypes.h" |
| #include "base/callback_forward.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "content/browser/download/download_net_log_parameters.h" |
| #include "content/browser/download/download_request_handle.h" |
| #include "content/common/content_export.h" |
| #include "content/public/browser/download_destination_observer.h" |
| #include "content/public/browser/download_item.h" |
| #include "net/base/net_errors.h" |
| #include "net/base/net_log.h" |
| #include "url/gurl.h" |
| |
| namespace content { |
| class DownloadFile; |
| class DownloadItemImplDelegate; |
| |
| // See download_item.h for usage. |
| class CONTENT_EXPORT DownloadItemImpl |
| : public DownloadItem, |
| public DownloadDestinationObserver { |
| public: |
| enum ResumeMode { |
| RESUME_MODE_INVALID = 0, |
| RESUME_MODE_IMMEDIATE_CONTINUE, |
| RESUME_MODE_IMMEDIATE_RESTART, |
| RESUME_MODE_USER_CONTINUE, |
| RESUME_MODE_USER_RESTART |
| }; |
| |
| // The maximum number of attempts we will make to resume automatically. |
| static const int kMaxAutoResumeAttempts; |
| |
| // Note that it is the responsibility of the caller to ensure that a |
| // DownloadItemImplDelegate passed to a DownloadItemImpl constructor |
| // outlives the DownloadItemImpl. |
| |
| // Constructing from persistent store: |
| // |bound_net_log| is constructed externally for our use. |
| DownloadItemImpl(DownloadItemImplDelegate* delegate, |
| uint32 id, |
| const base::FilePath& current_path, |
| const base::FilePath& target_path, |
| const std::vector<GURL>& url_chain, |
| const GURL& referrer_url, |
| const base::Time& start_time, |
| const base::Time& end_time, |
| const std::string& etag, |
| const std::string& last_modified, |
| int64 received_bytes, |
| int64 total_bytes, |
| DownloadItem::DownloadState state, |
| DownloadDangerType danger_type, |
| DownloadInterruptReason interrupt_reason, |
| bool opened, |
| const net::BoundNetLog& bound_net_log); |
| |
| // Constructing for a regular download. |
| // |bound_net_log| is constructed externally for our use. |
| DownloadItemImpl(DownloadItemImplDelegate* delegate, |
| uint32 id, |
| const DownloadCreateInfo& info, |
| const net::BoundNetLog& bound_net_log); |
| |
| // Constructing for the "Save Page As..." feature: |
| // |bound_net_log| is constructed externally for our use. |
| DownloadItemImpl(DownloadItemImplDelegate* delegate, |
| uint32 id, |
| const base::FilePath& path, |
| const GURL& url, |
| const std::string& mime_type, |
| scoped_ptr<DownloadRequestHandleInterface> request_handle, |
| const net::BoundNetLog& bound_net_log); |
| |
| virtual ~DownloadItemImpl(); |
| |
| // DownloadItem |
| virtual void AddObserver(DownloadItem::Observer* observer) OVERRIDE; |
| virtual void RemoveObserver(DownloadItem::Observer* observer) OVERRIDE; |
| virtual void UpdateObservers() OVERRIDE; |
| virtual void ValidateDangerousDownload() OVERRIDE; |
| virtual void StealDangerousDownload(const AcquireFileCallback& callback) |
| OVERRIDE; |
| virtual void Pause() OVERRIDE; |
| virtual void Resume() OVERRIDE; |
| virtual void Cancel(bool user_cancel) OVERRIDE; |
| virtual void Remove() OVERRIDE; |
| virtual void OpenDownload() OVERRIDE; |
| virtual void ShowDownloadInShell() OVERRIDE; |
| virtual uint32 GetId() const OVERRIDE; |
| virtual DownloadState GetState() const OVERRIDE; |
| virtual DownloadInterruptReason GetLastReason() const OVERRIDE; |
| virtual bool IsPaused() const OVERRIDE; |
| virtual bool IsTemporary() const OVERRIDE; |
| virtual bool CanResume() const OVERRIDE; |
| virtual bool IsDone() const OVERRIDE; |
| virtual const GURL& GetURL() const OVERRIDE; |
| virtual const std::vector<GURL>& GetUrlChain() const OVERRIDE; |
| virtual const GURL& GetOriginalUrl() const OVERRIDE; |
| virtual const GURL& GetReferrerUrl() const OVERRIDE; |
| virtual std::string GetSuggestedFilename() const OVERRIDE; |
| virtual std::string GetContentDisposition() const OVERRIDE; |
| virtual std::string GetMimeType() const OVERRIDE; |
| virtual std::string GetOriginalMimeType() const OVERRIDE; |
| virtual std::string GetRemoteAddress() const OVERRIDE; |
| virtual bool HasUserGesture() const OVERRIDE; |
| virtual PageTransition GetTransitionType() const OVERRIDE; |
| virtual const std::string& GetLastModifiedTime() const OVERRIDE; |
| virtual const std::string& GetETag() const OVERRIDE; |
| virtual bool IsSavePackageDownload() const OVERRIDE; |
| virtual const base::FilePath& GetFullPath() const OVERRIDE; |
| virtual const base::FilePath& GetTargetFilePath() const OVERRIDE; |
| virtual const base::FilePath& GetForcedFilePath() const OVERRIDE; |
| virtual base::FilePath GetFileNameToReportUser() const OVERRIDE; |
| virtual TargetDisposition GetTargetDisposition() const OVERRIDE; |
| virtual const std::string& GetHash() const OVERRIDE; |
| virtual const std::string& GetHashState() const OVERRIDE; |
| virtual bool GetFileExternallyRemoved() const OVERRIDE; |
| virtual void DeleteFile() OVERRIDE; |
| virtual bool IsDangerous() const OVERRIDE; |
| virtual DownloadDangerType GetDangerType() const OVERRIDE; |
| virtual bool TimeRemaining(base::TimeDelta* remaining) const OVERRIDE; |
| virtual int64 CurrentSpeed() const OVERRIDE; |
| virtual int PercentComplete() const OVERRIDE; |
| virtual bool AllDataSaved() const OVERRIDE; |
| virtual int64 GetTotalBytes() const OVERRIDE; |
| virtual int64 GetReceivedBytes() const OVERRIDE; |
| virtual base::Time GetStartTime() const OVERRIDE; |
| virtual base::Time GetEndTime() const OVERRIDE; |
| virtual bool CanShowInFolder() OVERRIDE; |
| virtual bool CanOpenDownload() OVERRIDE; |
| virtual bool ShouldOpenFileBasedOnExtension() OVERRIDE; |
| virtual bool GetOpenWhenComplete() const OVERRIDE; |
| virtual bool GetAutoOpened() OVERRIDE; |
| virtual bool GetOpened() const OVERRIDE; |
| virtual BrowserContext* GetBrowserContext() const OVERRIDE; |
| virtual WebContents* GetWebContents() const OVERRIDE; |
| virtual void OnContentCheckCompleted(DownloadDangerType danger_type) OVERRIDE; |
| virtual void SetOpenWhenComplete(bool open) OVERRIDE; |
| virtual void SetIsTemporary(bool temporary) OVERRIDE; |
| virtual void SetOpened(bool opened) OVERRIDE; |
| virtual void SetDisplayName(const base::FilePath& name) OVERRIDE; |
| virtual std::string DebugString(bool verbose) const OVERRIDE; |
| |
| // All remaining public interfaces virtual to allow for DownloadItemImpl |
| // mocks. |
| |
| // Determines the resume mode for an interrupted download. Requires |
| // last_reason_ to be set, but doesn't require the download to be in |
| // INTERRUPTED state. |
| virtual ResumeMode GetResumeMode() const; |
| |
| // Notify the download item that new origin information is available due to a |
| // resumption request receiving a response. |
| virtual void MergeOriginInfoOnResume( |
| const DownloadCreateInfo& new_create_info); |
| |
| // State transition operations on regular downloads -------------------------- |
| |
| // Start the download. |
| // |download_file| is the associated file on the storage medium. |
| // |req_handle| is the new request handle associated with the download. |
| virtual void Start(scoped_ptr<DownloadFile> download_file, |
| scoped_ptr<DownloadRequestHandleInterface> req_handle); |
| |
| // Needed because of intertwining with DownloadManagerImpl ------------------- |
| |
| // TODO(rdsmith): Unwind DownloadManagerImpl and DownloadItemImpl, |
| // removing these from the public interface. |
| |
| // Notify observers that this item is being removed by the user. |
| virtual void NotifyRemoved(); |
| |
| virtual void OnDownloadedFileRemoved(); |
| |
| // Provide a weak pointer reference to a DownloadDestinationObserver |
| // for use by download destinations. |
| virtual base::WeakPtr<DownloadDestinationObserver> |
| DestinationObserverAsWeakPtr(); |
| |
| // Get the download's BoundNetLog. |
| virtual const net::BoundNetLog& GetBoundNetLog() const; |
| |
| // DownloadItemImpl routines only needed by SavePackage ---------------------- |
| |
| // Called by SavePackage to set the total number of bytes on the item. |
| virtual void SetTotalBytes(int64 total_bytes); |
| |
| virtual void OnAllDataSaved(const std::string& final_hash); |
| |
| // Called by SavePackage to display progress when the DownloadItem |
| // should be considered complete. |
| virtual void MarkAsComplete(); |
| |
| // DownloadDestinationObserver |
| virtual void DestinationUpdate(int64 bytes_so_far, |
| int64 bytes_per_sec, |
| const std::string& hash_state) OVERRIDE; |
| virtual void DestinationError(DownloadInterruptReason reason) OVERRIDE; |
| virtual void DestinationCompleted(const std::string& final_hash) OVERRIDE; |
| |
| private: |
| // Fine grained states of a download. Note that active downloads are created |
| // in IN_PROGRESS_INTERNAL state. However, downloads creates via history can |
| // be created in COMPLETE_INTERNAL, CANCELLED_INTERNAL and |
| // INTERRUPTED_INTERNAL. |
| |
| enum DownloadInternalState { |
| // Includes both before and after file name determination, and paused |
| // downloads. |
| // TODO(rdsmith): Put in state variable for file name determination. |
| // Transitions from: |
| // <Initial creation> Active downloads are created in this state. |
| // RESUMING_INTERNAL |
| // Transitions to: |
| // COMPLETING_INTERNAL On final rename completion. |
| // CANCELLED_INTERNAL On cancel. |
| // INTERRUPTED_INTERNAL On interrupt. |
| // COMPLETE_INTERNAL On SavePackage download completion. |
| IN_PROGRESS_INTERNAL, |
| |
| // Between commit point (dispatch of download file release) and completed. |
| // Embedder may be opening the file in this state. |
| // Transitions from: |
| // IN_PROGRESS_INTERNAL |
| // Transitions to: |
| // COMPLETE_INTERNAL On successful completion. |
| COMPLETING_INTERNAL, |
| |
| // After embedder has had a chance to auto-open. User may now open |
| // or auto-open based on extension. |
| // Transitions from: |
| // COMPLETING_INTERNAL |
| // IN_PROGRESS_INTERNAL SavePackage only. |
| // <Initial creation> Completed persisted downloads. |
| // Transitions to: |
| // <none> Terminal state. |
| COMPLETE_INTERNAL, |
| |
| // User has cancelled the download. |
| // Transitions from: |
| // IN_PROGRESS_INTERNAL |
| // INTERRUPTED_INTERNAL |
| // RESUMING_INTERNAL |
| // <Initial creation> Canceleld persisted downloads. |
| // Transitions to: |
| // <none> Terminal state. |
| CANCELLED_INTERNAL, |
| |
| // An error has interrupted the download. |
| // Transitions from: |
| // IN_PROGRESS_INTERNAL |
| // RESUMING_INTERNAL |
| // <Initial creation> Interrupted persisted downloads. |
| // Transitions to: |
| // RESUMING_INTERNAL On resumption. |
| INTERRUPTED_INTERNAL, |
| |
| // A request to resume this interrupted download is in progress. |
| // Transitions from: |
| // INTERRUPTED_INTERNAL |
| // Transitions to: |
| // IN_PROGRESS_INTERNAL Once a server response is received from a |
| // resumption. |
| // INTERRUPTED_INTERNAL If the resumption request fails. |
| // CANCELLED_INTERNAL On cancel. |
| RESUMING_INTERNAL, |
| |
| MAX_DOWNLOAD_INTERNAL_STATE, |
| }; |
| |
| // Used with TransitionTo() to indicate whether or not to call |
| // UpdateObservers() after the state transition. |
| enum ShouldUpdateObservers { |
| UPDATE_OBSERVERS, |
| DONT_UPDATE_OBSERVERS |
| }; |
| |
| // Normal progression of a download ------------------------------------------ |
| |
| // These are listed in approximately chronological order. There are also |
| // public methods involved in normal download progression; see |
| // the implementation ordering in download_item_impl.cc. |
| |
| // Construction common to all constructors. |active| should be true for new |
| // downloads and false for downloads from the history. |
| // |download_type| indicates to the net log system what kind of download |
| // this is. |
| void Init(bool active, DownloadType download_type); |
| |
| // Called when the target path has been determined. |target_path| is the |
| // suggested target path. |disposition| indicates how the target path should |
| // be used (see TargetDisposition). |danger_type| is the danger level of |
| // |target_path| as determined by the caller. |intermediate_path| is the path |
| // to use to store the download until OnDownloadCompleting() is called. |
| virtual void OnDownloadTargetDetermined( |
| const base::FilePath& target_path, |
| TargetDisposition disposition, |
| DownloadDangerType danger_type, |
| const base::FilePath& intermediate_path); |
| |
| // Callback from file thread when we initialize the DownloadFile. |
| void OnDownloadFileInitialized(DownloadInterruptReason result); |
| |
| void OnDownloadRenamedToIntermediateName( |
| DownloadInterruptReason reason, const base::FilePath& full_path); |
| |
| // If all pre-requisites have been met, complete download processing, i.e. do |
| // internal cleanup, file rename, and potentially auto-open. (Dangerous |
| // downloads still may block on user acceptance after this point.) |
| void MaybeCompleteDownload(); |
| |
| // Called when the download is ready to complete. |
| // This may perform final rename if necessary and will eventually call |
| // DownloadItem::Completed(). |
| void OnDownloadCompleting(); |
| |
| void OnDownloadRenamedToFinalName(DownloadInterruptReason reason, |
| const base::FilePath& full_path); |
| |
| // Called if the embedder took over opening a download, to indicate that |
| // the download has been opened. |
| void DelayedDownloadOpened(bool auto_opened); |
| |
| // Called when the entire download operation (including renaming etc) |
| // is completed. |
| void Completed(); |
| |
| // Callback invoked when the URLRequest for a download resumption has started. |
| void OnResumeRequestStarted(DownloadItem* item, net::Error error); |
| |
| // Helper routines ----------------------------------------------------------- |
| |
| // Indicate that an error has occurred on the download. |
| void Interrupt(DownloadInterruptReason reason); |
| |
| // Destroy the DownloadFile object. If |destroy_file| is true, the file is |
| // destroyed with it. Otherwise, DownloadFile::Detach() is called before |
| // object destruction to prevent file destruction. Destroying the file also |
| // resets |current_path_|. |
| void ReleaseDownloadFile(bool destroy_file); |
| |
| // Check if a download is ready for completion. The callback provided |
| // may be called at some point in the future if an external entity |
| // state has change s.t. this routine should be checked again. |
| bool IsDownloadReadyForCompletion(const base::Closure& state_change_notify); |
| |
| // Call to transition state; all state transitions should go through this. |
| // |notify_action| specifies whether or not to call UpdateObservers() after |
| // the state transition. |
| void TransitionTo(DownloadInternalState new_state, |
| ShouldUpdateObservers notify_action); |
| |
| // Set the |danger_type_| and invoke obserers if necessary. |
| void SetDangerType(DownloadDangerType danger_type); |
| |
| void SetFullPath(const base::FilePath& new_path); |
| |
| void AutoResumeIfValid(); |
| |
| void ResumeInterruptedDownload(); |
| |
| static DownloadState InternalToExternalState( |
| DownloadInternalState internal_state); |
| static DownloadInternalState ExternalToInternalState( |
| DownloadState external_state); |
| |
| // Debugging routines -------------------------------------------------------- |
| static const char* DebugDownloadStateString(DownloadInternalState state); |
| static const char* DebugResumeModeString(ResumeMode mode); |
| |
| // Will be false for save package downloads retrieved from the history. |
| // TODO(rdsmith): Replace with a generalized enum for "download source". |
| const bool is_save_package_download_; |
| |
| // The handle to the request information. Used for operations outside the |
| // download system. |
| scoped_ptr<DownloadRequestHandleInterface> request_handle_; |
| |
| uint32 download_id_; |
| |
| // Display name for the download. If this is empty, then the display name is |
| // considered to be |target_path_.BaseName()|. |
| base::FilePath display_name_; |
| |
| // Full path to the downloaded or downloading file. This is the path to the |
| // physical file, if one exists. The final target path is specified by |
| // |target_path_|. |current_path_| can be empty if the in-progress path hasn't |
| // been determined. |
| base::FilePath current_path_; |
| |
| // Target path of an in-progress download. We may be downloading to a |
| // temporary or intermediate file (specified by |current_path_|. Once the |
| // download completes, we will rename the file to |target_path_|. |
| base::FilePath target_path_; |
| |
| // Whether the target should be overwritten, uniquified or prompted for. |
| TargetDisposition target_disposition_; |
| |
| // The chain of redirects that leading up to and including the final URL. |
| std::vector<GURL> url_chain_; |
| |
| // The URL of the page that initiated the download. |
| GURL referrer_url_; |
| |
| // Filename suggestion from DownloadSaveInfo. It could, among others, be the |
| // suggested filename in 'download' attribute of an anchor. Details: |
| // http://www.whatwg.org/specs/web-apps/current-work/#downloading-hyperlinks |
| std::string suggested_filename_; |
| |
| // If non-empty, contains an externally supplied path that should be used as |
| // the target path. |
| base::FilePath forced_file_path_; |
| |
| // Page transition that triggerred the download. |
| PageTransition transition_type_; |
| |
| // Whether the download was triggered with a user gesture. |
| bool has_user_gesture_; |
| |
| // Information from the request. |
| // Content-disposition field from the header. |
| std::string content_disposition_; |
| |
| // Mime-type from the header. Subject to change. |
| std::string mime_type_; |
| |
| // The value of the content type header sent with the downloaded item. It |
| // may be different from |mime_type_|, which may be set based on heuristics |
| // which may look at the file extension and first few bytes of the file. |
| std::string original_mime_type_; |
| |
| // The remote IP address where the download was fetched from. Copied from |
| // DownloadCreateInfo::remote_address. |
| std::string remote_address_; |
| |
| // Total bytes expected. |
| int64 total_bytes_; |
| |
| // Current received bytes. |
| int64 received_bytes_; |
| |
| // Current speed. Calculated by the DownloadFile. |
| int64 bytes_per_sec_; |
| |
| // Sha256 hash of the content. This might be empty either because |
| // the download isn't done yet or because the hash isn't needed |
| // (ChromeDownloadManagerDelegate::GenerateFileHash() returned false). |
| std::string hash_; |
| |
| // A blob containing the state of the hash algorithm. Only valid while the |
| // download is in progress. |
| std::string hash_state_; |
| |
| // Server's time stamp for the file. |
| std::string last_modified_time_; |
| |
| // Server's ETAG for the file. |
| std::string etag_; |
| |
| // Last reason. |
| DownloadInterruptReason last_reason_; |
| |
| // Start time for recording statistics. |
| base::TimeTicks start_tick_; |
| |
| // The current state of this download. |
| DownloadInternalState state_; |
| |
| // Current danger type for the download. |
| DownloadDangerType danger_type_; |
| |
| // The views of this item in the download shelf and download contents. |
| ObserverList<Observer> observers_; |
| |
| // Time the download was started. |
| base::Time start_time_; |
| |
| // Time the download completed. |
| base::Time end_time_; |
| |
| // Our delegate. |
| DownloadItemImplDelegate* delegate_; |
| |
| // In progress downloads may be paused by the user, we note it here. |
| bool is_paused_; |
| |
| // The number of times this download has been resumed automatically. |
| int auto_resume_count_; |
| |
| // A flag for indicating if the download should be opened at completion. |
| bool open_when_complete_; |
| |
| // A flag for indicating if the downloaded file is externally removed. |
| bool file_externally_removed_; |
| |
| // True if the download was auto-opened. We set this rather than using |
| // an observer as it's frequently possible for the download to be auto opened |
| // before the observer is added. |
| bool auto_opened_; |
| |
| // True if the item was downloaded temporarily. |
| bool is_temporary_; |
| |
| // True if we've saved all the data for the download. |
| bool all_data_saved_; |
| |
| // Error return from DestinationError. Stored separately from |
| // last_reason_ so that we can avoid handling destination errors until |
| // after file name determination has occurred. |
| DownloadInterruptReason destination_error_; |
| |
| // Did the user open the item either directly or indirectly (such as by |
| // setting always open files of this type)? The shelf also sets this field |
| // when the user closes the shelf before the item has been opened but should |
| // be treated as though the user opened it. |
| bool opened_; |
| |
| // Did the delegate delay calling Complete on this download? |
| bool delegate_delayed_complete_; |
| |
| // DownloadFile associated with this download. Note that this |
| // pointer may only be used or destroyed on the FILE thread. |
| // This pointer will be non-null only while the DownloadItem is in |
| // the IN_PROGRESS state. |
| scoped_ptr<DownloadFile> download_file_; |
| |
| // Net log to use for this download. |
| const net::BoundNetLog bound_net_log_; |
| |
| base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DownloadItemImpl); |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_IMPL_H_ |