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

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

Issue 14955002: [Resumption 6/11] Add a RESUMING_INTERNAL state to DownloadItem. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // File method ordering: Methods in this file are in the same order as 5 // File method ordering: Methods in this file are in the same order as
6 // in download_item_impl.h, with the following exception: The public 6 // in download_item_impl.h, with the following exception: The public
7 // interface Start is placed in chronological order with the other 7 // interface Start is placed in chronological order with the other
8 // (private) routines that together define a DownloadItem's state 8 // (private) routines that together define a DownloadItem's state
9 // transitions as the download progresses. See "Download progression 9 // transitions as the download progresses. See "Download progression
10 // cascade" later in this file. 10 // cascade" later in this file.
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 if (state_ != IN_PROGRESS_INTERNAL || is_paused_) 302 if (state_ != IN_PROGRESS_INTERNAL || is_paused_)
303 return; 303 return;
304 304
305 request_handle_->PauseRequest(); 305 request_handle_->PauseRequest();
306 is_paused_ = true; 306 is_paused_ = true;
307 UpdateObservers(); 307 UpdateObservers();
308 } 308 }
309 309
310 void DownloadItemImpl::Resume() { 310 void DownloadItemImpl::Resume() {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 switch (state_) {
313 case IN_PROGRESS_INTERNAL:
314 if (!is_paused_)
315 return;
316 request_handle_->ResumeRequest();
317 is_paused_ = false;
318 UpdateObservers();
319 return;
312 320
313 // Ignore irrelevant states. 321 case COMPLETING_INTERNAL:
314 if (state_ == COMPLETE_INTERNAL || 322 case COMPLETE_INTERNAL:
315 state_ == COMPLETING_INTERNAL || 323 case CANCELLED_INTERNAL:
316 state_ == CANCELLED_INTERNAL || 324 case RESUMING_INTERNAL:
317 (state_ == IN_PROGRESS_INTERNAL && !is_paused_)) 325 return;
318 return;
319 326
320 if (state_ == INTERRUPTED_INTERNAL) { 327 case INTERRUPTED_INTERNAL:
321 auto_resume_count_ = 0; // User input resets the counter. 328 auto_resume_count_ = 0; // User input resets the counter.
322 ResumeInterruptedDownload(); 329 ResumeInterruptedDownload();
323 return; 330 return;
331
332 case MAX_DOWNLOAD_INTERNAL_STATE:
333 NOTREACHED();
324 } 334 }
325 DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
326
327 request_handle_->ResumeRequest();
328 is_paused_ = false;
329 UpdateObservers();
330 } 335 }
331 336
332 void DownloadItemImpl::Cancel(bool user_cancel) { 337 void DownloadItemImpl::Cancel(bool user_cancel) {
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
334 339
335 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 340 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
336 if (state_ != IN_PROGRESS_INTERNAL && state_ != INTERRUPTED_INTERNAL) { 341 if (state_ != IN_PROGRESS_INTERNAL &&
337 // Small downloads might be complete before this method has 342 state_ != INTERRUPTED_INTERNAL &&
338 // a chance to run. 343 state_ != RESUMING_INTERNAL) {
344 // Small downloads might be complete before this method has a chance to run.
339 return; 345 return;
340 } 346 }
341 347
342 last_reason_ = user_cancel ? 348 last_reason_ = user_cancel ?
343 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED : 349 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
344 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN; 350 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
345 351
346 RecordDownloadCount(CANCELLED_COUNT); 352 RecordDownloadCount(CANCELLED_COUNT);
347 353
348 // TODO(rdsmith/benjhayden): Remove condition as part of 354 // TODO(rdsmith/benjhayden): Remove condition as part of
349 // |SavePackage| integration. 355 // |SavePackage| integration.
350 // |download_file_| can be NULL if Interrupt() is called after the 356 // |download_file_| can be NULL if Interrupt() is called after the
351 // download file has been released. 357 // download file has been released.
352 if (!is_save_package_download_ && download_file_) 358 if (!is_save_package_download_ && download_file_)
353 ReleaseDownloadFile(true); 359 ReleaseDownloadFile(true);
354 360
355 if (state_ != INTERRUPTED_INTERNAL) { 361 if (state_ == IN_PROGRESS_INTERNAL) {
356 // Cancel the originating URL request unless it's already been cancelled 362 // Cancel the originating URL request unless it's already been cancelled
357 // by interrupt. 363 // by interrupt.
358 request_handle_->CancelRequest(); 364 request_handle_->CancelRequest();
359 } 365 }
360 366
361 TransitionTo(CANCELLED_INTERNAL); 367 TransitionTo(CANCELLED_INTERNAL);
362 } 368 }
363 369
364 void DownloadItemImpl::Delete(DeleteReason reason) { 370 void DownloadItemImpl::Delete(DeleteReason reason) {
365 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 371 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 scoped_ptr<DownloadFile> file, 1047 scoped_ptr<DownloadFile> file,
1042 scoped_ptr<DownloadRequestHandleInterface> req_handle) { 1048 scoped_ptr<DownloadRequestHandleInterface> req_handle) {
1043 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1049 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1044 DCHECK(!download_file_.get()); 1050 DCHECK(!download_file_.get());
1045 DCHECK(file.get()); 1051 DCHECK(file.get());
1046 DCHECK(req_handle.get()); 1052 DCHECK(req_handle.get());
1047 1053
1048 download_file_ = file.Pass(); 1054 download_file_ = file.Pass();
1049 request_handle_ = req_handle.Pass(); 1055 request_handle_ = req_handle.Pass();
1050 1056
1057 if (IsCancelled()) {
1058 // The download was in the process of resuming when it was cancelled. Don't
1059 // proceed.
1060 ReleaseDownloadFile(true);
1061 request_handle_->CancelRequest();
1062 return;
1063 }
1064
1051 TransitionTo(IN_PROGRESS_INTERNAL); 1065 TransitionTo(IN_PROGRESS_INTERNAL);
1052 1066
1053 last_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1067 last_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1054 1068
1055 BrowserThread::PostTask( 1069 BrowserThread::PostTask(
1056 BrowserThread::FILE, FROM_HERE, 1070 BrowserThread::FILE, FROM_HERE,
1057 base::Bind(&DownloadFile::Initialize, 1071 base::Bind(&DownloadFile::Initialize,
1058 // Safe because we control download file lifetime. 1072 // Safe because we control download file lifetime.
1059 base::Unretained(download_file_.get()), 1073 base::Unretained(download_file_.get()),
1060 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1074 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 // we still need to set it auto-opened so that it can be removed from the 1333 // we still need to set it auto-opened so that it can be removed from the
1320 // download shelf. 1334 // download shelf.
1321 if (!IsTemporary()) 1335 if (!IsTemporary())
1322 OpenDownload(); 1336 OpenDownload();
1323 1337
1324 auto_opened_ = true; 1338 auto_opened_ = true;
1325 UpdateObservers(); 1339 UpdateObservers();
1326 } 1340 }
1327 } 1341 }
1328 1342
1343 void DownloadItemImpl::OnResumeRequestStarted(DownloadItem* item,
1344 net::Error error) {
1345 // If |item| is not NULL, then Start() has been called already, and nothing
1346 // more needs to be done here.
1347 if (item) {
1348 DCHECK_EQ(net::OK, error);
1349 DCHECK_EQ(static_cast<DownloadItem*>(this), item);
1350 return;
1351 }
1352 // Otherwise, the request failed without passing through
1353 // DownloadResourceHandler::OnResponseStarted.
1354 if (error == net::OK)
1355 error = net::ERR_FAILED;
1356 DownloadInterruptReason reason =
1357 ConvertNetErrorToInterruptReason(error, DOWNLOAD_INTERRUPT_FROM_NETWORK);
1358 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
1359 Interrupt(reason);
1360 }
1361
1329 // **** End of Download progression cascade 1362 // **** End of Download progression cascade
1330 1363
1331 // An error occurred somewhere. 1364 // An error occurred somewhere.
1332 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1365 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) {
1333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1334 1367
1335 // Somewhat counter-intuitively, it is possible for us to receive an 1368 // Somewhat counter-intuitively, it is possible for us to receive an
1336 // interrupt after we've already been interrupted. The generation of 1369 // interrupt after we've already been interrupted. The generation of
1337 // interrupts from the file thread Renames and the generation of 1370 // interrupts from the file thread Renames and the generation of
1338 // interrupts from disk writes go through two different mechanisms (driven 1371 // interrupts from disk writes go through two different mechanisms (driven
1339 // by rename requests from UI thread and by write requests from IO thread, 1372 // by rename requests from UI thread and by write requests from IO thread,
1340 // respectively), and since we choose not to keep state on the File thread, 1373 // respectively), and since we choose not to keep state on the File thread,
1341 // this is the place where the races collide. It's also possible for 1374 // this is the place where the races collide. It's also possible for
1342 // interrupts to race with cancels. 1375 // interrupts to race with cancels.
1343 1376
1344 // Whatever happens, the first one to hit the UI thread wins. 1377 // Whatever happens, the first one to hit the UI thread wins.
1345 if (state_ != IN_PROGRESS_INTERNAL) 1378 if (state_ != IN_PROGRESS_INTERNAL && state_ != RESUMING_INTERNAL)
1346 return; 1379 return;
1347 1380
1348 last_reason_ = reason; 1381 last_reason_ = reason;
1349 1382
1350 ResumeMode resume_mode = GetResumeMode(); 1383 ResumeMode resume_mode = GetResumeMode();
1351 // Cancel (delete file) if we're going to restart; no point in leaving 1384 // Cancel (delete file) if we're going to restart; no point in leaving
1352 // data around we aren't going to use. Also cancel if resumption isn't 1385 // data around we aren't going to use. Also cancel if resumption isn't
1353 // enabled for the same reason. 1386 // enabled for the same reason.
1354 bool resumption_enabled = CommandLine::ForCurrentProcess()->HasSwitch( 1387 bool resumption_enabled = CommandLine::ForCurrentProcess()->HasSwitch(
1355 switches::kEnableDownloadResumption); 1388 switches::kEnableDownloadResumption);
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1548 void DownloadItemImpl::ResumeInterruptedDownload() { 1581 void DownloadItemImpl::ResumeInterruptedDownload() {
1549 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1582 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1550 1583
1551 // If the flag for downloads resumption isn't enabled, ignore 1584 // If the flag for downloads resumption isn't enabled, ignore
1552 // this request. 1585 // this request.
1553 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1586 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1554 if (!command_line.HasSwitch(switches::kEnableDownloadResumption)) 1587 if (!command_line.HasSwitch(switches::kEnableDownloadResumption))
1555 return; 1588 return;
1556 1589
1557 // If we're not interrupted, ignore the request; our caller is drunk. 1590 // If we're not interrupted, ignore the request; our caller is drunk.
1558 if (!IsInterrupted()) 1591 if (state_ != INTERRUPTED_INTERNAL)
1559 return; 1592 return;
1560 1593
1561 // If we can't get a web contents, we can't resume the download. 1594 // If we can't get a web contents, we can't resume the download.
1562 // TODO(rdsmith): Find some alternative web contents to use--this 1595 // TODO(rdsmith): Find some alternative web contents to use--this
1563 // means we can't restart a download if it's a download imported 1596 // means we can't restart a download if it's a download imported
1564 // from the history. 1597 // from the history.
1565 if (!GetWebContents()) 1598 if (!GetWebContents())
1566 return; 1599 return;
1567 1600
1568 // Reset the appropriate state if restarting. 1601 // Reset the appropriate state if restarting.
1569 ResumeMode mode = GetResumeMode(); 1602 ResumeMode mode = GetResumeMode();
1570 if (mode == RESUME_MODE_IMMEDIATE_RESTART || 1603 if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
1571 mode == RESUME_MODE_USER_RESTART) { 1604 mode == RESUME_MODE_USER_RESTART) {
1572 received_bytes_ = 0; 1605 received_bytes_ = 0;
1573 hash_state_ = ""; 1606 hash_state_ = "";
1574 last_modified_time_ = ""; 1607 last_modified_time_ = "";
1575 etag_ = ""; 1608 etag_ = "";
1576 } 1609 }
1577 1610
1578 scoped_ptr<DownloadUrlParameters> download_params( 1611 scoped_ptr<DownloadUrlParameters> download_params(
1579 DownloadUrlParameters::FromWebContents(GetWebContents(), 1612 DownloadUrlParameters::FromWebContents(GetWebContents(),
1580 GetOriginalUrl())); 1613 GetOriginalUrl()));
1581 1614
1582 download_params->set_file_path(GetFullPath()); 1615 download_params->set_file_path(GetFullPath());
1583 download_params->set_offset(GetReceivedBytes()); 1616 download_params->set_offset(GetReceivedBytes());
1584 download_params->set_hash_state(GetHashState()); 1617 download_params->set_hash_state(GetHashState());
1585 download_params->set_last_modified(GetLastModifiedTime()); 1618 download_params->set_last_modified(GetLastModifiedTime());
1586 download_params->set_etag(GetETag()); 1619 download_params->set_etag(GetETag());
1620 download_params->set_callback(
1621 base::Bind(&DownloadItemImpl::OnResumeRequestStarted,
1622 weak_ptr_factory_.GetWeakPtr()));
1587 1623
1588 delegate_->ResumeInterruptedDownload(download_params.Pass(), GetGlobalId()); 1624 delegate_->ResumeInterruptedDownload(download_params.Pass(), GetGlobalId());
1589
1590 // Just in case we were interrupted while paused. 1625 // Just in case we were interrupted while paused.
1591 is_paused_ = false; 1626 is_paused_ = false;
1627
1628 TransitionTo(RESUMING_INTERNAL);
1592 } 1629 }
1593 1630
1594 // static 1631 // static
1595 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( 1632 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1596 DownloadInternalState internal_state) { 1633 DownloadInternalState internal_state) {
1597 switch (internal_state) { 1634 switch (internal_state) {
1598 case IN_PROGRESS_INTERNAL: 1635 case IN_PROGRESS_INTERNAL:
1599 return IN_PROGRESS; 1636 return IN_PROGRESS;
1600 case COMPLETING_INTERNAL: 1637 case COMPLETING_INTERNAL:
1601 return IN_PROGRESS; 1638 return IN_PROGRESS;
1602 case COMPLETE_INTERNAL: 1639 case COMPLETE_INTERNAL:
1603 return COMPLETE; 1640 return COMPLETE;
1604 case CANCELLED_INTERNAL: 1641 case CANCELLED_INTERNAL:
1605 return CANCELLED; 1642 return CANCELLED;
1606 case INTERRUPTED_INTERNAL: 1643 case INTERRUPTED_INTERNAL:
1607 return INTERRUPTED; 1644 return INTERRUPTED;
1608 default: 1645 case RESUMING_INTERNAL:
1609 NOTREACHED(); 1646 return INTERRUPTED;
1647 case MAX_DOWNLOAD_INTERNAL_STATE:
1648 break;
1610 } 1649 }
1650 NOTREACHED();
1611 return MAX_DOWNLOAD_STATE; 1651 return MAX_DOWNLOAD_STATE;
1612 } 1652 }
1613 1653
1614 // static 1654 // static
1615 DownloadItemImpl::DownloadInternalState 1655 DownloadItemImpl::DownloadInternalState
1616 DownloadItemImpl::ExternalToInternalState( 1656 DownloadItemImpl::ExternalToInternalState(
1617 DownloadState external_state) { 1657 DownloadState external_state) {
1618 switch (external_state) { 1658 switch (external_state) {
1619 case IN_PROGRESS: 1659 case IN_PROGRESS:
1620 return IN_PROGRESS_INTERNAL; 1660 return IN_PROGRESS_INTERNAL;
1621 case COMPLETE: 1661 case COMPLETE:
1622 return COMPLETE_INTERNAL; 1662 return COMPLETE_INTERNAL;
1623 case CANCELLED: 1663 case CANCELLED:
1624 return CANCELLED_INTERNAL; 1664 return CANCELLED_INTERNAL;
1625 case INTERRUPTED: 1665 case INTERRUPTED:
1626 return INTERRUPTED_INTERNAL; 1666 return INTERRUPTED_INTERNAL;
1627 default: 1667 default:
1628 NOTREACHED(); 1668 NOTREACHED();
1629 } 1669 }
1630 return MAX_DOWNLOAD_INTERNAL_STATE; 1670 return MAX_DOWNLOAD_INTERNAL_STATE;
1631 } 1671 }
1632 1672
1633 const char* DownloadItemImpl::DebugDownloadStateString( 1673 const char* DownloadItemImpl::DebugDownloadStateString(
1634 DownloadInternalState state) { 1674 DownloadInternalState state) {
1635 switch (state) { 1675 switch (state) {
1636 case IN_PROGRESS_INTERNAL: 1676 case IN_PROGRESS_INTERNAL:
1637 return "IN_PROGRESS"; 1677 return "IN_PROGRESS";
1638 case COMPLETING_INTERNAL: 1678 case COMPLETING_INTERNAL:
1639 return "COMPLETING"; 1679 return "COMPLETING";
1640 case COMPLETE_INTERNAL: 1680 case COMPLETE_INTERNAL:
1641 return "COMPLETE"; 1681 return "COMPLETE";
1642 case CANCELLED_INTERNAL: 1682 case CANCELLED_INTERNAL:
1643 return "CANCELLED"; 1683 return "CANCELLED";
1644 case INTERRUPTED_INTERNAL: 1684 case INTERRUPTED_INTERNAL:
1645 return "INTERRUPTED"; 1685 return "INTERRUPTED";
1646 default: 1686 case RESUMING_INTERNAL:
1647 NOTREACHED() << "Unknown download state " << state; 1687 return "RESUMING";
1648 return "unknown"; 1688 case MAX_DOWNLOAD_INTERNAL_STATE:
1689 break;
1649 }; 1690 };
1691 NOTREACHED() << "Unknown download state " << state;
1692 return "unknown";
1650 } 1693 }
1651 1694
1652 const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) { 1695 const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) {
1653 switch (mode) { 1696 switch (mode) {
1654 case RESUME_MODE_INVALID: 1697 case RESUME_MODE_INVALID:
1655 return "INVALID"; 1698 return "INVALID";
1656 case RESUME_MODE_IMMEDIATE_CONTINUE: 1699 case RESUME_MODE_IMMEDIATE_CONTINUE:
1657 return "IMMEDIATE_CONTINUE"; 1700 return "IMMEDIATE_CONTINUE";
1658 case RESUME_MODE_IMMEDIATE_RESTART: 1701 case RESUME_MODE_IMMEDIATE_RESTART:
1659 return "IMMEDIATE_RESTART"; 1702 return "IMMEDIATE_RESTART";
1660 case RESUME_MODE_USER_CONTINUE: 1703 case RESUME_MODE_USER_CONTINUE:
1661 return "USER_CONTINUE"; 1704 return "USER_CONTINUE";
1662 case RESUME_MODE_USER_RESTART: 1705 case RESUME_MODE_USER_RESTART:
1663 return "USER_RESTART"; 1706 return "USER_RESTART";
1664 } 1707 }
1665 NOTREACHED() << "Unknown resume mode " << mode; 1708 NOTREACHED() << "Unknown resume mode " << mode;
1666 return "unknown"; 1709 return "unknown";
1667 } 1710 }
1668 1711
1669 } // namespace content 1712 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_item_impl.h ('k') | content/browser/download/download_manager_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698