summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqinmin <qinmin@chromium.org>2016-03-25 21:13:38 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-26 04:14:58 +0000
commit30ac0f57a0fcae1a13e6374c05927a04caf526e5 (patch)
treebb56349228c53a3ee588e25971e935af6996f5fb
parent220c7edc3243b54970a13d91c690b2dffc15732d (diff)
downloadchromium_src-30ac0f57a0fcae1a13e6374c05927a04caf526e5.zip
chromium_src-30ac0f57a0fcae1a13e6374c05927a04caf526e5.tar.gz
chromium_src-30ac0f57a0fcae1a13e6374c05927a04caf526e5.tar.bz2
Switch to use download GUID to indentify download items
Download GUID is introduced by http://crrev.com/eef62b0282ec19ebc040785d0b7ac36de398cbc1 Unlike download Id, the GUID can live across browser sessions and will not be reused. This change switches the java class to also use the GUID. Chrome will temporarily use the old download Id as the notification Id. This is because the android notification requires an int to identify it, rather than a string. In the future, we will generate the notification Id from java side. The download Ids generated by the Android DownloadManager are not affected by this CL. However, they are only used in OMA downloads and when we call addCompletedDownload(). BUG=593020 Review URL: https://codereview.chromium.org/1809203006 Cr-Commit-Position: refs/heads/master@{#383443}
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java21
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java82
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java405
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java216
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotifier.java4
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java96
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java4
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java62
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java31
-rw-r--r--chrome/android/java_sources.gni2
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java36
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java40
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestBase.java5
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/download/MockDownloadNotificationService.java4
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java11
-rw-r--r--chrome/browser/android/download/chrome_download_delegate.cc15
-rw-r--r--chrome/browser/android/download/download_manager_service.cc62
-rw-r--r--chrome/browser/android/download/download_manager_service.h23
-rw-r--r--chrome/browser/android/download/download_manager_service_unittest.cc21
-rw-r--r--chrome/browser/android/download/mock_download_controller_android.cc5
-rw-r--r--chrome/browser/android/download/mock_download_controller_android.h6
-rw-r--r--content/browser/android/download_controller_android_impl.cc27
-rw-r--r--content/browser/android/download_controller_android_impl.h2
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java4
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/DownloadController.java43
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/DownloadInfo.java32
-rw-r--r--content/public/browser/android/download_controller_android.h5
27 files changed, 752 insertions, 512 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
index 65aa770..79c4a63 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
@@ -58,8 +58,8 @@ public class ChromeDownloadDelegate implements ContentViewDownloadDelegate {
public void onInfoBarButtonClicked(boolean confirm) {
assert mTab != null;
if (mPendingRequest == null) return;
- if (mPendingRequest.hasDownloadId()) {
- nativeDangerousDownloadValidated(mTab, mPendingRequest.getDownloadId(), confirm);
+ if (mPendingRequest.getDownloadGuid() != null) {
+ nativeDangerousDownloadValidated(mTab, mPendingRequest.getDownloadGuid(), confirm);
if (confirm) {
showDownloadStartNotification();
}
@@ -107,9 +107,10 @@ public class ChromeDownloadDelegate implements ContentViewDownloadDelegate {
@Override
public void onInfoBarDismissed() {
if (mPendingRequest != null) {
- if (mPendingRequest.hasDownloadId()) {
+ if (mPendingRequest.getDownloadGuid() != null) {
assert mTab != null;
- nativeDangerousDownloadValidated(mTab, mPendingRequest.getDownloadId(), false);
+ nativeDangerousDownloadValidated(
+ mTab, mPendingRequest.getDownloadGuid(), false);
} else if (!mPendingRequest.isGETRequest()) {
// Infobar was dismissed, discard the file if a POST download is pending.
discardFile(mPendingRequest.getFilePath());
@@ -269,15 +270,14 @@ public class ChromeDownloadDelegate implements ContentViewDownloadDelegate {
* Called when a danagerous download is about to start.
*
* @param filename File name of the download item.
- * @param downloadId ID of the download.
+ * @param downloadGuid GUID of the download.
*/
@Override
- public void onDangerousDownload(String filename, int downloadId) {
+ public void onDangerousDownload(String filename, String downloadGuid) {
DownloadInfo downloadInfo = new DownloadInfo.Builder()
.setFileName(filename)
.setDescription(filename)
- .setHasDownloadId(true)
- .setDownloadId(downloadId).build();
+ .setDownloadGuid(downloadGuid).build();
confirmDangerousDownload(downloadInfo);
}
@@ -416,7 +416,8 @@ public class ChromeDownloadDelegate implements ContentViewDownloadDelegate {
*/
private void enqueueDownloadManagerRequest(final DownloadInfo info) {
DownloadManagerService.getDownloadManagerService(
- mContext.getApplicationContext()).enqueueDownloadManagerRequest(info, true);
+ mContext.getApplicationContext()).enqueueDownloadManagerRequest(
+ new DownloadItem(true, info), true);
closeBlankTab();
}
@@ -630,7 +631,7 @@ public class ChromeDownloadDelegate implements ContentViewDownloadDelegate {
private static native String nativeGetDownloadWarningText(String filename);
private static native boolean nativeIsDownloadDangerous(String filename);
private static native void nativeDangerousDownloadValidated(
- Object tab, int downloadId, boolean accept);
+ Object tab, String downloadGuid, boolean accept);
private static native void nativeLaunchDownloadOverwriteInfoBar(ChromeDownloadDelegate delegate,
Tab tab, DownloadInfo downloadInfo, String fileName, String dirName,
String dirFullPath);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java
new file mode 100644
index 0000000..1708cb5
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.download;
+
+import org.chromium.content.browser.DownloadInfo;
+
+/**
+ * A generic class representing a download item. The item can be either downloaded through the
+ * Android DownloadManager, or through Chrome's network stack
+ */
+public class DownloadItem {
+ static final long INVALID_DOWNLOAD_ID = -1L;
+ private boolean mUseAndroidDownloadManager;
+ private DownloadInfo mDownloadInfo;
+ private long mDownloadId = INVALID_DOWNLOAD_ID;
+
+ public DownloadItem(boolean useAndroidDownloadManager, DownloadInfo info) {
+ mUseAndroidDownloadManager = useAndroidDownloadManager;
+ mDownloadInfo = info;
+ }
+
+ /**
+ * Sets the system download ID retrieved from Android DownloadManager.
+ *
+ * @param downloadId ID from the Android DownloadManager.
+ */
+ public void setSystemDownloadId(long downloadId) {
+ mDownloadId = downloadId;
+ }
+
+ /**
+ * @return whether the download item has a valid system download ID.
+ */
+ public boolean hasSystemDownloadId() {
+ return mDownloadId != INVALID_DOWNLOAD_ID;
+ }
+
+ /**
+ * @return notification ID for this download.
+ */
+ public int getNotificationId() {
+ if (mUseAndroidDownloadManager) {
+ return (int) mDownloadId;
+ }
+ return mDownloadInfo.getNotificationId();
+ }
+
+ /**
+ * @return System download ID from the Android DownloadManager.
+ */
+ public long getSystemDownloadId() {
+ return mDownloadId;
+ }
+
+ /**
+ * @return String ID that uniquely identifies the download.
+ */
+ public String getId() {
+ if (mUseAndroidDownloadManager) {
+ return String.valueOf(mDownloadId);
+ }
+ return mDownloadInfo.getDownloadGuid();
+ }
+
+ /**
+ * @return Info about the download.
+ */
+ public DownloadInfo getDownloadInfo() {
+ return mDownloadInfo;
+ }
+
+ /**
+ * Sets the system download info.
+ *
+ * @param info Download information.
+ */
+ public void setDownloadInfo(DownloadInfo info) {
+ mDownloadInfo = info;
+ }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index 676662e..90efe4e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -55,6 +55,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Chrome implementation of the {@link DownloadController.DownloadNotificationService} interface.
* This class is responsible for keeping track of which downloads are in progress. It generates
* updates for progress of downloads and handles cleaning up of interrupted progress notifications.
+ * TODO(qinmin): move BroadcastReceiver inheritance into DownloadManagerDelegate, as it handles all
+ * Android DownloadManager interactions. And DownloadManagerService should not know download Id
+ * issued by Android DownloadManager.
*/
public class DownloadManagerService extends BroadcastReceiver implements
DownloadController.DownloadNotificationService,
@@ -68,7 +71,6 @@ public class DownloadManagerService extends BroadcastReceiver implements
protected static final String PENDING_OMA_DOWNLOADS = "PendingOMADownloads";
private static final String UNKNOWN_MIME_TYPE = "application/unknown";
private static final long UPDATE_DELAY_MILLIS = 1000;
- private static final long INVALID_DOWNLOAD_ID = -1L;
private static final int UNKNOWN_DOWNLOAD_STATUS = -1;
// Values for the histogram MobileDownloadResumptionCount.
@@ -101,8 +103,8 @@ public class DownloadManagerService extends BroadcastReceiver implements
private static DownloadManagerService sDownloadManagerService;
private final SharedPreferences mSharedPrefs;
- private final ConcurrentHashMap<Integer, DownloadProgress> mDownloadProgressMap =
- new ConcurrentHashMap<Integer, DownloadProgress>(4, 0.75f, 2);
+ private final ConcurrentHashMap<String, DownloadProgress> mDownloadProgressMap =
+ new ConcurrentHashMap<String, DownloadProgress>(4, 0.75f, 2);
private final DownloadNotifier mDownloadNotifier;
// Delay between UI updates.
@@ -113,12 +115,11 @@ public class DownloadManagerService extends BroadcastReceiver implements
private final Handler mHandler;
private final Context mContext;
- private final LongSparseArray<DownloadInfo> mPendingDownloads =
- new LongSparseArray<DownloadInfo>();
+ private final LongSparseArray<DownloadItem> mSystemDownloadIdMap =
+ new LongSparseArray<DownloadItem>();
// Using vector for thread safety.
- @VisibleForTesting protected final Vector<Integer> mAutoResumableDownloadIds =
- new Vector<Integer>();
- private DownloadBroadcastReceiver mDownloadBroadcastReceiver;
+ @VisibleForTesting protected final Vector<String> mAutoResumableDownloadIds =
+ new Vector<String>();
private OMADownloadHandler mOMADownloadHandler;
private DownloadSnackbarController mDownloadSnackbarController;
private long mNativeDownloadManagerService;
@@ -132,22 +133,21 @@ public class DownloadManagerService extends BroadcastReceiver implements
private static class DownloadProgress {
final long mStartTimeInMillis;
boolean mCanDownloadWhileMetered;
- volatile DownloadInfo mDownloadInfo;
+ volatile DownloadItem mDownloadItem;
volatile int mDownloadStatus;
- volatile boolean mUpdateNotification;
DownloadProgress(long startTimeInMillis, boolean canDownloadWhileMetered,
- DownloadInfo downloadInfo, int downloadStatus, boolean updateNotification) {
+ DownloadItem downloadItem, int downloadStatus) {
mStartTimeInMillis = startTimeInMillis;
mCanDownloadWhileMetered = canDownloadWhileMetered;
- mDownloadInfo = downloadInfo;
+ mDownloadItem = downloadItem;
mDownloadStatus = downloadStatus;
- mUpdateNotification = updateNotification;
}
}
/**
* Class representing an OMA download entry to be stored in SharedPrefs.
+ * TODO(qinmin): Move all OMA related class and functions to a separate class.
*/
@VisibleForTesting
protected static class OMAEntry {
@@ -258,41 +258,45 @@ public class DownloadManagerService extends BroadcastReceiver implements
if (downloadInfo.getContentLength() == 0) {
status = DOWNLOAD_STATUS_FAILED;
}
- updateDownloadProgress(downloadInfo, status);
+ updateDownloadProgress(new DownloadItem(false, downloadInfo), status);
scheduleUpdateIfNeeded();
}
@Override
public void onDownloadUpdated(final DownloadInfo downloadInfo) {
- updateDownloadProgress(downloadInfo, DOWNLOAD_STATUS_IN_PROGRESS);
+ DownloadItem item = new DownloadItem(false, downloadInfo);
+ updateDownloadProgress(item, DOWNLOAD_STATUS_IN_PROGRESS);
// If user manually paused a download, this download is no longer auto resumable.
if (downloadInfo.isPaused()) {
- removeAutoResumableDownload(downloadInfo.getDownloadId());
+ removeAutoResumableDownload(item.getId());
}
scheduleUpdateIfNeeded();
}
@Override
public void onDownloadCancelled(final DownloadInfo downloadInfo) {
- updateDownloadProgress(downloadInfo, DOWNLOAD_STATUS_CANCELLED);
- removeAutoResumableDownload(downloadInfo.getDownloadId());
+ DownloadItem item = new DownloadItem(false, downloadInfo);
+ updateDownloadProgress(new DownloadItem(false, downloadInfo), DOWNLOAD_STATUS_CANCELLED);
+ removeAutoResumableDownload(item.getId());
scheduleUpdateIfNeeded();
}
@Override
public void onDownloadInterrupted(final DownloadInfo downloadInfo, boolean isAutoResumable) {
int status = DOWNLOAD_STATUS_INTERRUPTED;
+ DownloadItem item = new DownloadItem(false, downloadInfo);
if (!downloadInfo.isResumable()) {
status = DOWNLOAD_STATUS_FAILED;
} else if (isAutoResumable) {
- addAutoResumableDownload(downloadInfo.getDownloadId());
+ addAutoResumableDownload(item.getId());
}
- updateDownloadProgress(downloadInfo, status);
+ updateDownloadProgress(item, status);
scheduleUpdateIfNeeded();
}
/**
* Clear any pending OMA downloads by reading them from shared prefs.
+ * TODO(qinmin): move this to a separate class.
*/
public void clearPendingOMADownloads() {
if (mSharedPrefs.contains(PENDING_OMA_DOWNLOADS)) {
@@ -307,25 +311,27 @@ public class DownloadManagerService extends BroadcastReceiver implements
/**
* Async task to clear the pending OMA download from SharedPrefs and inform
* the OMADownloadHandler about download status.
+ * TODO(qinmin): move this to a separate file.
*/
private class ClearPendingOMADownloadTask extends
AsyncTask<Void, Void, Pair<Integer, Boolean>> {
- private DownloadInfo mDownloadInfo;
- private final long mDownloadId;
+ private final DownloadItem mDownloadItem;
private final String mInstallNotifyURI;
+ private DownloadInfo mDownloadInfo;
private int mFailureReason;
- public ClearPendingOMADownloadTask(long downloadId, String installNotifyURI) {
- mDownloadId = downloadId;
+ public ClearPendingOMADownloadTask(DownloadItem downloadItem, String installNotifyURI) {
+ mDownloadItem = downloadItem;
mInstallNotifyURI = installNotifyURI;
- mDownloadInfo = mPendingDownloads.get(downloadId);
+ mDownloadInfo = downloadItem.getDownloadInfo();
}
@Override
public Pair<Integer, Boolean> doInBackground(Void...voids) {
DownloadManager manager =
(DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
- Cursor c = manager.query(new DownloadManager.Query().setFilterById(mDownloadId));
+ Cursor c = manager.query(new DownloadManager.Query().setFilterById(
+ mDownloadItem.getSystemDownloadId()));
int statusIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
int reasonIndex = c.getColumnIndex(DownloadManager.COLUMN_REASON);
int filenameIndex = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
@@ -339,7 +345,6 @@ public class DownloadManagerService extends BroadcastReceiver implements
// Chrome has been killed, reconstruct a DownloadInfo.
mDownloadInfo = new DownloadInfo.Builder()
.setFileName(fileName)
- .setDownloadId((int) mDownloadId)
.setDescription(c.getString(
c.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION)))
.setMimeType(c.getString(
@@ -352,10 +357,11 @@ public class DownloadManagerService extends BroadcastReceiver implements
mDownloadInfo = DownloadInfo.Builder.fromDownloadInfo(mDownloadInfo)
.setFileName(fileName)
.build();
- canResolve = canResolveDownloadItem(mContext, mDownloadId);
+ mDownloadItem.setDownloadInfo(mDownloadInfo);
+ canResolve = canResolveDownloadItem(mContext, mDownloadItem);
} else if (status == DownloadManager.STATUS_FAILED) {
mFailureReason = c.getInt(reasonIndex);
- manager.remove(mDownloadId);
+ manager.remove(mDownloadItem.getSystemDownloadId());
}
}
c.close();
@@ -364,15 +370,17 @@ public class DownloadManagerService extends BroadcastReceiver implements
@Override
protected void onPostExecute(Pair<Integer, Boolean> result) {
+ long downloadId = mDownloadItem.getSystemDownloadId();
if (result.first == DownloadManager.STATUS_SUCCESSFUL) {
- mOMADownloadHandler.onDownloadCompleted(mDownloadInfo, mInstallNotifyURI);
- removeOMADownloadFromSharedPrefs(mDownloadId);
+ mOMADownloadHandler.onDownloadCompleted(
+ mDownloadInfo, downloadId, mInstallNotifyURI);
+ removeOMADownloadFromSharedPrefs(downloadId);
mDownloadSnackbarController.onDownloadSucceeded(
- mDownloadInfo, mDownloadId, result.second);
+ mDownloadInfo, downloadId, result.second);
} else if (result.first == DownloadManager.STATUS_FAILED) {
mOMADownloadHandler.onDownloadFailed(
- mDownloadInfo, mFailureReason, mInstallNotifyURI);
- removeOMADownloadFromSharedPrefs(mDownloadId);
+ mDownloadInfo, downloadId, mFailureReason, mInstallNotifyURI);
+ removeOMADownloadFromSharedPrefs(downloadId);
String fileName = mDownloadInfo.getFileName();
onDownloadFailed(fileName, mFailureReason);
}
@@ -382,13 +390,16 @@ public class DownloadManagerService extends BroadcastReceiver implements
/**
* Clear pending OMA downloads for a particular download ID.
*
- * @param downloadId Download identifier.
- * @param info Information about the download.
+ * @param downloadId Download identifier from Android DownloadManager.
* @param installNotifyURI URI to notify after installation.
*/
private void clearPendingOMADownload(long downloadId, String installNotifyURI) {
- ClearPendingOMADownloadTask task = new ClearPendingOMADownloadTask(
- downloadId, installNotifyURI);
+ DownloadItem item = mSystemDownloadIdMap.get(downloadId);
+ if (item == null) {
+ item = new DownloadItem(true, null);
+ item.setSystemDownloadId(downloadId);
+ }
+ ClearPendingOMADownloadTask task = new ClearPendingOMADownloadTask(item, installNotifyURI);
task.execute();
}
@@ -474,44 +485,43 @@ public class DownloadManagerService extends BroadcastReceiver implements
/**
* Updates notifications for all current downloads. Should not be called from UI thread.
*
- * @return A map that maps all download info to their corresponding download IDs in the
- * download manager and whether the download can be resolved. If a download fails,
- * its download ID is INVALID_DOWNLOAD_ID and the launching intent is null. If a
- * download is cancelled, return an empty map so that no action needs to be taken.
+ * @return A map that maps all completed download to whether the download can be resolved.
+ * If a download fails, its system download ID is DownloadItem.INVALID_DOWNLOAD_ID. If
+ * a download is cancelled, return an empty map so that no action needs to be taken.
*/
- private Map<DownloadInfo, Pair<Long, Boolean>> updateAllNotifications() {
+ private Map<DownloadItem, Boolean> updateAllNotifications() {
assert !ThreadUtils.runningOnUiThread();
- Map<DownloadInfo, Pair<Long, Boolean>> completionMap =
- new HashMap<DownloadInfo, Pair<Long, Boolean>>();
+ Map<DownloadItem, Boolean> downloadItems = new HashMap<DownloadItem, Boolean>();
for (DownloadProgress progress : mDownloadProgressMap.values()) {
if (progress != null) {
- DownloadInfo info = progress.mDownloadInfo;
+ DownloadItem item = progress.mDownloadItem;
+ DownloadInfo info = item.getDownloadInfo();
switch (progress.mDownloadStatus) {
case DOWNLOAD_STATUS_COMPLETE:
- mDownloadProgressMap.remove(info.getDownloadId());
- long downloadId = addCompletedDownload(info);
- if (downloadId == INVALID_DOWNLOAD_ID) {
- completionMap.put(info, Pair.create(INVALID_DOWNLOAD_ID, false));
- mDownloadNotifier.notifyDownloadFailed(info);
- } else {
+ mDownloadProgressMap.remove(item.getId());
+ boolean success = addCompletedDownload(item);
+ if (success) {
boolean canResolve = isOMADownloadDescription(info)
- || canResolveDownloadItem(mContext, downloadId);
- completionMap.put(info, Pair.create(downloadId, canResolve));
+ || canResolveDownloadItem(mContext, item);
+ downloadItems.put(item, canResolve);
mDownloadNotifier.notifyDownloadSuccessful(
- info, getLaunchIntentFromDownloadId(mContext, downloadId));
+ info, getLaunchIntentFromDownloadId(
+ mContext, item.getSystemDownloadId()));
broadcastDownloadSuccessful(info);
+ } else {
+ downloadItems.put(item, false);
+ mDownloadNotifier.notifyDownloadFailed(info);
}
break;
case DOWNLOAD_STATUS_FAILED:
- mDownloadProgressMap.remove(info.getDownloadId());
+ mDownloadProgressMap.remove(item.getId());
mDownloadNotifier.notifyDownloadFailed(info);
- completionMap.put(info, Pair.create(INVALID_DOWNLOAD_ID, false));
+ downloadItems.put(item, false);
Log.w(TAG, "Download failed: " + info.getFilePath());
break;
case DOWNLOAD_STATUS_IN_PROGRESS:
- if (!progress.mUpdateNotification) break;
- if (progress.mDownloadInfo.isPaused()) {
- mDownloadProgressMap.remove(info.getDownloadId());
+ if (info.isPaused()) {
+ mDownloadProgressMap.remove(item.getId());
mDownloadNotifier.notifyDownloadPaused(info, false);
if (info.isResumable()) {
recordDownloadResumption(UMA_DOWNLOAD_RESUMPTION_MANUAL_PAUSE);
@@ -522,16 +532,16 @@ public class DownloadManagerService extends BroadcastReceiver implements
}
break;
case DOWNLOAD_STATUS_CANCELLED:
- mDownloadProgressMap.remove(info.getDownloadId());
- mDownloadNotifier.cancelNotification(info.getDownloadId());
+ mDownloadProgressMap.remove(item.getId());
+ mDownloadNotifier.cancelNotification(item.getNotificationId());
break;
case DOWNLOAD_STATUS_INTERRUPTED:
// If the download can be auto resumed, keep it in the progress map so we
// can resume it once network becomes available.
boolean isAutoResumable =
- mAutoResumableDownloadIds.contains(info.getDownloadId());
+ mAutoResumableDownloadIds.contains(item.getId());
if (!isAutoResumable) {
- mDownloadProgressMap.remove(info.getDownloadId());
+ mDownloadProgressMap.remove(item.getId());
}
mDownloadNotifier.notifyDownloadPaused(info, isAutoResumable);
break;
@@ -541,17 +551,17 @@ public class DownloadManagerService extends BroadcastReceiver implements
}
}
}
- return completionMap;
+ return downloadItems;
}
/**
- * Add a completed download into DownloadManager.
+ * Adds a completed download into Android DownloadManager.
*
- * @param downloadInfo Information of the downloaded file.
- * @return download ID if the download is added to the DownloadManager, or
- * INVALID_DOWNLOAD_ID otherwise.
+ * @param downloadItem Information of the downloaded.
+ * @return true if the download is added to the DownloadManager, or false otherwise.
*/
- protected long addCompletedDownload(DownloadInfo downloadInfo) {
+ protected boolean addCompletedDownload(DownloadItem downloadItem) {
+ DownloadInfo downloadInfo = downloadItem.getDownloadInfo();
String mimeType = downloadInfo.getMimeType();
if (TextUtils.isEmpty(mimeType)) mimeType = UNKNOWN_MIME_TYPE;
String description = downloadInfo.getDescription();
@@ -559,10 +569,12 @@ public class DownloadManagerService extends BroadcastReceiver implements
try {
// Exceptions can be thrown when calling this, although it is not
// documented on Android SDK page.
- return mDownloadManagerDelegate.addCompletedDownload(
+ long downloadId = mDownloadManagerDelegate.addCompletedDownload(
mContext, downloadInfo.getFileName(), description, mimeType,
downloadInfo.getFilePath(), downloadInfo.getContentLength(),
downloadInfo.getOriginalUrl(), downloadInfo.getReferer());
+ downloadItem.setSystemDownloadId(downloadId);
+ return true;
} catch (RuntimeException e) {
Log.w(TAG, "Failed to add the download item to DownloadManager: ", e);
if (downloadInfo.getFilePath() != null) {
@@ -572,21 +584,22 @@ public class DownloadManagerService extends BroadcastReceiver implements
}
}
}
- return INVALID_DOWNLOAD_ID;
+ return false;
}
/**
* Handle auto opennable files after download completes.
+ * TODO(qinmin): move this to DownloadManagerDelegate.
*
- * @param info Information of the downloaded file.
- * @param downloadId Download identifier issued by the android DownloadManager.
+ * @param download A download item.
*/
- private void handleAutoOpenAfterDownload(DownloadInfo info, long downloadId) {
- if (isOMADownloadDescription(info)) {
- mOMADownloadHandler.handleOMADownload(info, downloadId);
+ private void handleAutoOpenAfterDownload(DownloadItem download) {
+ if (isOMADownloadDescription(download.getDownloadInfo())) {
+ mOMADownloadHandler.handleOMADownload(
+ download.getDownloadInfo(), download.getSystemDownloadId());
return;
}
- openDownloadedContent(downloadId);
+ openDownloadedContent(download.getSystemDownloadId());
}
/**
@@ -597,32 +610,32 @@ public class DownloadManagerService extends BroadcastReceiver implements
Runnable updateTask = new Runnable() {
@Override
public void run() {
- new AsyncTask<Void, Void, Map<DownloadInfo, Pair<Long, Boolean>>>() {
+ new AsyncTask<Void, Void, Map<DownloadItem, Boolean>>() {
@Override
- public Map<DownloadInfo, Pair<Long, Boolean>> doInBackground(
- Void... params) {
+ public Map<DownloadItem, Boolean> doInBackground(Void... params) {
return updateAllNotifications();
}
@Override
protected void onPostExecute(
- Map<DownloadInfo, Pair<Long, Boolean>> result) {
- for (Map.Entry<DownloadInfo, Pair<Long, Boolean>> entry :
- result.entrySet()) {
- DownloadInfo info = entry.getKey();
- long downloadId = entry.getValue().first;
- if (downloadId == INVALID_DOWNLOAD_ID) {
+ Map<DownloadItem, Boolean> result) {
+ for (Map.Entry<DownloadItem, Boolean> entry : result.entrySet()) {
+ DownloadItem download = entry.getKey();
+ if (!download.hasSystemDownloadId()) {
// TODO(qinmin): get the failure message from native.
- onDownloadFailed(info.getFileName(),
+ onDownloadFailed(download.getDownloadInfo().getFileName(),
DownloadManager.ERROR_UNKNOWN);
+ return;
+ }
+ boolean canResolve = entry.getValue();
+ if (canResolve && shouldOpenAfterDownload(
+ download.getDownloadInfo())) {
+ handleAutoOpenAfterDownload(download);
} else {
- boolean canResolve = entry.getValue().second;
- if (canResolve && shouldOpenAfterDownload(info)) {
- handleAutoOpenAfterDownload(info, downloadId);
- } else {
- mDownloadSnackbarController.onDownloadSucceeded(
- info, downloadId, canResolve);
- }
+ mDownloadSnackbarController.onDownloadSucceeded(
+ download.getDownloadInfo(),
+ download.getSystemDownloadId(),
+ canResolve);
}
}
}
@@ -637,25 +650,21 @@ public class DownloadManagerService extends BroadcastReceiver implements
/**
* Updates the progress of a download.
*
- * @param downloadInfo Information about the download.
+ * @param downloadItem Information about the download.
* @param downloadStatus Status of the download.
*/
- private void updateDownloadProgress(DownloadInfo downloadInfo, int downloadStatus) {
- assert downloadInfo.hasDownloadId();
- int downloadId = downloadInfo.getDownloadId();
- DownloadProgress progress = mDownloadProgressMap.get(downloadId);
+ private void updateDownloadProgress(DownloadItem downloadItem, int downloadStatus) {
+ String id = downloadItem.getId();
+ DownloadProgress progress = mDownloadProgressMap.get(id);
if (progress == null) {
- progress = new DownloadProgress(System.currentTimeMillis(), isActiveNetworkMetered(),
- downloadInfo, downloadStatus, true);
- mDownloadProgressMap.putIfAbsent(downloadId, progress);
- } else if (progress.mDownloadInfo.isPaused() && downloadInfo.isPaused()) {
- // when download is paused, this function can get called over and over. So stop updating
- // the notifications unless the status changes.
- progress.mUpdateNotification = false;
+ if (!downloadItem.getDownloadInfo().isPaused()) {
+ progress = new DownloadProgress(System.currentTimeMillis(),
+ isActiveNetworkMetered(), downloadItem, downloadStatus);
+ mDownloadProgressMap.putIfAbsent(id, progress);
+ }
} else {
progress.mDownloadStatus = downloadStatus;
- progress.mDownloadInfo = downloadInfo;
- progress.mUpdateNotification = true;
+ progress.mDownloadItem = downloadItem;
}
}
@@ -674,21 +683,21 @@ public class DownloadManagerService extends BroadcastReceiver implements
String action = intent.getAction();
if (!DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) return;
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID,
- INVALID_DOWNLOAD_ID);
- if (downloadId == INVALID_DOWNLOAD_ID) return;
+ DownloadItem.INVALID_DOWNLOAD_ID);
+ if (downloadId == DownloadItem.INVALID_DOWNLOAD_ID) return;
boolean isPendingOMADownload = mOMADownloadHandler.isPendingOMADownload(downloadId);
boolean isInOMASharedPrefs = isDownloadIdInOMASharedPrefs(downloadId);
if (isPendingOMADownload || isInOMASharedPrefs) {
clearPendingOMADownload(downloadId, null);
- mPendingDownloads.remove(downloadId);
+ mSystemDownloadIdMap.remove(downloadId);
return;
}
- DownloadInfo info = mPendingDownloads.get(downloadId);
- if (info != null) {
- DownloadCompletionTask task = new DownloadCompletionTask(info, downloadId);
+ DownloadItem downloadItem = mSystemDownloadIdMap.get(downloadId);
+ if (downloadItem != null) {
+ DownloadCompletionTask task = new DownloadCompletionTask(downloadItem);
task.execute();
- mPendingDownloads.remove(downloadId);
- if (mPendingDownloads.size() == 0) {
+ mSystemDownloadIdMap.remove(downloadId);
+ if (mSystemDownloadIdMap.size() == 0) {
mContext.unregisterReceiver(this);
}
}
@@ -698,27 +707,26 @@ public class DownloadManagerService extends BroadcastReceiver implements
* Async task to handle completed downloads.
*/
private class DownloadCompletionTask extends AsyncTask<Void, Void, Pair<Integer, Boolean>> {
- private final long mDownloadId;
- private final DownloadInfo mDownloadInfo;
+ private final DownloadItem mDownloadItem;
private int mFailureReason;
- public DownloadCompletionTask(DownloadInfo info, long downloadId) {
- mDownloadInfo = info;
- mDownloadId = downloadId;
+ public DownloadCompletionTask(DownloadItem downloadItem) {
+ mDownloadItem = downloadItem;
}
@Override
public Pair<Integer, Boolean> doInBackground(Void...voids) {
final DownloadManager manager =
(DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
- Cursor c = manager.query(new DownloadManager.Query().setFilterById(mDownloadId));
+ Cursor c = manager.query(new DownloadManager.Query().setFilterById(
+ mDownloadItem.getSystemDownloadId()));
int status = UNKNOWN_DOWNLOAD_STATUS;
boolean canResolve = false;
if (c.moveToNext()) {
status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
- canResolve = isOMADownloadDescription(mDownloadInfo)
- || canResolveDownloadItem(mContext, mDownloadId);
+ canResolve = isOMADownloadDescription(mDownloadItem.getDownloadInfo())
+ || canResolveDownloadItem(mContext, mDownloadItem);
} else if (status == DownloadManager.STATUS_FAILED) {
mFailureReason = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON));
}
@@ -731,15 +739,17 @@ public class DownloadManagerService extends BroadcastReceiver implements
protected void onPostExecute(Pair<Integer, Boolean> result) {
switch (result.first) {
case DownloadManager.STATUS_SUCCESSFUL:
- if (shouldOpenAfterDownload(mDownloadInfo) && result.second) {
- handleAutoOpenAfterDownload(mDownloadInfo, mDownloadId);
+ if (shouldOpenAfterDownload(mDownloadItem.getDownloadInfo()) && result.second) {
+ handleAutoOpenAfterDownload(mDownloadItem);
} else {
mDownloadSnackbarController.onDownloadSucceeded(
- mDownloadInfo, mDownloadId, result.second);
+ mDownloadItem.getDownloadInfo(),
+ mDownloadItem.getSystemDownloadId(),
+ result.second);
}
break;
case DownloadManager.STATUS_FAILED:
- onDownloadFailed(mDownloadInfo.getFileName(), mFailureReason);
+ onDownloadFailed(mDownloadItem.getDownloadInfo().getFileName(), mFailureReason);
break;
default:
break;
@@ -753,34 +763,36 @@ public class DownloadManagerService extends BroadcastReceiver implements
* content will be saved to the public directory on external storage. Otherwise, the
* download will be saved in the app directory and user will not get any notifications
* after download completion.
+ * TODO(qinmin): move this to DownloadManagerDelegate.
*
* @param info Download information about the download.
* @param notifyCompleted Whether to notify the user after Downloadmanager completes the
* download.
*/
- public void enqueueDownloadManagerRequest(final DownloadInfo info, boolean notifyCompleted) {
- EnqueueDownloadRequestTask task = new EnqueueDownloadRequestTask(info);
+ public void enqueueDownloadManagerRequest(
+ final DownloadItem item, boolean notifyCompleted) {
+ EnqueueDownloadRequestTask task = new EnqueueDownloadRequestTask(item);
task.execute(notifyCompleted);
}
/**
* Async task to enqueue a download request into DownloadManager.
*/
- private class EnqueueDownloadRequestTask extends
- AsyncTask<Boolean, Void, Boolean> {
+ private class EnqueueDownloadRequestTask extends AsyncTask<Boolean, Void, Boolean> {
private long mDownloadId;
- private DownloadInfo mDownloadInfo;
+ private final DownloadItem mDownloadItem;
private int mFailureReason;
- public EnqueueDownloadRequestTask(DownloadInfo downloadInfo) {
- mDownloadInfo = downloadInfo;
+ public EnqueueDownloadRequestTask(DownloadItem downloadItem) {
+ mDownloadItem = downloadItem;
}
@Override
public Boolean doInBackground(Boolean... booleans) {
boolean notifyCompleted = booleans[0];
- Uri uri = Uri.parse(mDownloadInfo.getUrl());
+ Uri uri = Uri.parse(mDownloadItem.getDownloadInfo().getUrl());
DownloadManager.Request request;
+ DownloadInfo info = mDownloadItem.getDownloadInfo();
try {
request = new DownloadManager.Request(uri);
} catch (IllegalArgumentException e) {
@@ -791,17 +803,17 @@ public class DownloadManagerService extends BroadcastReceiver implements
return false;
}
- request.setMimeType(mDownloadInfo.getMimeType());
+ request.setMimeType(info.getMimeType());
try {
if (notifyCompleted) {
// Set downloaded file destination to /sdcard/Download or, should it be
// set to one of several Environment.DIRECTORY* dirs depending on mimetype?
request.setDestinationInExternalPublicDir(
- Environment.DIRECTORY_DOWNLOADS, mDownloadInfo.getFileName());
+ Environment.DIRECTORY_DOWNLOADS, info.getFileName());
} else {
File dir = new File(mContext.getExternalFilesDir(null), DOWNLOAD_DIRECTORY);
if (dir.mkdir() || dir.isDirectory()) {
- File file = new File(dir, mDownloadInfo.getFileName());
+ File file = new File(dir, info.getFileName());
request.setDestinationUri(Uri.fromFile(file));
} else {
Log.e(TAG, "Cannot create download directory");
@@ -825,14 +837,14 @@ public class DownloadManagerService extends BroadcastReceiver implements
request.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_VISIBLE);
}
- String description = mDownloadInfo.getDescription();
+ String description = info.getDescription();
if (TextUtils.isEmpty(description)) {
- description = mDownloadInfo.getFileName();
+ description = info.getFileName();
}
request.setDescription(description);
- request.addRequestHeader("Cookie", mDownloadInfo.getCookie());
- request.addRequestHeader("Referer", mDownloadInfo.getReferer());
- request.addRequestHeader("User-Agent", mDownloadInfo.getUserAgent());
+ request.addRequestHeader("Cookie", info.getCookie());
+ request.addRequestHeader("Referer", info.getReferer());
+ request.addRequestHeader("User-Agent", info.getUserAgent());
DownloadManager manager =
(DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
@@ -854,13 +866,14 @@ public class DownloadManagerService extends BroadcastReceiver implements
@Override
protected void onPostExecute(Boolean result) {
- boolean isPendingOMADownload =
- mOMADownloadHandler.isPendingOMADownload(mDownloadInfo.getDownloadId());
+ boolean isPendingOMADownload = mOMADownloadHandler.isPendingOMADownload(
+ mDownloadItem.getSystemDownloadId());
if (!result) {
- onDownloadFailed(mDownloadInfo.getFileName(), mFailureReason);
+ onDownloadFailed(mDownloadItem.getDownloadInfo().getFileName(), mFailureReason);
if (isPendingOMADownload) {
mOMADownloadHandler.onDownloadFailed(
- mDownloadInfo, DownloadManager.ERROR_UNKNOWN, null);
+ mDownloadItem.getDownloadInfo(), mDownloadItem.getSystemDownloadId(),
+ DownloadManager.ERROR_UNKNOWN, null);
}
return;
}
@@ -868,8 +881,8 @@ public class DownloadManagerService extends BroadcastReceiver implements
if (isPendingOMADownload) {
// A new downloadId is generated, needs to update the OMADownloadHandler
// about this.
- mDownloadInfo = mOMADownloadHandler.updateDownloadInfo(
- mDownloadInfo, mDownloadId);
+ mOMADownloadHandler.updateDownloadInfo(
+ mDownloadItem.getSystemDownloadId(), mDownloadId);
// TODO(qinmin): use a file instead of shared prefs to save the
// OMA information in case chrome is killed. This will allow us to
// save more information like cookies and user agent.
@@ -879,11 +892,12 @@ public class DownloadManagerService extends BroadcastReceiver implements
addOMADownloadToSharedPrefs(entry.generateSharedPrefsString());
}
}
- if (mPendingDownloads.size() == 0) {
+ if (mSystemDownloadIdMap.size() == 0) {
mContext.registerReceiver(DownloadManagerService.this,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
- mPendingDownloads.put(mDownloadId, mDownloadInfo);
+ mDownloadItem.setSystemDownloadId(mDownloadId);
+ mSystemDownloadIdMap.put(mDownloadId, mDownloadItem);
}
}
@@ -979,18 +993,19 @@ public class DownloadManagerService extends BroadcastReceiver implements
* Return whether a download item can be resolved to any activity.
*
* @param context Context of the app.
- * @param downloadId ID of the download item in DownloadManager.
+ * @param download A download item.
* @return true if the download item can be resolved, or false otherwise.
*/
- private static boolean canResolveDownloadItem(Context context, long downloadId) {
+ private static boolean canResolveDownloadItem(Context context, DownloadItem download) {
assert !ThreadUtils.runningOnUiThread();
- Intent intent = getLaunchIntentFromDownloadId(context, downloadId);
+ Intent intent = getLaunchIntentFromDownloadId(context, download.getSystemDownloadId());
return (intent == null) ? false : ExternalNavigationDelegateImpl.resolveIntent(
context, intent, true);
}
/**
* Launch the intent for a given download item.
+ * TODO(qinmin): Move this to DownloadManagerDelegate.
*
* @param downloadId ID of the download item in DownloadManager.
*/
@@ -1079,25 +1094,27 @@ public class DownloadManagerService extends BroadcastReceiver implements
/**
* Called to cancel a download notification.
- * @param downloadId Id of the download.
+ * @param notificationId Notification Id of the download.
*/
- void cancelNotification(int downloadId) {
- mDownloadNotifier.cancelNotification(downloadId);
+ void cancelNotification(int notificationId) {
+ mDownloadNotifier.cancelNotification(notificationId);
}
/**
* Called to resume a paused download.
- * @param downloadId Id of the download.
+ * @param notificationId Notification Id of the download.
+ * @param downloadGuid GUID of the download.
* @param fileName Name of the download file.
* @param hasUserGesture Whether the resumption is triggered by user gesture.
*/
@VisibleForTesting
- protected void resumeDownload(int downloadId, String fileName, boolean hasUserGesture) {
+ protected void resumeDownload(
+ int notificationId, String downloadGuid, String fileName, boolean hasUserGesture) {
int uma = hasUserGesture ? UMA_DOWNLOAD_RESUMPTION_CLICKED
: UMA_DOWNLOAD_RESUMPTION_AUTO_STARTED;
recordDownloadResumption(uma);
if (hasUserGesture) {
- DownloadProgress progress = mDownloadProgressMap.get(downloadId);
+ DownloadProgress progress = mDownloadProgressMap.get(downloadGuid);
// If user manually resumes a download, update the connection type that the download
// can start. If the previous connection type is metered, manually resuming on an
// unmetered network should not affect the original connection type.
@@ -1105,29 +1122,37 @@ public class DownloadManagerService extends BroadcastReceiver implements
progress.mCanDownloadWhileMetered = isActiveNetworkMetered();
}
}
- nativeResumeDownload(mNativeDownloadManagerService, downloadId, fileName);
+ nativeResumeDownload(mNativeDownloadManagerService, notificationId, downloadGuid, fileName);
}
/**
* Called to cancel a download.
- * @param downloadId Id of the download.
+ * @param downloadGuid GUID of the download.
*/
- void cancelDownload(int downloadId) {
- nativeCancelDownload(mNativeDownloadManagerService, downloadId);
+ void cancelDownload(String downloadGuid) {
+ nativeCancelDownload(mNativeDownloadManagerService, downloadGuid);
}
/**
* Called to pause a download.
- * @param downloadId Id of the download.
+ * @param downloadGuid GUID of the download.
*/
- void pauseDownload(int downloadId) {
- nativePauseDownload(mNativeDownloadManagerService, downloadId);
+ void pauseDownload(String downloadGuid) {
+ nativePauseDownload(mNativeDownloadManagerService, downloadGuid);
+ // Calling pause will stop listening to the download item. Update its progress now.
+ DownloadProgress progress = mDownloadProgressMap.get(downloadGuid);
+ if (progress != null) {
+ DownloadInfo info = DownloadInfo.Builder.fromDownloadInfo(
+ progress.mDownloadItem.getDownloadInfo()).setIsPaused(true).build();
+ onDownloadUpdated(info);
+ }
}
@CalledByNative
- void onResumptionFailed(int downloadId, String fileName) {
+ void onResumptionFailed(int notificationId, String fileName) {
mDownloadNotifier.notifyDownloadFailed(
- new DownloadInfo.Builder().setDownloadId(downloadId).setFileName(fileName).build());
+ new DownloadInfo.Builder().setNotificationId(notificationId).setFileName(
+ fileName).build());
recordDownloadResumption(UMA_DOWNLOAD_RESUMPTION_FAILED);
}
@@ -1135,9 +1160,9 @@ public class DownloadManagerService extends BroadcastReceiver implements
* Called to record the UMA histograms for all auto paused downloads when browser is killed.
*/
private void recordAutoPausedDownloads() {
- List<DownloadNotificationService.PendingNotification> downloads =
- DownloadNotificationService.parseDownloadNotificationsFromSharedPrefs(mSharedPrefs);
- for (DownloadNotificationService.PendingNotification download : downloads) {
+ List<DownloadSharedPreferenceEntry> entries =
+ DownloadNotificationService.parseDownloadSharedPrefs(mSharedPrefs);
+ for (int i = 0; i < entries.size(); ++i) {
recordDownloadResumption(UMA_DOWNLOAD_RESUMPTION_BROWSER_KILLED);
}
}
@@ -1173,25 +1198,25 @@ public class DownloadManagerService extends BroadcastReceiver implements
/**
* Helper method to add an auto resumable download.
- * @param downloadId Id of the download item.
+ * @param guid Id of the download item.
*/
- private void addAutoResumableDownload(int downloadId) {
+ private void addAutoResumableDownload(String guid) {
if (mAutoResumableDownloadIds.isEmpty() && !mIsNetworkChangeNotifierDisabled) {
mNetworkChangeNotifier = new NetworkChangeNotifierAutoDetect(this, mContext,
new RegistrationPolicyAlwaysRegister());
}
- if (!mAutoResumableDownloadIds.contains(downloadId)) {
- mAutoResumableDownloadIds.add(downloadId);
+ if (!mAutoResumableDownloadIds.contains(guid)) {
+ mAutoResumableDownloadIds.add(guid);
}
}
/**
* Helper method to remove an auto resumable download.
- * @param downloadId Id of the download item.
+ * @param guid Id of the download item.
*/
- private void removeAutoResumableDownload(int downloadId) {
+ private void removeAutoResumableDownload(String guid) {
if (mAutoResumableDownloadIds.isEmpty()) return;
- mAutoResumableDownloadIds.remove(Integer.valueOf(downloadId));
+ mAutoResumableDownloadIds.remove(guid);
stopListenToConnectionChangeIfNotNeeded();
}
@@ -1200,10 +1225,10 @@ public class DownloadManagerService extends BroadcastReceiver implements
if (mAutoResumableDownloadIds.isEmpty()) return;
if (connectionType == ConnectionType.CONNECTION_NONE) return;
boolean isMetered = isActiveNetworkMetered();
- Iterator<Integer> iterator = mAutoResumableDownloadIds.iterator();
+ Iterator<String> iterator = mAutoResumableDownloadIds.iterator();
while (iterator.hasNext()) {
- final int downloadId = iterator.next();
- final DownloadProgress progress = mDownloadProgressMap.get(downloadId);
+ final String id = iterator.next();
+ final DownloadProgress progress = mDownloadProgressMap.get(id);
// Introduce some delay in each resumption so we don't start all of them immediately.
if (progress.mCanDownloadWhileMetered || !isMetered) {
// Remove the pending resumable item so that the task won't be posted again on the
@@ -1214,7 +1239,8 @@ public class DownloadManagerService extends BroadcastReceiver implements
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
- resumeDownload(downloadId, progress.mDownloadInfo.getFileName(), false);
+ resumeDownload(progress.mDownloadItem.getNotificationId(), id,
+ progress.mDownloadItem.getDownloadInfo().getFileName(), false);
}
}, mUpdateDelayInMillis);
}
@@ -1249,8 +1275,9 @@ public class DownloadManagerService extends BroadcastReceiver implements
public void updateActiveNetworkList(int[] activeNetIds) {}
private native long nativeInit();
- private native void nativeResumeDownload(
- long nativeDownloadManagerService, int downloadId, String fileName);
- private native void nativeCancelDownload(long nativeDownloadManagerService, int downloadId);
- private native void nativePauseDownload(long nativeDownloadManagerService, int downloadId);
+ private native void nativeResumeDownload(long nativeDownloadManagerService, int notificationId,
+ String downloadGuid, String fileName);
+ private native void nativeCancelDownload(
+ long nativeDownloadManagerService, String downloadGuid);
+ private native void nativePauseDownload(long nativeDownloadManagerService, String downloadGuid);
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
index b0a435a..c4f78fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -39,7 +39,8 @@ import java.util.Set;
* Chrome gets killed.
*/
public class DownloadNotificationService extends Service {
- static final String EXTRA_DOWNLOAD_ID = "DownloadId";
+ static final String EXTRA_DOWNLOAD_NOTIFICATION_ID = "DownloadNotificationId";
+ static final String EXTRA_DOWNLOAD_GUID = "DownloadGuid";
static final String EXTRA_DOWNLOAD_FILE_NAME = "DownloadFileName";
static final String ACTION_DOWNLOAD_CANCEL =
"org.chromium.chrome.browser.download.DOWNLOAD_CANCEL";
@@ -58,50 +59,6 @@ public class DownloadNotificationService extends Service {
private Context mContext;
/**
- * Class representing a pending notification entry.
- */
- @VisibleForTesting
- static class PendingNotification {
- public final int downloadId;
- public final String fileName;
- public final boolean isResumable;
-
- PendingNotification(int downloadId, String fileName, boolean isResumable) {
- this.downloadId = downloadId;
- this.fileName = fileName;
- this.isResumable = isResumable;
- }
-
- /**
- * Parse the pending notification from a String object in SharedPrefs.
- *
- * @param notification String containing the notification ID, file name and whether it is
- * resumable.
- * @return a PendingNotification object.
- */
- static PendingNotification parseFromString(String notification) {
- String[] values = notification.split(",", 3);
- if (values.length == 3) {
- try {
- int id = Integer.parseInt(values[0]);
- boolean isResumable = "1".equals(values[1]);
- return new PendingNotification(id, values[2], isResumable);
- } catch (NumberFormatException nfe) {
- Log.w(TAG, "Exception while parsing pending download:" + notification);
- }
- }
- return new PendingNotification(-1, "", false);
- }
-
- /**
- * Generate a string for the PendingNotification instance to be inserted into SharedPrefs.
- */
- String getNotificationString() {
- return downloadId + "," + (isResumable ? "1" : "0") + "," + fileName;
- }
- }
-
- /**
* Class for clients to access.
*/
public class LocalBinder extends Binder {
@@ -157,7 +114,8 @@ public class DownloadNotificationService extends Service {
/**
* Add a in-progress download notification.
- * @param downloadId ID of the download.
+ * @param notificationId Notification ID of the download.
+ * @param downloadGuid GUID of the download.
* @param fileName File name of the download.
* @param percentage Percentage completed. Value should be between 0 to 100 if
* the percentage can be determined, or -1 if it is unknown.
@@ -165,9 +123,8 @@ public class DownloadNotificationService extends Service {
* @param startTime Time when download started.
* @param isResumable whether the download can be resumed.
*/
- public void notifyDownloadProgress(
- int downloadId, String fileName, int percentage, long timeRemainingInMillis,
- long startTime, boolean isResumable) {
+ public void notifyDownloadProgress(int notificationId, String downloadGuid, String fileName,
+ int percentage, long timeRemainingInMillis, long startTime, boolean isResumable) {
boolean indeterminate = percentage == INVALID_DOWNLOAD_PERCENTAGE;
NotificationCompat.Builder builder = buildNotification(
android.R.drawable.stat_sys_download, fileName, null);
@@ -181,40 +138,43 @@ public class DownloadNotificationService extends Service {
if (startTime > 0) builder.setWhen(startTime);
builder.addAction(android.R.drawable.ic_menu_close_clear_cancel,
mContext.getResources().getString(R.string.download_notification_cancel_button),
- buildPendingIntent(ACTION_DOWNLOAD_CANCEL, downloadId, fileName));
+ buildPendingIntent(ACTION_DOWNLOAD_CANCEL, notificationId, downloadGuid, fileName));
if (isResumable) {
builder.addAction(android.R.drawable.ic_media_pause,
mContext.getResources().getString(R.string.download_notification_pause_button),
- buildPendingIntent(ACTION_DOWNLOAD_PAUSE, downloadId, fileName));
+ buildPendingIntent(ACTION_DOWNLOAD_PAUSE, notificationId, downloadGuid,
+ fileName));
}
- updateNotification(downloadId, builder.build());
- addPendingDownloadToSharedPrefs(new PendingNotification(downloadId, fileName, isResumable));
+ updateNotification(notificationId, builder.build());
+ addEntryToSharedPrefs(new DownloadSharedPreferenceEntry(
+ notificationId, isResumable, true, downloadGuid, fileName));
}
/**
* Cancel a download notification.
- * @param downloadId ID of the download.
+ * @param notificationId Notification ID of the download.
*/
- public void cancelNotification(int downloadId) {
- mNotificationManager.cancel(NOTIFICATION_NAMESPACE, downloadId);
- removePendingDownloadFromSharedPrefs(downloadId);
+ public void cancelNotification(int notificationId) {
+ mNotificationManager.cancel(NOTIFICATION_NAMESPACE, notificationId);
+ removeEntryFromSharedPrefs(notificationId);
}
/**
* Change a download notification to paused state.
- * @param downloadId ID of the download.
+ * @param notificationId Notification ID of the download.
+ * @param downloadGuid GUID of the download.
* @param fileName File name of the download.
* @param isResumable whether download is resumable.
* @param isAutoResumable whether download is can be resumed automatically.
*/
- public void notifyDownloadPaused(
- int downloadId, String fileName, boolean isResumable, boolean isAutoResumable) {
+ public void notifyDownloadPaused(int notificationId, String downloadGuid, String fileName,
+ boolean isResumable, boolean isAutoResumable) {
NotificationCompat.Builder builder = buildNotification(
android.R.drawable.ic_media_pause,
fileName,
mContext.getResources().getString(R.string.download_notification_paused));
PendingIntent cancelIntent =
- buildPendingIntent(ACTION_DOWNLOAD_CANCEL, downloadId, fileName);
+ buildPendingIntent(ACTION_DOWNLOAD_CANCEL, notificationId, downloadGuid, fileName);
builder.setDeleteIntent(cancelIntent);
builder.addAction(android.R.drawable.ic_menu_close_clear_cancel,
mContext.getResources().getString(R.string.download_notification_cancel_button),
@@ -222,22 +182,23 @@ public class DownloadNotificationService extends Service {
if (isResumable) {
builder.addAction(android.R.drawable.stat_sys_download_done,
mContext.getResources().getString(R.string.download_notification_resume_button),
- buildPendingIntent(ACTION_DOWNLOAD_RESUME, downloadId, fileName));
+ buildPendingIntent(ACTION_DOWNLOAD_RESUME, notificationId, downloadGuid,
+ fileName));
}
- updateNotification(downloadId, builder.build());
+ updateNotification(notificationId, builder.build());
// If download is not auto resumable, there is no need to keep it in SharedPreferences.
if (!isResumable || !isAutoResumable) {
- removePendingDownloadFromSharedPrefs(downloadId);
+ removeEntryFromSharedPrefs(notificationId);
}
}
/**
* Add a download successful notification.
- * @param downloadId ID of the download.
+ * @param notificationId Notification ID of the download.
* @param fileName File name of the download.
* @param intent Intent to launch when clicking the notification.
*/
- public void notifyDownloadSuccessful(int downloadId, String fileName, Intent intent) {
+ public void notifyDownloadSuccessful(int notificationId, String fileName, Intent intent) {
NotificationCompat.Builder builder = buildNotification(
android.R.drawable.stat_sys_download_done,
fileName,
@@ -246,23 +207,23 @@ public class DownloadNotificationService extends Service {
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
- updateNotification(downloadId, builder.build());
- removePendingDownloadFromSharedPrefs(downloadId);
+ updateNotification(notificationId, builder.build());
+ removeEntryFromSharedPrefs(notificationId);
}
/**
* Add a download failed notification.
- * @param downloadId ID of the download.
+ * @param notificationId Notification ID of the download.
* @param fileName File name of the download.
* @param intent Intent to launch when clicking the notification.
*/
- public void notifyDownloadFailed(int downloadId, String fileName) {
+ public void notifyDownloadFailed(int notificationId, String fileName) {
NotificationCompat.Builder builder = buildNotification(
android.R.drawable.stat_sys_download_done,
fileName,
mContext.getResources().getString(R.string.download_notification_failed));
- updateNotification(downloadId, builder.build());
- removePendingDownloadFromSharedPrefs(downloadId);
+ updateNotification(notificationId, builder.build());
+ removeEntryFromSharedPrefs(notificationId);
}
/**
@@ -270,26 +231,27 @@ public class DownloadNotificationService extends Service {
*/
@VisibleForTesting
void pauseAllDownloads() {
- List<PendingNotification> notifications =
- parseDownloadNotificationsFromSharedPrefs(mSharedPrefs);
- for (int i = 0; i < notifications.size(); ++i) {
- PendingNotification notification = notifications.get(i);
- if (notification.downloadId > 0) {
- notifyDownloadPaused(notification.downloadId, notification.fileName,
- notification.isResumable, true);
+ List<DownloadSharedPreferenceEntry> entries = parseDownloadSharedPrefs(mSharedPrefs);
+ for (int i = 0; i < entries.size(); ++i) {
+ DownloadSharedPreferenceEntry entry = entries.get(i);
+ if (entry.notificationId > 0) {
+ notifyDownloadPaused(entry.notificationId, entry.downloadGuid, entry.fileName,
+ entry.isResumable, true);
}
}
}
- private PendingIntent buildPendingIntent(String action, int downloadId, String fileName) {
+ private PendingIntent buildPendingIntent(
+ String action, int notificationId, String downloadGuid, String fileName) {
ComponentName component = new ComponentName(
mContext.getPackageName(), DownloadBroadcastReceiver.class.getName());
Intent intent = new Intent(action);
intent.setComponent(component);
- intent.putExtra(EXTRA_DOWNLOAD_ID, downloadId);
+ intent.putExtra(EXTRA_DOWNLOAD_NOTIFICATION_ID, notificationId);
+ intent.putExtra(EXTRA_DOWNLOAD_GUID, downloadGuid);
intent.putExtra(EXTRA_DOWNLOAD_FILE_NAME, fileName);
return PendingIntent.getBroadcast(
- mContext, downloadId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
/**
@@ -316,8 +278,10 @@ public class DownloadNotificationService extends Service {
* @param intent Intent with the download operation.
*/
private void handleDownloadOperation(final Intent intent) {
- final int downloadId = IntentUtils.safeGetIntExtra(
- intent, DownloadNotificationService.EXTRA_DOWNLOAD_ID, -1);
+ final int notificationId = IntentUtils.safeGetIntExtra(
+ intent, DownloadNotificationService.EXTRA_DOWNLOAD_NOTIFICATION_ID, -1);
+ final String guid = IntentUtils.safeGetStringExtra(
+ intent, DownloadNotificationService.EXTRA_DOWNLOAD_GUID);
final String fileName = IntentUtils.safeGetStringExtra(
intent, DownloadNotificationService.EXTRA_DOWNLOAD_FILE_NAME);
// If browser process already goes away, the download should have already paused. Do nothing
@@ -336,16 +300,16 @@ public class DownloadNotificationService extends Service {
// TODO(qinmin): Alternatively, we can delete the downloaded content on
// SD card, and remove the download ID from the SharedPreferences so we
// don't need to restart the browser process. http://crbug.com/579643.
- service.cancelDownload(downloadId);
- cancelNotification(downloadId);
+ service.cancelDownload(guid);
+ cancelNotification(notificationId);
break;
case ACTION_DOWNLOAD_PAUSE:
- service.pauseDownload(downloadId);
+ service.pauseDownload(guid);
break;
case ACTION_DOWNLOAD_RESUME:
- service.resumeDownload(downloadId, fileName, true);
- notifyDownloadProgress(
- downloadId, fileName, INVALID_DOWNLOAD_PERCENTAGE, 0, 0, true);
+ service.resumeDownload(notificationId, guid, fileName, true);
+ notifyDownloadProgress(notificationId, guid, fileName,
+ INVALID_DOWNLOAD_PERCENTAGE, 0, 0, true);
break;
default:
Log.e(TAG, "Unrecognized intent action.", intent);
@@ -384,52 +348,56 @@ public class DownloadNotificationService extends Service {
&& !ACTION_DOWNLOAD_PAUSE.equals(intent.getAction())) {
return false;
}
- if (!intent.hasExtra(DownloadNotificationService.EXTRA_DOWNLOAD_ID)
- || !intent.hasExtra(DownloadNotificationService.EXTRA_DOWNLOAD_FILE_NAME)) {
+ if (!intent.hasExtra(EXTRA_DOWNLOAD_NOTIFICATION_ID)
+ || !intent.hasExtra(EXTRA_DOWNLOAD_FILE_NAME)
+ || !intent.hasExtra(EXTRA_DOWNLOAD_GUID)) {
return false;
}
- final int downloadId = IntentUtils.safeGetIntExtra(
- intent, DownloadNotificationService.EXTRA_DOWNLOAD_ID, -1);
- if (downloadId == -1) return false;
- final String fileName = IntentUtils.safeGetStringExtra(
- intent, DownloadNotificationService.EXTRA_DOWNLOAD_FILE_NAME);
+ final int notificationId =
+ IntentUtils.safeGetIntExtra(intent, EXTRA_DOWNLOAD_NOTIFICATION_ID, -1);
+ if (notificationId == -1) return false;
+ final String fileName = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_FILE_NAME);
if (fileName == null) return false;
+ final String guid = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_GUID);
+ if (!DownloadSharedPreferenceEntry.isValidGUID(guid)) return false;
return true;
}
/**
- * Add a pending download to SharedPrefs, the string consists of the download ID, file name and
- * whether it is resumable. If the download ID already exists in SharedPrefs, do nothing.
- * @param pendingNotification Pending download entry.
+ * Add a DownloadSharedPreferenceEntry to SharedPrefs. If the notification ID already exists
+ * in SharedPrefs, do nothing.
+ * @param DownloadSharedPreferenceEntry A DownloadSharedPreferenceEntry to be added.
*/
- private void addPendingDownloadToSharedPrefs(PendingNotification pendingNotification) {
- Set<String> pendingDownloads = DownloadManagerService.getStoredDownloadInfo(
+ private void addEntryToSharedPrefs(DownloadSharedPreferenceEntry pendingEntry) {
+ Set<String> entries = DownloadManagerService.getStoredDownloadInfo(
mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS);
- for (String download : pendingDownloads) {
- PendingNotification notification = PendingNotification.parseFromString(download);
- if (notification.downloadId == pendingNotification.downloadId) return;
+ for (String entryString : entries) {
+ DownloadSharedPreferenceEntry entry =
+ DownloadSharedPreferenceEntry.parseFromString(entryString);
+ if (entry.notificationId == pendingEntry.notificationId) return;
}
- pendingDownloads.add(pendingNotification.getNotificationString());
+ entries.add(pendingEntry.getSharedPreferenceString());
DownloadManagerService.storeDownloadInfo(
- mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS, pendingDownloads);
+ mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS, entries);
}
/**
- * Removes a pending donwload from SharedPrefs.
- * @param downloadId ID to be removed.
+ * Removes a DownloadSharedPreferenceEntry from SharedPrefs.
+ * @param notificationId Notification ID to be removed.
*/
- private void removePendingDownloadFromSharedPrefs(int downloadId) {
- Set<String> pendingDownloads = DownloadManagerService.getStoredDownloadInfo(
+ private void removeEntryFromSharedPrefs(int notificationId) {
+ Set<String> entries = DownloadManagerService.getStoredDownloadInfo(
mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS);
- for (String download : pendingDownloads) {
- PendingNotification notification = PendingNotification.parseFromString(download);
- if (notification.downloadId == downloadId) {
- pendingDownloads.remove(download);
- if (pendingDownloads.isEmpty()) {
+ for (String entryString : entries) {
+ DownloadSharedPreferenceEntry entry =
+ DownloadSharedPreferenceEntry.parseFromString(entryString);
+ if (entry.notificationId == notificationId) {
+ entries.remove(entryString);
+ if (entries.isEmpty()) {
mSharedPrefs.edit().remove(PENDING_DOWNLOAD_NOTIFICATIONS).apply();
} else {
DownloadManagerService.storeDownloadInfo(
- mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS, pendingDownloads);
+ mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS, entries);
}
break;
}
@@ -444,17 +412,17 @@ public class DownloadNotificationService extends Service {
}
/**
- * Parse the download notifications from the shared preference and return a list of them.
- * @return a list of parsed notifications.
+ * Parse the DownloadSharedPreferenceEntry from the shared preference and return a list of them.
+ * @return a list of parsed DownloadSharedPreferenceEntry.
*/
- static List<PendingNotification> parseDownloadNotificationsFromSharedPrefs(
+ static List<DownloadSharedPreferenceEntry> parseDownloadSharedPrefs(
SharedPreferences prefs) {
- List<PendingNotification> result = new ArrayList<PendingNotification>();
+ List<DownloadSharedPreferenceEntry> result = new ArrayList<DownloadSharedPreferenceEntry>();
if (prefs.contains(PENDING_DOWNLOAD_NOTIFICATIONS)) {
- Set<String> pendingDownloads = DownloadManagerService.getStoredDownloadInfo(
+ Set<String> entries = DownloadManagerService.getStoredDownloadInfo(
prefs, PENDING_DOWNLOAD_NOTIFICATIONS);
- for (String download : pendingDownloads) {
- result.add(PendingNotification.parseFromString(download));
+ for (String entryString : entries) {
+ result.add(DownloadSharedPreferenceEntry.parseFromString(entryString));
}
}
return result;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotifier.java
index d75619d..4c16ae4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotifier.java
@@ -43,9 +43,9 @@ public interface DownloadNotifier {
/**
* Cancel the notification for a download.
- * @param downloadId the downloadId of the cancelled download.
+ * @param notificationId The notification ID of the cancelled download.
*/
- void cancelNotification(int downloadId);
+ void cancelNotification(int notificationId);
/**
* Called to clear all the pending download entries in SharedPreferences.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java
new file mode 100644
index 0000000..a231496
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java
@@ -0,0 +1,96 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.download;
+
+import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
+
+import java.util.UUID;
+
+/**
+ * Class representing the download information stored in SharedPreferences to construct a
+ * download notification.
+ */
+public class DownloadSharedPreferenceEntry {
+ private static final String TAG = "DownloadEntry";
+ // Current version of the DownloadSharedPreferenceEntry. When changing the SharedPreference,
+ // we need to change the version number too.
+ @VisibleForTesting static final int VERSION = 1;
+ public final int notificationId;
+ public final boolean isResumable;
+ // This field is not yet used, but will soon be used. We add it here to avoid changing the
+ // format of the SharedPreference string again.
+ public final boolean isStartedOnMeteredNetwork;
+ public final String fileName;
+ public final String downloadGuid;
+
+ DownloadSharedPreferenceEntry(int notificationId, boolean isResumable,
+ boolean isStartedOnMeteredNetwork, String guid, String fileName) {
+ this.notificationId = notificationId;
+ this.isResumable = isResumable;
+ this.isStartedOnMeteredNetwork = isStartedOnMeteredNetwork;
+ this.downloadGuid = guid;
+ this.fileName = fileName;
+ }
+
+ /**
+ * Parse the pending notification from a String object in SharedPrefs.
+ *
+ * @param sharedPrefString String from SharedPreference, containing the notification ID, GUID,
+ * file name, whether it is resumable and whether download started on a metered network.
+ * @return a DownloadSharedPreferenceEntry object.
+ */
+ static DownloadSharedPreferenceEntry parseFromString(String sharedPrefString) {
+ String[] values = sharedPrefString.split(",", 6);
+ if (values.length == 6) {
+ try {
+ int version = Integer.parseInt(values[0]);
+ // Ignore all SharedPreference entries that has an invalid version for now.
+ if (version != VERSION) {
+ return new DownloadSharedPreferenceEntry(-1, false, false, null, "");
+ }
+ int id = Integer.parseInt(values[1]);
+ boolean isResumable = "1".equals(values[2]);
+ boolean isStartedOnMeteredNetwork = "1".equals(values[3]);
+ if (!isValidGUID(values[4])) {
+ return new DownloadSharedPreferenceEntry(-1, false, false, null, "");
+ }
+ return new DownloadSharedPreferenceEntry(
+ id, isResumable, isStartedOnMeteredNetwork, values[4], values[5]);
+ } catch (NumberFormatException nfe) {
+ Log.w(TAG, "Exception while parsing pending download:" + sharedPrefString);
+ }
+ }
+ return new DownloadSharedPreferenceEntry(-1, false, false, null, "");
+ }
+
+ /**
+ * @return a string for the DownloadSharedPreferenceEntry instance to be inserted into
+ * SharedPrefs.
+ */
+ String getSharedPreferenceString() {
+ return VERSION + "," + notificationId + "," + (isResumable ? "1" : "0") + ","
+ + (isStartedOnMeteredNetwork ? "1" : "0") + "," + downloadGuid + "," + fileName;
+ }
+
+ /**
+ * Check if a string is a valid GUID. GUID is RFC 4122 compliant, it should have format
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
+ * TODO(qinmin): move this to base/.
+ * @return true if the string is a valid GUID, or false otherwise.
+ */
+ static boolean isValidGUID(String guid) {
+ if (guid == null) return false;
+ try {
+ // Java UUID class doesn't check the length of the string. Need to convert it back to
+ // string so that we can validate the length of the original string.
+ UUID uuid = UUID.fromString(guid);
+ String uuidString = uuid.toString();
+ return guid.equalsIgnoreCase(uuidString);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java
index 354b656..d918315 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java
@@ -35,7 +35,7 @@ public class DownloadSnackbarController implements SnackbarManager.SnackbarContr
Pair<DownloadInfo, Long> download = (Pair<DownloadInfo, Long>) actionData;
DownloadManagerService manager = DownloadManagerService.getDownloadManagerService(mContext);
manager.openDownloadedContent(download.second);
- manager.cancelNotification(download.first.getDownloadId());
+ manager.cancelNotification(download.first.getNotificationId());
}
@Override
@@ -46,7 +46,7 @@ public class DownloadSnackbarController implements SnackbarManager.SnackbarContr
* Called to display the download succeeded snackbar.
*
* @param downloadInfo Info of the download.
- * @param downloadId Id of the download.
+ * @param downloadId Id of the download from Android DownloadManager.
* @param canBeResolved Whether the download can be resolved to any activity.
*/
public void onDownloadSucceeded(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java
index 11002e7..0bbb1e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java
@@ -244,13 +244,15 @@ public class OMADownloadHandler {
// Send notification if required attributes are missing.
if (omaInfo.getTypes().isEmpty() || getSize(omaInfo) <= 0
|| omaInfo.isValueEmpty(OMA_OBJECT_URI)) {
- sendNotification(omaInfo, mDownloadInfo, DOWNLOAD_STATUS_INVALID_DESCRIPTOR);
+ sendNotification(omaInfo, mDownloadInfo, DownloadItem.INVALID_DOWNLOAD_ID,
+ DOWNLOAD_STATUS_INVALID_DESCRIPTOR);
return;
}
// Check version. Null version are treated as 1.0.
String version = omaInfo.getValue(OMA_DD_VERSION);
if (version != null && !version.startsWith("1.")) {
- sendNotification(omaInfo, mDownloadInfo, DOWNLOAD_STATUS_INVALID_DDVERSION);
+ sendNotification(omaInfo, mDownloadInfo, DownloadItem.INVALID_DOWNLOAD_ID,
+ DOWNLOAD_STATUS_INVALID_DDVERSION);
return;
}
// Check device capabilities.
@@ -274,16 +276,17 @@ public class OMADownloadHandler {
* Called when the content is successfully downloaded by the Android DownloadManager.
*
* @param downloadInfo The information about the download.
+ * @param downloadId Download Id from the Android DownloadManager.
* @param notifyURI The previously saved installNotifyURI attribute.
*/
- public void onDownloadCompleted(DownloadInfo downloadInfo, String notifyURI) {
- long downloadId = downloadInfo.getDownloadId();
+ public void onDownloadCompleted(DownloadInfo downloadInfo, long downloadId, String notifyURI) {
OMAInfo omaInfo = mPendingOMADownloads.get(downloadId);
if (omaInfo == null) {
omaInfo = new OMAInfo();
omaInfo.addAttributeValue(OMA_INSTALL_NOTIFY_URI, notifyURI);
}
- sendInstallNotificationAndNextStep(omaInfo, downloadInfo, DOWNLOAD_STATUS_SUCCESS);
+ sendInstallNotificationAndNextStep(
+ omaInfo, downloadInfo, downloadId, DOWNLOAD_STATUS_SUCCESS);
mPendingOMADownloads.remove(downloadId);
}
@@ -291,10 +294,12 @@ public class OMADownloadHandler {
* Called when android DownloadManager fails to download the content.
*
* @param downloadInfo The information about the download.
+ * @param downloadId Download Id from the Android DownloadManager.
* @param reason The reason of failure.
* @param notifyURI The previously saved installNotifyURI attribute.
*/
- public void onDownloadFailed(DownloadInfo downloadInfo, int reason, String notifyURI) {
+ public void onDownloadFailed(
+ DownloadInfo downloadInfo, long downloadId, int reason, String notifyURI) {
String status = DOWNLOAD_STATUS_DEVICE_ABORTED;
switch (reason) {
case DownloadManager.ERROR_CANNOT_RESUME:
@@ -311,13 +316,12 @@ public class OMADownloadHandler {
default:
break;
}
- long downloadId = downloadInfo.getDownloadId();
OMAInfo omaInfo = mPendingOMADownloads.get(downloadId);
if (omaInfo == null) {
// Just send the notification in this case.
omaInfo = new OMAInfo();
omaInfo.addAttributeValue(OMA_INSTALL_NOTIFY_URI, notifyURI);
- sendInstallNotificationAndNextStep(omaInfo, downloadInfo, status);
+ sendInstallNotificationAndNextStep(omaInfo, downloadInfo, downloadId, status);
return;
}
showDownloadWarningDialog(
@@ -332,11 +336,12 @@ public class OMADownloadHandler {
*
* @param omaInfo Information about the OMA content.
* @param downloadInfo Information about the download.
+ * @param downloadId Id of the download in Android DownloadManager.
* @param statusMessage The message to send to the notification server.
*/
private void sendInstallNotificationAndNextStep(
- OMAInfo omaInfo, DownloadInfo downloadInfo, String statusMessage) {
- if (!sendNotification(omaInfo, downloadInfo, statusMessage)) {
+ OMAInfo omaInfo, DownloadInfo downloadInfo, long downloadId, String statusMessage) {
+ if (!sendNotification(omaInfo, downloadInfo, downloadId, statusMessage)) {
showNextUrlDialog(omaInfo);
}
}
@@ -346,14 +351,15 @@ public class OMADownloadHandler {
*
* @param omaInfo Information about the OMA content.
* @param downloadInfo Information about the download.
+ * @param downloadId Id of the download in Android DownloadManager.
* @param statusMessage The message to send to the notification server.
* @return true if the notification ise sent, or false otherwise.
*/
private boolean sendNotification(
- OMAInfo omaInfo, DownloadInfo downloadInfo, String statusMessage) {
+ OMAInfo omaInfo, DownloadInfo downloadInfo, long downloadId, String statusMessage) {
if (omaInfo == null) return false;
if (omaInfo.isValueEmpty(OMA_INSTALL_NOTIFY_URI)) return false;
- PostStatusTask task = new PostStatusTask(omaInfo, downloadInfo, statusMessage);
+ PostStatusTask task = new PostStatusTask(omaInfo, downloadInfo, downloadId, statusMessage);
task.execute();
return true;
}
@@ -388,7 +394,9 @@ public class OMADownloadHandler {
if (which == AlertDialog.BUTTON_POSITIVE) {
downloadOMAContent(downloadId, downloadInfo, omaInfo);
} else {
- sendNotification(omaInfo, downloadInfo, DOWNLOAD_STATUS_USER_CANCELLED);
+ sendNotification(omaInfo, downloadInfo,
+ DownloadItem.INVALID_DOWNLOAD_ID,
+ DOWNLOAD_STATUS_USER_CANCELLED);
}
}
};
@@ -419,7 +427,8 @@ public class OMADownloadHandler {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE) {
- sendInstallNotificationAndNextStep(omaInfo, downloadInfo, statusMessage);
+ sendInstallNotificationAndNextStep(omaInfo, downloadInfo,
+ DownloadItem.INVALID_DOWNLOAD_ID, statusMessage);
}
}
};
@@ -592,16 +601,16 @@ public class OMADownloadHandler {
.setFileName(fileName)
.setUrl(url)
.setMimeType(mimeType)
- .setDownloadId((int) downloadId)
.setDescription(omaInfo.getValue(OMA_DESCRIPTION))
.setContentLength(getSize(omaInfo))
.build();
// If installNotifyURI is not empty, the downloaded content cannot
// be used until the PostStatusTask gets a 200-series response.
// Don't show complete notification until that happens.
- DownloadManagerService.getDownloadManagerService(mContext)
- .enqueueDownloadManagerRequest(
- newInfo, omaInfo.isValueEmpty(OMA_INSTALL_NOTIFY_URI));
+ DownloadItem item = new DownloadItem(true, newInfo);
+ item.setSystemDownloadId(downloadId);
+ DownloadManagerService.getDownloadManagerService(mContext).enqueueDownloadManagerRequest(
+ item, omaInfo.isValueEmpty(OMA_INSTALL_NOTIFY_URI));
mPendingOMADownloads.put(downloadId, omaInfo);
}
@@ -618,18 +627,13 @@ public class OMADownloadHandler {
/**
* Updates the download information with the new download Id.
*
- * @param downloadInfo Information about the download.
+ * @param oldDownloadId Old download Id from the DownloadManager.
* @param newDownloadId New download Id from the DownloadManager.
- * @return the new download information with the new Id.
*/
- public DownloadInfo updateDownloadInfo(DownloadInfo downloadInfo, long newDownloadId) {
- long oldDownloadId = downloadInfo.getDownloadId();
+ public void updateDownloadInfo(long oldDownloadId, long newDownloadId) {
OMAInfo omaInfo = mPendingOMADownloads.get(oldDownloadId);
mPendingOMADownloads.remove(oldDownloadId);
mPendingOMADownloads.put(newDownloadId, omaInfo);
- return DownloadInfo.Builder.fromDownloadInfo(downloadInfo)
- .setDownloadId((int) newDownloadId)
- .build();
}
/**
@@ -651,12 +655,14 @@ public class OMADownloadHandler {
private final OMAInfo mOMAInfo;
private final DownloadInfo mDownloadInfo;
private final String mStatusMessage;
+ private final long mDownloadId;
public PostStatusTask(
- OMAInfo omaInfo, DownloadInfo downloadInfo, String statusMessage) {
+ OMAInfo omaInfo, DownloadInfo downloadInfo, long downloadId, String statusMessage) {
mOMAInfo = omaInfo;
mDownloadInfo = downloadInfo;
mStatusMessage = statusMessage;
+ mDownloadId = downloadId;
}
@Override
@@ -726,9 +732,9 @@ public class OMADownloadHandler {
}
}
showNextUrlDialog(mOMAInfo);
- } else if (mDownloadInfo.getDownloadId() > 0) {
+ } else if (mDownloadId != DownloadItem.INVALID_DOWNLOAD_ID) {
// Remove the downloaded content.
- manager.remove(mDownloadInfo.getDownloadId());
+ manager.remove(mDownloadId);
}
}
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
index 3f63aab..a744a76 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
@@ -36,7 +36,7 @@ public class SystemDownloadNotifier implements DownloadNotifier {
private final Object mLock = new Object();
@Nullable private DownloadNotificationService mBoundService;
private boolean mServiceStarted;
- private Set<Integer> mActiveDownloadIds = new HashSet<Integer>();
+ private Set<Integer> mActiveNotificationIds = new HashSet<Integer>();
private List<PendingNotificationInfo> mPendingNotifications =
new ArrayList<PendingNotificationInfo>();
@@ -122,7 +122,7 @@ public class SystemDownloadNotifier implements DownloadNotifier {
notifyDownloadFailed(info.downloadInfo);
break;
case DOWNLOAD_NOTIFICATION_TYPE_CANCEL:
- cancelNotification(info.downloadInfo.getDownloadId());
+ cancelNotification(info.downloadInfo.getNotificationId());
break;
case DOWNLOAD_NOTIFICATION_TYPE_CLEAR:
clearPendingDownloads();
@@ -150,7 +150,7 @@ public class SystemDownloadNotifier implements DownloadNotifier {
*/
private void stopServiceIfNeeded() {
assert Thread.holdsLock(mLock);
- if (mActiveDownloadIds.isEmpty() && mServiceStarted) {
+ if (mActiveNotificationIds.isEmpty() && mServiceStarted) {
stopService();
mServiceStarted = false;
}
@@ -179,8 +179,8 @@ public class SystemDownloadNotifier implements DownloadNotifier {
}
@Override
- public void cancelNotification(int downloadId) {
- DownloadInfo info = new DownloadInfo.Builder().setDownloadId(downloadId).build();
+ public void cancelNotification(int notificationId) {
+ DownloadInfo info = new DownloadInfo.Builder().setNotificationId(notificationId).build();
updateDownloadNotification(DOWNLOAD_NOTIFICATION_TYPE_CANCEL, info, null, -1, false);
}
@@ -227,9 +227,9 @@ public class SystemDownloadNotifier implements DownloadNotifier {
synchronized (mLock) {
startAndBindToServiceIfNeeded();
if (type == DOWNLOAD_NOTIFICATION_TYPE_PROGRESS) {
- mActiveDownloadIds.add(info.getDownloadId());
+ mActiveNotificationIds.add(info.getNotificationId());
} else if (type != DOWNLOAD_NOTIFICATION_TYPE_CLEAR) {
- mActiveDownloadIds.remove(info.getDownloadId());
+ mActiveNotificationIds.remove(info.getNotificationId());
}
if (mBoundService == null) {
// We need to wait for the service to connect before we can handle
@@ -240,27 +240,30 @@ public class SystemDownloadNotifier implements DownloadNotifier {
} else {
switch (type) {
case DOWNLOAD_NOTIFICATION_TYPE_PROGRESS:
- mBoundService.notifyDownloadProgress(info.getDownloadId(),
- info.getFileName(), info.getPercentCompleted(),
- info.getTimeRemainingInMillis(), startTime, info.isResumable());
+
+ mBoundService.notifyDownloadProgress(info.getNotificationId(),
+ info.getDownloadGuid(), info.getFileName(),
+ info.getPercentCompleted(), info.getTimeRemainingInMillis(),
+ startTime, info.isResumable());
break;
case DOWNLOAD_NOTIFICATION_TYPE_PAUSE:
assert info.isResumable();
- mBoundService.notifyDownloadPaused(info.getDownloadId(), info.getFileName(),
+ mBoundService.notifyDownloadPaused(info.getNotificationId(),
+ info.getDownloadGuid(), info.getFileName(),
info.isResumable(), isAutoResumable);
break;
case DOWNLOAD_NOTIFICATION_TYPE_SUCCESS:
mBoundService.notifyDownloadSuccessful(
- info.getDownloadId(), info.getFileName(), intent);
+ info.getNotificationId(), info.getFileName(), intent);
stopServiceIfNeeded();
break;
case DOWNLOAD_NOTIFICATION_TYPE_FAILURE:
mBoundService.notifyDownloadFailed(
- info.getDownloadId(), info.getFileName());
+ info.getNotificationId(), info.getFileName());
stopServiceIfNeeded();
break;
case DOWNLOAD_NOTIFICATION_TYPE_CANCEL:
- mBoundService.cancelNotification(info.getDownloadId());
+ mBoundService.cancelNotification(info.getNotificationId());
stopServiceIfNeeded();
break;
case DOWNLOAD_NOTIFICATION_TYPE_CLEAR:
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index d683fb8..6a6ab30 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -281,10 +281,12 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTabInfo.java",
"java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java",
"java/src/org/chromium/chrome/browser/download/DownloadBroadcastReceiver.java",
+ "java/src/org/chromium/chrome/browser/download/DownloadItem.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
"java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java",
"java/src/org/chromium/chrome/browser/download/DownloadNotifier.java",
+ "java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java",
"java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java",
"java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java",
"java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
index c32a7af..4c3927b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
@@ -33,6 +33,7 @@ import java.util.HashSet;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
@@ -131,8 +132,8 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
}
@Override
- public void cancelNotification(int downloadId) {
- assertCorrectExpectedCall(MethodID.CANCEL_DOWNLOAD_ID, downloadId);
+ public void cancelNotification(int notificationId) {
+ assertCorrectExpectedCall(MethodID.CANCEL_DOWNLOAD_ID, notificationId);
}
@Override
@@ -225,7 +226,6 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
static class MockOMADownloadHandler extends OMADownloadHandler {
protected boolean mSuccess;
protected String mNofityURI;
- protected DownloadInfo mDownloadInfo;
protected long mDownloadId;
MockOMADownloadHandler(Context context) {
@@ -237,7 +237,8 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
}
@Override
- public void onDownloadCompleted(DownloadInfo downloadInfo, String notifyURI) {
+ public void onDownloadCompleted(
+ DownloadInfo downloadInfo, long downloadId, String notifyURI) {
mSuccess = true;
mNofityURI = notifyURI;
}
@@ -248,13 +249,8 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
}
@Override
- public DownloadInfo updateDownloadInfo(DownloadInfo downloadInfo, long newDownloadId) {
- mDownloadInfo = downloadInfo;
+ public void updateDownloadInfo(long oldDownloadId, long newDownloadId) {
mDownloadId = newDownloadId;
- mDownloadInfo = DownloadInfo.Builder.fromDownloadInfo(downloadInfo)
- .setDownloadId((int) newDownloadId)
- .build();
- return mDownloadInfo;
}
@Override
@@ -273,8 +269,9 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
}
@Override
- protected long addCompletedDownload(DownloadInfo downloadInfo) {
- return 1L;
+ protected boolean addCompletedDownload(DownloadItem downloadItem) {
+ downloadItem.setSystemDownloadId(1L);
+ return true;
}
@Override
@@ -286,7 +283,8 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
protected void init() {}
@Override
- protected void resumeDownload(int downloadId, String fileName, boolean hasUserGesture) {
+ protected void resumeDownload(int notificationId, String downloadGuid, String fileName,
+ boolean hasUserGesture) {
mResumed = true;
}
}
@@ -298,9 +296,9 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
}
private DownloadInfo getDownloadInfo() {
- return new Builder().setContentLength(100)
- .setDownloadId(mRandom.nextInt(1000))
- .setHasDownloadId(true)
+ return new Builder()
+ .setContentLength(100)
+ .setDownloadGuid(UUID.randomUUID().toString())
.build();
}
@@ -534,7 +532,6 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
try {
DownloadInfo info = new DownloadInfo.Builder()
- .setDownloadId(0)
.setMimeType(OMADownloadHandler.OMA_DRM_MESSAGE_MIME)
.setFileName("test.gzip")
.setUrl(testServer.getURL("/chrome/test/data/android/download/test.gzip"))
@@ -546,14 +543,15 @@ public class DownloadManagerServiceTest extends InstrumentationTestCase {
final MockOMADownloadHandler handler = new MockOMADownloadHandler(context);
dService.setOMADownloadHandler(handler);
handler.setDownloadId(0);
- dService.enqueueDownloadManagerRequest(info, true);
+ DownloadItem item = new DownloadItem(true, info);
+ item.setSystemDownloadId(0);
+ dService.enqueueDownloadManagerRequest(item, true);
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
return handler.mDownloadId != 0;
}
});
- handler.mDownloadId = handler.mDownloadInfo.getDownloadId();
Set<String> downloads = dService.getStoredDownloadInfo(
PreferenceManager.getDefaultSharedPreferences(context),
DownloadManagerService.PENDING_OMA_DOWNLOADS);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java
index 26bf7cc..d0b47c4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.test.util.Feature;
import java.util.HashSet;
import java.util.Set;
+import java.util.UUID;
/**
* Tests of {@link DownloadNotificationService}.
@@ -73,10 +74,10 @@ public class DownloadNotificationServiceTest extends
Context mockContext = new AdvancedMockContext(getSystemContext());
getService().setContext(mockContext);
Set<String> notifications = new HashSet<String>();
- notifications.add(new DownloadNotificationService.PendingNotification(1, "test1", true)
- .getNotificationString());
- notifications.add(new DownloadNotificationService.PendingNotification(2, "test2", true)
- .getNotificationString());
+ notifications.add(new DownloadSharedPreferenceEntry(1, true, true,
+ UUID.randomUUID().toString(), "test1").getSharedPreferenceString());
+ notifications.add(new DownloadSharedPreferenceEntry(2, true, true,
+ UUID.randomUUID().toString(), "test2").getSharedPreferenceString());
SharedPreferences sharedPrefs =
PreferenceManager.getDefaultSharedPreferences(mockContext);
SharedPreferences.Editor editor = sharedPrefs.edit();
@@ -103,7 +104,7 @@ public class DownloadNotificationServiceTest extends
getService().setContext(mockContext);
startNotificationService();
DownloadNotificationService service = bindNotificationService();
- service.notifyDownloadProgress(1, "test", -1, 1L, 1L, true);
+ service.notifyDownloadProgress(1, UUID.randomUUID().toString(), "test", -1, 1L, 1L, true);
assertEquals(1, getService().getNotificationIds().size());
assertTrue(getService().getNotificationIds().contains(1));
@@ -123,18 +124,21 @@ public class DownloadNotificationServiceTest extends
@SmallTest
@Feature({"Download"})
public void testParseDownloadNotifications() {
- String notification = "1,0,test.pdf";
- DownloadNotificationService.PendingNotification pendingNotification =
- DownloadNotificationService.PendingNotification.parseFromString(notification);
- assertEquals(1, pendingNotification.downloadId);
- assertEquals("test.pdf", pendingNotification.fileName);
- assertFalse(pendingNotification.isResumable);
-
- notification = "2,1,test,2.pdf";
- pendingNotification =
- DownloadNotificationService.PendingNotification.parseFromString(notification);
- assertEquals(2, pendingNotification.downloadId);
- assertEquals("test,2.pdf", pendingNotification.fileName);
- assertTrue(pendingNotification.isResumable);
+ String uuid = UUID.randomUUID().toString();
+ String notification =
+ DownloadSharedPreferenceEntry.VERSION + ",1,0,1," + uuid + ",test.pdf";
+ DownloadSharedPreferenceEntry entry =
+ DownloadSharedPreferenceEntry.parseFromString(notification);
+ assertEquals(1, entry.notificationId);
+ assertEquals("test.pdf", entry.fileName);
+ assertFalse(entry.isResumable);
+ assertEquals(uuid, entry.downloadGuid);
+
+ notification = DownloadSharedPreferenceEntry.VERSION + ",2,1,1," + uuid + ",test,2.pdf";
+ entry = DownloadSharedPreferenceEntry.parseFromString(notification);
+ assertEquals(2, entry.notificationId);
+ assertEquals("test,2.pdf", entry.fileName);
+ assertTrue(entry.isResumable);
+ assertEquals(uuid, entry.downloadGuid);
}
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestBase.java
index 7cb1982..e6b3341 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestBase.java
@@ -225,10 +225,11 @@ public abstract class DownloadTestBase extends ChromeActivityTestCaseBase<Chrome
@Override
public void enqueueDownloadManagerRequest(
- final DownloadInfo info, boolean notifyCompleted) {
+ final DownloadItem item, boolean notifyCompleted) {
// Intentionally do not call super, since DownloadManager does not work in test
// environment.
- mEnqueueHttpGetDownloadCallbackHelper.notifyCalled(info, notifyCompleted);
+ mEnqueueHttpGetDownloadCallbackHelper.notifyCalled(
+ item.getDownloadInfo(), notifyCompleted);
}
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/MockDownloadNotificationService.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/MockDownloadNotificationService.java
index bc0f05a..af5f904 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/MockDownloadNotificationService.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/MockDownloadNotificationService.java
@@ -42,8 +42,8 @@ public class MockDownloadNotificationService extends DownloadNotificationService
}
@Override
- public void cancelNotification(int downloadId) {
- mNotificationIds.remove(Integer.valueOf(downloadId));
+ public void cancelNotification(int notificationId) {
+ mNotificationIds.remove(Integer.valueOf(notificationId));
}
@Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
index 766b879..c441ca7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
@@ -13,6 +13,8 @@ import org.chromium.base.test.util.AdvancedMockContext;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.DownloadInfo;
+import java.util.UUID;
+
/**
* Tests of {@link SystemDownloadNotifier}.
*/
@@ -67,7 +69,8 @@ public class SystemDownloadNotifierTest extends InstrumentationTestCase {
@SmallTest
@Feature({"Download"})
public void testNotificationNotHandledUntilServiceConnection() {
- DownloadInfo info = new DownloadInfo.Builder().setDownloadId(1).build();
+ DownloadInfo info = new DownloadInfo.Builder()
+ .setDownloadGuid(UUID.randomUUID().toString()).setNotificationId(1).build();
mDownloadNotifier.notifyDownloadProgress(info, 1L);
assertTrue(mDownloadNotifier.mStarted);
@@ -83,10 +86,12 @@ public class SystemDownloadNotifierTest extends InstrumentationTestCase {
@Feature({"Download"})
public void testServiceStoppedWhenAllDownloadsFinish() {
onServiceConnected();
- DownloadInfo info = new DownloadInfo.Builder().setDownloadId(1).build();
+ DownloadInfo info = new DownloadInfo.Builder()
+ .setDownloadGuid(UUID.randomUUID().toString()).setNotificationId(1).build();
mDownloadNotifier.notifyDownloadProgress(info, 1L);
assertTrue(mDownloadNotifier.mStarted);
- DownloadInfo info2 = new DownloadInfo.Builder().setDownloadId(2).build();
+ DownloadInfo info2 = new DownloadInfo.Builder()
+ .setDownloadGuid(UUID.randomUUID().toString()).setNotificationId(2).build();
mDownloadNotifier.notifyDownloadProgress(info2, 1L);
mDownloadNotifier.notifyDownloadFailed(info);
diff --git a/chrome/browser/android/download/chrome_download_delegate.cc b/chrome/browser/android/download/chrome_download_delegate.cc
index 5fa5db1..8ce3fac 100644
--- a/chrome/browser/android/download/chrome_download_delegate.cc
+++ b/chrome/browser/android/download/chrome_download_delegate.cc
@@ -48,14 +48,17 @@ static jboolean IsDownloadDangerous(JNIEnv* env,
}
// Called when a dangerous download is validated.
-static void DangerousDownloadValidated(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jobject>& tab,
- jint download_id,
- jboolean accept) {
+static void DangerousDownloadValidated(
+ JNIEnv* env,
+ const JavaParamRef<jclass>& clazz,
+ const JavaParamRef<jobject>& tab,
+ const JavaParamRef<jstring>& jdownload_guid,
+ jboolean accept) {
+ std::string download_guid =
+ base::android::ConvertJavaStringToUTF8(env, jdownload_guid);
TabAndroid* tab_android = TabAndroid::GetNativeTab(env, tab);
DownloadControllerAndroid::Get()->DangerousDownloadValidated(
- tab_android->web_contents(), download_id, accept);
+ tab_android->web_contents(), download_guid, accept);
}
// static
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc
index 0e0ed61..935f174 100644
--- a/chrome/browser/android/download/download_manager_service.cc
+++ b/chrome/browser/android/download/download_manager_service.cc
@@ -57,26 +57,34 @@ DownloadManagerService::~DownloadManagerService() {
manager_->RemoveObserver(this);
}
-void DownloadManagerService::ResumeDownload(JNIEnv* env,
- jobject obj,
- uint32_t download_id,
- jstring fileName) {
- ResumeDownloadInternal(download_id, ConvertJavaStringToUTF8(env, fileName),
- true);
+void DownloadManagerService::ResumeDownload(
+ JNIEnv* env,
+ jobject obj,
+ uint32_t download_id,
+ const JavaParamRef<jstring>& jdownload_guid,
+ jstring fileName) {
+ std::string download_guid = ConvertJavaStringToUTF8(env, jdownload_guid);
+ ResumeDownloadInternal(download_id, download_guid,
+ ConvertJavaStringToUTF8(env, fileName), true);
}
-void DownloadManagerService::CancelDownload(JNIEnv* env,
- jobject obj,
- uint32_t download_id) {
- CancelDownloadInternal(download_id, true);
+void DownloadManagerService::CancelDownload(
+ JNIEnv* env,
+ jobject obj,
+ const JavaParamRef<jstring>& jdownload_guid) {
+ std::string download_guid = ConvertJavaStringToUTF8(env, jdownload_guid);
+ CancelDownloadInternal(download_guid, true);
}
-void DownloadManagerService::PauseDownload(JNIEnv* env,
- jobject obj,
- uint32_t download_id) {
- content::DownloadItem* item = manager_->GetDownload(download_id);
+void DownloadManagerService::PauseDownload(
+ JNIEnv* env,
+ jobject obj,
+ const JavaParamRef<jstring>& jdownload_guid) {
+ std::string download_guid = ConvertJavaStringToUTF8(env, jdownload_guid);
+ content::DownloadItem* item = manager_->GetDownloadByGuid(download_guid);
if (item)
item->Pause();
+ item->RemoveObserver(content::DownloadControllerAndroid::Get());
}
void DownloadManagerService::ManagerGoingDown(
@@ -96,14 +104,16 @@ void DownloadManagerService::ResumeDownloadItem(content::DownloadItem* item,
resume_callback_for_testing_.Run(true);
}
-void DownloadManagerService::ResumeDownloadInternal(uint32_t download_id,
- const std::string& fileName,
- bool retry) {
+void DownloadManagerService::ResumeDownloadInternal(
+ uint32_t download_id,
+ const std::string& download_guid,
+ const std::string& fileName,
+ bool retry) {
if (!manager_) {
OnResumptionFailed(download_id, fileName);
return;
}
- content::DownloadItem* item = manager_->GetDownload(download_id);
+ content::DownloadItem* item = manager_->GetDownloadByGuid(download_guid);
if (item) {
ResumeDownloadItem(item, fileName);
return;
@@ -120,25 +130,27 @@ void DownloadManagerService::ResumeDownloadInternal(uint32_t download_id,
// created item might not be loaded from download history. So user might wait
// indefinitely to see the failed notification. See http://crbug.com/577893.
base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DownloadManagerService::ResumeDownloadInternal,
- base::Unretained(this), download_id, fileName, false),
+ FROM_HERE, base::Bind(&DownloadManagerService::ResumeDownloadInternal,
+ base::Unretained(this), download_id, download_guid,
+ fileName, false),
base::TimeDelta::FromMilliseconds(kRetryIntervalInMilliseconds));
}
-void DownloadManagerService::CancelDownloadInternal(uint32_t download_id,
- bool retry) {
+void DownloadManagerService::CancelDownloadInternal(
+ const std::string& download_guid,
+ bool retry) {
if (!manager_)
return;
- content::DownloadItem* item = manager_->GetDownload(download_id);
+ content::DownloadItem* item = manager_->GetDownloadByGuid(download_guid);
if (item) {
item->Cancel(true);
+ item->RemoveObserver(content::DownloadControllerAndroid::Get());
return;
}
if (retry) {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::Bind(&DownloadManagerService::CancelDownloadInternal,
- base::Unretained(this), download_id, false),
+ base::Unretained(this), download_guid, false),
base::TimeDelta::FromMilliseconds(kRetryIntervalInMilliseconds));
}
}
diff --git a/chrome/browser/android/download/download_manager_service.h b/chrome/browser/android/download/download_manager_service.h
index f1a5f9e..aa65a32 100644
--- a/chrome/browser/android/download/download_manager_service.h
+++ b/chrome/browser/android/download/download_manager_service.h
@@ -13,6 +13,8 @@
#include "base/macros.h"
#include "content/public/browser/download_manager.h"
+using base::android::JavaParamRef;
+
namespace content {
class DownloadItem;
}
@@ -29,20 +31,26 @@ class DownloadManagerService : public content::DownloadManager::Observer {
content::DownloadManager* manager);
~DownloadManagerService() override;
- // Called to resume downloading the item that has ID equal to |download_id|.
- // If the DownloadItem is not yet created, retry after a while.
+ // Called to resume downloading the item that has GUID equal to
+ // |jdownload_guid|. If the DownloadItem is not yet created, retry after
+ // a while.
void ResumeDownload(JNIEnv* env,
jobject obj,
uint32_t download_id,
+ const JavaParamRef<jstring>& jdownload_guid,
jstring fileName);
- // Called to cancel a download item that has ID equal to |download_id|.
+ // Called to cancel a download item that has GUID equal to |jdownload_guid|.
// If the DownloadItem is not yet created, retry after a while.
- void CancelDownload(JNIEnv* env, jobject obj, uint32_t download_id);
+ void CancelDownload(JNIEnv* env,
+ jobject obj,
+ const JavaParamRef<jstring>& jdownload_guid);
- // Called to pause a download item that has ID equal to |download_id|.
+ // Called to pause a download item that has GUID equal to |jdownload_guid|.
// If the DownloadItem is not yet created, do nothing as it is already paused.
- void PauseDownload(JNIEnv* env, jobject obj, uint32_t download_id);
+ void PauseDownload(JNIEnv* env,
+ jobject obj,
+ const JavaParamRef<jstring>& jdownload_guid);
// content::DownloadManager::Observer methods.
void ManagerGoingDown(content::DownloadManager* manager) override;
@@ -58,12 +66,13 @@ class DownloadManagerService : public content::DownloadManager::Observer {
// Helper function to start the download resumption. If |retry| is true,
// chrome will retry the resumption if the download item is not loaded.
void ResumeDownloadInternal(uint32_t download_id,
+ const std::string& download_guid,
const std::string& fileName,
bool retry);
// Helper function to cancel a download. If |retry| is true,
// chrome will retry the cancellation if the download item is not loaded.
- void CancelDownloadInternal(uint32_t download_id, bool retry);
+ void CancelDownloadInternal(const std::string& download_guid, bool retry);
// Called to notify the java side that download resumption failed.
void OnResumptionFailed(uint32_t download_id, const std::string& fileName);
diff --git a/chrome/browser/android/download/download_manager_service_unittest.cc b/chrome/browser/android/download/download_manager_service_unittest.cc
index b987c8b..c5d60d7a 100644
--- a/chrome/browser/android/download/download_manager_service_unittest.cc
+++ b/chrome/browser/android/download/download_manager_service_unittest.cc
@@ -36,9 +36,10 @@ class DownloadManagerServiceTest : public testing::Test {
&manager_)),
finished_(false),
success_(false) {
- ON_CALL(manager_, GetDownload(_))
+ ON_CALL(manager_, GetDownloadByGuid(_))
.WillByDefault(
- ::testing::Invoke(this, &DownloadManagerServiceTest::GetDownload));
+ ::testing::Invoke(this,
+ &DownloadManagerServiceTest::GetDownloadByGuid));
}
void OnResumptionDone(bool success) {
@@ -46,12 +47,14 @@ class DownloadManagerServiceTest : public testing::Test {
success_ = success;
}
- void StartDownload(int download_id) {
+ void StartDownload(const std::string& download_guid) {
JNIEnv* env = base::android::AttachCurrentThread();
service_->set_resume_callback_for_testing(base::Bind(
&DownloadManagerServiceTest::OnResumptionDone, base::Unretained(this)));
service_->ResumeDownload(
- env, nullptr, download_id,
+ env, nullptr, 0, JavaParamRef<jstring>(
+ env, base::android::ConvertUTF8ToJavaString(
+ env, download_guid).obj()),
base::android::ConvertUTF8ToJavaString(env, "test").obj());
while (!finished_)
message_loop_.RunUntilIdle();
@@ -64,7 +67,9 @@ class DownloadManagerServiceTest : public testing::Test {
}
protected:
- content::DownloadItem* GetDownload(uint32_t) { return download_.get(); }
+ content::DownloadItem* GetDownloadByGuid(const std::string&) {
+ return download_.get();
+ }
base::MessageLoop message_loop_;
scoped_ptr<content::MockDownloadItem> download_;
@@ -78,7 +83,7 @@ class DownloadManagerServiceTest : public testing::Test {
// Test that resumption will fail if no download item is found before times out.
TEST_F(DownloadManagerServiceTest, ResumptionTimeOut) {
- StartDownload(1);
+ StartDownload("0000");
EXPECT_FALSE(success_);
}
@@ -86,13 +91,13 @@ TEST_F(DownloadManagerServiceTest, ResumptionTimeOut) {
// resumed.
TEST_F(DownloadManagerServiceTest, ResumptionWithResumableItem) {
CreateDownloadItem(true);
- StartDownload(1);
+ StartDownload("0000");
EXPECT_TRUE(success_);
}
// Test that resumption fails if the target download item is not resumable.
TEST_F(DownloadManagerServiceTest, ResumptionWithNonResumableItem) {
CreateDownloadItem(false);
- StartDownload(1);
+ StartDownload("0000");
EXPECT_FALSE(success_);
}
diff --git a/chrome/browser/android/download/mock_download_controller_android.cc b/chrome/browser/android/download/mock_download_controller_android.cc
index f072e9e..7551330 100644
--- a/chrome/browser/android/download/mock_download_controller_android.cc
+++ b/chrome/browser/android/download/mock_download_controller_android.cc
@@ -34,8 +34,9 @@ void MockDownloadControllerAndroid::StartContextMenuDownload(
}
void MockDownloadControllerAndroid::DangerousDownloadValidated(
- content::WebContents* web_contents, int download_id, bool accept) {
-}
+ content::WebContents* web_contents,
+ const std::string& download_guid,
+ bool accept) {}
void MockDownloadControllerAndroid::AcquireFileAccessPermission(
content::WebContents* web_contents,
diff --git a/chrome/browser/android/download/mock_download_controller_android.h b/chrome/browser/android/download/mock_download_controller_android.h
index 50e621e..d74e7dfe 100644
--- a/chrome/browser/android/download/mock_download_controller_android.h
+++ b/chrome/browser/android/download/mock_download_controller_android.h
@@ -33,9 +33,9 @@ class MockDownloadControllerAndroid
const content::ContextMenuParams& params,
content::WebContents* web_contents,
bool is_link, const std::string& extra_headers) override;
- void DangerousDownloadValidated(
- content::WebContents* web_contents, int download_id,
- bool accept) override;
+ void DangerousDownloadValidated(content::WebContents* web_contents,
+ const std::string& download_guid,
+ bool accept) override;
void AcquireFileAccessPermission(
content::WebContents* web_contents,
const AcquireFileAccessPermissionCallback& callback) override;
diff --git a/content/browser/android/download_controller_android_impl.cc b/content/browser/android/download_controller_android_impl.cc
index a09532f..abbd4c3 100644
--- a/content/browser/android/download_controller_android_impl.cc
+++ b/content/browser/android/download_controller_android_impl.cc
@@ -453,6 +453,8 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
OnDangerousDownload(item);
JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jguid =
+ ConvertUTF8ToJavaString(env, item->GetGuid());
ScopedJavaLocalRef<jstring> jurl =
ConvertUTF8ToJavaString(env, item->GetURL().spec());
ScopedJavaLocalRef<jstring> jmime_type =
@@ -473,8 +475,9 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
Java_DownloadController_onDownloadUpdated(
env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
jmime_type.obj(), jfilename.obj(), jpath.obj(),
- item->GetReceivedBytes(), item->GetId(), item->PercentComplete(),
- time_delta.InMilliseconds(), item->HasUserGesture(), item->IsPaused(),
+ item->GetReceivedBytes(), item->GetId(), jguid.obj(),
+ item->PercentComplete(), time_delta.InMilliseconds(),
+ item->HasUserGesture(), item->IsPaused(),
// Get all requirements that allows a download to be resumable.
!item->GetBrowserContext()->IsOffTheRecord());
break;
@@ -488,12 +491,13 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
Java_DownloadController_onDownloadCompleted(
env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
jmime_type.obj(), jfilename.obj(), jpath.obj(),
- item->GetReceivedBytes(), item->GetId(),
+ item->GetReceivedBytes(), item->GetId(), jguid.obj(),
joriginal_url.obj(), jreferrer_url.obj(), item->HasUserGesture());
break;
case DownloadItem::CANCELLED:
Java_DownloadController_onDownloadCancelled(
- env, GetJavaObject()->Controller(env).obj(), item->GetId());
+ env, GetJavaObject()->Controller(env).obj(), item->GetId(),
+ jguid.obj());
break;
case DownloadItem::INTERRUPTED:
// When device loses/changes network, we get a NETWORK_TIMEOUT,
@@ -502,8 +506,9 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
Java_DownloadController_onDownloadInterrupted(
env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
jmime_type.obj(), jfilename.obj(), jpath.obj(),
- item->GetReceivedBytes(), item->GetId(), item->CanResume(),
- IsInterruptedDownloadAutoResumable(item));
+ item->GetReceivedBytes(), item->GetId(), jguid.obj(),
+ item->CanResume(), IsInterruptedDownloadAutoResumable(item));
+ item->RemoveObserver(this);
break;
case DownloadItem::MAX_DOWNLOAD_STATE:
NOTREACHED();
@@ -514,12 +519,14 @@ void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
env, item->GetTargetFilePath().BaseName().value());
+ ScopedJavaLocalRef<jstring> jguid =
+ ConvertUTF8ToJavaString(env, item->GetGuid());
ScopedJavaLocalRef<jobject> view_core = GetContentViewCoreFromWebContents(
item->GetWebContents());
if (!view_core.is_null()) {
Java_DownloadController_onDangerousDownload(
env, GetJavaObject()->Controller(env).obj(), view_core.obj(),
- jfilename.obj(), item->GetId());
+ jfilename.obj(), jguid.obj());
}
}
@@ -559,12 +566,14 @@ void DownloadControllerAndroidImpl::StartContextMenuDownload(
}
void DownloadControllerAndroidImpl::DangerousDownloadValidated(
- WebContents* web_contents, int download_id, bool accept) {
+ WebContents* web_contents,
+ const std::string& download_guid,
+ bool accept) {
if (!web_contents)
return;
DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
- DownloadItem* item = dlm->GetDownload(download_id);
+ DownloadItem* item = dlm->GetDownloadByGuid(download_guid);
if (!item)
return;
if (accept)
diff --git a/content/browser/android/download_controller_android_impl.h b/content/browser/android/download_controller_android_impl.h
index 9045d29..78d6544 100644
--- a/content/browser/android/download_controller_android_impl.h
+++ b/content/browser/android/download_controller_android_impl.h
@@ -102,7 +102,7 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid {
bool is_link,
const std::string& extra_headers) override;
void DangerousDownloadValidated(WebContents* web_contents,
- int download_id,
+ const std::string& download_guid,
bool accept) override;
// DownloadItem::Observer interface.
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java
index 4caff13..5153062 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java
@@ -26,9 +26,9 @@ public interface ContentViewDownloadDelegate {
* Notify the host application that a download has an extension indicating
* a dangerous file type.
* @param filename File name of the downloaded file.
- * @param downloadId The download id.
+ * @param downloadGuid The download GUID.
*/
- void onDangerousDownload(String filename, int downloadId);
+ void onDangerousDownload(String filename, String downloadGuid);
/**
* Called when file access has been requested to complete a download.
diff --git a/content/public/android/java/src/org/chromium/content/browser/DownloadController.java b/content/public/android/java/src/org/chromium/content/browser/DownloadController.java
index 63a5eb7..5e2c29f 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DownloadController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DownloadController.java
@@ -118,11 +118,13 @@ public class DownloadController {
/**
* Notifies the download delegate that a download completed and passes along info about the
* download. This can be either a POST download or a GET download with authentication.
+ * TODO(qinmin): Generate the notificationId in the java side, the native downloadId is going
+ * to be deprecated.
*/
@CalledByNative
private void onDownloadCompleted(String url, String mimeType, String filename, String path,
- long contentLength, int downloadId, String originalUrl, String refererUrl,
- boolean hasUserGesture) {
+ long contentLength, int notificationId, String downloadGuid, String originalUrl,
+ String refererUrl, boolean hasUserGesture) {
if (sDownloadNotificationService == null) return;
DownloadInfo downloadInfo = new DownloadInfo.Builder()
.setUrl(url)
@@ -131,8 +133,8 @@ public class DownloadController {
.setFilePath(path)
.setContentLength(contentLength)
.setDescription(filename)
- .setDownloadId(downloadId)
- .setHasDownloadId(true)
+ .setNotificationId(notificationId)
+ .setDownloadGuid(downloadGuid)
.setOriginalUrl(originalUrl)
.setReferer(refererUrl)
.setHasUserGesture(hasUserGesture)
@@ -146,7 +148,8 @@ public class DownloadController {
*/
@CalledByNative
private void onDownloadInterrupted(String url, String mimeType, String filename, String path,
- long contentLength, int downloadId, boolean isResumable, boolean isAutoResumable) {
+ long contentLength, int notificationId, String downloadGuid, boolean isResumable,
+ boolean isAutoResumable) {
if (sDownloadNotificationService == null) return;
DownloadInfo downloadInfo = new DownloadInfo.Builder()
.setUrl(url)
@@ -155,8 +158,8 @@ public class DownloadController {
.setFilePath(path)
.setContentLength(contentLength)
.setDescription(filename)
- .setDownloadId(downloadId)
- .setHasDownloadId(true)
+ .setNotificationId(notificationId)
+ .setDownloadGuid(downloadGuid)
.setIsResumable(isResumable)
.build();
sDownloadNotificationService.onDownloadInterrupted(downloadInfo, isAutoResumable);
@@ -164,14 +167,17 @@ public class DownloadController {
/**
* Called when a download was cancelled.
- * @param downloadId Id of the download item.
+ * @param notificationId Notification Id of the download item.
+ * @param downloadGuid GUID of the download item.
+ * TODO(qinmin): Generate the notificationId in the java side, the native downloadId is going
+ * to be deprecated.
*/
@CalledByNative
- private void onDownloadCancelled(int downloadId) {
+ private void onDownloadCancelled(int notificationId, String downloadGuid) {
if (sDownloadNotificationService == null) return;
DownloadInfo downloadInfo = new DownloadInfo.Builder()
- .setDownloadId(downloadId)
- .setHasDownloadId(true)
+ .setNotificationId(notificationId)
+ .setDownloadGuid(downloadGuid)
.build();
sDownloadNotificationService.onDownloadCancelled(downloadInfo);
}
@@ -179,10 +185,12 @@ public class DownloadController {
/**
* Notifies the download delegate about progress of a download. Downloads that use Chrome
* network stack use custom notification to display the progress of downloads.
+ * TODO(qinmin): Generate the notificationId in the java side, the native downloadId is going
+ * to be deprecated.
*/
@CalledByNative
- private void onDownloadUpdated(String url, String mimeType, String filename,
- String path, long contentLength, int downloadId, int percentCompleted,
+ private void onDownloadUpdated(String url, String mimeType, String filename, String path,
+ long contentLength, int notificationId, String downloadGuid, int percentCompleted,
long timeRemainingInMs, boolean hasUserGesture, boolean isPaused, boolean isResumable) {
if (sDownloadNotificationService == null) return;
DownloadInfo downloadInfo = new DownloadInfo.Builder()
@@ -192,8 +200,8 @@ public class DownloadController {
.setFilePath(path)
.setContentLength(contentLength)
.setDescription(filename)
- .setDownloadId(downloadId)
- .setHasDownloadId(true)
+ .setNotificationId(notificationId)
+ .setDownloadGuid(downloadGuid)
.setPercentCompleted(percentCompleted)
.setTimeRemainingInMillis(timeRemainingInMs)
.setHasUserGesture(hasUserGesture)
@@ -207,11 +215,10 @@ public class DownloadController {
* Notifies the download delegate that a dangerous download started.
*/
@CalledByNative
- private void onDangerousDownload(ContentViewCore view, String filename,
- int downloadId) {
+ private void onDangerousDownload(ContentViewCore view, String filename, String downloadGuid) {
ContentViewDownloadDelegate downloadDelegate = downloadDelegateFromView(view);
if (downloadDelegate != null) {
- downloadDelegate.onDangerousDownload(filename, downloadId);
+ downloadDelegate.onDangerousDownload(filename, downloadGuid);
}
}
diff --git a/content/public/android/java/src/org/chromium/content/browser/DownloadInfo.java b/content/public/android/java/src/org/chromium/content/browser/DownloadInfo.java
index 39da754..f6297be 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DownloadInfo.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DownloadInfo.java
@@ -18,8 +18,8 @@ public final class DownloadInfo {
private final String mReferer;
private final String mOriginalUrl;
private final long mContentLength;
- private final boolean mHasDownloadId;
- private final int mDownloadId;
+ private final int mNotificationId;
+ private final String mDownloadGuid;
private final boolean mHasUserGesture;
private final String mContentDisposition;
private final boolean mIsGETRequest;
@@ -39,8 +39,8 @@ public final class DownloadInfo {
mReferer = builder.mReferer;
mOriginalUrl = builder.mOriginalUrl;
mContentLength = builder.mContentLength;
- mHasDownloadId = builder.mHasDownloadId;
- mDownloadId = builder.mDownloadId;
+ mNotificationId = builder.mNotificationId;
+ mDownloadGuid = builder.mDownloadGuid;
mHasUserGesture = builder.mHasUserGesture;
mIsGETRequest = builder.mIsGETRequest;
mContentDisposition = builder.mContentDisposition;
@@ -94,12 +94,12 @@ public final class DownloadInfo {
return mIsGETRequest;
}
- public boolean hasDownloadId() {
- return mHasDownloadId;
+ public int getNotificationId() {
+ return mNotificationId;
}
- public int getDownloadId() {
- return mDownloadId;
+ public String getDownloadGuid() {
+ return mDownloadGuid;
}
public boolean hasUserGesture() {
@@ -144,8 +144,8 @@ public final class DownloadInfo {
private String mOriginalUrl;
private long mContentLength;
private boolean mIsGETRequest;
- private boolean mHasDownloadId;
- private int mDownloadId;
+ private int mNotificationId;
+ private String mDownloadGuid;
private boolean mHasUserGesture;
private String mContentDisposition;
private int mPercentCompleted = -1;
@@ -208,13 +208,13 @@ public final class DownloadInfo {
return this;
}
- public Builder setHasDownloadId(boolean hasDownloadId) {
- mHasDownloadId = hasDownloadId;
+ public Builder setNotificationId(int notificationId) {
+ mNotificationId = notificationId;
return this;
}
- public Builder setDownloadId(int downloadId) {
- mDownloadId = downloadId;
+ public Builder setDownloadGuid(String downloadGuid) {
+ mDownloadGuid = downloadGuid;
return this;
}
@@ -270,8 +270,8 @@ public final class DownloadInfo {
.setReferer(downloadInfo.getReferer())
.setOriginalUrl(downloadInfo.getOriginalUrl())
.setContentLength(downloadInfo.getContentLength())
- .setHasDownloadId(downloadInfo.hasDownloadId())
- .setDownloadId(downloadInfo.getDownloadId())
+ .setNotificationId(downloadInfo.getNotificationId())
+ .setDownloadGuid(downloadInfo.getDownloadGuid())
.setHasUserGesture(downloadInfo.hasUserGesture())
.setContentDisposition(downloadInfo.getContentDisposition())
.setIsGETRequest(downloadInfo.isGETRequest())
diff --git a/content/public/browser/android/download_controller_android.h b/content/public/browser/android/download_controller_android.h
index e048afd..2ef664e 100644
--- a/content/public/browser/android/download_controller_android.h
+++ b/content/public/browser/android/download_controller_android.h
@@ -41,8 +41,9 @@ class CONTENT_EXPORT DownloadControllerAndroid : public DownloadItem::Observer {
bool is_link, const std::string& extra_headers) = 0;
// Called when a dangerous download item is verified or rejected.
- virtual void DangerousDownloadValidated(
- WebContents* web_contents, int download_id, bool accept) = 0;
+ virtual void DangerousDownloadValidated(WebContents* web_contents,
+ const std::string& download_guid,
+ bool accept) = 0;
// Callback when user permission prompt finishes. Args: whether file access
// permission is acquired.