[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 5 | // File method ordering: Methods in this file are in the same order as |
| 6 | // in download_item_impl.h, with the following exception: The public |
[email protected] | 513b7e3 | 2012-11-30 21:02:37 | [diff] [blame] | 7 | // interface Start is placed in chronological order with the other |
| 8 | // (private) routines that together define a DownloadItem's state |
| 9 | // transitions as the download progresses. See "Download progression |
| 10 | // cascade" later in this file. |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 11 | |
| 12 | // A regular DownloadItem (created for a download in this session of the |
| 13 | // browser) normally goes through the following states: |
| 14 | // * Created (when download starts) |
| 15 | // * Destination filename determined |
| 16 | // * Entered into the history database. |
| 17 | // * Made visible in the download shelf. |
| 18 | // * All the data is saved. Note that the actual data download occurs |
| 19 | // in parallel with the above steps, but until those steps are |
| 20 | // complete, the state of the data save will be ignored. |
| 21 | // * Download file is renamed to its final name, and possibly |
| 22 | // auto-opened. |
| 23 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 24 | #include "content/browser/download/download_item_impl.h" |
| 25 | |
| 26 | #include <vector> |
| 27 | |
| 28 | #include "base/basictypes.h" |
| 29 | #include "base/bind.h" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 30 | #include "base/command_line.h" |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 31 | #include "base/file_util.h" |
| 32 | #include "base/format_macros.h" |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 33 | #include "base/logging.h" |
| 34 | #include "base/metrics/histogram.h" |
[email protected] | 5bcef5c7 | 2011-12-07 23:03:24 | [diff] [blame] | 35 | #include "base/stl_util.h" |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 36 | #include "base/stringprintf.h" |
| 37 | #include "base/utf_string_conversions.h" |
| 38 | #include "content/browser/download/download_create_info.h" |
[email protected] | f363dae | 2012-01-31 06:08:23 | [diff] [blame] | 39 | #include "content/browser/download/download_file.h" |
[email protected] | bf3b08a | 2012-03-08 01:52:34 | [diff] [blame] | 40 | #include "content/browser/download/download_interrupt_reasons_impl.h" |
[email protected] | db1d8f7 | 2012-07-13 19:23:16 | [diff] [blame] | 41 | #include "content/browser/download/download_item_impl_delegate.h" |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 42 | #include "content/browser/download/download_request_handle.h" |
| 43 | #include "content/browser/download/download_stats.h" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 44 | #include "content/browser/renderer_host/render_view_host_impl.h" |
[email protected] | 93ddb3c | 2012-04-11 21:44:29 | [diff] [blame] | 45 | #include "content/browser/web_contents/web_contents_impl.h" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 46 | #include "content/public/browser/browser_context.h" |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 47 | #include "content/public/browser/browser_thread.h" |
| 48 | #include "content/public/browser/content_browser_client.h" |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 49 | #include "content/public/browser/download_danger_type.h" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 50 | #include "content/public/browser/download_interrupt_reasons.h" |
| 51 | #include "content/public/browser/download_url_parameters.h" |
| 52 | #include "content/public/common/content_switches.h" |
| 53 | #include "content/public/common/referrer.h" |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 54 | #include "net/base/net_util.h" |
| 55 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 56 | namespace content { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 57 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 58 | namespace { |
| 59 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 60 | void DeleteDownloadedFile(const FilePath& path) { |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 61 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 62 | |
| 63 | // Make sure we only delete files. |
| 64 | if (!file_util::DirectoryExists(path)) |
| 65 | file_util::Delete(path, false); |
| 66 | } |
| 67 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 68 | // Classes to null out request handle calls (for SavePage DownloadItems, which |
| 69 | // may have, e.g., Cancel() called on them without it doing anything) |
| 70 | // and to DCHECK on them (for history DownloadItems, which should never have |
| 71 | // any operation that implies an off-thread component, since they don't |
| 72 | // have any). |
| 73 | class NullDownloadRequestHandle : public DownloadRequestHandleInterface { |
| 74 | public: |
| 75 | NullDownloadRequestHandle() {} |
| 76 | |
| 77 | // DownloadRequestHandleInterface calls |
[email protected] | b172aee | 2012-04-10 17:05:26 | [diff] [blame] | 78 | virtual WebContents* GetWebContents() const OVERRIDE { |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 79 | return NULL; |
| 80 | } |
| 81 | virtual DownloadManager* GetDownloadManager() const OVERRIDE { |
| 82 | return NULL; |
| 83 | } |
| 84 | virtual void PauseRequest() const OVERRIDE {} |
| 85 | virtual void ResumeRequest() const OVERRIDE {} |
| 86 | virtual void CancelRequest() const OVERRIDE {} |
| 87 | virtual std::string DebugString() const OVERRIDE { |
| 88 | return "Null DownloadRequestHandle"; |
| 89 | } |
| 90 | }; |
| 91 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 92 | // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that |
| 93 | // takes ownership of the DownloadFile and hence implicitly destroys it |
| 94 | // at the end of the function. |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 95 | static void DownloadFileDetach(scoped_ptr<DownloadFile> download_file) { |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 96 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 97 | download_file->Detach(); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) { |
| 101 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 102 | download_file->Cancel(); |
| 103 | } |
| 104 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 105 | } // namespace |
| 106 | |
[email protected] | e582fdd | 2011-12-20 16:48:17 | [diff] [blame] | 107 | const char DownloadItem::kEmptyFileHash[] = ""; |
| 108 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 109 | // The maximum number of attempts we will make to resume automatically. |
| 110 | const int DownloadItemImpl::kMaxAutoResumeAttempts = 5; |
| 111 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 112 | // Constructor for reading from the history service. |
[email protected] | db1d8f7 | 2012-07-13 19:23:16 | [diff] [blame] | 113 | DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 114 | DownloadId download_id, |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 115 | const FilePath& path, |
| 116 | const GURL& url, |
| 117 | const GURL& referrer_url, |
| 118 | const base::Time& start_time, |
| 119 | const base::Time& end_time, |
| 120 | int64 received_bytes, |
| 121 | int64 total_bytes, |
| 122 | DownloadItem::DownloadState state, |
| 123 | bool opened, |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 124 | const net::BoundNetLog& bound_net_log) |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 125 | : is_save_package_download_(false), |
| 126 | download_id_(download_id), |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 127 | current_path_(path), |
| 128 | target_path_(path), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 129 | target_disposition_(TARGET_DISPOSITION_OVERWRITE), |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 130 | url_chain_(1, url), |
| 131 | referrer_url_(referrer_url), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 132 | transition_type_(PAGE_TRANSITION_LINK), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 133 | has_user_gesture_(false), |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 134 | total_bytes_(total_bytes), |
| 135 | received_bytes_(received_bytes), |
[email protected] | e384fd8 | 2011-11-30 06:37:20 | [diff] [blame] | 136 | bytes_per_sec_(0), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 137 | last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 138 | start_tick_(base::TimeTicks()), |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 139 | state_(ExternalToInternalState(state)), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 140 | danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 141 | start_time_(start_time), |
| 142 | end_time_(end_time), |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 143 | delegate_(delegate), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 144 | is_paused_(false), |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 145 | auto_resume_count_(0), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 146 | open_when_complete_(false), |
| 147 | file_externally_removed_(false), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 148 | auto_opened_(false), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 149 | is_temporary_(false), |
| 150 | all_data_saved_(false), |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 151 | opened_(opened), |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 152 | delegate_delayed_complete_(false), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 153 | bound_net_log_(bound_net_log), |
| 154 | ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 155 | delegate_->Attach(); |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 156 | if (state_ == IN_PROGRESS_INTERNAL) |
| 157 | state_ = CANCELLED_INTERNAL; |
| 158 | if (state_ == COMPLETE_INTERNAL) |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 159 | all_data_saved_ = true; |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 160 | Init(false /* not actively downloading */, SRC_HISTORY_IMPORT); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | // Constructing for a regular download: |
| 164 | DownloadItemImpl::DownloadItemImpl( |
[email protected] | db1d8f7 | 2012-07-13 19:23:16 | [diff] [blame] | 165 | DownloadItemImplDelegate* delegate, |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 166 | const DownloadCreateInfo& info, |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 167 | const net::BoundNetLog& bound_net_log) |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 168 | : is_save_package_download_(false), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 169 | download_id_(info.download_id), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 170 | target_disposition_( |
[email protected] | 3a2b2b5c | 2012-11-01 23:55:30 | [diff] [blame] | 171 | (info.save_info->prompt_for_save_location) ? |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 172 | TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 173 | url_chain_(info.url_chain), |
| 174 | referrer_url_(info.referrer_url), |
[email protected] | c873c86 | 2012-10-17 15:32:12 | [diff] [blame] | 175 | suggested_filename_(UTF16ToUTF8(info.save_info->suggested_name)), |
| 176 | forced_file_path_(info.save_info->file_path), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 177 | transition_type_(info.transition_type), |
| 178 | has_user_gesture_(info.has_user_gesture), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 179 | content_disposition_(info.content_disposition), |
| 180 | mime_type_(info.mime_type), |
| 181 | original_mime_type_(info.original_mime_type), |
[email protected] | 28aa2ed | 2011-12-06 06:27:38 | [diff] [blame] | 182 | remote_address_(info.remote_address), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 183 | total_bytes_(info.total_bytes), |
| 184 | received_bytes_(0), |
[email protected] | e384fd8 | 2011-11-30 06:37:20 | [diff] [blame] | 185 | bytes_per_sec_(0), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 186 | last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 187 | start_tick_(base::TimeTicks::Now()), |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 188 | state_(IN_PROGRESS_INTERNAL), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 189 | danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 190 | start_time_(info.start_time), |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 191 | delegate_(delegate), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 192 | is_paused_(false), |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 193 | auto_resume_count_(0), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 194 | open_when_complete_(false), |
| 195 | file_externally_removed_(false), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 196 | auto_opened_(false), |
[email protected] | c873c86 | 2012-10-17 15:32:12 | [diff] [blame] | 197 | is_temporary_(!info.save_info->file_path.empty()), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 198 | all_data_saved_(false), |
| 199 | opened_(false), |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 200 | delegate_delayed_complete_(false), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 201 | bound_net_log_(bound_net_log), |
| 202 | ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 203 | delegate_->Attach(); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 204 | Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); |
[email protected] | ef17c9a | 2012-02-09 05:08:09 | [diff] [blame] | 205 | |
| 206 | // Link the event sources. |
| 207 | bound_net_log_.AddEvent( |
| 208 | net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, |
[email protected] | 2fa0891 | 2012-06-14 20:56:26 | [diff] [blame] | 209 | info.request_bound_net_log.source().ToEventParametersCallback()); |
[email protected] | ef17c9a | 2012-02-09 05:08:09 | [diff] [blame] | 210 | |
| 211 | info.request_bound_net_log.AddEvent( |
| 212 | net::NetLog::TYPE_DOWNLOAD_STARTED, |
[email protected] | 2fa0891 | 2012-06-14 20:56:26 | [diff] [blame] | 213 | bound_net_log_.source().ToEventParametersCallback()); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 214 | } |
| 215 | |
| 216 | // Constructing for the "Save Page As..." feature: |
[email protected] | db1d8f7 | 2012-07-13 19:23:16 | [diff] [blame] | 217 | DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 218 | const FilePath& path, |
| 219 | const GURL& url, |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 220 | DownloadId download_id, |
[email protected] | 6474b11 | 2012-05-04 19:35:27 | [diff] [blame] | 221 | const std::string& mime_type, |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 222 | const net::BoundNetLog& bound_net_log) |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 223 | : is_save_package_download_(true), |
| 224 | request_handle_(new NullDownloadRequestHandle()), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 225 | download_id_(download_id), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 226 | current_path_(path), |
| 227 | target_path_(path), |
| 228 | target_disposition_(TARGET_DISPOSITION_OVERWRITE), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 229 | url_chain_(1, url), |
| 230 | referrer_url_(GURL()), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 231 | transition_type_(PAGE_TRANSITION_LINK), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 232 | has_user_gesture_(false), |
[email protected] | 6474b11 | 2012-05-04 19:35:27 | [diff] [blame] | 233 | mime_type_(mime_type), |
| 234 | original_mime_type_(mime_type), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 235 | total_bytes_(0), |
| 236 | received_bytes_(0), |
[email protected] | e384fd8 | 2011-11-30 06:37:20 | [diff] [blame] | 237 | bytes_per_sec_(0), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 238 | last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 239 | start_tick_(base::TimeTicks::Now()), |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 240 | state_(IN_PROGRESS_INTERNAL), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 241 | danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 242 | start_time_(base::Time::Now()), |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 243 | delegate_(delegate), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 244 | is_paused_(false), |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 245 | auto_resume_count_(0), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 246 | open_when_complete_(false), |
| 247 | file_externally_removed_(false), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 248 | auto_opened_(false), |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 249 | is_temporary_(false), |
| 250 | all_data_saved_(false), |
| 251 | opened_(false), |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 252 | delegate_delayed_complete_(false), |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 253 | bound_net_log_(bound_net_log), |
| 254 | ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 255 | delegate_->Attach(); |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 256 | Init(true /* actively downloading */, SRC_SAVE_PAGE_AS); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | DownloadItemImpl::~DownloadItemImpl() { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 260 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 261 | |
| 262 | // Should always have been nuked before now, at worst in |
| 263 | // DownloadManager shutdown. |
| 264 | DCHECK(!download_file_.get()); |
| 265 | |
[email protected] | 7e834f0 | 2012-08-09 20:38:56 | [diff] [blame] | 266 | FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this)); |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 267 | delegate_->AssertStateConsistent(this); |
| 268 | delegate_->Detach(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 269 | } |
| 270 | |
| 271 | void DownloadItemImpl::AddObserver(Observer* observer) { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 272 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 273 | |
| 274 | observers_.AddObserver(observer); |
| 275 | } |
| 276 | |
| 277 | void DownloadItemImpl::RemoveObserver(Observer* observer) { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 278 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 279 | |
| 280 | observers_.RemoveObserver(observer); |
| 281 | } |
| 282 | |
| 283 | void DownloadItemImpl::UpdateObservers() { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 284 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 285 | |
| 286 | FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this)); |
| 287 | } |
| 288 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 289 | void DownloadItemImpl::DangerousDownloadValidated() { |
| 290 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | db6234e | 2012-09-25 17:23:01 | [diff] [blame] | 291 | DCHECK_EQ(IN_PROGRESS, GetState()); |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 292 | DCHECK(IsDangerous()); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 293 | |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 294 | VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
| 295 | |
[email protected] | db6234e | 2012-09-25 17:23:01 | [diff] [blame] | 296 | if (GetState() != IN_PROGRESS) |
| 297 | return; |
| 298 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 299 | UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated", |
| 300 | GetDangerType(), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 301 | DOWNLOAD_DANGER_TYPE_MAX); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 302 | |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 303 | danger_type_ = DOWNLOAD_DANGER_TYPE_USER_VALIDATED; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 304 | |
| 305 | bound_net_log_.AddEvent( |
| 306 | net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 307 | base::Bind(&ItemCheckedNetLogCallback, GetDangerType())); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 308 | |
| 309 | UpdateObservers(); |
| 310 | |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 311 | MaybeCompleteDownload(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 312 | } |
| 313 | |
[email protected] | f9dcbcf | 2013-01-07 18:03:18 | [diff] [blame] | 314 | void DownloadItemImpl::Pause() { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 315 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 316 | |
[email protected] | f9dcbcf | 2013-01-07 18:03:18 | [diff] [blame] | 317 | // Ignore irrelevant states. |
| 318 | if (state_ != IN_PROGRESS_INTERNAL || is_paused_) |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 319 | return; |
| 320 | |
[email protected] | f9dcbcf | 2013-01-07 18:03:18 | [diff] [blame] | 321 | request_handle_->PauseRequest(); |
| 322 | is_paused_ = true; |
| 323 | UpdateObservers(); |
| 324 | } |
| 325 | |
| 326 | void DownloadItemImpl::Resume() { |
| 327 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 328 | |
| 329 | // Ignore irrelevant states. |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 330 | if (state_ == COMPLETE_INTERNAL || state_ == COMPLETING_INTERNAL || |
| 331 | !is_paused_) |
[email protected] | f9dcbcf | 2013-01-07 18:03:18 | [diff] [blame] | 332 | return; |
| 333 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 334 | if (state_ == INTERRUPTED_INTERNAL) { |
| 335 | auto_resume_count_ = 0; // User input resets the counter. |
| 336 | ResumeInterruptedDownload(); |
| 337 | return; |
| 338 | } |
| 339 | DCHECK_EQ(IN_PROGRESS_INTERNAL, state_); |
| 340 | |
[email protected] | f9dcbcf | 2013-01-07 18:03:18 | [diff] [blame] | 341 | request_handle_->ResumeRequest(); |
| 342 | is_paused_ = false; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 343 | UpdateObservers(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 344 | } |
| 345 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 346 | void DownloadItemImpl::Cancel(bool user_cancel) { |
| 347 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 348 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 349 | VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 350 | if (state_ != IN_PROGRESS_INTERNAL && state_ != INTERRUPTED_INTERNAL) { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 351 | // Small downloads might be complete before this method has |
| 352 | // a chance to run. |
| 353 | return; |
| 354 | } |
| 355 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 356 | last_reason_ = user_cancel ? |
| 357 | DOWNLOAD_INTERRUPT_REASON_USER_CANCELED : |
| 358 | DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN; |
| 359 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 360 | RecordDownloadCount(CANCELLED_COUNT); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 361 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 362 | CancelDownloadFile(); |
| 363 | |
[email protected] | b882211a | 2013-01-15 07:50:09 | [diff] [blame] | 364 | if (state_ != INTERRUPTED_INTERNAL) { |
| 365 | // Cancel the originating URL request unless it's already been cancelled |
| 366 | // by interrupt. |
| 367 | request_handle_->CancelRequest(); |
| 368 | } |
| 369 | |
| 370 | TransitionTo(CANCELLED_INTERNAL); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 371 | } |
| 372 | |
| 373 | void DownloadItemImpl::Delete(DeleteReason reason) { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 374 | VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 375 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 376 | |
| 377 | switch (reason) { |
| 378 | case DELETE_DUE_TO_USER_DISCARD: |
| 379 | UMA_HISTOGRAM_ENUMERATION( |
| 380 | "Download.UserDiscard", GetDangerType(), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 381 | DOWNLOAD_DANGER_TYPE_MAX); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 382 | break; |
| 383 | case DELETE_DUE_TO_BROWSER_SHUTDOWN: |
| 384 | UMA_HISTOGRAM_ENUMERATION( |
| 385 | "Download.Discard", GetDangerType(), |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 386 | DOWNLOAD_DANGER_TYPE_MAX); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 387 | break; |
| 388 | default: |
| 389 | NOTREACHED(); |
| 390 | } |
| 391 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 392 | // Delete the file if it exists and is not owned by a DownloadFile object. |
| 393 | // (In the latter case the DownloadFile object will delete it on cancel.) |
| 394 | if (!current_path_.empty() && download_file_.get() == NULL) { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 395 | BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 396 | base::Bind(&DeleteDownloadedFile, current_path_)); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 397 | } |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 398 | Remove(); |
| 399 | // We have now been deleted. |
| 400 | } |
| 401 | |
| 402 | void DownloadItemImpl::Remove() { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 403 | VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 404 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 405 | |
| 406 | delegate_->AssertStateConsistent(this); |
| 407 | Cancel(true); |
| 408 | delegate_->AssertStateConsistent(this); |
| 409 | |
| 410 | NotifyRemoved(); |
| 411 | delegate_->DownloadRemoved(this); |
| 412 | // We have now been deleted. |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 413 | } |
| 414 | |
| 415 | void DownloadItemImpl::OpenDownload() { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 416 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 417 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 418 | if (state_ == IN_PROGRESS_INTERNAL) { |
[email protected] | 71f5584 | 2012-03-24 04:09:02 | [diff] [blame] | 419 | // We don't honor the open_when_complete_ flag for temporary |
| 420 | // downloads. Don't set it because it shows up in the UI. |
| 421 | if (!IsTemporary()) |
| 422 | open_when_complete_ = !open_when_complete_; |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 423 | return; |
| 424 | } |
| 425 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 426 | if (state_ != COMPLETE_INTERNAL || file_externally_removed_) |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 427 | return; |
| 428 | |
| 429 | // Ideally, we want to detect errors in opening and report them, but we |
| 430 | // don't generally have the proper interface for that to the external |
| 431 | // program that opens the file. So instead we spawn a check to update |
| 432 | // the UI if the file has been deleted in parallel with the open. |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 433 | delegate_->CheckForFileRemoval(this); |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 434 | RecordOpen(GetEndTime(), !GetOpened()); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 435 | opened_ = true; |
| 436 | FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this)); |
[email protected] | ffc0c2d | 2013-01-21 15:32:12 | [diff] [blame] | 437 | delegate_->OpenDownload(this); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 438 | } |
| 439 | |
| 440 | void DownloadItemImpl::ShowDownloadInShell() { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 441 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 442 | |
[email protected] | ffc0c2d | 2013-01-21 15:32:12 | [diff] [blame] | 443 | delegate_->ShowDownloadInShell(this); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 444 | } |
| 445 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 446 | int32 DownloadItemImpl::GetId() const { |
| 447 | return download_id_.local(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 448 | } |
| 449 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 450 | DownloadId DownloadItemImpl::GetGlobalId() const { |
| 451 | return download_id_; |
| 452 | } |
| 453 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 454 | DownloadItem::DownloadState DownloadItemImpl::GetState() const { |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 455 | return InternalToExternalState(state_); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 456 | } |
| 457 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 458 | DownloadInterruptReason DownloadItemImpl::GetLastReason() const { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 459 | return last_reason_; |
| 460 | } |
| 461 | |
| 462 | bool DownloadItemImpl::IsPaused() const { |
| 463 | return is_paused_; |
| 464 | } |
| 465 | |
| 466 | bool DownloadItemImpl::IsTemporary() const { |
| 467 | return is_temporary_; |
| 468 | } |
| 469 | |
[email protected] | b882211a | 2013-01-15 07:50:09 | [diff] [blame] | 470 | // TODO(rdsmith): Figure out whether or not we want this probe routine |
| 471 | // to consider interrupted (resumably) downloads partial downloads. |
| 472 | // Conceptually the answer is probably yes, but everywhere that currently |
| 473 | // uses the routine is using it as a synonym for IsInProgress(). |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 474 | bool DownloadItemImpl::IsPartialDownload() const { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 475 | DownloadState state = InternalToExternalState(state_); |
[email protected] | b882211a | 2013-01-15 07:50:09 | [diff] [blame] | 476 | return (state == IN_PROGRESS); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 477 | } |
| 478 | |
| 479 | bool DownloadItemImpl::IsInProgress() const { |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 480 | return InternalToExternalState(state_) == IN_PROGRESS; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 481 | } |
| 482 | |
| 483 | bool DownloadItemImpl::IsCancelled() const { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 484 | return InternalToExternalState(state_) == CANCELLED; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 485 | } |
| 486 | |
| 487 | bool DownloadItemImpl::IsInterrupted() const { |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 488 | return InternalToExternalState(state_) == INTERRUPTED; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 489 | } |
| 490 | |
| 491 | bool DownloadItemImpl::IsComplete() const { |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 492 | return InternalToExternalState(state_) == COMPLETE; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 493 | } |
| 494 | |
| 495 | const GURL& DownloadItemImpl::GetURL() const { |
| 496 | return url_chain_.empty() ? |
| 497 | GURL::EmptyGURL() : url_chain_.back(); |
| 498 | } |
| 499 | |
| 500 | const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const { |
| 501 | return url_chain_; |
| 502 | } |
| 503 | |
| 504 | const GURL& DownloadItemImpl::GetOriginalUrl() const { |
| 505 | return url_chain_.front(); |
| 506 | } |
| 507 | |
| 508 | const GURL& DownloadItemImpl::GetReferrerUrl() const { |
| 509 | return referrer_url_; |
| 510 | } |
| 511 | |
| 512 | std::string DownloadItemImpl::GetSuggestedFilename() const { |
| 513 | return suggested_filename_; |
| 514 | } |
| 515 | |
| 516 | std::string DownloadItemImpl::GetContentDisposition() const { |
| 517 | return content_disposition_; |
| 518 | } |
| 519 | |
| 520 | std::string DownloadItemImpl::GetMimeType() const { |
| 521 | return mime_type_; |
| 522 | } |
| 523 | |
| 524 | std::string DownloadItemImpl::GetOriginalMimeType() const { |
| 525 | return original_mime_type_; |
| 526 | } |
| 527 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 528 | std::string DownloadItemImpl::GetRemoteAddress() const { |
| 529 | return remote_address_; |
| 530 | } |
| 531 | |
| 532 | bool DownloadItemImpl::HasUserGesture() const { |
| 533 | return has_user_gesture_; |
| 534 | }; |
| 535 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 536 | PageTransition DownloadItemImpl::GetTransitionType() const { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 537 | return transition_type_; |
| 538 | }; |
| 539 | |
| 540 | const std::string& DownloadItemImpl::GetLastModifiedTime() const { |
| 541 | return last_modified_time_; |
| 542 | } |
| 543 | |
| 544 | const std::string& DownloadItemImpl::GetETag() const { |
| 545 | return etag_; |
| 546 | } |
| 547 | |
[email protected] | fb904eb5 | 2012-11-05 18:54:55 | [diff] [blame] | 548 | bool DownloadItemImpl::IsSavePackageDownload() const { |
| 549 | return is_save_package_download_; |
| 550 | } |
| 551 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 552 | const FilePath& DownloadItemImpl::GetFullPath() const { |
| 553 | return current_path_; |
| 554 | } |
| 555 | |
| 556 | const FilePath& DownloadItemImpl::GetTargetFilePath() const { |
| 557 | return target_path_; |
| 558 | } |
| 559 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 560 | const FilePath& DownloadItemImpl::GetForcedFilePath() const { |
| 561 | // TODO(asanka): Get rid of GetForcedFilePath(). We should instead just |
| 562 | // require that clients respect GetTargetFilePath() if it is already set. |
| 563 | return forced_file_path_; |
| 564 | } |
| 565 | |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 566 | // TODO(asanka): Get rid of GetUserVerifiedFilePath(). http://crbug.com/134237. |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 567 | FilePath DownloadItemImpl::GetUserVerifiedFilePath() const { |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 568 | return (IsDangerous() || |
| 569 | danger_type_ == DOWNLOAD_DANGER_TYPE_USER_VALIDATED) ? |
| 570 | GetFullPath() : GetTargetFilePath(); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 571 | } |
| 572 | |
| 573 | FilePath DownloadItemImpl::GetFileNameToReportUser() const { |
| 574 | if (!display_name_.empty()) |
| 575 | return display_name_; |
| 576 | return target_path_.BaseName(); |
| 577 | } |
| 578 | |
| 579 | DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const { |
| 580 | return target_disposition_; |
| 581 | } |
| 582 | |
| 583 | const std::string& DownloadItemImpl::GetHash() const { |
| 584 | return hash_; |
| 585 | } |
| 586 | |
| 587 | const std::string& DownloadItemImpl::GetHashState() const { |
| 588 | return hash_state_; |
| 589 | } |
| 590 | |
| 591 | bool DownloadItemImpl::GetFileExternallyRemoved() const { |
| 592 | return file_externally_removed_; |
| 593 | } |
| 594 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 595 | bool DownloadItemImpl::IsDangerous() const { |
[email protected] | ae4a1b2 | 2013-01-08 18:45:36 | [diff] [blame] | 596 | #ifdef OS_WIN |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 597 | // TODO(noelutz): At this point only the windows views UI supports |
| 598 | // warnings based on dangerous content. |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 599 | return (danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE || |
| 600 | danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL || |
| 601 | danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT || |
| 602 | danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 603 | #else |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 604 | return (danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE || |
| 605 | danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 606 | #endif |
| 607 | } |
| 608 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 609 | DownloadDangerType DownloadItemImpl::GetDangerType() const { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 610 | return danger_type_; |
| 611 | } |
| 612 | |
| 613 | bool DownloadItemImpl::TimeRemaining(base::TimeDelta* remaining) const { |
| 614 | if (total_bytes_ <= 0) |
| 615 | return false; // We never received the content_length for this download. |
| 616 | |
| 617 | int64 speed = CurrentSpeed(); |
| 618 | if (speed == 0) |
| 619 | return false; |
| 620 | |
| 621 | *remaining = base::TimeDelta::FromSeconds( |
| 622 | (total_bytes_ - received_bytes_) / speed); |
| 623 | return true; |
| 624 | } |
| 625 | |
| 626 | int64 DownloadItemImpl::CurrentSpeed() const { |
| 627 | if (is_paused_) |
| 628 | return 0; |
| 629 | return bytes_per_sec_; |
| 630 | } |
| 631 | |
| 632 | int DownloadItemImpl::PercentComplete() const { |
| 633 | // If the delegate is delaying completion of the download, then we have no |
| 634 | // idea how long it will take. |
| 635 | if (delegate_delayed_complete_ || total_bytes_ <= 0) |
| 636 | return -1; |
| 637 | |
| 638 | return static_cast<int>(received_bytes_ * 100.0 / total_bytes_); |
| 639 | } |
| 640 | |
| 641 | bool DownloadItemImpl::AllDataSaved() const { |
| 642 | return all_data_saved_; |
| 643 | } |
| 644 | |
| 645 | int64 DownloadItemImpl::GetTotalBytes() const { |
| 646 | return total_bytes_; |
| 647 | } |
| 648 | |
| 649 | int64 DownloadItemImpl::GetReceivedBytes() const { |
| 650 | return received_bytes_; |
| 651 | } |
| 652 | |
| 653 | base::Time DownloadItemImpl::GetStartTime() const { |
| 654 | return start_time_; |
| 655 | } |
| 656 | |
| 657 | base::Time DownloadItemImpl::GetEndTime() const { |
| 658 | return end_time_; |
| 659 | } |
| 660 | |
| 661 | bool DownloadItemImpl::CanShowInFolder() { |
[email protected] | 35b176f | 2012-12-27 01:38:03 | [diff] [blame] | 662 | // A download can be shown in the folder if the downloaded file is in a known |
| 663 | // location. |
| 664 | return CanOpenDownload() && !GetFullPath().empty(); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 665 | } |
| 666 | |
| 667 | bool DownloadItemImpl::CanOpenDownload() { |
[email protected] | 35b176f | 2012-12-27 01:38:03 | [diff] [blame] | 668 | // We can open the file or mark it for opening on completion if the download |
| 669 | // is expected to complete successfully. Exclude temporary downloads, since |
| 670 | // they aren't owned by the download system. |
| 671 | return (IsInProgress() || IsComplete()) && !IsTemporary() && |
| 672 | !file_externally_removed_; |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 673 | } |
| 674 | |
| 675 | bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() { |
| 676 | return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath()); |
| 677 | } |
| 678 | |
| 679 | bool DownloadItemImpl::GetOpenWhenComplete() const { |
| 680 | return open_when_complete_; |
| 681 | } |
| 682 | |
| 683 | bool DownloadItemImpl::GetAutoOpened() { |
| 684 | return auto_opened_; |
| 685 | } |
| 686 | |
| 687 | bool DownloadItemImpl::GetOpened() const { |
| 688 | return opened_; |
| 689 | } |
| 690 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 691 | BrowserContext* DownloadItemImpl::GetBrowserContext() const { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 692 | return delegate_->GetBrowserContext(); |
| 693 | } |
| 694 | |
| 695 | WebContents* DownloadItemImpl::GetWebContents() const { |
| 696 | // TODO(rdsmith): Remove null check after removing GetWebContents() from |
| 697 | // paths that might be used by DownloadItems created from history import. |
| 698 | // Currently such items have null request_handle_s, where other items |
| 699 | // (regular and SavePackage downloads) have actual objects off the pointer. |
| 700 | if (request_handle_.get()) |
| 701 | return request_handle_->GetWebContents(); |
| 702 | return NULL; |
| 703 | } |
| 704 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 705 | void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type) { |
[email protected] | 96c3bdbaa | 2012-08-31 16:39:54 | [diff] [blame] | 706 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 707 | DCHECK(AllDataSaved()); |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 708 | VLOG(20) << __FUNCTION__ << " danger_type=" << danger_type |
| 709 | << " download=" << DebugString(true); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 710 | SetDangerType(danger_type); |
| 711 | UpdateObservers(); |
| 712 | } |
[email protected] | 96c3bdbaa | 2012-08-31 16:39:54 | [diff] [blame] | 713 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 714 | void DownloadItemImpl::SetOpenWhenComplete(bool open) { |
| 715 | open_when_complete_ = open; |
| 716 | } |
[email protected] | 96c3bdbaa | 2012-08-31 16:39:54 | [diff] [blame] | 717 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 718 | void DownloadItemImpl::SetIsTemporary(bool temporary) { |
| 719 | is_temporary_ = temporary; |
| 720 | } |
[email protected] | 96c3bdbaa | 2012-08-31 16:39:54 | [diff] [blame] | 721 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 722 | void DownloadItemImpl::SetOpened(bool opened) { |
| 723 | opened_ = opened; |
| 724 | } |
| 725 | |
| 726 | void DownloadItemImpl::SetDisplayName(const FilePath& name) { |
| 727 | display_name_ = name; |
| 728 | } |
| 729 | |
| 730 | std::string DownloadItemImpl::DebugString(bool verbose) const { |
| 731 | std::string description = |
| 732 | base::StringPrintf("{ id = %d" |
| 733 | " state = %s", |
| 734 | download_id_.local(), |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 735 | DebugDownloadStateString(state_)); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 736 | |
| 737 | // Construct a string of the URL chain. |
| 738 | std::string url_list("<none>"); |
| 739 | if (!url_chain_.empty()) { |
| 740 | std::vector<GURL>::const_iterator iter = url_chain_.begin(); |
| 741 | std::vector<GURL>::const_iterator last = url_chain_.end(); |
| 742 | url_list = (*iter).spec(); |
| 743 | ++iter; |
| 744 | for ( ; verbose && (iter != last); ++iter) { |
| 745 | url_list += " ->\n\t"; |
| 746 | const GURL& next_url = *iter; |
| 747 | url_list += next_url.spec(); |
| 748 | } |
| 749 | } |
| 750 | |
| 751 | if (verbose) { |
| 752 | description += base::StringPrintf( |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 753 | " total = %" PRId64 |
| 754 | " received = %" PRId64 |
| 755 | " reason = %s" |
| 756 | " paused = %c" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 757 | " resume_mode = %s" |
| 758 | " auto_resume_count = %d" |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 759 | " danger = %d" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 760 | " all_data_saved = %c" |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 761 | " last_modified = '%s'" |
| 762 | " etag = '%s'" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 763 | " has_download_file = %s" |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 764 | " url_chain = \n\t\"%s\"\n\t" |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 765 | " full_path = \"%" PRFilePath "\"\n\t" |
| 766 | " target_path = \"%" PRFilePath "\"", |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 767 | GetTotalBytes(), |
| 768 | GetReceivedBytes(), |
| 769 | InterruptReasonDebugString(last_reason_).c_str(), |
| 770 | IsPaused() ? 'T' : 'F', |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 771 | DebugResumeModeString(GetResumeMode()), |
| 772 | auto_resume_count_, |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 773 | GetDangerType(), |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 774 | AllDataSaved() ? 'T' : 'F', |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 775 | GetLastModifiedTime().c_str(), |
| 776 | GetETag().c_str(), |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 777 | download_file_.get() ? "true" : "false", |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 778 | url_list.c_str(), |
| 779 | GetFullPath().value().c_str(), |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 780 | GetTargetFilePath().value().c_str()); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 781 | } else { |
| 782 | description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); |
| 783 | } |
| 784 | |
| 785 | description += " }"; |
| 786 | |
| 787 | return description; |
| 788 | } |
| 789 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 790 | DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const { |
| 791 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 792 | if (!IsInterrupted()) |
| 793 | return RESUME_MODE_INVALID; |
| 794 | |
| 795 | // We can't continue without a handle on the intermediate file. |
| 796 | const bool force_restart = current_path_.empty(); |
| 797 | |
| 798 | // We won't auto-restart if we've used up our attempts or the |
| 799 | // download has been paused by user action. |
| 800 | const bool force_user = |
| 801 | (auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_); |
| 802 | |
| 803 | ResumeMode mode = RESUME_MODE_INVALID; |
| 804 | |
| 805 | switch(last_reason_) { |
| 806 | case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR: |
| 807 | case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT: |
| 808 | if (force_restart && force_user) |
| 809 | mode = RESUME_MODE_USER_RESTART; |
| 810 | else if (force_restart) |
| 811 | mode = RESUME_MODE_IMMEDIATE_RESTART; |
| 812 | else if (force_user) |
| 813 | mode = RESUME_MODE_USER_CONTINUE; |
| 814 | else |
| 815 | mode = RESUME_MODE_IMMEDIATE_CONTINUE; |
| 816 | break; |
| 817 | |
| 818 | case DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION: |
| 819 | case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE: |
| 820 | case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT: |
| 821 | if (force_user) |
| 822 | mode = RESUME_MODE_USER_RESTART; |
| 823 | else |
| 824 | mode = RESUME_MODE_IMMEDIATE_RESTART; |
| 825 | break; |
| 826 | |
| 827 | case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED: |
| 828 | case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED: |
| 829 | case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN: |
| 830 | case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED: |
| 831 | case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN: |
| 832 | case DOWNLOAD_INTERRUPT_REASON_CRASH: |
| 833 | if (force_restart) |
| 834 | mode = RESUME_MODE_USER_RESTART; |
| 835 | else |
| 836 | mode = RESUME_MODE_USER_CONTINUE; |
| 837 | break; |
| 838 | |
| 839 | case DOWNLOAD_INTERRUPT_REASON_FILE_FAILED: |
| 840 | case DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED: |
| 841 | case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE: |
| 842 | case DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG: |
| 843 | case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE: |
| 844 | mode = RESUME_MODE_USER_RESTART; |
| 845 | break; |
| 846 | |
| 847 | case DOWNLOAD_INTERRUPT_REASON_NONE: |
| 848 | case DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED: |
| 849 | case DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT: |
| 850 | case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED: |
| 851 | case DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED: |
| 852 | case DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED: |
| 853 | mode = RESUME_MODE_INVALID; |
| 854 | break; |
| 855 | } |
| 856 | |
| 857 | return mode; |
| 858 | } |
| 859 | |
| 860 | void DownloadItemImpl::ResumeInterruptedDownload() { |
| 861 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 862 | |
| 863 | // If the flag for downloads resumption isn't enabled, ignore |
| 864 | // this request. |
| 865 | const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 866 | if (!command_line.HasSwitch(switches::kEnableDownloadResumption)) |
| 867 | return; |
| 868 | |
| 869 | // Handle the case of clicking 'Resume' in the download shelf. |
| 870 | DCHECK(IsInterrupted()); |
| 871 | |
| 872 | DVLOG(20) << __FUNCTION__ << "()" << DebugString(true); |
| 873 | |
| 874 | // If we can't get a web contents, we can't resume the download. |
| 875 | // TODO(rdsmith): Find some alternative web contents to use--this |
| 876 | // means we can't restart a download if it's a download imported |
| 877 | // from the history. |
| 878 | if (!GetWebContents()) |
| 879 | return; |
| 880 | |
| 881 | // Reset the appropriate state if restarting. |
| 882 | ResumeMode mode = GetResumeMode(); |
| 883 | if (mode == RESUME_MODE_IMMEDIATE_RESTART || |
| 884 | mode == RESUME_MODE_USER_RESTART) { |
| 885 | received_bytes_ = 0; |
| 886 | hash_state_ = ""; |
| 887 | last_modified_time_ = ""; |
| 888 | etag_ = ""; |
| 889 | } |
| 890 | |
| 891 | scoped_ptr<DownloadUrlParameters> download_params( |
| 892 | DownloadUrlParameters::FromWebContents(GetWebContents(), |
| 893 | GetOriginalUrl())); |
| 894 | |
| 895 | download_params->set_file_path(GetFullPath()); |
| 896 | download_params->set_offset(GetReceivedBytes()); |
| 897 | download_params->set_hash_state(GetHashState()); |
| 898 | download_params->set_last_modified(GetLastModifiedTime()); |
| 899 | download_params->set_etag(GetETag()); |
| 900 | |
| 901 | delegate_->ResumeInterruptedDownload(download_params.Pass(), GetGlobalId()); |
| 902 | |
| 903 | // Just in case we were interrupted while paused. |
| 904 | is_paused_ = false; |
| 905 | } |
| 906 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 907 | void DownloadItemImpl::NotifyRemoved() { |
| 908 | FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); |
| 909 | } |
| 910 | |
| 911 | void DownloadItemImpl::OnDownloadedFileRemoved() { |
| 912 | file_externally_removed_ = true; |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 913 | VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 914 | UpdateObservers(); |
| 915 | } |
| 916 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 917 | base::WeakPtr<DownloadDestinationObserver> |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 918 | DownloadItemImpl::DestinationObserverAsWeakPtr() { |
| 919 | return weak_ptr_factory_.GetWeakPtr(); |
| 920 | } |
| 921 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 922 | const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const { |
| 923 | return bound_net_log_; |
| 924 | } |
| 925 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 926 | void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { |
| 927 | total_bytes_ = total_bytes; |
[email protected] | 96c3bdbaa | 2012-08-31 16:39:54 | [diff] [blame] | 928 | } |
| 929 | |
[email protected] | 16dcd30 | 2012-07-02 17:16:51 | [diff] [blame] | 930 | // Updates from the download thread may have been posted while this download |
| 931 | // was being cancelled in the UI thread, so we'll accept them unless we're |
| 932 | // complete. |
[email protected] | 443853c6 | 2011-12-22 19:22:41 | [diff] [blame] | 933 | void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, |
[email protected] | 16dcd30 | 2012-07-02 17:16:51 | [diff] [blame] | 934 | int64 bytes_per_sec, |
[email protected] | 443853c6 | 2011-12-22 19:22:41 | [diff] [blame] | 935 | const std::string& hash_state) { |
[email protected] | 16dcd30 | 2012-07-02 17:16:51 | [diff] [blame] | 936 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 937 | VLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far |
| 938 | << " per_sec=" << bytes_per_sec << " download=" << DebugString(true); |
[email protected] | 336721e | 2012-06-29 08:09:38 | [diff] [blame] | 939 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 940 | if (state_ != IN_PROGRESS_INTERNAL) { |
[email protected] | 16dcd30 | 2012-07-02 17:16:51 | [diff] [blame] | 941 | // Ignore if we're no longer in-progress. This can happen if we race a |
| 942 | // Cancel on the UI thread with an update on the FILE thread. |
| 943 | // |
| 944 | // TODO(rdsmith): Arguably we should let this go through, as this means |
| 945 | // the download really did get further than we know before it was |
| 946 | // cancelled. But the gain isn't very large, and the code is more |
| 947 | // fragile if it has to support in progress updates in a non-in-progress |
| 948 | // state. This issue should be readdressed when we revamp performance |
| 949 | // reporting. |
| 950 | return; |
| 951 | } |
| 952 | bytes_per_sec_ = bytes_per_sec; |
| 953 | hash_state_ = hash_state; |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 954 | received_bytes_ = bytes_so_far; |
| 955 | |
| 956 | // If we've received more data than we were expecting (bad server info?), |
| 957 | // revert to 'unknown size mode'. |
| 958 | if (received_bytes_ > total_bytes_) |
| 959 | total_bytes_ = 0; |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 960 | |
| 961 | if (bound_net_log_.IsLoggingAllEvents()) { |
| 962 | bound_net_log_.AddEvent( |
| 963 | net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, |
[email protected] | 2fa0891 | 2012-06-14 20:56:26 | [diff] [blame] | 964 | net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 965 | } |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 966 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 967 | UpdateObservers(); |
| 968 | } |
| 969 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 970 | void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 971 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 972 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 973 | DCHECK_EQ(IN_PROGRESS_INTERNAL, state_); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 974 | DCHECK(!all_data_saved_); |
| 975 | all_data_saved_ = true; |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 976 | VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 977 | |
| 978 | // Store final hash and null out intermediate serialized hash state. |
| 979 | hash_ = final_hash; |
| 980 | hash_state_ = ""; |
| 981 | |
[email protected] | 196e972 | 2012-03-28 05:14:04 | [diff] [blame] | 982 | UpdateObservers(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 983 | } |
| 984 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 985 | void DownloadItemImpl::MarkAsComplete() { |
| 986 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 987 | |
| 988 | DCHECK(all_data_saved_); |
| 989 | end_time_ = base::Time::Now(); |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 990 | TransitionTo(COMPLETE_INTERNAL); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 991 | } |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 992 | void DownloadItemImpl::DestinationUpdate(int64 bytes_so_far, |
| 993 | int64 bytes_per_sec, |
| 994 | const std::string& hash_state) { |
| 995 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 996 | VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 997 | |
| 998 | if (!IsInProgress()) { |
| 999 | // Ignore if we're no longer in-progress. This can happen if we race a |
| 1000 | // Cancel on the UI thread with an update on the FILE thread. |
| 1001 | // |
| 1002 | // TODO(rdsmith): Arguably we should let this go through, as this means |
| 1003 | // the download really did get further than we know before it was |
| 1004 | // cancelled. But the gain isn't very large, and the code is more |
| 1005 | // fragile if it has to support in progress updates in a non-in-progress |
| 1006 | // state. This issue should be readdressed when we revamp performance |
| 1007 | // reporting. |
| 1008 | return; |
| 1009 | } |
| 1010 | bytes_per_sec_ = bytes_per_sec; |
| 1011 | hash_state_ = hash_state; |
| 1012 | received_bytes_ = bytes_so_far; |
| 1013 | |
| 1014 | // If we've received more data than we were expecting (bad server info?), |
| 1015 | // revert to 'unknown size mode'. |
| 1016 | if (received_bytes_ > total_bytes_) |
| 1017 | total_bytes_ = 0; |
| 1018 | |
| 1019 | if (bound_net_log_.IsLoggingAllEvents()) { |
| 1020 | bound_net_log_.AddEvent( |
| 1021 | net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, |
| 1022 | net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); |
| 1023 | } |
| 1024 | |
| 1025 | UpdateObservers(); |
| 1026 | } |
| 1027 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1028 | void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) { |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1029 | // The DestinationError and Interrupt routines are being kept separate |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1030 | // to allow for a future merging of the Cancel and Interrupt routines. |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1031 | Interrupt(reason); |
| 1032 | } |
| 1033 | |
| 1034 | void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1035 | VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1036 | if (!IsInProgress()) |
| 1037 | return; |
| 1038 | OnAllDataSaved(final_hash); |
| 1039 | MaybeCompleteDownload(); |
| 1040 | } |
| 1041 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1042 | // **** Download progression cascade |
| 1043 | |
| 1044 | void DownloadItemImpl::Init(bool active, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1045 | DownloadType download_type) { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1046 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1047 | |
| 1048 | if (active) |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1049 | RecordDownloadCount(START_COUNT); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1050 | |
| 1051 | if (target_path_.empty()) |
| 1052 | target_path_ = current_path_; |
| 1053 | std::string file_name; |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1054 | if (download_type == SRC_HISTORY_IMPORT) { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1055 | // target_path_ works for History and Save As versions. |
| 1056 | file_name = target_path_.AsUTF8Unsafe(); |
| 1057 | } else { |
| 1058 | // See if it's set programmatically. |
| 1059 | file_name = forced_file_path_.AsUTF8Unsafe(); |
| 1060 | // Possibly has a 'download' attribute for the anchor. |
| 1061 | if (file_name.empty()) |
| 1062 | file_name = suggested_filename_; |
| 1063 | // From the URL file name. |
| 1064 | if (file_name.empty()) |
| 1065 | file_name = GetURL().ExtractFileName(); |
| 1066 | } |
| 1067 | |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1068 | base::Callback<base::Value*(net::NetLog::LogLevel)> active_data = base::Bind( |
| 1069 | &ItemActivatedNetLogCallback, this, download_type, &file_name); |
| 1070 | if (active) { |
| 1071 | bound_net_log_.BeginEvent( |
| 1072 | net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); |
| 1073 | } else { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1074 | bound_net_log_.AddEvent( |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1075 | net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1076 | } |
| 1077 | |
| 1078 | VLOG(20) << __FUNCTION__ << "() " << DebugString(true); |
| 1079 | } |
| 1080 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1081 | // We're starting the download. |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1082 | void DownloadItemImpl::Start( |
| 1083 | scoped_ptr<DownloadFile> file, |
| 1084 | scoped_ptr<DownloadRequestHandleInterface> req_handle) { |
| 1085 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1086 | DCHECK(!download_file_.get()); |
| 1087 | DCHECK(file.get()); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1088 | DCHECK(req_handle.get()); |
| 1089 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1090 | download_file_ = file.Pass(); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1091 | request_handle_ = req_handle.Pass(); |
| 1092 | |
| 1093 | TransitionTo(IN_PROGRESS_INTERNAL); |
| 1094 | |
| 1095 | last_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE; |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1096 | |
| 1097 | BrowserThread::PostTask( |
| 1098 | BrowserThread::FILE, FROM_HERE, |
| 1099 | base::Bind(&DownloadFile::Initialize, |
| 1100 | // Safe because we control download file lifetime. |
| 1101 | base::Unretained(download_file_.get()), |
| 1102 | base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, |
| 1103 | weak_ptr_factory_.GetWeakPtr()))); |
| 1104 | } |
| 1105 | |
| 1106 | void DownloadItemImpl::OnDownloadFileInitialized( |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1107 | DownloadInterruptReason result) { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1108 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1109 | if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1110 | Interrupt(result); |
| 1111 | // TODO(rdsmith): It makes no sense to continue along the |
| 1112 | // regular download path after we've gotten an error. But it's |
| 1113 | // the way the code has historically worked, and this allows us |
| 1114 | // to get the download persisted and observers of the download manager |
| 1115 | // notified, so tests work. When we execute all side effects of cancel |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1116 | // (including queue removal) immediately rather than waiting for |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1117 | // persistence we should replace this comment with a "return;". |
| 1118 | } |
| 1119 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1120 | // If we're resuming an interrupted download, we may already know |
| 1121 | // the download target so we can skip target name determination. |
| 1122 | if (!GetTargetFilePath().empty() && !GetFullPath().empty()) { |
| 1123 | delegate_->ShowDownloadInBrowser(this); |
| 1124 | MaybeCompleteDownload(); |
| 1125 | return; |
| 1126 | } |
| 1127 | |
| 1128 | // The target path might be set and the full path empty if we failed |
| 1129 | // the intermediate rename--re-do file name determination in this case. |
| 1130 | // TODO(rdsmith,asanka): Clean up this logic. |
| 1131 | target_path_ = FilePath(); |
| 1132 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1133 | delegate_->DetermineDownloadTarget( |
| 1134 | this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined, |
| 1135 | weak_ptr_factory_.GetWeakPtr())); |
| 1136 | } |
| 1137 | |
| 1138 | // Called by delegate_ when the download target path has been |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1139 | // determined. |
| 1140 | void DownloadItemImpl::OnDownloadTargetDetermined( |
| 1141 | const FilePath& target_path, |
| 1142 | TargetDisposition disposition, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1143 | DownloadDangerType danger_type, |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1144 | const FilePath& intermediate_path) { |
| 1145 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1146 | |
| 1147 | // If the |target_path| is empty, then we consider this download to be |
| 1148 | // canceled. |
| 1149 | if (target_path.empty()) { |
| 1150 | Cancel(true); |
| 1151 | return; |
| 1152 | } |
| 1153 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1154 | // TODO(rdsmith,asanka): We are ignoring the possibility that the download |
| 1155 | // has been interrupted at this point until we finish the intermediate |
| 1156 | // rename and set the full path. That's dangerous, because we might race |
| 1157 | // with resumption, either manual (because the interrupt is visible to the |
| 1158 | // UI) or automatic. If we keep the "ignore an error on download until file |
| 1159 | // name determination complete" semantics, we need to make sure that the |
| 1160 | // error is kept completely invisible until that point. |
| 1161 | |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1162 | VLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition |
| 1163 | << " " << danger_type << " " << DebugString(true); |
| 1164 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1165 | target_path_ = target_path; |
| 1166 | target_disposition_ = disposition; |
| 1167 | SetDangerType(danger_type); |
| 1168 | // TODO(asanka): SetDangerType() doesn't need to send a notification here. |
| 1169 | |
| 1170 | // We want the intermediate and target paths to refer to the same directory so |
| 1171 | // that they are both on the same device and subject to same |
| 1172 | // space/permission/availability constraints. |
| 1173 | DCHECK(intermediate_path.DirName() == target_path.DirName()); |
| 1174 | |
| 1175 | // Rename to intermediate name. |
| 1176 | // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a |
| 1177 | // spurious rename when we can just rename to the final |
| 1178 | // filename. Unnecessary renames may cause bugs like |
| 1179 | // http://crbug.com/74187. |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1180 | DCHECK(!is_save_package_download_); |
[email protected] | dd7ef80 | 2012-10-25 20:59:24 | [diff] [blame] | 1181 | DCHECK(download_file_.get()); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1182 | DownloadFile::RenameCompletionCallback callback = |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1183 | base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, |
| 1184 | weak_ptr_factory_.GetWeakPtr()); |
| 1185 | BrowserThread::PostTask( |
| 1186 | BrowserThread::FILE, FROM_HERE, |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1187 | base::Bind(&DownloadFile::RenameAndUniquify, |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1188 | // Safe because we control download file lifetime. |
| 1189 | base::Unretained(download_file_.get()), |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1190 | intermediate_path, callback)); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1191 | } |
| 1192 | |
| 1193 | void DownloadItemImpl::OnDownloadRenamedToIntermediateName( |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1194 | DownloadInterruptReason reason, |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1195 | const FilePath& full_path) { |
| 1196 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1197 | VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
[email protected] | 5fb7145 | 2012-12-11 21:37:22 | [diff] [blame] | 1198 | if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1199 | Interrupt(reason); |
[email protected] | 5fb7145 | 2012-12-11 21:37:22 | [diff] [blame] | 1200 | else |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1201 | SetFullPath(full_path); |
[email protected] | 5fb7145 | 2012-12-11 21:37:22 | [diff] [blame] | 1202 | delegate_->ShowDownloadInBrowser(this); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1203 | |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1204 | MaybeCompleteDownload(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1205 | } |
| 1206 | |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1207 | // When SavePackage downloads MHTML to GData (see |
| 1208 | // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it |
| 1209 | // does for non-SavePackage downloads, but SavePackage downloads never satisfy |
| 1210 | // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls |
| 1211 | // DownloadItem::UpdateObservers() when the upload completes so that SavePackage |
| 1212 | // notices that the upload has completed and runs its normal Finish() pathway. |
| 1213 | // MaybeCompleteDownload() is never the mechanism by which SavePackage completes |
| 1214 | // downloads. SavePackage always uses its own Finish() to mark downloads |
| 1215 | // complete. |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 1216 | void DownloadItemImpl::MaybeCompleteDownload() { |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1217 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1218 | DCHECK(!is_save_package_download_); |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1219 | |
[email protected] | 9829962 | 2013-01-03 22:26:50 | [diff] [blame] | 1220 | if (!IsDownloadReadyForCompletion( |
| 1221 | base::Bind(&DownloadItemImpl::MaybeCompleteDownload, |
| 1222 | weak_ptr_factory_.GetWeakPtr()))) |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1223 | return; |
| 1224 | |
| 1225 | // TODO(rdsmith): DCHECK that we only pass through this point |
| 1226 | // once per download. The natural way to do this is by a state |
| 1227 | // transition on the DownloadItem. |
| 1228 | |
| 1229 | // Confirm we're in the proper set of states to be here; |
| 1230 | // have all data, have a history handle, (validated or safe). |
| 1231 | DCHECK_EQ(IN_PROGRESS_INTERNAL, state_); |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 1232 | DCHECK(!IsDangerous()); |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1233 | DCHECK(all_data_saved_); |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1234 | |
| 1235 | OnDownloadCompleting(); |
[email protected] | fc03de2 | 2011-12-06 23:28:12 | [diff] [blame] | 1236 | } |
| 1237 | |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1238 | // Called by MaybeCompleteDownload() when it has determined that the download |
| 1239 | // is ready for completion. |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1240 | void DownloadItemImpl::OnDownloadCompleting() { |
| 1241 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1242 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1243 | if (state_ != IN_PROGRESS_INTERNAL) |
| 1244 | return; |
| 1245 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1246 | VLOG(20) << __FUNCTION__ << "()" |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1247 | << " " << DebugString(true); |
[email protected] | e9e6b12 | 2012-09-12 19:21:45 | [diff] [blame] | 1248 | DCHECK(!GetTargetFilePath().empty()); |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 1249 | DCHECK(!IsDangerous()); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1250 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1251 | // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration. |
| 1252 | if (is_save_package_download_) { |
| 1253 | // Avoid doing anything on the file thread; there's nothing we control |
| 1254 | // there. |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1255 | // Strictly speaking, this skips giving the embedder a chance to open |
| 1256 | // the download. But on a save package download, there's no real |
| 1257 | // concept of opening. |
| 1258 | Completed(); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1259 | return; |
| 1260 | } |
| 1261 | |
[email protected] | dd7ef80 | 2012-10-25 20:59:24 | [diff] [blame] | 1262 | DCHECK(download_file_.get()); |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1263 | // Unilaterally rename; even if it already has the right name, |
| 1264 | // we need theannotation. |
| 1265 | DownloadFile::RenameCompletionCallback callback = |
| 1266 | base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, |
| 1267 | weak_ptr_factory_.GetWeakPtr()); |
| 1268 | BrowserThread::PostTask( |
| 1269 | BrowserThread::FILE, FROM_HERE, |
| 1270 | base::Bind(&DownloadFile::RenameAndAnnotate, |
| 1271 | base::Unretained(download_file_.get()), |
| 1272 | GetTargetFilePath(), callback)); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1273 | } |
| 1274 | |
| 1275 | void DownloadItemImpl::OnDownloadRenamedToFinalName( |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1276 | DownloadInterruptReason reason, |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1277 | const FilePath& full_path) { |
| 1278 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1279 | DCHECK(!is_save_package_download_); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1280 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1281 | // If a cancel or interrupt hit, we'll cancel the DownloadFile, which |
| 1282 | // will result in deleting the file on the file thread. So we don't |
| 1283 | // care about the name having been changed. |
| 1284 | if (state_ != IN_PROGRESS_INTERNAL) |
| 1285 | return; |
| 1286 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1287 | VLOG(20) << __FUNCTION__ << "()" |
| 1288 | << " full_path = \"" << full_path.value() << "\"" |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1289 | << " " << DebugString(false); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1290 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1291 | if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1292 | Interrupt(reason); |
| 1293 | return; |
| 1294 | } |
| 1295 | |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1296 | DCHECK(target_path_ == full_path); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1297 | |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1298 | if (full_path != current_path_) { |
| 1299 | // full_path is now the current and target file path. |
| 1300 | DCHECK(!full_path.empty()); |
| 1301 | SetFullPath(full_path); |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1302 | } |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1303 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1304 | // Complete the download and release the DownloadFile. |
[email protected] | dd7ef80 | 2012-10-25 20:59:24 | [diff] [blame] | 1305 | DCHECK(download_file_.get()); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1306 | BrowserThread::PostTask( |
| 1307 | BrowserThread::FILE, FROM_HERE, |
[email protected] | c7e94670 | 2012-12-18 11:55:09 | [diff] [blame] | 1308 | base::Bind(&DownloadFileDetach, base::Passed(&download_file_))); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1309 | |
| 1310 | // We're not completely done with the download item yet, but at this |
| 1311 | // point we're committed to complete the download. Cancels (or Interrupts, |
| 1312 | // though it's not clear how they could happen) after this point will be |
| 1313 | // ignored. |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1314 | TransitionTo(COMPLETING_INTERNAL); |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1315 | |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1316 | if (delegate_->ShouldOpenDownload( |
| 1317 | this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened, |
| 1318 | weak_ptr_factory_.GetWeakPtr()))) { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1319 | Completed(); |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1320 | } else { |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1321 | delegate_delayed_complete_ = true; |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1322 | } |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1323 | } |
| 1324 | |
| 1325 | void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1326 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1327 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1328 | auto_opened_ = auto_opened; |
| 1329 | Completed(); |
| 1330 | } |
| 1331 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1332 | void DownloadItemImpl::Completed() { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 1333 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1334 | |
| 1335 | VLOG(20) << __FUNCTION__ << "() " << DebugString(false); |
| 1336 | |
[email protected] | 336721e | 2012-06-29 08:09:38 | [diff] [blame] | 1337 | DCHECK(all_data_saved_); |
| 1338 | end_time_ = base::Time::Now(); |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1339 | TransitionTo(COMPLETE_INTERNAL); |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1340 | RecordDownloadCompleted(start_tick_, received_bytes_); |
[email protected] | 336721e | 2012-06-29 08:09:38 | [diff] [blame] | 1341 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1342 | if (auto_opened_) { |
| 1343 | // If it was already handled by the delegate, do nothing. |
| 1344 | } else if (GetOpenWhenComplete() || |
| 1345 | ShouldOpenFileBasedOnExtension() || |
| 1346 | IsTemporary()) { |
| 1347 | // If the download is temporary, like in drag-and-drop, do not open it but |
| 1348 | // we still need to set it auto-opened so that it can be removed from the |
| 1349 | // download shelf. |
| 1350 | if (!IsTemporary()) |
| 1351 | OpenDownload(); |
| 1352 | |
| 1353 | auto_opened_ = true; |
| 1354 | UpdateObservers(); |
| 1355 | } |
| 1356 | } |
| 1357 | |
[email protected] | 4d4c522 | 2012-09-06 19:29:22 | [diff] [blame] | 1358 | // **** End of Download progression cascade |
| 1359 | |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1360 | // An error occurred somewhere. |
| 1361 | void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1362 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1363 | |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1364 | // Somewhat counter-intuitively, it is possible for us to receive an |
| 1365 | // interrupt after we've already been interrupted. The generation of |
| 1366 | // interrupts from the file thread Renames and the generation of |
| 1367 | // interrupts from disk writes go through two different mechanisms (driven |
| 1368 | // by rename requests from UI thread and by write requests from IO thread, |
| 1369 | // respectively), and since we choose not to keep state on the File thread, |
| 1370 | // this is the place where the races collide. It's also possible for |
| 1371 | // interrupts to race with cancels. |
| 1372 | |
| 1373 | // Whatever happens, the first one to hit the UI thread wins. |
[email protected] | d682597 | 2012-11-10 01:22:52 | [diff] [blame] | 1374 | if (state_ != IN_PROGRESS_INTERNAL) |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1375 | return; |
| 1376 | |
| 1377 | last_reason_ = reason; |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1378 | |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1379 | TransitionTo(INTERRUPTED_INTERNAL); |
| 1380 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1381 | ResumeMode resume_mode = GetResumeMode(); |
| 1382 | if (resume_mode == RESUME_MODE_IMMEDIATE_RESTART || |
| 1383 | resume_mode == RESUME_MODE_USER_RESTART) { |
| 1384 | // Remove the download file; no point in leaving data around we |
| 1385 | // aren't going to use. |
| 1386 | CancelDownloadFile(); |
| 1387 | } else { |
| 1388 | // Keep the file around and maybe re-use it. |
| 1389 | BrowserThread::PostTask( |
| 1390 | BrowserThread::FILE, FROM_HERE, |
| 1391 | base::Bind(&DownloadFileDetach, base::Passed(&download_file_))); |
| 1392 | } |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1393 | |
| 1394 | // Cancel the originating URL request. |
| 1395 | request_handle_->CancelRequest(); |
| 1396 | |
| 1397 | RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1398 | AutoResumeIfValid(); |
[email protected] | bde0e4f | 2012-11-08 22:49:59 | [diff] [blame] | 1399 | } |
| 1400 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1401 | void DownloadItemImpl::CancelDownloadFile() { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1402 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1403 | |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1404 | // TODO(rdsmith/benjhayden): Remove condition as part of |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1405 | // |SavePackage| integration. |
| 1406 | // |download_file_| can be NULL if Interrupt() is called after the |
| 1407 | // download file has been released. |
[email protected] | 0e13f5c | 2012-10-29 13:24:06 | [diff] [blame] | 1408 | if (!is_save_package_download_ && download_file_.get()) { |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1409 | BrowserThread::PostTask( |
| 1410 | BrowserThread::FILE, FROM_HERE, |
| 1411 | // Will be deleted at end of task execution. |
[email protected] | c7e94670 | 2012-12-18 11:55:09 | [diff] [blame] | 1412 | base::Bind(&DownloadFileCancel, base::Passed(&download_file_))); |
[email protected] | 53ac00e8 | 2012-10-18 20:59:20 | [diff] [blame] | 1413 | } |
| 1414 | } |
| 1415 | |
[email protected] | 9829962 | 2013-01-03 22:26:50 | [diff] [blame] | 1416 | bool DownloadItemImpl::IsDownloadReadyForCompletion( |
| 1417 | const base::Closure& state_change_notification) { |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1418 | // If we don't have all the data, the download is not ready for |
| 1419 | // completion. |
| 1420 | if (!AllDataSaved()) |
| 1421 | return false; |
| 1422 | |
| 1423 | // If the download is dangerous, but not yet validated, it's not ready for |
| 1424 | // completion. |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 1425 | if (IsDangerous()) |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1426 | return false; |
| 1427 | |
| 1428 | // If the download isn't active (e.g. has been cancelled) it's not |
| 1429 | // ready for completion. |
| 1430 | if (state_ != IN_PROGRESS_INTERNAL) |
| 1431 | return false; |
| 1432 | |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1433 | // If the target filename hasn't been determined, then it's not ready for |
| 1434 | // completion. This is checked in ReadyForDownloadCompletionDone(). |
| 1435 | if (GetTargetFilePath().empty()) |
| 1436 | return false; |
| 1437 | |
| 1438 | // This is checked in NeedsRename(). Without this conditional, |
| 1439 | // browser_tests:DownloadTest.DownloadMimeType fails the DCHECK. |
| 1440 | if (target_path_.DirName() != current_path_.DirName()) |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1441 | return false; |
| 1442 | |
[email protected] | 9829962 | 2013-01-03 22:26:50 | [diff] [blame] | 1443 | // Give the delegate a chance to hold up a stop sign. It'll call |
| 1444 | // use back through the passed callback if it does and that state changes. |
| 1445 | if (!delegate_->ShouldCompleteDownload(this, state_change_notification)) |
| 1446 | return false; |
| 1447 | |
[email protected] | 18710a42a | 2012-10-17 19:50:43 | [diff] [blame] | 1448 | return true; |
| 1449 | } |
| 1450 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1451 | void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) { |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1452 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1453 | |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1454 | if (state_ == new_state) |
| 1455 | return; |
| 1456 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1457 | DownloadInternalState old_state = state_; |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1458 | state_ = new_state; |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1459 | |
| 1460 | switch (state_) { |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1461 | case COMPLETING_INTERNAL: |
| 1462 | bound_net_log_.AddEvent( |
| 1463 | net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1464 | base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_)); |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1465 | break; |
| 1466 | case COMPLETE_INTERNAL: |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1467 | bound_net_log_.AddEvent( |
| 1468 | net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1469 | base::Bind(&ItemFinishedNetLogCallback, auto_opened_)); |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1470 | break; |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1471 | case INTERRUPTED_INTERNAL: |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1472 | bound_net_log_.AddEvent( |
| 1473 | net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1474 | base::Bind(&ItemInterruptedNetLogCallback, last_reason_, |
| 1475 | received_bytes_, &hash_state_)); |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1476 | break; |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1477 | case IN_PROGRESS_INTERNAL: |
| 1478 | if (old_state == INTERRUPTED_INTERNAL) { |
| 1479 | bound_net_log_.AddEvent( |
| 1480 | net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED, |
| 1481 | base::Bind(&ItemResumingNetLogCallback, |
| 1482 | false, last_reason_, received_bytes_, &hash_state_)); |
| 1483 | } |
| 1484 | break; |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1485 | case CANCELLED_INTERNAL: |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1486 | bound_net_log_.AddEvent( |
| 1487 | net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1488 | base::Bind(&ItemCanceledNetLogCallback, received_bytes_, |
| 1489 | &hash_state_)); |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1490 | break; |
| 1491 | default: |
| 1492 | break; |
| 1493 | } |
| 1494 | |
[email protected] | 3d95e54 | 2012-11-20 00:52:08 | [diff] [blame] | 1495 | VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true) |
| 1496 | << " " << InternalToExternalState(old_state) |
| 1497 | << " " << InternalToExternalState(state_); |
[email protected] | 1138ff0 | 2012-03-14 21:14:28 | [diff] [blame] | 1498 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1499 | // Only update observers on user visible state changes. |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1500 | if (InternalToExternalState(state_) != InternalToExternalState(old_state)) |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1501 | UpdateObservers(); |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1502 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1503 | bool is_done = (state_ != IN_PROGRESS_INTERNAL && |
| 1504 | state_ != COMPLETING_INTERNAL); |
| 1505 | bool was_done = (old_state != IN_PROGRESS_INTERNAL && |
| 1506 | old_state != COMPLETING_INTERNAL); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1507 | // Termination |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1508 | if (is_done && !was_done) |
[email protected] | 2fa0891 | 2012-06-14 20:56:26 | [diff] [blame] | 1509 | bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1510 | |
| 1511 | // Resumption |
| 1512 | if (was_done && !is_done) { |
| 1513 | std::string file_name(target_path_.BaseName().AsUTF8Unsafe()); |
| 1514 | bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, |
| 1515 | base::Bind(&ItemActivatedNetLogCallback, |
| 1516 | this, SRC_ACTIVE_DOWNLOAD, |
| 1517 | &file_name)); |
| 1518 | } |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1519 | } |
| 1520 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1521 | void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) { |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 1522 | if (danger_type != danger_type_) { |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1523 | bound_net_log_.AddEvent( |
| 1524 | net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 1525 | base::Bind(&ItemCheckedNetLogCallback, danger_type)); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1526 | } |
[email protected] | cda7906 | 2013-01-17 01:50:52 | [diff] [blame] | 1527 | danger_type_ = danger_type; |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1528 | } |
| 1529 | |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 1530 | void DownloadItemImpl::SetFullPath(const FilePath& new_path) { |
[email protected] | 0634626a | 2012-05-03 19:04:26 | [diff] [blame] | 1531 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 1532 | VLOG(20) << __FUNCTION__ << "()" |
| 1533 | << " new_path = \"" << new_path.value() << "\"" |
| 1534 | << " " << DebugString(true); |
| 1535 | DCHECK(!new_path.empty()); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1536 | |
[email protected] | 3d833de | 2012-05-30 23:32:06 | [diff] [blame] | 1537 | bound_net_log_.AddEvent( |
| 1538 | net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED, |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1539 | base::Bind(&ItemRenamedNetLogCallback, ¤t_path_, &new_path)); |
[email protected] | 6313d14 | 2012-11-26 23:13:42 | [diff] [blame] | 1540 | |
| 1541 | current_path_ = new_path; |
| 1542 | UpdateObservers(); |
[email protected] | c09a8fd | 2011-11-21 19:54:50 | [diff] [blame] | 1543 | } |
| 1544 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1545 | void DownloadItemImpl::AutoResumeIfValid() { |
| 1546 | DVLOG(20) << __FUNCTION__ << "() " << DebugString(true); |
| 1547 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1548 | ResumeMode mode = GetResumeMode(); |
| 1549 | |
| 1550 | if (mode != RESUME_MODE_IMMEDIATE_RESTART && |
| 1551 | mode != RESUME_MODE_IMMEDIATE_CONTINUE) { |
| 1552 | return; |
| 1553 | } |
| 1554 | |
| 1555 | auto_resume_count_++; |
| 1556 | |
| 1557 | ResumeInterruptedDownload(); |
| 1558 | } |
| 1559 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1560 | // static |
| 1561 | DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( |
| 1562 | DownloadInternalState internal_state) { |
| 1563 | switch (internal_state) { |
| 1564 | case IN_PROGRESS_INTERNAL: |
| 1565 | return IN_PROGRESS; |
| 1566 | case COMPLETING_INTERNAL: |
| 1567 | return IN_PROGRESS; |
| 1568 | case COMPLETE_INTERNAL: |
| 1569 | return COMPLETE; |
| 1570 | case CANCELLED_INTERNAL: |
| 1571 | return CANCELLED; |
| 1572 | case INTERRUPTED_INTERNAL: |
| 1573 | return INTERRUPTED; |
| 1574 | default: |
| 1575 | NOTREACHED(); |
| 1576 | } |
| 1577 | return MAX_DOWNLOAD_STATE; |
| 1578 | } |
[email protected] | 5009b7a | 2012-02-21 18:47:03 | [diff] [blame] | 1579 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1580 | // static |
| 1581 | DownloadItemImpl::DownloadInternalState |
| 1582 | DownloadItemImpl::ExternalToInternalState( |
| 1583 | DownloadState external_state) { |
| 1584 | switch (external_state) { |
| 1585 | case IN_PROGRESS: |
| 1586 | return IN_PROGRESS_INTERNAL; |
| 1587 | case COMPLETE: |
| 1588 | return COMPLETE_INTERNAL; |
| 1589 | case CANCELLED: |
| 1590 | return CANCELLED_INTERNAL; |
| 1591 | case INTERRUPTED: |
| 1592 | return INTERRUPTED_INTERNAL; |
| 1593 | default: |
| 1594 | NOTREACHED(); |
| 1595 | } |
| 1596 | return MAX_DOWNLOAD_INTERNAL_STATE; |
| 1597 | } |
[email protected] | a6e1201 | 2012-02-08 02:24:08 | [diff] [blame] | 1598 | |
[email protected] | d0d36825 | 2012-09-24 17:13:42 | [diff] [blame] | 1599 | const char* DownloadItemImpl::DebugDownloadStateString( |
| 1600 | DownloadInternalState state) { |
| 1601 | switch (state) { |
| 1602 | case IN_PROGRESS_INTERNAL: |
| 1603 | return "IN_PROGRESS"; |
| 1604 | case COMPLETING_INTERNAL: |
| 1605 | return "COMPLETING"; |
| 1606 | case COMPLETE_INTERNAL: |
| 1607 | return "COMPLETE"; |
| 1608 | case CANCELLED_INTERNAL: |
| 1609 | return "CANCELLED"; |
| 1610 | case INTERRUPTED_INTERNAL: |
| 1611 | return "INTERRUPTED"; |
| 1612 | default: |
| 1613 | NOTREACHED() << "Unknown download state " << state; |
| 1614 | return "unknown"; |
| 1615 | }; |
| 1616 | } |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1617 | |
[email protected] | 8d68a3e0 | 2013-01-12 15:57:10 | [diff] [blame] | 1618 | const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) { |
| 1619 | switch (mode) { |
| 1620 | case RESUME_MODE_INVALID: |
| 1621 | return "INVALID"; |
| 1622 | case RESUME_MODE_IMMEDIATE_CONTINUE: |
| 1623 | return "IMMEDIATE_CONTINUE"; |
| 1624 | case RESUME_MODE_IMMEDIATE_RESTART: |
| 1625 | return "IMMEDIATE_RESTART"; |
| 1626 | case RESUME_MODE_USER_CONTINUE: |
| 1627 | return "USER_CONTINUE"; |
| 1628 | case RESUME_MODE_USER_RESTART: |
| 1629 | return "USER_RESTART"; |
| 1630 | } |
| 1631 | NOTREACHED() << "Unknown resume mode " << mode; |
| 1632 | return "unknown"; |
| 1633 | } |
| 1634 | |
[email protected] | 3586962 | 2012-10-26 23:23:55 | [diff] [blame] | 1635 | } // namespace content |