Commit f011f43c authored by Min Qin's avatar Min Qin Committed by Commit Bot

Reland "Move DownloadManagerBridge to chrome/browser/download"

This reverts commit e1946c92.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> Revert "Move DownloadManagerBridge to chrome/browser/download"
> 
> This reverts commit fdf71331.
> 
> Reason for revert: compile failure:https://ci.chromium.org/p/chrome/builders/ci/android_arm64-builder-perf/129178
> 
> Original change's description:
> > Move DownloadManagerBridge to chrome/browser/download
> > 
> > Part of the modulization effort.
> > 
> > Bug: 1013759
> > Change-Id: I3a250fb293925ebe3c98fc068003b32568112ff9
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1902072
> > Reviewed-by: Shakti Sahu <shaktisahu@chromium.org>
> > Reviewed-by: David Trainor <dtrainor@chromium.org>
> > Commit-Queue: Min Qin <qinmin@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#715066}
> 
> TBR=dtrainor@chromium.org,qinmin@chromium.org,shaktisahu@chromium.org
> 
> Change-Id: I8751d6528d8b800a409657b3fdbd9a8c7897e0ae
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 1013759
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1915219
> Reviewed-by: Tommy Steimel <steimel@chromium.org>
> Commit-Queue: Tommy Steimel <steimel@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#715097}

TBR=dtrainor@chromium.org,qinmin@chromium.org,shaktisahu@chromium.org,steimel@chromium.org

