OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/download/download_item.h" | 5 #include "chrome/browser/download/download_item.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/timer.h" | 8 #include "base/timer.h" |
9 #include "chrome/browser/download/download_manager.h" | 9 #include "chrome/browser/download/download_manager.h" |
10 #include "chrome/browser/download/download_util.h" | 10 #include "chrome/browser/download/download_util.h" |
11 #include "chrome/browser/history/download_types.h" | 11 #include "chrome/browser/history/download_types.h" |
| 12 #include "chrome/common/extensions/extension.h" |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 // Update frequency (milliseconds). | 16 // Update frequency (milliseconds). |
16 const int kUpdateTimeMs = 1000; | 17 const int kUpdateTimeMs = 1000; |
17 | 18 |
18 } // namespace | 19 } // namespace |
19 | 20 |
20 // Constructor for reading from the history service. | 21 // Constructor for reading from the history service. |
21 DownloadItem::DownloadItem(const DownloadCreateInfo& info) | 22 DownloadItem::DownloadItem(DownloadManager* download_manager, |
| 23 const DownloadCreateInfo& info) |
22 : id_(-1), | 24 : id_(-1), |
23 full_path_(info.path), | 25 full_path_(info.path), |
24 url_(info.url), | 26 url_(info.url), |
25 referrer_url_(info.referrer_url), | 27 referrer_url_(info.referrer_url), |
26 mime_type_(info.mime_type), | 28 mime_type_(info.mime_type), |
27 original_mime_type_(info.original_mime_type), | 29 original_mime_type_(info.original_mime_type), |
28 total_bytes_(info.total_bytes), | 30 total_bytes_(info.total_bytes), |
29 received_bytes_(info.received_bytes), | 31 received_bytes_(info.received_bytes), |
30 start_tick_(base::TimeTicks()), | 32 start_tick_(base::TimeTicks()), |
31 state_(static_cast<DownloadState>(info.state)), | 33 state_(static_cast<DownloadState>(info.state)), |
32 start_time_(info.start_time), | 34 start_time_(info.start_time), |
33 db_handle_(info.db_handle), | 35 db_handle_(info.db_handle), |
34 manager_(NULL), | 36 download_manager_(download_manager), |
35 is_paused_(false), | 37 is_paused_(false), |
36 open_when_complete_(false), | 38 open_when_complete_(false), |
37 safety_state_(SAFE), | 39 safety_state_(SAFE), |
38 auto_opened_(false), | 40 auto_opened_(false), |
39 original_name_(info.original_name), | 41 original_name_(info.original_name), |
40 render_process_id_(-1), | 42 render_process_id_(-1), |
41 request_id_(-1), | 43 request_id_(-1), |
42 save_as_(false), | 44 save_as_(false), |
43 is_otr_(false), | 45 is_otr_(false), |
44 is_extension_install_(info.is_extension_install), | 46 is_extension_install_(info.is_extension_install), |
45 name_finalized_(false), | 47 name_finalized_(false), |
46 is_temporary_(false), | 48 is_temporary_(false), |
47 need_final_rename_(false) { | 49 need_final_rename_(false) { |
48 if (state_ == IN_PROGRESS) | 50 if (state_ == IN_PROGRESS) |
49 state_ = CANCELLED; | 51 state_ = CANCELLED; |
50 Init(false /* don't start progress timer */); | 52 Init(false /* don't start progress timer */); |
51 } | 53 } |
52 | 54 |
53 // Constructor for DownloadItem created via user action in the main thread. | 55 // Constructing for a regular download: |
54 DownloadItem::DownloadItem(int32 download_id, | 56 DownloadItem::DownloadItem(DownloadManager* download_manager, |
55 const FilePath& path, | 57 const DownloadCreateInfo& info, |
56 int path_uniquifier, | 58 bool is_otr) |
57 const GURL& url, | 59 : id_(info.download_id), |
58 const GURL& referrer_url, | 60 full_path_(info.path), |
59 const std::string& mime_type, | 61 path_uniquifier_(info.path_uniquifier), |
60 const std::string& original_mime_type, | 62 url_(info.url), |
61 const FilePath& original_name, | 63 referrer_url_(info.referrer_url), |
62 const base::Time start_time, | 64 mime_type_(info.mime_type), |
63 int64 download_size, | 65 original_mime_type_(info.original_mime_type), |
64 int render_process_id, | 66 total_bytes_(info.total_bytes), |
65 int request_id, | |
66 bool is_dangerous, | |
67 bool save_as, | |
68 bool is_otr, | |
69 bool is_extension_install, | |
70 bool is_temporary) | |
71 : id_(download_id), | |
72 full_path_(path), | |
73 path_uniquifier_(path_uniquifier), | |
74 url_(url), | |
75 referrer_url_(referrer_url), | |
76 mime_type_(mime_type), | |
77 original_mime_type_(original_mime_type), | |
78 total_bytes_(download_size), | |
79 received_bytes_(0), | 67 received_bytes_(0), |
80 start_tick_(base::TimeTicks::Now()), | 68 start_tick_(base::TimeTicks::Now()), |
81 state_(IN_PROGRESS), | 69 state_(IN_PROGRESS), |
82 start_time_(start_time), | 70 start_time_(info.start_time), |
83 db_handle_(DownloadManager::kUninitializedHandle), | 71 db_handle_(DownloadManager::kUninitializedHandle), |
84 manager_(NULL), | 72 download_manager_(download_manager), |
85 is_paused_(false), | 73 is_paused_(false), |
86 open_when_complete_(false), | 74 open_when_complete_(false), |
87 safety_state_(is_dangerous ? DANGEROUS : SAFE), | 75 safety_state_(info.is_dangerous ? DANGEROUS : SAFE), |
88 auto_opened_(false), | 76 auto_opened_(false), |
89 original_name_(original_name), | 77 original_name_(info.original_name), |
90 render_process_id_(render_process_id), | 78 render_process_id_(info.child_id), |
91 request_id_(request_id), | 79 request_id_(info.request_id), |
92 save_as_(save_as), | 80 save_as_(info.prompt_user_for_save_location), |
93 is_otr_(is_otr), | 81 is_otr_(is_otr), |
94 is_extension_install_(is_extension_install), | 82 is_extension_install_(info.is_extension_install), |
95 name_finalized_(false), | 83 name_finalized_(false), |
96 is_temporary_(is_temporary), | 84 is_temporary_(!info.save_info.file_path.empty()), |
97 need_final_rename_(false) { | 85 need_final_rename_(false) { |
98 Init(true /* start progress timer */); | 86 Init(true /* start progress timer */); |
99 } | 87 } |
100 | 88 |
101 void DownloadItem::Init(bool start_timer) { | 89 // Constructing for the "Save Page As..." feature: |
102 file_name_ = full_path_.BaseName(); | 90 DownloadItem::DownloadItem(DownloadManager* download_manager, |
103 if (start_timer) | 91 const FilePath& path, |
104 StartProgressTimer(); | 92 const GURL& url, |
| 93 bool is_otr) |
| 94 : id_(1), |
| 95 full_path_(path), |
| 96 path_uniquifier_(0), |
| 97 url_(url), |
| 98 referrer_url_(GURL()), |
| 99 mime_type_(std::string()), |
| 100 original_mime_type_(std::string()), |
| 101 total_bytes_(0), |
| 102 received_bytes_(0), |
| 103 start_tick_(base::TimeTicks::Now()), |
| 104 state_(IN_PROGRESS), |
| 105 start_time_(base::Time::Now()), |
| 106 db_handle_(DownloadManager::kUninitializedHandle), |
| 107 download_manager_(download_manager), |
| 108 is_paused_(false), |
| 109 open_when_complete_(false), |
| 110 safety_state_(SAFE), |
| 111 auto_opened_(false), |
| 112 original_name_(FilePath()), |
| 113 render_process_id_(-1), |
| 114 request_id_(-1), |
| 115 save_as_(false), |
| 116 is_otr_(is_otr), |
| 117 is_extension_install_(false), |
| 118 name_finalized_(false), |
| 119 is_temporary_(false), |
| 120 need_final_rename_(false) { |
| 121 Init(true /* start progress timer */); |
105 } | 122 } |
106 | 123 |
107 DownloadItem::~DownloadItem() { | 124 DownloadItem::~DownloadItem() { |
108 state_ = REMOVING; | 125 state_ = REMOVING; |
109 UpdateObservers(); | 126 UpdateObservers(); |
110 } | 127 } |
111 | 128 |
112 void DownloadItem::AddObserver(Observer* observer) { | 129 void DownloadItem::AddObserver(Observer* observer) { |
113 observers_.AddObserver(observer); | 130 observers_.AddObserver(observer); |
114 } | 131 } |
115 | 132 |
116 void DownloadItem::RemoveObserver(Observer* observer) { | 133 void DownloadItem::RemoveObserver(Observer* observer) { |
117 observers_.RemoveObserver(observer); | 134 observers_.RemoveObserver(observer); |
118 } | 135 } |
119 | 136 |
120 void DownloadItem::UpdateObservers() { | 137 void DownloadItem::UpdateObservers() { |
121 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this)); | 138 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this)); |
122 } | 139 } |
123 | 140 |
124 void DownloadItem::NotifyObserversDownloadFileCompleted() { | 141 void DownloadItem::NotifyObserversDownloadFileCompleted() { |
125 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadFileCompleted(this)); | 142 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadFileCompleted(this)); |
126 } | 143 } |
127 | 144 |
128 void DownloadItem::NotifyObserversDownloadOpened() { | 145 bool DownloadItem::CanOpenDownload() { |
129 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this)); | 146 FilePath file_to_use = full_path(); |
| 147 if (!original_name().value().empty()) |
| 148 file_to_use = original_name(); |
| 149 |
| 150 return !Extension::IsExtension(file_to_use) && |
| 151 !download_manager_->IsExecutableFile(file_to_use); |
130 } | 152 } |
131 | 153 |
132 // If we've received more data than we were expecting (bad server info?), revert | 154 bool DownloadItem::ShouldOpenFileBasedOnExtension() { |
133 // to 'unknown size mode'. | 155 return download_manager_->ShouldOpenFileBasedOnExtension(full_path()); |
| 156 } |
| 157 |
| 158 void DownloadItem::OpenFilesBasedOnExtension(bool open) { |
| 159 return download_manager_->OpenFilesBasedOnExtension(full_path(), open); |
| 160 } |
| 161 |
| 162 void DownloadItem::OpenDownload() { |
| 163 if (state() == DownloadItem::IN_PROGRESS) { |
| 164 open_when_complete_ = !open_when_complete_; |
| 165 } else if (state() == DownloadItem::COMPLETE) { |
| 166 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this)); |
| 167 download_manager_->OpenDownload(this, NULL); |
| 168 } |
| 169 } |
| 170 |
| 171 void DownloadItem::ShowDownloadInShell() { |
| 172 download_manager_->ShowDownloadInShell(this); |
| 173 } |
| 174 |
| 175 void DownloadItem::DangerousDownloadValidated() { |
| 176 download_manager_->DangerousDownloadValidated(this); |
| 177 } |
| 178 |
134 void DownloadItem::UpdateSize(int64 bytes_so_far) { | 179 void DownloadItem::UpdateSize(int64 bytes_so_far) { |
135 received_bytes_ = bytes_so_far; | 180 received_bytes_ = bytes_so_far; |
| 181 |
| 182 // If we've received more data than we were expecting (bad server info?), |
| 183 // revert to 'unknown size mode'. |
136 if (received_bytes_ > total_bytes_) | 184 if (received_bytes_ > total_bytes_) |
137 total_bytes_ = 0; | 185 total_bytes_ = 0; |
138 } | 186 } |
139 | 187 |
140 void DownloadItem::StartProgressTimer() { | 188 void DownloadItem::StartProgressTimer() { |
141 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateTimeMs), this, | 189 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateTimeMs), this, |
142 &DownloadItem::UpdateObservers); | 190 &DownloadItem::UpdateObservers); |
143 } | 191 } |
144 | 192 |
145 void DownloadItem::StopProgressTimer() { | 193 void DownloadItem::StopProgressTimer() { |
(...skipping 15 matching lines...) Expand all Loading... |
161 // Triggered by a user action. | 209 // Triggered by a user action. |
162 void DownloadItem::Cancel(bool update_history) { | 210 void DownloadItem::Cancel(bool update_history) { |
163 if (state_ != IN_PROGRESS) { | 211 if (state_ != IN_PROGRESS) { |
164 // Small downloads might be complete before this method has a chance to run. | 212 // Small downloads might be complete before this method has a chance to run. |
165 return; | 213 return; |
166 } | 214 } |
167 state_ = CANCELLED; | 215 state_ = CANCELLED; |
168 UpdateObservers(); | 216 UpdateObservers(); |
169 StopProgressTimer(); | 217 StopProgressTimer(); |
170 if (update_history) | 218 if (update_history) |
171 manager_->DownloadCancelled(id_); | 219 download_manager_->DownloadCancelled(id_); |
172 } | 220 } |
173 | 221 |
174 void DownloadItem::Finished(int64 size) { | 222 void DownloadItem::Finished(int64 size) { |
175 state_ = COMPLETE; | 223 state_ = COMPLETE; |
176 UpdateSize(size); | 224 UpdateSize(size); |
177 StopProgressTimer(); | 225 StopProgressTimer(); |
178 } | 226 } |
179 | 227 |
180 void DownloadItem::Remove(bool delete_on_disk) { | 228 void DownloadItem::Remove(bool delete_on_disk) { |
181 Cancel(true); | 229 Cancel(true); |
182 state_ = REMOVING; | 230 state_ = REMOVING; |
183 if (delete_on_disk) | 231 if (delete_on_disk) |
184 manager_->DeleteDownload(full_path_); | 232 download_manager_->DeleteDownload(full_path_); |
185 manager_->RemoveDownload(db_handle_); | 233 download_manager_->RemoveDownload(db_handle_); |
186 // We have now been deleted. | 234 // We have now been deleted. |
187 } | 235 } |
188 | 236 |
189 bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const { | 237 bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const { |
190 if (total_bytes_ <= 0) | 238 if (total_bytes_ <= 0) |
191 return false; // We never received the content_length for this download. | 239 return false; // We never received the content_length for this download. |
192 | 240 |
193 int64 speed = CurrentSpeed(); | 241 int64 speed = CurrentSpeed(); |
194 if (speed == 0) | 242 if (speed == 0) |
195 return false; | 243 return false; |
(...skipping 17 matching lines...) Expand all Loading... |
213 } | 261 } |
214 | 262 |
215 void DownloadItem::Rename(const FilePath& full_path) { | 263 void DownloadItem::Rename(const FilePath& full_path) { |
216 DCHECK(!full_path.empty()); | 264 DCHECK(!full_path.empty()); |
217 full_path_ = full_path; | 265 full_path_ = full_path; |
218 file_name_ = full_path_.BaseName(); | 266 file_name_ = full_path_.BaseName(); |
219 } | 267 } |
220 | 268 |
221 void DownloadItem::TogglePause() { | 269 void DownloadItem::TogglePause() { |
222 DCHECK(state_ == IN_PROGRESS); | 270 DCHECK(state_ == IN_PROGRESS); |
223 manager_->PauseDownload(id_, !is_paused_); | 271 download_manager_->PauseDownload(id_, !is_paused_); |
224 is_paused_ = !is_paused_; | 272 is_paused_ = !is_paused_; |
225 UpdateObservers(); | 273 UpdateObservers(); |
226 } | 274 } |
227 | 275 |
228 void DownloadItem::OnNameFinalized() { | 276 void DownloadItem::OnNameFinalized() { |
229 name_finalized_ = true; | 277 name_finalized_ = true; |
230 | 278 |
231 // The download file is meant to be completed if both the filename is | 279 // The download file is meant to be completed if both the filename is |
232 // finalized and the file data is downloaded. The ordering of these two | 280 // finalized and the file data is downloaded. The ordering of these two |
233 // actions is indeterministic. Thus, if we are still in downloading the | 281 // actions is indeterministic. Thus, if we are still in downloading the |
234 // file, delay the notification. | 282 // file, delay the notification. |
235 if (state() == DownloadItem::COMPLETE) | 283 if (state() == DownloadItem::COMPLETE) |
236 NotifyObserversDownloadFileCompleted(); | 284 NotifyObserversDownloadFileCompleted(); |
237 } | 285 } |
238 | 286 |
239 FilePath DownloadItem::GetFileName() const { | 287 FilePath DownloadItem::GetFileName() const { |
240 if (safety_state_ == DownloadItem::SAFE) | 288 if (safety_state_ == DownloadItem::SAFE) |
241 return file_name_; | 289 return file_name_; |
242 if (path_uniquifier_ > 0) { | 290 if (path_uniquifier_ > 0) { |
243 FilePath name(original_name_); | 291 FilePath name(original_name_); |
244 download_util::AppendNumberToPath(&name, path_uniquifier_); | 292 download_util::AppendNumberToPath(&name, path_uniquifier_); |
245 return name; | 293 return name; |
246 } | 294 } |
247 return original_name_; | 295 return original_name_; |
248 } | 296 } |
| 297 |
| 298 void DownloadItem::Init(bool start_timer) { |
| 299 file_name_ = full_path_.BaseName(); |
| 300 if (start_timer) |
| 301 StartProgressTimer(); |
| 302 } |
OLD | NEW |