Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: content/browser/download/download_item.cc

Issue 8503018: Split DownloadItem into an ABC, an Impl, and a Mock. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: merge Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/download/download_item.h ('k') | content/browser/download/download_item_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "content/browser/download/download_item.h" 5 #include "content/browser/download/download_item.h"
6 6
7 #include <vector>
8
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/file_util.h"
12 #include "base/format_macros.h"
13 #include "base/i18n/case_conversion.h"
14 #include "base/i18n/string_search.h"
15 #include "base/logging.h"
16 #include "base/metrics/histogram.h"
17 #include "base/stringprintf.h"
18 #include "base/utf_string_conversions.h"
19 #include "content/browser/download/download_create_info.h"
20 #include "content/browser/download/download_file.h"
21 #include "content/browser/download/download_file_manager.h"
22 #include "content/browser/download/download_id.h"
23 #include "content/browser/download/download_manager.h"
24 #include "content/browser/download/download_persistent_store_info.h"
25 #include "content/browser/download/download_request_handle.h"
26 #include "content/browser/download/download_stats.h"
27 #include "content/browser/download/interrupt_reasons.h"
28 #include "content/browser/tab_contents/tab_contents.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/content_browser_client.h"
31 #include "content/public/browser/download_manager_delegate.h"
32 #include "net/base/net_util.h"
33
34 using content::BrowserThread;
35
36 // A DownloadItem normally goes through the following states:
37 // * Created (when download starts)
38 // * Made visible to consumers (e.g. Javascript) after the
39 // destination file has been determined.
40 // * Entered into the history database.
41 // * Made visible in the download shelf.
42 // * All data is saved. Note that the actual data download occurs
43 // in parallel with the above steps, but until those steps are
44 // complete, completion of the data download will be ignored.
45 // * Download file is renamed to its final name, and possibly
46 // auto-opened.
47 // TODO(rdsmith): This progress should be reflected in
48 // DownloadItem::DownloadState and a state transition table/state diagram.
49 //
50 // TODO(rdsmith): This description should be updated to reflect the cancel
51 // pathways.
52
53 namespace {
54
55 static void DeleteDownloadedFile(const FilePath& path) {
56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
57
58 // Make sure we only delete files.
59 if (!file_util::DirectoryExists(path))
60 file_util::Delete(path, false);
61 }
62
63 const char* DebugSafetyStateString(DownloadItem::SafetyState state) {
64 switch (state) {
65 case DownloadItem::SAFE:
66 return "SAFE";
67 case DownloadItem::DANGEROUS:
68 return "DANGEROUS";
69 case DownloadItem::DANGEROUS_BUT_VALIDATED:
70 return "DANGEROUS_BUT_VALIDATED";
71 default:
72 NOTREACHED() << "Unknown safety state " << state;
73 return "unknown";
74 };
75 }
76
77 const char* DebugDownloadStateString(DownloadItem::DownloadState state) {
78 switch (state) {
79 case DownloadItem::IN_PROGRESS:
80 return "IN_PROGRESS";
81 case DownloadItem::COMPLETE:
82 return "COMPLETE";
83 case DownloadItem::CANCELLED:
84 return "CANCELLED";
85 case DownloadItem::REMOVING:
86 return "REMOVING";
87 case DownloadItem::INTERRUPTED:
88 return "INTERRUPTED";
89 default:
90 NOTREACHED() << "Unknown download state " << state;
91 return "unknown";
92 };
93 }
94
95 // Classes to null out request handle calls (for SavePage DownloadItems, which
96 // may have, e.g., Cancel() called on them without it doing anything)
97 // and to DCHECK on them (for history DownloadItems, which should never have
98 // any operation that implies an off-thread component, since they don't
99 // have any).
100 class NullDownloadRequestHandle : public DownloadRequestHandleInterface {
101 public:
102 NullDownloadRequestHandle() {}
103
104 // DownloadRequestHandleInterface calls
105 virtual TabContents* GetTabContents() const OVERRIDE {
106 return NULL;
107 }
108 virtual DownloadManager* GetDownloadManager() const OVERRIDE {
109 return NULL;
110 }
111 virtual void PauseRequest() const OVERRIDE {}
112 virtual void ResumeRequest() const OVERRIDE {}
113 virtual void CancelRequest() const OVERRIDE {}
114 virtual std::string DebugString() const OVERRIDE {
115 return "Null DownloadRequestHandle";
116 }
117 };
118
119
120 } // namespace
121
122 // Our download table ID starts at 1, so we use 0 to represent a download that 7 // Our download table ID starts at 1, so we use 0 to represent a download that
123 // has started, but has not yet had its data persisted in the table. We use fake 8 // has started, but has not yet had its data persisted in the table. We use fake
124 // database handles in incognito mode starting at -1 and progressively getting 9 // database handles in incognito mode starting at -1 and progressively getting
125 // more negative. 10 // more negative.
126 // static 11 // static
127 const int DownloadItem::kUninitializedHandle = 0; 12 const int DownloadItem::kUninitializedHandle = 0;
128 13
129 const char DownloadItem::kEmptyFileHash[] = ""; 14 const char DownloadItem::kEmptyFileHash[] = "";
130 15
131 // Constructor for reading from the history service. 16 DownloadItem::~DownloadItem() {
132 DownloadItem::DownloadItem(DownloadManager* download_manager,
133 const DownloadPersistentStoreInfo& info)
134 : download_id_(download_manager->GetNextId()),
135 full_path_(info.path),
136 url_chain_(1, info.url),
137 referrer_url_(info.referrer_url),
138 total_bytes_(info.total_bytes),
139 received_bytes_(info.received_bytes),
140 start_tick_(base::TimeTicks()),
141 state_(static_cast<DownloadState>(info.state)),
142 start_time_(info.start_time),
143 end_time_(info.end_time),
144 db_handle_(info.db_handle),
145 download_manager_(download_manager),
146 is_paused_(false),
147 open_when_complete_(false),
148 file_externally_removed_(false),
149 safety_state_(SAFE),
150 auto_opened_(false),
151 is_otr_(false),
152 is_temporary_(false),
153 all_data_saved_(false),
154 opened_(info.opened),
155 open_enabled_(true),
156 delegate_delayed_complete_(false) {
157 if (IsInProgress())
158 state_ = CANCELLED;
159 if (IsComplete())
160 all_data_saved_ = true;
161 Init(false /* not actively downloading */);
162 } 17 }
163
164 // Constructing for a regular download:
165 DownloadItem::DownloadItem(DownloadManager* download_manager,
166 const DownloadCreateInfo& info,
167 DownloadRequestHandleInterface* request_handle,
168 bool is_otr)
169 : state_info_(info.original_name, info.save_info.file_path,
170 info.has_user_gesture, info.transition_type,
171 info.prompt_user_for_save_location, info.path_uniquifier,
172 DownloadStateInfo::NOT_DANGEROUS),
173 request_handle_(request_handle),
174 download_id_(info.download_id),
175 full_path_(info.path),
176 url_chain_(info.url_chain),
177 referrer_url_(info.referrer_url),
178 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)),
179 content_disposition_(info.content_disposition),
180 mime_type_(info.mime_type),
181 original_mime_type_(info.original_mime_type),
182 referrer_charset_(info.referrer_charset),
183 total_bytes_(info.total_bytes),
184 received_bytes_(0),
185 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
186 start_tick_(base::TimeTicks::Now()),
187 state_(IN_PROGRESS),
188 start_time_(info.start_time),
189 db_handle_(DownloadItem::kUninitializedHandle),
190 download_manager_(download_manager),
191 is_paused_(false),
192 open_when_complete_(false),
193 file_externally_removed_(false),
194 safety_state_(SAFE),
195 auto_opened_(false),
196 is_otr_(is_otr),
197 is_temporary_(!info.save_info.file_path.empty()),
198 all_data_saved_(false),
199 opened_(false),
200 open_enabled_(true),
201 delegate_delayed_complete_(false) {
202 Init(true /* actively downloading */);
203 }
204
205 // Constructing for the "Save Page As..." feature:
206 DownloadItem::DownloadItem(DownloadManager* download_manager,
207 const FilePath& path,
208 const GURL& url,
209 bool is_otr,
210 DownloadId download_id)
211 : request_handle_(new NullDownloadRequestHandle()),
212 download_id_(download_id),
213 full_path_(path),
214 url_chain_(1, url),
215 referrer_url_(GURL()),
216 total_bytes_(0),
217 received_bytes_(0),
218 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
219 start_tick_(base::TimeTicks::Now()),
220 state_(IN_PROGRESS),
221 start_time_(base::Time::Now()),
222 db_handle_(DownloadItem::kUninitializedHandle),
223 download_manager_(download_manager),
224 is_paused_(false),
225 open_when_complete_(false),
226 file_externally_removed_(false),
227 safety_state_(SAFE),
228 auto_opened_(false),
229 is_otr_(is_otr),
230 is_temporary_(false),
231 all_data_saved_(false),
232 opened_(false),
233 open_enabled_(true),
234 delegate_delayed_complete_(false) {
235 Init(true /* actively downloading */);
236 }
237
238 DownloadItem::~DownloadItem() {
239 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
240 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241
242 TransitionTo(REMOVING);
243 download_manager_->AssertQueueStateConsistent(this);
244 }
245
246 void DownloadItem::AddObserver(Observer* observer) {
247 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
248 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
249
250 observers_.AddObserver(observer);
251 }
252
253 void DownloadItem::RemoveObserver(Observer* observer) {
254 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
255 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
256
257 observers_.RemoveObserver(observer);
258 }
259
260 void DownloadItem::UpdateObservers() {
261 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
262 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263
264 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
265 }
266
267 bool DownloadItem::CanShowInFolder() {
268 return !IsCancelled() && !file_externally_removed_;
269 }
270
271 bool DownloadItem::CanOpenDownload() {
272 return !file_externally_removed_;
273 }
274
275 bool DownloadItem::ShouldOpenFileBasedOnExtension() {
276 return download_manager_->delegate()->ShouldOpenFileBasedOnExtension(
277 GetUserVerifiedFilePath());
278 }
279
280 void DownloadItem::OpenDownload() {
281 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
282 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
283
284 if (IsPartialDownload()) {
285 open_when_complete_ = !open_when_complete_;
286 return;
287 }
288
289 if (!IsComplete() || file_externally_removed_)
290 return;
291
292 // Ideally, we want to detect errors in opening and report them, but we
293 // don't generally have the proper interface for that to the external
294 // program that opens the file. So instead we spawn a check to update
295 // the UI if the file has been deleted in parallel with the open.
296 download_manager_->CheckForFileRemoval(this);
297 download_stats::RecordOpen(end_time(), !opened());
298 opened_ = true;
299 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
300 download_manager_->MarkDownloadOpened(this);
301
302 // For testing: If download opening is disabled on this item,
303 // make the rest of the routine a no-op.
304 if (!open_enabled_)
305 return;
306
307 content::GetContentClient()->browser()->OpenItem(full_path());
308 }
309
310 void DownloadItem::ShowDownloadInShell() {
311 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
312 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313
314 content::GetContentClient()->browser()->ShowItemInFolder(full_path());
315 }
316
317 void DownloadItem::DangerousDownloadValidated() {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
319 DCHECK_EQ(DANGEROUS, safety_state());
320
321 UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated",
322 GetDangerType(),
323 DownloadStateInfo::DANGEROUS_TYPE_MAX);
324
325 safety_state_ = DANGEROUS_BUT_VALIDATED;
326 UpdateObservers();
327
328 download_manager_->MaybeCompleteDownload(this);
329 }
330
331 void DownloadItem::UpdateSize(int64 bytes_so_far) {
332 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
333 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
334
335 received_bytes_ = bytes_so_far;
336
337 // If we've received more data than we were expecting (bad server info?),
338 // revert to 'unknown size mode'.
339 if (received_bytes_ > total_bytes_)
340 total_bytes_ = 0;
341 }
342
343 // Updates from the download thread may have been posted while this download
344 // was being cancelled in the UI thread, so we'll accept them unless we're
345 // complete.
346 void DownloadItem::Update(int64 bytes_so_far) {
347 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
348 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
349
350 if (!IsInProgress()) {
351 NOTREACHED();
352 return;
353 }
354 UpdateSize(bytes_so_far);
355 UpdateObservers();
356 }
357
358 // Triggered by a user action.
359 void DownloadItem::Cancel(bool user_cancel) {
360 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
361 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
362
363 last_reason_ = user_cancel ?
364 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
365 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
366
367 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
368 if (!IsPartialDownload()) {
369 // Small downloads might be complete before this method has
370 // a chance to run.
371 return;
372 }
373
374 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
375
376 TransitionTo(CANCELLED);
377 if (user_cancel)
378 download_manager_->DownloadCancelledInternal(this);
379 }
380
381 void DownloadItem::MarkAsComplete() {
382 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
383 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
384
385 DCHECK(all_data_saved_);
386 end_time_ = base::Time::Now();
387 TransitionTo(COMPLETE);
388 }
389
390 void DownloadItem::DelayedDownloadOpened() {
391 auto_opened_ = true;
392 Completed();
393 }
394
395 void DownloadItem::OnAllDataSaved(int64 size, const std::string& final_hash) {
396 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
397 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398
399 DCHECK(!all_data_saved_);
400 all_data_saved_ = true;
401 UpdateSize(size);
402 hash_ = final_hash;
403 }
404
405 void DownloadItem::OnDownloadedFileRemoved() {
406 file_externally_removed_ = true;
407 UpdateObservers();
408 }
409
410 void DownloadItem::Completed() {
411 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
412 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
413
414 VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
415
416 DCHECK(all_data_saved_);
417 end_time_ = base::Time::Now();
418 TransitionTo(COMPLETE);
419 download_manager_->DownloadCompleted(id());
420 download_stats::RecordDownloadCompleted(start_tick_, received_bytes_);
421
422 if (auto_opened_) {
423 // If it was already handled by the delegate, do nothing.
424 } else if (open_when_complete() ||
425 ShouldOpenFileBasedOnExtension() ||
426 is_temporary()) {
427 // If the download is temporary, like in drag-and-drop, do not open it but
428 // we still need to set it auto-opened so that it can be removed from the
429 // download shelf.
430 if (!is_temporary())
431 OpenDownload();
432
433 auto_opened_ = true;
434 UpdateObservers();
435 }
436 }
437
438 void DownloadItem::TransitionTo(DownloadState new_state) {
439 if (state_ == new_state)
440 return;
441
442 state_ = new_state;
443 UpdateObservers();
444 }
445
446 void DownloadItem::UpdateSafetyState() {
447 SafetyState updated_value = state_info_.IsDangerous() ?
448 DownloadItem::DANGEROUS : DownloadItem::SAFE;
449 if (updated_value != safety_state_) {
450 safety_state_ = updated_value;
451 UpdateObservers();
452 }
453 }
454
455 void DownloadItem::UpdateTarget() {
456 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
457 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
458
459 if (state_info_.target_name.value().empty())
460 state_info_.target_name = full_path_.BaseName();
461 }
462
463 void DownloadItem::Interrupted(int64 size, InterruptReason reason) {
464 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
465 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
466
467 if (!IsInProgress())
468 return;
469
470 last_reason_ = reason;
471 UpdateSize(size);
472 download_stats::RecordDownloadInterrupted(reason,
473 received_bytes_,
474 total_bytes_);
475 TransitionTo(INTERRUPTED);
476 }
477
478 void DownloadItem::Delete(DeleteReason reason) {
479 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
480 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
481
482 switch (reason) {
483 case DELETE_DUE_TO_USER_DISCARD:
484 UMA_HISTOGRAM_ENUMERATION("Download.UserDiscard", GetDangerType(),
485 DownloadStateInfo::DANGEROUS_TYPE_MAX);
486 break;
487 case DELETE_DUE_TO_BROWSER_SHUTDOWN:
488 UMA_HISTOGRAM_ENUMERATION("Download.Discard", GetDangerType(),
489 DownloadStateInfo::DANGEROUS_TYPE_MAX);
490 break;
491 default:
492 NOTREACHED();
493 }
494
495 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
496 base::Bind(&DeleteDownloadedFile, full_path_));
497 Remove();
498 // We have now been deleted.
499 }
500
501 void DownloadItem::Remove() {
502 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
503 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
504
505 download_manager_->AssertQueueStateConsistent(this);
506 Cancel(true);
507 download_manager_->AssertQueueStateConsistent(this);
508
509 TransitionTo(REMOVING);
510 download_manager_->RemoveDownload(db_handle_);
511 // We have now been deleted.
512 }
513
514 bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const {
515 if (total_bytes_ <= 0)
516 return false; // We never received the content_length for this download.
517
518 int64 speed = CurrentSpeed();
519 if (speed == 0)
520 return false;
521
522 *remaining = base::TimeDelta::FromSeconds(
523 (total_bytes_ - received_bytes_) / speed);
524 return true;
525 }
526
527 int64 DownloadItem::CurrentSpeed() const {
528 if (is_paused_)
529 return 0;
530 base::TimeDelta diff = base::TimeTicks::Now() - start_tick_;
531 int64 diff_ms = diff.InMilliseconds();
532 return diff_ms == 0 ? 0 : received_bytes_ * 1000 / diff_ms;
533 }
534
535 int DownloadItem::PercentComplete() const {
536 // If the delegate is delaying completion of the download, then we have no
537 // idea how long it will take.
538 if (delegate_delayed_complete_ || total_bytes_ <= 0)
539 return -1;
540
541 return static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
542 }
543
544 void DownloadItem::OnPathDetermined(const FilePath& path) {
545 full_path_ = path;
546 UpdateTarget();
547 }
548
549 void DownloadItem::Rename(const FilePath& full_path) {
550 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
551 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
552
553 VLOG(20) << __FUNCTION__ << "()"
554 << " full_path = \"" << full_path.value() << "\""
555 << " " << DebugString(true);
556 DCHECK(!full_path.empty());
557 full_path_ = full_path;
558 }
559
560 void DownloadItem::TogglePause() {
561 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
562 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
563
564 DCHECK(IsInProgress());
565 if (is_paused_)
566 request_handle_->ResumeRequest();
567 else
568 request_handle_->PauseRequest();
569 is_paused_ = !is_paused_;
570 UpdateObservers();
571 }
572
573 void DownloadItem::OnDownloadCompleting(DownloadFileManager* file_manager) {
574 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
575 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
576
577 VLOG(20) << __FUNCTION__ << "()"
578 << " needs rename = " << NeedsRename()
579 << " " << DebugString(true);
580 DCHECK_NE(DANGEROUS, safety_state());
581 DCHECK(file_manager);
582
583 if (NeedsRename()) {
584 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
585 base::Bind(&DownloadFileManager::RenameCompletingDownloadFile,
586 file_manager, global_id(),
587 GetTargetFilePath(), safety_state() == SAFE));
588 return;
589 }
590
591 Completed();
592
593 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
594 base::Bind(&DownloadFileManager::CompleteDownload,
595 file_manager, global_id()));
596 }
597
598 void DownloadItem::OnDownloadRenamedToFinalName(const FilePath& full_path) {
599 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
600 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
601
602 VLOG(20) << __FUNCTION__ << "()"
603 << " full_path = \"" << full_path.value() << "\""
604 << " needed rename = " << NeedsRename()
605 << " " << DebugString(false);
606 DCHECK(NeedsRename());
607
608 Rename(full_path);
609
610 if (download_manager_->delegate()->ShouldOpenDownload(this)) {
611 Completed();
612 } else {
613 delegate_delayed_complete_ = true;
614 }
615 }
616
617 bool DownloadItem::MatchesQuery(const string16& query) const {
618 if (query.empty())
619 return true;
620
621 DCHECK_EQ(query, base::i18n::ToLower(query));
622
623 string16 url_raw(UTF8ToUTF16(GetURL().spec()));
624 if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_raw))
625 return true;
626
627 // TODO(phajdan.jr): write a test case for the following code.
628 // A good test case would be:
629 // "/\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd",
630 // L"/\x4f60\x597d\x4f60\x597d",
631 // "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD"
632 std::string languages;
633 TabContents* tab = GetTabContents();
634 if (tab) {
635 languages = content::GetContentClient()->browser()->GetAcceptLangs(
636 tab->browser_context());
637 }
638 string16 url_formatted(net::FormatUrl(GetURL(), languages));
639 if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_formatted))
640 return true;
641
642 string16 path(full_path().LossyDisplayName());
643 return base::i18n::StringSearchIgnoringCaseAndAccents(query, path);
644 }
645
646 void DownloadItem::SetFileCheckResults(const DownloadStateInfo& state) {
647 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
648 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
649
650 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
651 state_info_ = state;
652 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
653
654 UpdateSafetyState();
655 }
656
657 DownloadStateInfo::DangerType DownloadItem::GetDangerType() const {
658 return state_info_.danger;
659 }
660
661 bool DownloadItem::IsDangerous() const {
662 return state_info_.IsDangerous();
663 }
664
665 void DownloadItem::MarkFileDangerous() {
666 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
667 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
668 state_info_.danger = DownloadStateInfo::DANGEROUS_FILE;
669 UpdateSafetyState();
670 }
671
672 void DownloadItem::MarkUrlDangerous() {
673 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
674 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
675 state_info_.danger = DownloadStateInfo::DANGEROUS_URL;
676 UpdateSafetyState();
677 }
678
679 void DownloadItem::MarkContentDangerous() {
680 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
681 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
682 state_info_.danger = DownloadStateInfo::DANGEROUS_CONTENT;
683 UpdateSafetyState();
684 }
685
686 DownloadPersistentStoreInfo DownloadItem::GetPersistentStoreInfo() const {
687 return DownloadPersistentStoreInfo(full_path(),
688 GetURL(),
689 referrer_url(),
690 start_time(),
691 end_time(),
692 received_bytes(),
693 total_bytes(),
694 state(),
695 db_handle(),
696 opened());
697 }
698
699 TabContents* DownloadItem::GetTabContents() const {
700 // TODO(rdsmith): Remove null check after removing GetTabContents() from
701 // paths that might be used by DownloadItems created from history import.
702 // Currently such items have null request_handle_s, where other items
703 // (regular and SavePackage downloads) have actual objects off the pointer.
704 if (request_handle_.get())
705 return request_handle_->GetTabContents();
706 return NULL;
707 }
708
709 FilePath DownloadItem::GetTargetFilePath() const {
710 return full_path_.DirName().Append(state_info_.target_name);
711 }
712
713 FilePath DownloadItem::GetFileNameToReportUser() const {
714 if (state_info_.path_uniquifier > 0) {
715 FilePath name(state_info_.target_name);
716 DownloadFile::AppendNumberToPath(&name, state_info_.path_uniquifier);
717 return name;
718 }
719 return state_info_.target_name;
720 }
721
722 FilePath DownloadItem::GetUserVerifiedFilePath() const {
723 return (safety_state_ == DownloadItem::SAFE) ?
724 GetTargetFilePath() : full_path_;
725 }
726
727 void DownloadItem::OffThreadCancel(DownloadFileManager* file_manager) {
728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
729 request_handle_->CancelRequest();
730
731 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
732 base::Bind(&DownloadFileManager::CancelDownload,
733 file_manager, global_id()));
734 }
735
736 void DownloadItem::Init(bool active) {
737 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
738 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
739
740 UpdateTarget();
741 if (active) {
742 download_stats::RecordDownloadCount(download_stats::START_COUNT);
743 }
744 VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
745 }
746
747 // TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
748 // |IsPartialDownload()|, when resuming interrupted downloads is implemented.
749 bool DownloadItem::IsPartialDownload() const {
750 return (state_ == IN_PROGRESS);
751 }
752
753 bool DownloadItem::IsInProgress() const {
754 return (state_ == IN_PROGRESS);
755 }
756
757 bool DownloadItem::IsCancelled() const {
758 return (state_ == CANCELLED) ||
759 (state_ == INTERRUPTED);
760 }
761
762 bool DownloadItem::IsInterrupted() const {
763 return (state_ == INTERRUPTED);
764 }
765
766 bool DownloadItem::IsComplete() const {
767 return (state_ == COMPLETE);
768 }
769
770 const GURL& DownloadItem::GetURL() const {
771 return url_chain_.empty() ?
772 GURL::EmptyGURL() : url_chain_.back();
773 }
774
775 std::string DownloadItem::DebugString(bool verbose) const {
776 std::string description =
777 base::StringPrintf("{ id = %d"
778 " state = %s",
779 download_id_.local(),
780 DebugDownloadStateString(state()));
781
782 // Construct a string of the URL chain.
783 std::string url_list("<none>");
784 if (!url_chain_.empty()) {
785 std::vector<GURL>::const_iterator iter = url_chain_.begin();
786 std::vector<GURL>::const_iterator last = url_chain_.end();
787 url_list = (*iter).spec();
788 ++iter;
789 for ( ; verbose && (iter != last); ++iter) {
790 url_list += " ->\n\t";
791 const GURL& next_url = *iter;
792 url_list += next_url.spec();
793 }
794 }
795
796 if (verbose) {
797 description += base::StringPrintf(
798 " db_handle = %" PRId64
799 " total_bytes = %" PRId64
800 " received_bytes = %" PRId64
801 " is_paused = %c"
802 " is_otr = %c"
803 " safety_state = %s"
804 " url_chain = \n\t\"%s\"\n\t"
805 " target_name = \"%" PRFilePath "\""
806 " full_path = \"%" PRFilePath "\"",
807 db_handle(),
808 total_bytes(),
809 received_bytes(),
810 is_paused() ? 'T' : 'F',
811 is_otr() ? 'T' : 'F',
812 DebugSafetyStateString(safety_state()),
813 url_list.c_str(),
814 state_info_.target_name.value().c_str(),
815 full_path().value().c_str());
816 } else {
817 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
818 }
819
820 description += " }";
821
822 return description;
823 }
OLDNEW
« no previous file with comments | « content/browser/download/download_item.h ('k') | content/browser/download/download_item_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698