blob: 343b097e10d84259c4bf3ea33086dd48f4fe9d2f [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <jni.h>
#include "base/android/callback_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/clipboard_types.h"
#include "content/public/browser/render_frame_host.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/clipboard/clipboard_metadata.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
// Must come after all headers that specialize FromJniType() / ToJniType().
#include "chrome/browser/enterprise/util/jni_headers/DataProtectionBridge_jni.h"
using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserContext;
using content::ClipboardEndpoint;
using content::ClipboardPasteData;
using content::GlobalRenderFrameHostId;
using content::RenderFrameHost;
namespace {
// TODO(crbug.com/410835513): Unify with other declarations of
// CreateDataEndpoint
std::unique_ptr<ui::DataTransferEndpoint> CreateDataEndpoint(
RenderFrameHost* render_frame_host) {
if (!render_frame_host->GetMainFrame()->GetLastCommittedURL().is_valid()) {
return nullptr;
}
return std::make_unique<ui::DataTransferEndpoint>(
render_frame_host->GetMainFrame()->GetLastCommittedURL(),
ui::DataTransferEndpointOptions{
.notify_if_restricted =
render_frame_host->HasTransientUserActivation(),
.off_the_record =
render_frame_host->GetBrowserContext()->IsOffTheRecord(),
});
}
// TODO(crbug.com/410835513): Unify with other declarations of
// CreateClipboardEndpoint
ClipboardEndpoint CreateClipboardEndpoint(RenderFrameHost* render_frame_host) {
return ClipboardEndpoint(
CreateDataEndpoint(render_frame_host).get(),
base::BindRepeating(
[](GlobalRenderFrameHostId rfh_id) -> BrowserContext* {
auto* rfh = RenderFrameHost::FromID(rfh_id);
if (!rfh) {
return nullptr;
}
return rfh->GetBrowserContext();
},
render_frame_host->GetGlobalId()),
*render_frame_host);
}
void VerifyCopyIsAllowedByPolicy(
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback,
const ui::ClipboardMetadata& metadata,
const content::ClipboardPasteData& data) {
RenderFrameHost* render_frame_host =
RenderFrameHost::FromJavaRenderFrameHost(jrender_frame_host);
base::OnceCallback<void(bool)> boolean_java_callback =
base::BindOnce(&base::android::RunBooleanCallbackAndroid,
ScopedJavaGlobalRef<jobject>(j_callback));
enterprise_data_protection::IsClipboardCopyAllowedByPolicy(
CreateClipboardEndpoint(render_frame_host), metadata, data,
base::BindOnce(
[](base::OnceCallback<void(bool)> callback,
const ui::ClipboardFormatType& type,
const ClipboardPasteData& data,
std::optional<std::u16string> replacement_data) {
std::move(callback).Run(!data.empty());
},
std::move(boolean_java_callback)));
}
void VerifyShareIsAllowedByPolicy(
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback,
const ui::ClipboardMetadata& metadata,
const content::ClipboardPasteData& data) {
RenderFrameHost* render_frame_host =
RenderFrameHost::FromJavaRenderFrameHost(jrender_frame_host);
base::OnceCallback<void(bool)> boolean_java_callback =
base::BindOnce(&base::android::RunBooleanCallbackAndroid,
ScopedJavaGlobalRef<jobject>(j_callback));
enterprise_data_protection::IsClipboardShareAllowedByPolicy(
CreateClipboardEndpoint(render_frame_host), metadata, data,
base::BindOnce(
[](base::OnceCallback<void(bool)> callback,
const ui::ClipboardFormatType& type,
const ClipboardPasteData& data,
std::optional<std::u16string> replacement_data) {
std::move(callback).Run(!data.empty());
},
std::move(boolean_java_callback)));
}
void VerifyGenericCopyActionIsAllowedByPolicy(
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback,
const ui::ClipboardMetadata& metadata,
const content::ClipboardPasteData& data) {
RenderFrameHost* render_frame_host =
RenderFrameHost::FromJavaRenderFrameHost(jrender_frame_host);
base::OnceCallback<void(bool)> boolean_java_callback =
base::BindOnce(&base::android::RunBooleanCallbackAndroid,
ScopedJavaGlobalRef<jobject>(j_callback));
enterprise_data_protection::IsClipboardGenericCopyActionAllowedByPolicy(
CreateClipboardEndpoint(render_frame_host), metadata, data,
base::BindOnce(
[](base::OnceCallback<void(bool)> callback,
const ui::ClipboardFormatType& type,
const ClipboardPasteData& data,
std::optional<std::u16string> replacement_data) {
std::move(callback).Run(!data.empty());
},
std::move(boolean_java_callback)));
}
} // namespace
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyCopyTextIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_text,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string text = base::android::ConvertJavaStringToUTF16(env, j_text);
ClipboardPasteData data;
data.text = text;
VerifyCopyIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
.size = text.size() * sizeof(std::u16string::value_type),
.format_type = ui::ClipboardFormatType::PlainTextType(),
},
data);
}
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyCopyUrlIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_url,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string url = base::android::ConvertJavaStringToUTF16(env, j_url);
ClipboardPasteData data;
data.text = url;
VerifyCopyIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
.size = url.size() * sizeof(std::u16string::value_type),
.format_type = ui::ClipboardFormatType::UrlType(),
},
data);
}
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyCopyImageIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_image_uri,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string image_uri =
base::android::ConvertJavaStringToUTF16(env, j_image_uri);
ClipboardPasteData data;
data.text = image_uri;
VerifyCopyIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
// TODO(crbug.com/344593255): Retrieve the bitmap size when it's
// needed by the data controls logic.
.format_type = ui::ClipboardFormatType::BitmapType(),
},
data);
}
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyShareTextIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_text,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string text = base::android::ConvertJavaStringToUTF16(env, j_text);
ClipboardPasteData data;
data.text = text;
VerifyShareIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
.size = text.size() * sizeof(std::u16string::value_type),
.format_type = ui::ClipboardFormatType::PlainTextType(),
},
data);
}
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyShareUrlIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_url,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string url = base::android::ConvertJavaStringToUTF16(env, j_url);
ClipboardPasteData data;
data.text = url;
VerifyShareIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
.size = url.size() * sizeof(std::u16string::value_type),
.format_type = ui::ClipboardFormatType::UrlType(),
},
data);
}
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyShareImageIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_image_uri,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string image_uri =
base::android::ConvertJavaStringToUTF16(env, j_image_uri);
ClipboardPasteData data;
data.text = image_uri;
VerifyShareIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
// TODO(crbug.com/344593255): Retrieve the bitmap size when it's
// needed by the data controls logic.
.format_type = ui::ClipboardFormatType::BitmapType(),
},
data);
}
// TODO(crbug.com/387484337) Add instrumentation tests
void JNI_DataProtectionBridge_VerifyGenericCopyImageActionIsAllowedByPolicy(
JNIEnv* env,
const JavaParamRef<jstring>& j_image_uri,
const base::android::JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobject>& j_callback) {
std::u16string image_uri =
base::android::ConvertJavaStringToUTF16(env, j_image_uri);
ClipboardPasteData data;
data.text = image_uri;
VerifyGenericCopyActionIsAllowedByPolicy(
jrender_frame_host, j_callback,
{
// TODO(crbug.com/344593255): Retrieve the bitmap size when it's
// needed by the data controls logic.
.format_type = ui::ClipboardFormatType::BitmapType(),
},
data);
}