New issue
Advanced search Search tips

Issue 664677 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 476037
Owner:
Closed: Jan 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug



Sign in to add a comment

Unresumable temporary download files are kept around on storage

Project Member Reported by dfalcant...@chromium.org, Nov 12 2016

Issue description

If a download is interrupted by killing Clank and a new download is triggered for the same file when Clank restarts, the old download is unresumable.  Attempting to trigger that can pop up a snackbar saying something to that effect and then cancels the older download, but it doesn't seem to delete the temporary file.
 

Comment 1 by qin...@chromium.org, Nov 14 2016

The problem is caused by that download path is not immediately written to the history db after it is determined.
As a result, if Chrome gets killed immediately after download starts, the history db may not store the download path. When resume is called, it will find no temporary file exists and thus creating a new file instead, assuming no conflict.

Comment 2 by qin...@chromium.org, Nov 21 2016

Thanks for Asanka's comments on the code review about the issue, very insightful:

sky@ is correctly pointing out that there's a window during which the temporary
file exists on disk, but the history update task hasn't run yet. If Chrome were
to be killed during this window, then once again Chrome won't be able to
associate the file on disk with the download entry.

The window is even larger than that. The |DownloadItem::GetCurrentPath| only
returns a non-empty path after the download target determination phase has
completed successfully, including the time spent prompting the user. The
temporary file on disk is created as soon as Chrome starts receiving response
body data from the server which happens *before* target determination.

So the order of tasks is (roughly):

  1. (IO thread) Response headers processed for network request. Download
process starts.
  2. (IO thread) Reads response body and queues up to a max of 100 segments
until step 5 below.
  3. (UI thread) DownloadManager starts setting up UI thread state for download.
  3.1 (UI -> FILE) DM posts task to handle DownloadFile construction.
  4. (FILE thread) DownloadFileImpl created, which creates a temporary file on
disk.
  5. (FILE thread) DownloadFileImpl writes queued data to temporary file.
Hereafter, data queued from IO thread is flushed ASAP on FILE thread to download
file.
  5.1 (FILE -> UI) DFI posts task to update DownloadItem with DownloadFile
construction result.
  6. (UI thread) DOwnloadItemImpl initiates download target determination
sequence.
  6.1 ... lots of stuff happens on multiple threads including FILE and DB
threads.
  7. (UI thread) DownloadItemImpl finalizes download target determination.
  8. (UI -> FILE) DownloadItemImpl posts a task to rename intermediate file to
something closer to the target filename.
  9. (FILE thread) DownloadFileImpl renames intermediate file.
  10. (FILE -> UI) DFI posts task to update DownloadItemImpl with rename result.
  11. (UI thread) DownloadItemImpl receives name of intermediate file.
  12. (UI thread) DownloadItemImpl notifies observers of update to DownloadItem
which includes the new current path.
  13. (UI thread) DownloadHistory calls into history:: to update download record
in download DB.
  14. (UI -> history thread) HistoryService schedules a task to perform DB
operation.
  15. (history thread) HistoryBackend runs query to update DB record.
  16. (history thread) *after this CL* commits pending transaction.

So the delay between the file landing on disk and the history DB being current
is the time between step 4 and step 16, which includes lots of thread hops and
user interaction.

This CL ameliorates the problem by narrowing the window by ~5s, but falls short
of fix it. Additionally we'd need to:

 * Account for stray .crdownload files in the download directory. Only Chrome
creates those, and at this point .crdownload is a well known extension (search
GitHub for .crdownload). So we can assume with some confidence that any such
file on the download directory is likely Chrome's doing. Unfortunately, this
doesn't easily hold true for folks who run multiple instances of Chrome/Chromium
where it's possible that what looks like a stray .crdownload file may be
accounted for by a different instance of Chrome.

* Make step 5.1 communicate the temporary filename to DownloadItemImpl. That
narrows the window further and eliminates the delay caused by download target
determination. The latter is important since that also removes the delay due to
any necessary user prompting.

Project Member

Comment 3 by bugdroid1@chromium.org, Nov 28 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/64558cd6c0e060c1f127f8f36f692529c8087aae

commit 64558cd6c0e060c1f127f8f36f692529c8087aae
Author: qinmin <qinmin@chromium.org>
Date: Mon Nov 28 22:30:29 2016

Fix an issue that temp files are left permanently on storage after chrome crash

When download path is determined, Chrome will commit that information to history.
However, the information is not committed immediately.
As a result, if Chrome crashes before the next commit, the path information is lost.
When resuming the download later, Chrome will generate a new target path.
And the old temp file is left permanently on external storage.
This might not be a big issue for desktop, as Chrome rarely gets killed and there are ample storage.
However, this has a great impact on android.
This CL requests the path information to be committed immediately to address the issue.

BUG= 664677 

Review-Url: https://codereview.chromium.org/2508503002
Cr-Commit-Position: refs/heads/master@{#434738}

[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/chrome/browser/download/download_history.cc
[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/chrome/browser/download/download_history.h
[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/chrome/browser/download/download_history_unittest.cc
[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/components/history/core/browser/history_backend.cc
[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/components/history/core/browser/history_backend.h
[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/components/history/core/browser/history_service.cc
[modify] https://crrev.com/64558cd6c0e060c1f127f8f36f692529c8087aae/components/history/core/browser/history_service.h

Comment 4 by vabr@chromium.org, Dec 2 2016

Components: Privacy
Privacy FYI as leaving parts of downloads undeleted by accident might be a privacy issue.

Comment 5 by dah...@chromium.org, Dec 15 2016

Labels: M-57

Comment 6 by dah...@chromium.org, Dec 15 2016

Labels: -M-56
Cc: dtrainor@chromium.org
+dtrainor as FYI

Comment 8 by qin...@chromium.org, Jan 24 2017

Labels: -M-57 M-58
Mergedinto: 476037
Status: Duplicate (was: Assigned)

Sign in to add a comment