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

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

Powered by Google App Engine
This is Rietveld 408576698