Android (and possibly other things like download extensions) have been using download IDs on the assumption that a download ID will refer to exactly one download, even across sessions. This is only a safe assumption to make within a single session.
In order to safely persist and use IDs outside of core downloads, one would need to observe and react to every download creation and removal happening within a profile and its associated OTR profiles. Otherwise, there could be changes to the list of downloads that could cause the ID to be assigned to a different download.
Fixing this is necessary for automatic resumption of downloads on Android where a background process that has no insight into the users profile needs to produce resumption signals for a download. I.e. the background process needs a reference to a download that survives across sessions. The download itself doesn't need to survive, but the reference should never resolve to a different download. This is currently not possible via download IDs.
One proposal: GUIDs! Let's give each download a GUID.
Pros: Fulfills all requirements. Also, we don't need to wait for the history DB to create the first ID (i.e. DownloadItem::Start() doesn't need an async hop via the delegate to determine its ID).
Cons: Downloads extensions API lists the ID as a 'long'. The documentation in downloads.idl says:
// An identifier that is persistent across browser sessions.
long id;
N.b. "persistent across browser sessions" is misleading since unbeknownst to the extension, Chrome could reuse the ID to refer to some other download.
After discussing with benjhayden@ and asargent@ among others, we've come up with the following plan:
1. Introduce GUIDs for downloads, which uniquely identify the download during
its lifetime. Each new download gets a new GUID, hence a lookup based on an
old GUID won't accidentally refer to a different download. Regular old
download IDs will still be available for the moment.
2. Android services that need to refer to downloads can shift to using GUIDs at
this point.
3. I'll start moving consumers away from download IDs.
3.1. Extensions will expose the GUID, but will also maintain its own mapping
based on hashing the GUID. In the absence of unlikely conflicts with other
known downloads, this would mean that download IDs will be stable across
sessions. I'll also update the documentation so that it's clear what the
guarantees of IDs are and recommend switching over to GUIDs if cross session
stability is desired.
3.2. Native consumers who are interested in the lifetime of downloads will
switch to observing them rather than looking them up at arbitrary times using IDs.
3.3. Native consumers who want to invoke a method on DownloadItem at some
arbitrary time will instead be switched over to using callback based APIs
(assuming they can't be switched over to being DownloadItem::Observers.
4. Once all interested parties switch away from download IDs, we'll remove IDs
entirely.
Steps 1 and 4 involve download history schema changes. Extensions won't observe any changes until step 3.1 is complete and no changes from then onwards.
Note that at step 3.1, the mapping between downloads and existing IDs will break since the new ID assigned to a download will likely be different from the one assigned to it using the current scheme. However, from that point on, the IDs should be stable again.
Comment 1 by asanka@chromium.org
, Mar 8 2016