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

Get display names for all download on InProgressManager initialization

With recent changes, the target path is not a content Uri if download
is written to a content Uri. This may cause some undesirable effect
for resumption.
We kept the target path earlier due to display names.
This Cl solves both issues by loading the display names from ContentResolver
on initialization time, and pass them to all the download items
so that could be used later. The target path will be changed to content Uri
once intermediate file rename completes.

TBR=dtrainor@chromium.org
BUG=931021

Change-Id: I36bf5245ea1f7d36aa707a4b0f1065a5b0f8b133
Reviewed-on: https://chromium-review.googlesource.com/c/1479934
Commit-Queue: Min Qin <qinmin@chromium.org>
Reviewed-by: default avatarMin Qin <qinmin@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarXing Liu <xingliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#636738}
parent a57833de
......@@ -354,8 +354,8 @@ public abstract class AppHooks {
/**
* @return A new {@link DownloadCollectionBridge} instance.
*/
public DownloadCollectionBridge createDownloadCollectionBridge() {
return new DownloadCollectionBridge();
public DownloadCollectionBridge getDownloadCollectionBridge() {
return DownloadCollectionBridge.getDownloadCollectionBridge();
}
/**
......
......@@ -36,7 +36,6 @@ import org.chromium.base.task.AsyncTask;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.AppHooks;
import org.chromium.chrome.browser.download.DownloadMetrics.DownloadOpenSource;
import org.chromium.chrome.browser.download.DownloadNotificationUmaHelper.UmaBackgroundDownload;
import org.chromium.chrome.browser.download.DownloadNotificationUmaHelper.UmaDownloadResumption;
......@@ -49,7 +48,6 @@ import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.util.ConversionUtils;
import org.chromium.chrome.browser.util.FeatureUtilities;
import org.chromium.components.download.DownloadCollectionBridge;
import org.chromium.components.download.DownloadState;
import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.components.feature_engagement.Tracker;
......@@ -231,8 +229,6 @@ public class DownloadManagerService
DownloadNotifier downloadNotifier = new SystemDownloadNotifier();
sDownloadManagerService = new DownloadManagerService(
downloadNotifier, new Handler(), UPDATE_DELAY_MILLIS);
DownloadCollectionBridge.setDownloadCollectionBridge(
AppHooks.get().createDownloadCollectionBridge());
}
return sDownloadManagerService;
}
......
......@@ -76,6 +76,7 @@ import org.chromium.chrome.browser.util.ConversionUtils;
import org.chromium.chrome.browser.webapps.WebApkVersionManager;
import org.chromium.chrome.browser.webapps.WebappRegistry;
import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory;
import org.chromium.components.download.DownloadCollectionBridge;
import org.chromium.components.minidump_uploader.CrashFileManager;
import org.chromium.components.signin.AccountManagerFacade;
import org.chromium.components.signin.AccountsChangeObserver;
......@@ -176,6 +177,11 @@ public class ProcessInitializationHandler {
UniqueIdentificationGeneratorFactory.registerGenerator(SyncController.GENERATOR_ID,
new UuidBasedUniqueIdentificationGenerator(
application, SESSIONS_UUID_PREF_KEY), false);
// Set up the DownloadCollectionBridge early as display names may be immediately retrieved
// after native is loaded.
DownloadCollectionBridge.setDownloadCollectionBridge(
AppHooks.get().getDownloadCollectionBridge());
}
/**
......
......@@ -145,13 +145,10 @@ ScopedJavaLocalRef<jobject> DownloadManagerService::CreateJavaDownloadInfo(
? std::string() : item->GetOriginalUrl().spec();
content::BrowserContext* browser_context =
content::DownloadItemUtils::GetBrowserContext(item);
base::FilePath display_path = item->GetFullPath().IsContentUri()
? item->GetFullPath()
: item->GetTargetFilePath();
return Java_DownloadInfo_createDownloadInfo(
env, ConvertUTF8ToJavaString(env, item->GetGuid()),
ConvertUTF8ToJavaString(env, item->GetFileNameToReportUser().value()),
ConvertUTF8ToJavaString(env, display_path.value()),
ConvertUTF8ToJavaString(env, item->GetTargetFilePath().value()),
ConvertUTF8ToJavaString(env, item->GetTabUrl().spec()),
ConvertUTF8ToJavaString(env, item->GetMimeType()),
item->GetReceivedBytes(), item->GetTotalBytes(),
......
......@@ -556,6 +556,7 @@ if (!is_ios) {
deps += [
"//components/autofill_assistant/browser",
"//components/autofill_assistant/browser:proto",
"//components/download/internal/common:internal_java",
"//content/public/test/android:web_test_java_support",
"//content/test:web_test_support",
"//testing/android/native_test:native_test_support",
......
......@@ -4,6 +4,8 @@
#include "components/download/internal/common/android/download_collection_bridge.h"
#include <utility>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/files/file_util.h"
......@@ -129,4 +131,38 @@ bool DownloadCollectionBridge::renameDownloadUri(
jdisplay_name);
}
// static
void DownloadCollectionBridge::GetDisplayNamesForDownloads(
GetDisplayNamesCallback cb) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobjectArray> jdisplay_infos =
Java_DownloadCollectionBridge_getDisplayNamesForDownloads(env);
auto result = std::make_unique<std::map<std::string, base::FilePath>>();
if (!jdisplay_infos) {
std::move(cb).Run(std::move(result));
return;
}
jsize count = env->GetArrayLength(jdisplay_infos.obj());
for (jsize i = 0; i < count; ++i) {
base::android::ScopedJavaLocalRef<jobject> jdisplay_info(
env, env->GetObjectArrayElement(jdisplay_infos.obj(), i));
ScopedJavaLocalRef<jstring> juri =
Java_DisplayNameInfo_getDownloadUri(env, jdisplay_info);
ScopedJavaLocalRef<jstring> jdisplay_name =
Java_DisplayNameInfo_getDisplayName(env, jdisplay_info);
if (juri && jdisplay_name) {
std::string uri = ConvertJavaStringToUTF8(env, juri);
std::string display_name = ConvertJavaStringToUTF8(env, jdisplay_name);
result->emplace(uri, display_name);
}
}
std::move(cb).Run(std::move(result));
}
// static
bool DownloadCollectionBridge::NeedToRetrieveDisplayNames() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_DownloadCollectionBridge_needToRetrieveDisplayNames(env);
}
} // namespace download
......@@ -5,12 +5,15 @@
#ifndef COMPONENTS_DOWNLOAD_INTERNAL_COMMON_ANDROID_DOWNLOAD_COLLECTION_BRIDGE_H_
#define COMPONENTS_DOWNLOAD_INTERNAL_COMMON_ANDROID_DOWNLOAD_COLLECTION_BRIDGE_H_
#include <map>
#include <memory>
#include <string>
#include "base/files/file.h"
#include "base/macros.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/in_progress_download_manager.h"
namespace download {
......@@ -19,31 +22,38 @@ namespace download {
class COMPONENTS_DOWNLOAD_EXPORT DownloadCollectionBridge {
public:
// Creates the intermediate URI for download to write to.
// Called on non UI thread.
static base::FilePath CreateIntermediateUriForPublish(
const GURL& original_url,
const GURL& referrer_url,
const base::FilePath& file_name,
const std::string& mime_type);
// Returns whether a download needs to be published.
// Can be called on any thread.
static bool ShouldPublishDownload(const base::FilePath& file_path);
// Moves existing file content to the intermediate Uri, and remove
// |source_path|.
// Called on non UI thread.
static DownloadInterruptReason MoveFileToIntermediateUri(
const base::FilePath& source_path,
const base::FilePath& destination_uri);
// Deletes the intermediate Uri that is being written to.
// Called on non UI thread.
static void DeleteIntermediateUri(const base::FilePath& intermediate_uri);
// Publishes the intermediate Uri to public download collection, and returns
// the final Uri.
// Called on non UI thread.
static base::FilePath PublishDownload(const base::FilePath& intermediate_uri);
// Opens the intermediate Uri for writing.
// Called on non UI thread.
static base::File OpenIntermediateUri(const base::FilePath& intermediate_uri);
// Checks whether a file name exists.
// Called on non UI thread.
static bool FileNameExists(const base::FilePath& file_name);
// Renames a content URI download to |new_display_name|. Returns true on
......@@ -52,6 +62,17 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadCollectionBridge {
static bool renameDownloadUri(const base::FilePath& download_uri,
const base::FilePath& new_display_name);
// Whether download display names needs to be retrieved.
// TODO(qinmin): move display names to history and in-progress DB.
// Can be called on any thread.
static bool NeedToRetrieveDisplayNames();
using GetDisplayNamesCallback =
base::OnceCallback<void(InProgressDownloadManager::DisplayNames)>;
// Gets the display name for all downloads.
// Called on non UI thread.
static void GetDisplayNamesForDownloads(GetDisplayNamesCallback cb);
private:
DISALLOW_COPY_AND_ASSIGN(DownloadCollectionBridge);
};
......
......@@ -24,6 +24,29 @@ public class DownloadCollectionBridge {
// Guards access to sDownloadCollectionBridge.
private static final Object sLock = new Object();
/**
* Class representing the Uri and display name pair for downloads.
*/
protected static class DisplayNameInfo {
private final String mUri;
private final String mDisplayName;
public DisplayNameInfo(String uri, String displayName) {
mUri = uri;
mDisplayName = displayName;
}
@CalledByNative("DisplayNameInfo")
private String getDownloadUri() {
return mUri;
}
@CalledByNative("DisplayNameInfo")
private String getDisplayName() {
return mDisplayName;
}
}
/**
* Return getDownloadCollectionBridge singleton.
*/
......@@ -109,6 +132,21 @@ public class DownloadCollectionBridge {
return false;
}
/**
* @return Whether download display names needs to be retrieved.
*/
protected boolean needToGetDisplayNames() {
return false;
}
/**
* Gets the display names for all downloads
* @return an array of download Uri and display name pair.
*/
protected DisplayNameInfo[] getDisplayNames() {
return null;
}
/**
* Creates an intermediate URI for download to be written into. On completion, call
* nativeOnCreateIntermediateUriResult() with |callbackId|.
......@@ -203,4 +241,21 @@ public class DownloadCollectionBridge {
private static boolean renameDownloadUri(final String downloadUri, final String displayName) {
return getDownloadCollectionBridge().rename(downloadUri, displayName);
}
/**
* @return Whether download display names needs to be retrieved.
*/
@CalledByNative
private static boolean needToRetrieveDisplayNames() {
return getDownloadCollectionBridge().needToGetDisplayNames();
}
/**
* Gets the display names for all downloads
* @return an array of download Uri and display name pair.
*/
@CalledByNative
private static DisplayNameInfo[] getDisplayNamesForDownloads() {
return getDownloadCollectionBridge().getDisplayNames();
}
}
......@@ -1598,6 +1598,13 @@ void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
if (DOWNLOAD_INTERRUPT_REASON_NONE == reason) {
SetFullPath(full_path);
#if defined(OS_ANDROID)
// For content URIs, target file path is the same as the current path.
if (full_path.IsContentUri()) {
SetDisplayName(GetTargetFilePath().BaseName());
destination_info_.target_path = full_path;
}
#endif // defined(OS_ANDROID)
} else {
// TODO(asanka): Even though the rename failed, it may still be possible to
// recover the partial state from the 'before' name.
......@@ -1691,7 +1698,7 @@ void DownloadItemImpl::OnDownloadCompleting() {
base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
weak_ptr_factory_.GetWeakPtr());
#if defined(OS_ANDROID)
if (DownloadCollectionBridge::ShouldPublishDownload(GetTargetFilePath())) {
if (GetTargetFilePath().IsContentUri()) {
GetDownloadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&DownloadFile::PublishDownload,
......@@ -1736,15 +1743,7 @@ void DownloadItemImpl::OnDownloadRenamedToFinalName(
return;
}
#if defined(OS_ANDROID)
// Target file path may be different from the full path if the latter is a
// content Uri.
if (GetTargetFilePath() != full_path) {
DCHECK(full_path.IsContentUri());
}
#else
DCHECK(GetTargetFilePath() == full_path);
#endif // defined(OS_ANDROID)
if (full_path != GetFullPath()) {
// full_path is now the current and target file path.
......@@ -2075,12 +2074,7 @@ bool DownloadItemImpl::IsDownloadReadyForCompletion(
// directory.
DCHECK(!GetTargetFilePath().empty());
DCHECK(!GetFullPath().empty());
#if defined(OS_ANDROID)
DCHECK(GetFullPath().IsContentUri() ||
GetTargetFilePath().DirName() == GetFullPath().DirName());
#else
DCHECK(GetTargetFilePath().DirName() == GetFullPath().DirName());
#endif // defined(OS_ANDROID)
// Give the delegate a chance to hold up a stop sign. It'll call
// use back through the passed callback if it does and that state changes.
......@@ -2123,16 +2117,6 @@ void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
case IN_PROGRESS_INTERNAL:
DCHECK(!GetFullPath().empty()) << "Current output path must be known.";
DCHECK(!GetTargetFilePath().empty()) << "Target path must be known.";
#if defined(OS_ANDROID)
DCHECK(GetFullPath().IsContentUri() ||
GetFullPath().DirName() == GetTargetFilePath().DirName())
<< "Current output directory must match target directory or current "
"output path is a content uri.";
#else
DCHECK(GetFullPath().DirName() == GetTargetFilePath().DirName())
<< "Current output directory must match target directory.";
#endif // defined(OS_ANDROID)
DCHECK(GetFullPath().DirName() == GetTargetFilePath().DirName())
<< "Current output directory must match target directory.";
DCHECK(download_file_) << "Output file must be owned by download item.";
......@@ -2147,14 +2131,8 @@ void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
DCHECK(!download_file_)
<< "Download file must be released prior to completion.";
DCHECK(!GetTargetFilePath().empty()) << "Target path must be known.";
#if defined(OS_ANDROID)
DCHECK(GetFullPath().IsContentUri() ||
GetFullPath() == GetTargetFilePath())
<< "Current output path must match target path or is a content Uri.";
#else
DCHECK(GetFullPath() == GetTargetFilePath())
<< "Current output path must match target path.";
#endif // defined(OS_ANDROID)
TRACE_EVENT_INSTANT2("download", "DownloadItemCompleting",
TRACE_EVENT_SCOPE_THREAD, "bytes_so_far",
......
......@@ -8,6 +8,7 @@
#include "base/optional.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/download/database/download_db_entry.h"
#include "components/download/database/download_db_impl.h"
#include "components/download/database/download_namespace.h"
......@@ -27,6 +28,10 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h"
#if defined(OS_ANDROID)
#include "components/download/internal/common/android/download_collection_bridge.h"
#endif
namespace download {
namespace {
......@@ -126,6 +131,16 @@ void CreateDownloadHandlerForNavigation(
main_task_runner);
}
#if defined(OS_ANDROID)
void OnDownloadDisplayNamesReturned(
DownloadCollectionBridge::GetDisplayNamesCallback callback,
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
InProgressDownloadManager::DisplayNames download_names) {
main_task_runner->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::move(download_names)));
}
#endif
} // namespace
InProgressDownloadManager::InProgressDownloadManager(
......@@ -244,7 +259,7 @@ void InProgressDownloadManager::Initialize(
DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD,
in_progress_db_dir));
download_db_cache_->Initialize(base::BindOnce(
&InProgressDownloadManager::OnInitialized, weak_factory_.GetWeakPtr()));
&InProgressDownloadManager::OnDBInitialized, weak_factory_.GetWeakPtr()));
}
void InProgressDownloadManager::ShutDown() {
......@@ -412,11 +427,32 @@ void InProgressDownloadManager::StartDownloadWithItem(
download_start_observer_->OnDownloadStarted(download);
}
void InProgressDownloadManager::OnInitialized(
void InProgressDownloadManager::OnDBInitialized(
bool success,
std::unique_ptr<std::vector<DownloadDBEntry>> entries) {
#if defined(OS_ANDROID)
if (DownloadCollectionBridge::NeedToRetrieveDisplayNames()) {
DownloadCollectionBridge::GetDisplayNamesCallback callback =
base::BindOnce(&InProgressDownloadManager::OnDownloadNamesRetrieved,
weak_factory_.GetWeakPtr(), std::move(entries));
GetDownloadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
&DownloadCollectionBridge::GetDisplayNamesForDownloads,
base::BindOnce(&OnDownloadDisplayNamesReturned, std::move(callback),
base::ThreadTaskRunnerHandle::Get())));
return;
}
#endif
OnDownloadNamesRetrieved(std::move(entries), nullptr);
}
void InProgressDownloadManager::OnDownloadNamesRetrieved(
std::unique_ptr<std::vector<DownloadDBEntry>> entries,
DisplayNames display_names) {
std::set<uint32_t> download_ids;
int num_duplicates = 0;
display_names_ = std::move(display_names);
for (const auto& entry : *entries) {
base::Optional<DownloadEntry> download_entry =
CreateDownloadEntryFromDownloadDBEntry(entry);
......@@ -434,6 +470,14 @@ void InProgressDownloadManager::OnInitialized(
num_duplicates++;
continue;
}
#if defined(OS_ANDROID)
const base::FilePath& path = item->GetTargetFilePath();
auto iter = display_names_->find(path.value());
if (iter != display_names_->end()) {
DCHECK(path.IsContentUri());
item->SetDisplayName(iter->second);
}
#endif
item->AddObserver(download_db_cache_.get());
in_progress_downloads_.emplace_back(std::move(item));
download_ids.insert(download_id);
......@@ -480,8 +524,21 @@ InProgressDownloadManager::TakeInProgressDownloads() {
return std::move(in_progress_downloads_);
}
base::FilePath InProgressDownloadManager::GetDownloadDisplayName(
const base::FilePath& path) {
#if defined(OS_ANDROID)
if (!display_names_)
return base::FilePath();
auto iter = display_names_->find(path.value());
if (iter != display_names_->end())
return iter->second;
#endif
return base::FilePath();
}
void InProgressDownloadManager::OnAllInprogressDownloadsLoaded() {
download_entries_.clear();
display_names_.reset();
}
void InProgressDownloadManager::AddInProgressDownloadForTest(
......
......@@ -120,18 +120,14 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// Target path of an in-progress download. We may be downloading to a
// temporary or intermediate file (specified by |current_path|). Once the
// download completes, we will rename the file to |target_path|.
// |target_path| should be a valid file path on the system. However, if
// download is directly written to a content Uri, the |target_path| should
// be ignored and |full_path| should be used instead. For content Uris,
// |full_path| is used as both the intermediate and final download target.
// |target_path| should be a valid file path on the system. On Android, this
// could be a content Uri.
base::FilePath target_path;
// Full path to the downloaded or downloading file. This is the path to the
// physical file, if one exists. The final target path is specified by
// |target_path|. |current_path| can be empty if the in-progress path
// hasn't been determined. For download that is directly written to a
// content Uri, use |current_path| instead of |target_path| as the latter
// is not a content Uri.
// hasn't been determined.
base::FilePath current_path;
// Current received bytes.
......
......@@ -5,8 +5,10 @@
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_IN_PROGRESS_DOWNLOAD_MANAGER_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_IN_PROGRESS_DOWNLOAD_MANAGER_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/memory/scoped_refptr.h"
......@@ -44,6 +46,8 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
base::OnceCallback<void(std::unique_ptr<DownloadCreateInfo> info,
DownloadItemImpl*,
bool /* should_persist_new_download */)>;
using DisplayNames = std::unique_ptr<
std::map<std::string /*content URI*/, base::FilePath /* display name*/>>;
// Class to be notified when download starts/stops.
class COMPONENTS_DOWNLOAD_EXPORT Delegate {
......@@ -151,6 +155,10 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// enabled by default.
void OnAllInprogressDownloadsLoaded();
// Gets the display name for a download. For non-android platforms, this
// always returns an empty path.
base::FilePath GetDownloadDisplayName(const base::FilePath& path);
void set_file_factory(std::unique_ptr<DownloadFileFactory> file_factory) {
file_factory_ = std::move(file_factory);
}
......@@ -185,9 +193,14 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
void OnUrlDownloadHandlerCreated(
UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) override;
// Called when the object is initialized.
void OnInitialized(bool success,
std::unique_ptr<std::vector<DownloadDBEntry>> entries);
// Called when the in-progress DB is initialized.
void OnDBInitialized(bool success,
std::unique_ptr<std::vector<DownloadDBEntry>> entries);
// Called when download display names are retrieved,
void OnDownloadNamesRetrieved(
std::unique_ptr<std::vector<DownloadDBEntry>> entries,
DisplayNames display_names);
// Start a DownloadItemImpl.
void StartDownloadWithItem(
......@@ -243,6 +256,10 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// is not available.
scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter_;
// Mapping between download URIs and display names.
// TODO(qinmin): move display name to history and in-progress DB.
DisplayNames display_names_;
// Used to check if the URL is safe.
URLSecurityPolicy url_security_policy_;
......
......@@ -673,13 +673,10 @@ void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
void DownloadManagerImpl::OnHistoryQueryComplete(
base::OnceClosure load_history_downloads_cb) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (base::FeatureList::IsEnabled(
download::features::kDownloadDBForNewDownloads) &&
!in_progress_cache_initialized_) {
if (!in_progress_cache_initialized_)
load_history_downloads_cb_ = std::move(load_history_downloads_cb);
} else {
else
std::move(load_history_downloads_cb).Run();
}
}
void DownloadManagerImpl::CheckForFileRemoval(
......@@ -1018,6 +1015,10 @@ download::DownloadItem* DownloadManagerImpl::CreateDownloadItem(
item->SetDelegate(this);
}
}
base::FilePath display_name =
in_progress_manager_->GetDownloadDisplayName(target_path);
if (!display_name.empty())
item->SetDisplayName(display_name);
download::DownloadItemImpl* download = item.get();
DownloadItemUtils::AttachInfo(download, GetBrowserContext(), nullptr);
OnDownloadCreated(std::move(item));
......
......@@ -2149,6 +2149,7 @@ test("content_unittests") {
deps += [
"//base:base_java_unittest_support",
"//build/config/freetype",
"//components/download/internal/common:internal_java",
"//content/public/android:content_java",
"//media/capture/content/android",
"//media/capture/content/android:screen_capture_java",
......
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