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

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

Powered by Google App Engine
This is Rietveld 408576698