Change-Id: I762766e0a307a5d6ad12bd702d072bacd5680b73
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1013759
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1915290Reviewed-by: default avatarMin Qin <qinmin@chromium.org>
Commit-Queue: Min Qin <qinmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715129}
parent d37db53d
......@@ -2593,7 +2593,6 @@ generate_jni("chrome_jni_headers") {
"java/src/org/chromium/chrome/browser/download/DownloadController.java",
"java/src/org/chromium/chrome/browser/download/DownloadItem.java",
"java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
"java/src/org/chromium/chrome/browser/download/DownloadMediaData.java",
"java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java",
......
......@@ -487,7 +487,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/download/DownloadItem.java",
"java/src/org/chromium/chrome/browser/download/DownloadLocationCustomView.java",
"java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
"java/src/org/chromium/chrome/browser/download/DownloadMediaData.java",
"java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java",
......
......@@ -335,7 +335,7 @@ public class DownloadBroadcastManager extends Service {
intent, DownloadNotificationService.EXTRA_DOWNLOAD_FILE_PATH);
if (ContentUriUtils.isContentUri(downloadFilePath)) {
// On Q+, content URI is being used and there is no download ID.
openDownloadWithId(context, intent, DownloadItem.INVALID_DOWNLOAD_ID, contentId);
openDownloadWithId(context, intent, DownloadConstants.INVALID_DOWNLOAD_ID, contentId);
} else {
long[] ids =
intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
......@@ -360,7 +360,8 @@ public class DownloadBroadcastManager extends Service {
* Called to open a particular download item with the given ID.
* @param context Context of the receiver.
* @param intent Intent from the notification.
* @param id ID from the Android DownloadManager, or DownloadItem.INVALID_DOWNLOAD_ID on Q+.
* @param id ID from the Android DownloadManager, or DownloadConstants.INVALID_DOWNLOAD_ID on
* Q+.
* @param contentId Content ID of the download.
*/
private void openDownloadWithId(Context context, Intent intent, long id, ContentId contentId) {
......
......@@ -391,7 +391,7 @@ public class DownloadInfoBarController implements OfflineContentProvider.Observe
return false;
}
if (DownloadUtils.shouldAutoOpenDownload(offlineItem.mimeType, true)) {
if (MimeUtils.canAutoOpenMimeType(offlineItem.mimeType)) {
return false;
}
......
......@@ -21,12 +21,10 @@ import org.chromium.components.offline_items_collection.OfflineItemState;
* DownloadManager must be queried for the correct status.
*/
public class DownloadItem {
static final long INVALID_DOWNLOAD_ID = -1L;
private final ContentId mContentId = new ContentId();
private boolean mUseAndroidDownloadManager;
private DownloadInfo mDownloadInfo;
private long mDownloadId = INVALID_DOWNLOAD_ID;
private long mDownloadId = DownloadConstants.INVALID_DOWNLOAD_ID;
private long mStartTime;
private long mEndTime;
private boolean mHasBeenExternallyRemoved;
......
......@@ -19,7 +19,6 @@ import android.provider.MediaStore.MediaColumns;
import android.text.TextUtils;
import android.util.Pair;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
......@@ -68,8 +67,6 @@ import org.chromium.net.RegistrationPolicyAlwaysRegister;
import org.chromium.ui.widget.Toast;
import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
......@@ -89,18 +86,6 @@ import java.util.concurrent.RejectedExecutionException;
public class DownloadManagerService implements DownloadController.DownloadNotificationService,
NetworkChangeNotifierAutoDetect.Observer,
DownloadServiceDelegate, ProfileManager.Observer {
// Download status.
@IntDef({DownloadStatus.IN_PROGRESS, DownloadStatus.COMPLETE, DownloadStatus.FAILED,
DownloadStatus.CANCELLED, DownloadStatus.INTERRUPTED})
@Retention(RetentionPolicy.SOURCE)
public @interface DownloadStatus {
int IN_PROGRESS = 0;
int COMPLETE = 1;
int FAILED = 2;
int CANCELLED = 3;
int INTERRUPTED = 4;
}
private static final String TAG = "DownloadService";
private static final String DOWNLOAD_DIRECTORY = "Download";
private static final String DOWNLOAD_UMA_ENTRY = "DownloadUmaEntry";
......@@ -601,7 +586,7 @@ public class DownloadManagerService implements DownloadController.DownloadNotifi
info.getFileName(), info.getDescription(), info.getMimeType(),
info.getFilePath(), info.getBytesReceived(), info.getOriginalUrl(),
info.getReferrer(), info.getDownloadGuid());
success = systemDownloadId != DownloadItem.INVALID_DOWNLOAD_ID;
success = systemDownloadId != DownloadConstants.INVALID_DOWNLOAD_ID;
if (success) item.setSystemDownloadId(systemDownloadId);
}
boolean canResolve = success
......@@ -823,8 +808,7 @@ public class DownloadManagerService implements DownloadController.DownloadNotifi
downloadItem.setSystemDownloadId(response.downloadId);
if (!response.result) {
onDownloadFailed(downloadItem, response.failureReason);
recordDownloadCompletionStats(
true, DownloadManagerService.DownloadStatus.FAILED, 0, 0, 0, 0);
recordDownloadCompletionStats(true, DownloadStatus.FAILED, 0, 0, 0, 0);
return;
}
......@@ -838,7 +822,7 @@ public class DownloadManagerService implements DownloadController.DownloadNotifi
boolean isSupportedMimeType, String originalUrl, String referrer,
@Nullable String mimeType) {
assert !ThreadUtils.runningOnUiThread();
if (downloadId == DownloadItem.INVALID_DOWNLOAD_ID) {
if (downloadId == DownloadConstants.INVALID_DOWNLOAD_ID) {
if (!ContentUriUtils.isContentUri(filePath)) return null;
return getLaunchIntentFromDownloadUri(
filePath, isSupportedMimeType, originalUrl, referrer, mimeType);
......@@ -1249,9 +1233,8 @@ public class DownloadManagerService implements DownloadController.DownloadNotifi
public void onSuccessNotificationShown(
DownloadInfo info, boolean canResolve, int notificationId, long systemDownloadId) {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_OFFLINE_CONTENT_PROVIDER)) {
if (canResolve
&& DownloadUtils.shouldAutoOpenDownload(
info.getMimeType(), info.hasUserGesture())) {
if (canResolve && MimeUtils.canAutoOpenMimeType(info.getMimeType())
&& info.hasUserGesture()) {
DownloadItem item = new DownloadItem(false, info);
item.setSystemDownloadId(systemDownloadId);
handleAutoOpenAfterDownload(item);
......@@ -1389,9 +1372,8 @@ public class DownloadManagerService implements DownloadController.DownloadNotifi
@Override
protected void onPostExecute(Boolean canResolve) {
if (DownloadUtils.shouldAutoOpenDownload(
result.mimeType, item.getDownloadInfo().hasUserGesture())
&& canResolve) {
if (MimeUtils.canAutoOpenMimeType(result.mimeType)
&& item.getDownloadInfo().hasUserGesture() && canResolve) {
handleAutoOpenAfterDownload(item);
} else {
getInfoBarController(item.getDownloadInfo().isOffTheRecord())
......@@ -1821,9 +1803,8 @@ public class DownloadManagerService implements DownloadController.DownloadNotifi
boolean isSupportedMimeType = isSupportedMimeType(info.getMimeType());
boolean canResolve = MimeUtils.isOMADownloadDescription(info.getMimeType())
|| canResolveDownloadItem(downloadItem, isSupportedMimeType);
return canResolve
&& DownloadUtils.shouldAutoOpenDownload(
info.getMimeType(), info.hasUserGesture());
return canResolve && MimeUtils.canAutoOpenMimeType(info.getMimeType())
&& info.hasUserGesture();
}
@Override
protected void onPostExecute(Boolean result) {
......
......@@ -80,11 +80,8 @@ import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
......@@ -107,13 +104,6 @@ public class DownloadUtils {
private static final int[] BYTES_STRINGS = {
R.string.download_ui_kb, R.string.download_ui_mb, R.string.download_ui_gb};
// Set will be more expensive to initialize, so use an ArrayList here.
private static final List<String> MIME_TYPES_TO_OPEN = new ArrayList<String>(Arrays.asList(
MimeUtils.OMA_DOWNLOAD_DESCRIPTOR_MIME, "application/pdf", "application/x-x509-ca-cert",
"application/x-x509-user-cert", "application/x-x509-server-cert",
"application/x-pkcs12", "application/application/x-pem-file", "application/pkix-cert",
"application/x-wifi-config"));
private static final String TAG = "download";
private static final String DEFAULT_MIME_TYPE = "*/*";
......@@ -389,21 +379,6 @@ public class DownloadUtils {
return uri != null ? uri.toString() : new String();
}
/**
* Determines if the download should be immediately opened after
* downloading.
*
* @param mimeType The mime type of the download.
* @param hasUserGesture Whether the download is associated with an user gesture.
* @return true if the downloaded content should be opened, or false otherwise.
*/
@VisibleForTesting
@CalledByNative
public static boolean shouldAutoOpenDownload(String mimeType, boolean hasUserGesture) {
return hasUserGesture && MIME_TYPES_TO_OPEN.contains(mimeType);
}
/**
* Utility method to open an {@link OfflineItem}, which can be a chrome download, offline page.
* Falls back to open download home.
......@@ -1014,25 +989,6 @@ public class DownloadUtils {
return primaryPath == null ? false : path.contains(primaryPath);
}
/**
* Parses an originating URL string and returns a valid Uri that can be inserted into
* DownloadProvider. The returned Uri has to be null or non-empty http(s) scheme.
* @param originalUrl String representation of the originating URL.
* @return A valid Uri that can be accepted by DownloadProvider.
*/
public static Uri parseOriginalUrl(String originalUrl) {
Uri originalUri = TextUtils.isEmpty(originalUrl) ? null : Uri.parse(originalUrl);
if (originalUri != null) {
String scheme = originalUri.normalizeScheme().getScheme();
if (scheme == null
|| (!scheme.equals(UrlConstants.HTTPS_SCHEME)
&& !scheme.equals(UrlConstants.HTTP_SCHEME))) {
originalUri = null;
}
}
return originalUri;
}
/**
* @return The status of prompt for download pref, defined by {@link DownloadPromptStatus}.
*/
......
......@@ -290,7 +290,7 @@ public class OMADownloadHandler extends BroadcastReceiver {
OMAInfo omaInfo = null;
final DownloadManager manager =
(DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
boolean isContentUri = (mDownloadId == DownloadItem.INVALID_DOWNLOAD_ID)
boolean isContentUri = (mDownloadId == DownloadConstants.INVALID_DOWNLOAD_ID)
&& ContentUriUtils.isContentUri(mDownloadInfo.getFilePath());
try {
ParcelFileDescriptor fd = null;
......@@ -336,14 +336,14 @@ public class OMADownloadHandler extends BroadcastReceiver {
// Send notification if required attributes are missing.
if (omaInfo.getTypes().isEmpty() || getSize(omaInfo) <= 0
|| omaInfo.isValueEmpty(OMA_OBJECT_URI)) {
sendNotification(omaInfo, mDownloadInfo, DownloadItem.INVALID_DOWNLOAD_ID,
sendNotification(omaInfo, mDownloadInfo, DownloadConstants.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, DownloadItem.INVALID_DOWNLOAD_ID,
sendNotification(omaInfo, mDownloadInfo, DownloadConstants.INVALID_DOWNLOAD_ID,
DOWNLOAD_STATUS_INVALID_DDVERSION);
return;
}
......@@ -369,8 +369,8 @@ public class OMADownloadHandler extends BroadcastReceiver {
String action = intent.getAction();
if (!DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) return;
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, DownloadItem.INVALID_DOWNLOAD_ID);
if (downloadId == DownloadItem.INVALID_DOWNLOAD_ID) return;
DownloadManager.EXTRA_DOWNLOAD_ID, DownloadConstants.INVALID_DOWNLOAD_ID);
if (downloadId == DownloadConstants.INVALID_DOWNLOAD_ID) return;
boolean isPendingOMADownload = isPendingOMADownload(downloadId);
boolean isInOMASharedPrefs = isDownloadIdInOMASharedPrefs(downloadId);
if (isPendingOMADownload || isInOMASharedPrefs) {
......@@ -517,8 +517,7 @@ public class OMADownloadHandler extends BroadcastReceiver {
if (which == AlertDialog.BUTTON_POSITIVE) {
downloadOMAContent(downloadId, downloadInfo, omaInfo);
} else {
sendNotification(omaInfo, downloadInfo,
DownloadItem.INVALID_DOWNLOAD_ID,
sendNotification(omaInfo, downloadInfo, DownloadConstants.INVALID_DOWNLOAD_ID,
DOWNLOAD_STATUS_USER_CANCELLED);
}
};
......@@ -549,7 +548,7 @@ public class OMADownloadHandler extends BroadcastReceiver {
DialogInterface.OnClickListener clickListener = (dialog, which) -> {
if (which == AlertDialog.BUTTON_POSITIVE) {
sendInstallNotificationAndNextStep(omaInfo, downloadInfo,
DownloadItem.INVALID_DOWNLOAD_ID, statusMessage);
DownloadConstants.INVALID_DOWNLOAD_ID, statusMessage);
}
};
new AlertDialog
......@@ -853,11 +852,11 @@ public class OMADownloadHandler extends BroadcastReceiver {
@Override
protected void onPostExecute(Boolean canResolve) {
if (result.downloadStatus == DownloadManagerService.DownloadStatus.COMPLETE) {
if (result.downloadStatus == DownloadStatus.COMPLETE) {
onDownloadCompleted(item.getDownloadInfo(), downloadId, installNotifyURI);
removeOMADownloadFromSharedPrefs(downloadId);
showDownloadOnInfoBar(item, result.downloadStatus);
} else if (result.downloadStatus == DownloadManagerService.DownloadStatus.FAILED) {
} else if (result.downloadStatus == DownloadStatus.FAILED) {
onDownloadFailed(item.getDownloadInfo(), downloadId, result.failureReason,
installNotifyURI);
removeOMADownloadFromSharedPrefs(downloadId);
......@@ -875,9 +874,9 @@ public class OMADownloadHandler extends BroadcastReceiver {
if (infobarController == null) return;
OfflineItem offlineItem = DownloadItem.createOfflineItem(downloadItem);
offlineItem.id.namespace = LegacyHelpers.LEGACY_ANDROID_DOWNLOAD_NAMESPACE;
if (downloadStatus == DownloadManagerService.DownloadStatus.COMPLETE) {
if (downloadStatus == DownloadStatus.COMPLETE) {
offlineItem.state = OfflineItemState.COMPLETE;
} else if (downloadStatus == DownloadManagerService.DownloadStatus.FAILED) {
} else if (downloadStatus == DownloadStatus.FAILED) {
offlineItem.state = OfflineItemState.FAILED;
}
......@@ -1050,7 +1049,7 @@ public class OMADownloadHandler extends BroadcastReceiver {
protected void onPostExecute(Boolean success) {
if (success) {
showNextUrlDialog(mOMAInfo);
} else if (mDownloadId != DownloadItem.INVALID_DOWNLOAD_ID) {
} else if (mDownloadId != DownloadConstants.INVALID_DOWNLOAD_ID) {
// Remove the downloaded content.
((DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE))
.remove(mDownloadId);
......
......@@ -8,7 +8,6 @@ import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import android.util.Log;
import android.util.Pair;
......@@ -485,23 +484,4 @@ public class DownloadManagerServiceTest {
mService.onConnectionTypeChanged(ConnectionType.CONNECTION_2G);
Assert.assertEquals(resumableIdCount, mService.mAutoResumableDownloadIds.size());
}
/**
* Test to make sure {@link DownloadUtils#shouldAutoOpenDownload}
* returns the right result for varying MIME types and Content-Dispositions.
*/
@Test
@SmallTest
@Feature({"Download"})
public void testshouldAutoOpenDownload() {
// Should not open any download type MIME types.
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/download", true));
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/x-download", true));
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/octet-stream", true));
Assert.assertTrue(DownloadUtils.shouldAutoOpenDownload("application/pdf", true));
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/pdf", false));
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/x-download", true));
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/x-download", true));
Assert.assertFalse(DownloadUtils.shouldAutoOpenDownload("application/x-download", true));
}
}
......@@ -291,12 +291,12 @@ public class OMADownloadHandlerTest {
4, true);
DownloadQueryResultVerifier verifier =
new DownloadQueryResultVerifier(DownloadManagerService.DownloadStatus.COMPLETE);
new DownloadQueryResultVerifier(DownloadStatus.COMPLETE);
DownloadManagerBridge.queryDownloadResult(downloadId1, verifier);
waitForQueryCompletion(verifier);
manager.remove(downloadId1);
verifier = new DownloadQueryResultVerifier(DownloadManagerService.DownloadStatus.CANCELLED);
verifier = new DownloadQueryResultVerifier(DownloadStatus.CANCELLED);
DownloadManagerBridge.queryDownloadResult(downloadId1, verifier);
waitForQueryCompletion(verifier);
}
......
......@@ -7,13 +7,17 @@ import("//build/config/android/rules.gni")
android_library("java") {
java_files = [
"java/src/org/chromium/chrome/browser/download/DirectoryOption.java",
"java/src/org/chromium/chrome/browser/download/DownloadFilter.java",
"java/src/org/chromium/chrome/browser/download/DownloadConstants.java",
"java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java",
"java/src/org/chromium/chrome/browser/download/DownloadFileProvider.java",
"java/src/org/chromium/chrome/browser/download/DownloadFilter.java",
"java/src/org/chromium/chrome/browser/download/DownloadInfo.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadStatus.java",
"java/src/org/chromium/chrome/browser/download/MediaStoreHelper.java",
"java/src/org/chromium/chrome/browser/download/DownloadStartupUtils.java",
"java/src/org/chromium/chrome/browser/download/MimeUtils.java",
"java/src/org/chromium/chrome/browser/download/UriUtils.java",
]
deps = [
......@@ -32,6 +36,7 @@ android_library("java") {
generate_jni("jni_headers") {
sources = [
"java/src/org/chromium/chrome/browser/download/DownloadInfo.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadStartupUtils.java",
"java/src/org/chromium/chrome/browser/download/MimeUtils.java",
]
......
......@@ -10,7 +10,7 @@
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/feature_list.h"
#include "chrome/android/chrome_jni_headers/DownloadManagerBridge_jni.h"
#include "chrome/browser/download/android/jni_headers/DownloadManagerBridge_jni.h"
#include "components/download/public/common/download_features.h"
#include "url/gurl.h"
......@@ -22,14 +22,13 @@ using download::DownloadItem;
static void JNI_DownloadManagerBridge_OnAddCompletedDownloadDone(
JNIEnv* env,
jlong callback_id,
jlong download_id,
jboolean can_resolve) {
jlong download_id) {
DCHECK(callback_id);
// Convert java long long int to c++ pointer, take ownership.
std::unique_ptr<AddCompletedDownloadCallback> cb(
reinterpret_cast<AddCompletedDownloadCallback*>(callback_id));
std::move(*cb).Run(download_id, can_resolve);
std::move(*cb).Run(download_id);
}
void DownloadManagerBridge::AddCompletedDownload(
......
......@@ -9,7 +9,7 @@
#include "components/download/public/common/download_item.h"
using DownloadItem = download::DownloadItem;
using AddCompletedDownloadCallback = base::OnceCallback<void(int64_t, bool)>;
using AddCompletedDownloadCallback = base::OnceCallback<void(int64_t)>;
// This class pairs with DownloadManagerBridge on Java side, that handles all
// the android DownloadManager related functionalities. Both classes have only
......
......@@ -110,9 +110,9 @@ std::string DownloadUtils::RemapGenericMimeType(const std::string& mime_type,
// static
bool DownloadUtils::ShouldAutoOpenDownload(download::DownloadItem* item) {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_DownloadUtils_shouldAutoOpenDownload(
env, ConvertUTF8ToJavaString(env, item->GetMimeType()),
IsDownloadUserInitiated(item));
return Java_MimeUtils_canAutoOpenMimeType(
env, ConvertUTF8ToJavaString(env, item->GetMimeType())) &&
IsDownloadUserInitiated(item);
}
// static
......
// Copyright 2013 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;
/**
* Constants that are used in download.
*/
public class DownloadConstants { static final long INVALID_DOWNLOAD_ID = -1L; }
......@@ -13,7 +13,6 @@ import android.os.Build;
import android.os.Environment;
import android.support.v4.app.NotificationManagerCompat;
import android.text.TextUtils;
import android.util.Pair;
import org.chromium.base.Callback;
import org.chromium.base.ContentUriUtils;
......@@ -100,7 +99,7 @@ public class DownloadManagerBridge {
NotificationManagerCompat.from(getContext());
boolean useSystemNotification = !notificationManager.areNotificationsEnabled();
long downloadId = getDownloadIdForDownloadGuid(downloadGuid);
if (downloadId != DownloadItem.INVALID_DOWNLOAD_ID) return downloadId;
if (downloadId != DownloadConstants.INVALID_DOWNLOAD_ID) return downloadId;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
Class<?> c = manager.getClass();
......@@ -109,7 +108,7 @@ public class DownloadManagerBridge {
String.class, long.class, boolean.class, Uri.class, Uri.class};
Method method = c.getMethod("addCompletedDownload", args);
// OriginalUri has to be null or non-empty http(s) scheme.
Uri originalUri = DownloadUtils.parseOriginalUrl(originalUrl);
Uri originalUri = UriUtils.parseOriginalUrl(originalUrl);
Uri refererUri = TextUtils.isEmpty(referer) ? null : Uri.parse(referer);
downloadId = (Long) method.invoke(manager, fileName, description, true, mimeType,
filePath, fileSizeBytes, useSystemNotification, originalUri, refererUri);
......@@ -189,10 +188,10 @@ public class DownloadManagerBridge {
(DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
Cursor c = manager.query(new DownloadManager.Query().setFilterById(downloadId));
if (c == null) {
result.downloadStatus = DownloadManagerService.DownloadStatus.CANCELLED;
result.downloadStatus = DownloadStatus.CANCELLED;
return result;
}
result.downloadStatus = DownloadManagerService.DownloadStatus.IN_PROGRESS;
result.downloadStatus = DownloadStatus.IN_PROGRESS;
if (c.moveToNext()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
result.downloadStatus = getDownloadStatus(status);
......@@ -205,7 +204,7 @@ public class DownloadManagerBridge {
result.bytesTotal =
c.getLong(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
} else {
result.downloadStatus = DownloadManagerService.DownloadStatus.CANCELLED;
result.downloadStatus = DownloadStatus.CANCELLED;
}
c.close();
......@@ -277,8 +276,7 @@ public class DownloadManagerBridge {
/**
* This function is meant to be called as the last step of a download. It will add the download
* to the android's DownloadManager and determine if the download can be resolved to any
* activity so that it can be auto-opened.
* to the android's DownloadManager if the download is not a content URI.
*/
@CalledByNative
private static void addCompletedDownload(String fileName, String description,
......@@ -286,25 +284,19 @@ public class DownloadManagerBridge {
String referrer, String downloadGuid, long callbackId) {
final String mimeType =
MimeUtils.remapGenericMimeType(originalMimeType, originalUrl, fileName);
AsyncTask<Pair<Long, Boolean>> task = new AsyncTask<Pair<Long, Boolean>>() {
AsyncTask<Long> task = new AsyncTask<Long>() {
@Override
protected Pair<Long, Boolean> doInBackground() {
protected Long doInBackground() {
long downloadId = ContentUriUtils.isContentUri(filePath)
? DownloadItem.INVALID_DOWNLOAD_ID
? DownloadConstants.INVALID_DOWNLOAD_ID
: addCompletedDownload(fileName, description, mimeType, filePath,
fileSizeBytes, originalUrl, referrer, downloadGuid);
boolean success = ContentUriUtils.isContentUri(filePath)
|| downloadId != DownloadItem.INVALID_DOWNLOAD_ID;
boolean canResolve = success
&& DownloadManagerService.canResolveDownload(
filePath, mimeType, downloadId);
return Pair.create(downloadId, canResolve);
return downloadId;
}
@Override
protected void onPostExecute(Pair<Long, Boolean> result) {
DownloadManagerBridgeJni.get().onAddCompletedDownloadDone(
callbackId, result.first, result.second);
protected void onPostExecute(Long downloadId) {
DownloadManagerBridgeJni.get().onAddCompletedDownloadDone(callbackId, downloadId);
}
};
try {
......@@ -313,18 +305,18 @@ public class DownloadManagerBridge {
// Reaching thread limit, update will be reschduled for the next run.
Log.e(TAG, "Thread limit reached, reschedule notification update later.");
DownloadManagerBridgeJni.get().onAddCompletedDownloadDone(
callbackId, DownloadItem.INVALID_DOWNLOAD_ID, false);
callbackId, DownloadConstants.INVALID_DOWNLOAD_ID);
}
}
private static int getDownloadStatus(int downloadManagerStatus) {
switch (downloadManagerStatus) {
case DownloadManager.STATUS_SUCCESSFUL:
return DownloadManagerService.DownloadStatus.COMPLETE;
return DownloadStatus.COMPLETE;
case DownloadManager.STATUS_FAILED:
return DownloadManagerService.DownloadStatus.FAILED;
return DownloadStatus.FAILED;
default:
return DownloadManagerService.DownloadStatus.IN_PROGRESS;
return DownloadStatus.IN_PROGRESS;
}
}
......@@ -459,6 +451,6 @@ public class DownloadManagerBridge {
@NativeMethods
interface Natives {
void onAddCompletedDownloadDone(long callbackId, long downloadId, boolean canResolve);
void onAddCompletedDownloadDone(long callbackId, long downloadId);
}
}
// Copyright 2019 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 androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Status of a download item.
*/
@IntDef({DownloadStatus.IN_PROGRESS, DownloadStatus.COMPLETE, DownloadStatus.FAILED,
DownloadStatus.CANCELLED, DownloadStatus.INTERRUPTED})
@Retention(RetentionPolicy.SOURCE)
public @interface DownloadStatus {
int IN_PROGRESS = 0;
int COMPLETE = 1;
int FAILED = 2;
int CANCELLED = 3;
int INTERRUPTED = 4;
}
\ No newline at end of file
......@@ -9,8 +9,10 @@ import android.webkit.MimeTypeMap;
import org.chromium.base.annotations.CalledByNative;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
/**
* Utility class for MIME type related operations.
......@@ -29,6 +31,14 @@ public class MimeUtils {
private static final HashSet<String> GENERIC_MIME_TYPES = new HashSet<String>(Arrays.asList(
"text/plain", "application/octet-stream", "binary/octet-stream", "octet/stream",
"application/download", "application/force-download", "application/unknown"));
// Set will be more expensive to initialize, so use an ArrayList here.
private static final List<String> MIME_TYPES_TO_OPEN = new ArrayList<String>(Arrays.asList(
MimeUtils.OMA_DOWNLOAD_DESCRIPTOR_MIME, "application/pdf", "application/x-x509-ca-cert",
"application/x-x509-user-cert", "application/x-x509-server-cert",
"application/x-pkcs12", "application/application/x-pem-file", "application/pkix-cert",
"application/x-wifi-config"));
/**
* If the given MIME type is null, or one of the "generic" types (text/plain
* or application/octet-stream) map it to a type that Android can deal with.
......@@ -82,4 +92,16 @@ public class MimeUtils {
public static boolean isOMADownloadDescription(String mimeType) {
return OMA_DOWNLOAD_DESCRIPTOR_MIME.equalsIgnoreCase(mimeType);
}
/**
* Determines if the download should be immediately opened after
* downloading.
*
* @param mimeType The mime type of the download.
* @return true if the downloaded content should be opened, or false otherwise.
*/
@CalledByNative
public static boolean canAutoOpenMimeType(String mimeType) {
return MIME_TYPES_TO_OPEN.contains(mimeType);
}
}
// Copyright 2019 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 android.net.Uri;
import android.text.TextUtils;
import org.chromium.chrome.browser.util.UrlConstants;
/**
* Utility class for Uri related operations.
*/
public class UriUtils {
/**
* Parses an originating URL string and returns a valid Uri that can be inserted into
* DownloadManager. The returned Uri has to be null or non-empty http(s) scheme.
* @param originalUrl String representation of the originating URL.
* @return A valid Uri that can be accepted by DownloadManager.
*/
public static Uri parseOriginalUrl(String originalUrl) {
Uri originalUri = TextUtils.isEmpty(originalUrl) ? null : Uri.parse(originalUrl);
if (originalUri != null) {
String scheme = originalUri.normalizeScheme().getScheme();
if (scheme == null
|| (!scheme.equals(UrlConstants.HTTPS_SCHEME)
&& !scheme.equals(UrlConstants.HTTP_SCHEME))) {
originalUri = null;
}
}
return originalUri;
}
}
......@@ -27,4 +27,22 @@ public class MimeUtilsTest {
Assert.assertEquals("txt", MimeUtils.getFileExtension("http://file.ext", "file.txt"));
Assert.assertEquals("txt", MimeUtils.getFileExtension("http://file.ext", "file name.txt"));
}
/**
* Test to make sure {@link DownloadUtils#shouldAutoOpenDownload}
* returns the right result for varying MIME types and Content-Dispositions.
*/
@Test
@SmallTest
@Feature({"Download"})
public void testCanAutoOpenMimeType() {
// Should not open any download type MIME types.
Assert.assertFalse(MimeUtils.canAutoOpenMimeType("application/download"));
Assert.assertFalse(MimeUtils.canAutoOpenMimeType("application/x-download"));
Assert.assertFalse(MimeUtils.canAutoOpenMimeType("application/octet-stream"));
Assert.assertTrue(MimeUtils.canAutoOpenMimeType("application/pdf"));
Assert.assertTrue(MimeUtils.canAutoOpenMimeType("application/x-x509-server-cert"));
Assert.assertTrue(MimeUtils.canAutoOpenMimeType("application/x-wifi-config"));
Assert.assertTrue(MimeUtils.canAutoOpenMimeType("application/pkix-cert"));
}
}
......@@ -492,18 +492,15 @@ void DownloadOfflineContentProvider::AddCompletedDownload(DownloadItem* item) {
DownloadManagerBridge::AddCompletedDownload(
item,
base::BindOnce(&DownloadOfflineContentProvider::AddCompletedDownloadDone,
weak_ptr_factory_.GetWeakPtr(), item));
weak_ptr_factory_.GetWeakPtr(), item->GetGuid()));
#endif
}
void DownloadOfflineContentProvider::AddCompletedDownloadDone(
DownloadItem* item,
int64_t system_download_id,
bool can_resolve) {
const std::string& download_guid,
int64_t system_download_id) {
#if defined(OS_ANDROID)
if (!can_resolve)
return;
DownloadItem* item = GetDownload(download_guid);
if (DownloadUtils::IsOmaDownloadDescription(item->GetMimeType())) {
DownloadManagerService::GetInstance()->HandleOMADownload(
item, system_download_id);
......
......@@ -116,9 +116,8 @@ class DownloadOfflineContentProvider
VisualsCallback callback,
const SkBitmap& bitmap);
void AddCompletedDownload(DownloadItem* item);
void AddCompletedDownloadDone(DownloadItem* item,
int64_t system_download_id,
bool can_resolve);
void AddCompletedDownloadDone(const std::string& download_guid,
int64_t system_download_id);
void OnRenameDownloadCallbackDone(RenameCallback callback,
DownloadItem* item,
DownloadItem::DownloadRenameResult result);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment