Skip to content

Commit

Permalink
Add a flag to show a warning dialog for dangerous download
Browse files Browse the repository at this point in the history
This dialog will replace the original infobar when the flag is enabled

Bug: 1234151
Change-Id: I96a4fd07c62d82807ed8cbfba6d387437da867fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3059761
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Reviewed-by: Xing Liu <xingliu@chromium.org>
Reviewed-by: Shakti Sahu <shaktisahu@chromium.org>
Commit-Queue: Min Qin <qinmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#908711}
  • Loading branch information
Min Qin authored and Chromium LUCI CQ committed Aug 5, 2021
1 parent 7602ffe commit 28d0794
Show file tree
Hide file tree
Showing 14 changed files with 366 additions and 0 deletions.
2 changes: 2 additions & 0 deletions chrome/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2993,6 +2993,8 @@ static_library("browser") {
"download/android/available_offline_content_provider.h",
"download/android/chrome_duplicate_download_infobar_delegate.cc",
"download/android/chrome_duplicate_download_infobar_delegate.h",
"download/android/dangerous_download_dialog_bridge.cc",
"download/android/dangerous_download_dialog_bridge.h",
"download/android/dangerous_download_infobar_delegate.cc",
"download/android/dangerous_download_infobar_delegate.h",
"download/android/download_controller.cc",
Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/download/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ android_library("file_provider_java") {

android_library("java") {
sources = [
"java/src/org/chromium/chrome/browser/download/DangerousDownloadDialogBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadConstants.java",
"java/src/org/chromium/chrome/browser/download/DownloadDelegateImpl.java",
"java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java",
Expand All @@ -37,6 +38,7 @@ android_library("java") {
"java/src/org/chromium/chrome/browser/download/MediaStoreHelper.java",
"java/src/org/chromium/chrome/browser/download/MimeUtils.java",
"java/src/org/chromium/chrome/browser/download/StringUtils.java",
"java/src/org/chromium/chrome/browser/download/dialogs/DangerousDownloadDialog.java",
"java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialog.java",
"java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialogImpl.java",
"java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialogProperties.java",
Expand Down Expand Up @@ -124,6 +126,7 @@ android_library_factory("factory_java") {

generate_jni("jni_headers") {
sources = [
"java/src/org/chromium/chrome/browser/download/DangerousDownloadDialogBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadInfo.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerBridge.java",
Expand Down
104 changes: 104 additions & 0 deletions chrome/browser/download/android/dangerous_download_dialog_bridge.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2021 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.

#include "chrome/browser/download/android/dangerous_download_dialog_bridge.h"

#include <algorithm>
#include <string>

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/android/android_theme_resources.h"
#include "chrome/browser/android/resource_mapper.h"
#include "chrome/browser/download/android/jni_headers/DangerousDownloadDialogBridge_jni.h"
#include "chrome/grit/generated_resources.h"
#include "ui/android/window_android.h"
#include "ui/base/l10n/l10n_util.h"

using base::android::JavaParamRef;

namespace {
// Helper method to find a download from a list of downloads based on its GUID.
download::DownloadItem* FindAndRemoveDownload(
JNIEnv* env,
std::vector<download::DownloadItem*>* downloads,
const JavaParamRef<jstring>& jdownload_guid) {
std::string guid = ConvertJavaStringToUTF8(env, jdownload_guid);

auto iter = std::find_if(downloads->begin(), downloads->end(),
[&guid](download::DownloadItem* download) {
return download->GetGuid() == guid;
});

if (iter == downloads->end())
return nullptr;

download::DownloadItem* result = *iter;
downloads->erase(iter);
return result;
}

} // namespace

DangerousDownloadDialogBridge::DangerousDownloadDialogBridge() {
JNIEnv* env = base::android::AttachCurrentThread();
java_object_.Reset(Java_DangerousDownloadDialogBridge_create(
env, reinterpret_cast<intptr_t>(this)));
}

DangerousDownloadDialogBridge::~DangerousDownloadDialogBridge() {
for (auto* download_item : download_items_)
download_item->RemoveObserver(this);
Java_DangerousDownloadDialogBridge_destroy(
base::android::AttachCurrentThread(), java_object_);
}

void DangerousDownloadDialogBridge::Show(download::DownloadItem* download_item,
ui::WindowAndroid* window_android) {
// Don't shown dangerous download again if it is already showing.
if (std::find(download_items_.begin(), download_items_.end(),
download_item) != download_items_.end()) {
return;
}
download_item->AddObserver(this);
download_items_.push_back(download_item);

JNIEnv* env = base::android::AttachCurrentThread();
Java_DangerousDownloadDialogBridge_showDialog(
env, java_object_, window_android->GetJavaObject(),
base::android::ConvertUTF8ToJavaString(env, download_item->GetGuid()),
base::android::ConvertUTF16ToJavaString(
env,
base::UTF8ToUTF16(download_item->GetFileNameToReportUser().value())),
download_item->GetTotalBytes(),
ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_INFOBAR_WARNING));
}

void DangerousDownloadDialogBridge::OnDownloadDestroyed(
download::DownloadItem* download_item) {
auto iter =
std::find(download_items_.begin(), download_items_.end(), download_item);
if (iter != download_items_.end())
download_items_.erase(iter);
}

void DangerousDownloadDialogBridge::Accepted(
JNIEnv* env,
const JavaParamRef<jstring>& jdownload_guid) {
download::DownloadItem* download =
FindAndRemoveDownload(env, &download_items_, jdownload_guid);
if (download)
download->ValidateDangerousDownload();
}

void DangerousDownloadDialogBridge::Cancelled(
JNIEnv* env,
const JavaParamRef<jstring>& jdownload_guid) {
download::DownloadItem* download =
FindAndRemoveDownload(env, &download_items_, jdownload_guid);
if (download)
download->Remove();
}
50 changes: 50 additions & 0 deletions chrome/browser/download/android/dangerous_download_dialog_bridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2021 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.

#ifndef CHROME_BROWSER_DOWNLOAD_ANDROID_DANGEROUS_DOWNLOAD_DIALOG_BRIDGE_H_
#define CHROME_BROWSER_DOWNLOAD_ANDROID_DANGEROUS_DOWNLOAD_DIALOG_BRIDGE_H_

#include <vector>

#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "components/download/public/common/download_item.h"
#include "ui/gfx/native_widget_types.h"

// Class for showing dialogs to asks whether user wants to download a dangerous
// file.
class DangerousDownloadDialogBridge : public download::DownloadItem::Observer {
public:
DangerousDownloadDialogBridge();
DangerousDownloadDialogBridge(const DangerousDownloadDialogBridge&) = delete;
DangerousDownloadDialogBridge& operator=(
const DangerousDownloadDialogBridge&) = delete;

~DangerousDownloadDialogBridge() override;

// Called to create and show a dialog for a dangerous download.
void Show(download::DownloadItem* download_item,
ui::WindowAndroid* window_android);

// Called from Java via JNI.
void Accepted(JNIEnv* env,
const base::android::JavaParamRef<jstring>& jdownload_guid);

// Called from Java via JNI.
void Cancelled(JNIEnv* env,
const base::android::JavaParamRef<jstring>& jdownload_guid);

// download::DownloadItem::Observer:
void OnDownloadDestroyed(download::DownloadItem* download_item) override;

private:
// Download items that are requesting the dialog. Could get deleted while
// the dialog is showing.
std::vector<download::DownloadItem*> download_items_;

// The corresponding java object.
base::android::ScopedJavaGlobalRef<jobject> java_object_;
};

#endif // CHROME_BROWSER_DOWNLOAD_ANDROID_DANGEROUS_DOWNLOAD_DIALOG_BRIDGE_H_
14 changes: 14 additions & 0 deletions chrome/browser/download/android/download_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,20 @@ void DownloadController::OnDangerousDownload(DownloadItem* item) {
return;
}

if (base::FeatureList::IsEnabled(
chrome::android::kEnableDangerousDownloadDialog)) {
ui::ViewAndroid* view_android =
web_contents ? web_contents->GetNativeView() : nullptr;
ui::WindowAndroid* window_android =
view_android ? view_android->GetWindowAndroid() : nullptr;
if (!dangerous_download_bridge_) {
dangerous_download_bridge_ =
std::make_unique<DangerousDownloadDialogBridge>();
}
dangerous_download_bridge_->Show(item, window_android);
return;
}

DangerousDownloadInfoBarDelegate::Create(
infobars::ContentInfoBarManager::FromWebContents(web_contents), item);
}
Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/download/android/download_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "base/android/scoped_java_ref.h"
#include "base/memory/singleton.h"
#include "chrome/browser/download/android/dangerous_download_dialog_bridge.h"
#include "chrome/browser/download/android/download_controller_base.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_key.h"
Expand Down Expand Up @@ -105,6 +106,8 @@ class DownloadController : public DownloadControllerBase {
// from the beginning and all downloaded data will be lost.
StrongValidatorsMap strong_validators_map_;

std::unique_ptr<DangerousDownloadDialogBridge> dangerous_download_bridge_;

DISALLOW_COPY_AND_ASSIGN(DownloadController);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2021 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.app.Activity;

import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.download.dialogs.DangerousDownloadDialog;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modaldialog.ModalDialogManagerHolder;

/**
* Glues dangerous download dialogs UI code and handles the communication to download native
* backend.
*/
public class DangerousDownloadDialogBridge {
private long mNativeDangerousDownloadDialogBridge;

/**
* Constructor, taking a pointer to the native instance.
* @nativeDangerousDownloadDialogBridge Pointer to the native object.
*/
public DangerousDownloadDialogBridge(long nativeDangerousDownloadDialogBridge) {
mNativeDangerousDownloadDialogBridge = nativeDangerousDownloadDialogBridge;
}

@CalledByNative
public static DangerousDownloadDialogBridge create(long nativeDialog) {
return new DangerousDownloadDialogBridge(nativeDialog);
}

/**
* Called to show a warning dialog for dangerous download.
* @param windowAndroid Window to show the dialog.
* @param guid GUID of the download.
* @param fileName Name of the download file.
* @param totalBytes Total bytes of the file.
* @param iconId The icon resource for the warning dialog.
*/
@CalledByNative
public void showDialog(WindowAndroid windowAndroid, String guid, String fileName,
long totalBytes, int iconId) {
Activity activity = windowAndroid.getActivity().get();
if (activity == null) onCancel(guid);

new DangerousDownloadDialog().show(activity,
((ModalDialogManagerHolder) activity).getModalDialogManager(), fileName, totalBytes,
iconId, (accepted) -> {
if (accepted) {
onAccepted(guid);
} else {
onCancel(guid);
}
});
}

@CalledByNative
private void destroy() {
mNativeDangerousDownloadDialogBridge = 0;
}

private void onAccepted(String guid) {
DangerousDownloadDialogBridgeJni.get().accepted(mNativeDangerousDownloadDialogBridge, guid);
}

private void onCancel(String guid) {
DangerousDownloadDialogBridgeJni.get().cancelled(
mNativeDangerousDownloadDialogBridge, guid);
}

@NativeMethods
interface Natives {
void accepted(long nativeDangerousDownloadDialogBridge, String guid);
void cancelled(long nativeDangerousDownloadDialogBridge, String guid);
}
}

0 comments on commit 28d0794

Please sign in to comment.