Skip to content

Commit

Permalink
DLP: Hook policy checks before paste in Blink
Browse files Browse the repository at this point in the history
- Inserted policy checks before replying back
on paste events to the renderer (Blink).
- The policy checks will be applied first before
the content checks.

Bug: 1180116
Change-Id: Ic76aa2fc4b722939d60f3384d9cb1d1b62fff4a0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2706944
Reviewed-by: Darwin Huang <huangdarwin@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Sergey Poromov <poromov@chromium.org>
Commit-Queue: Aya Elsayed <ayaelattar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#859010}
  • Loading branch information
ayamahmod authored and Chromium LUCI CQ committed Mar 2, 2021
1 parent b8bfdbf commit 84e6ef3
Show file tree
Hide file tree
Showing 10 changed files with 282 additions and 62 deletions.
4 changes: 4 additions & 0 deletions ash/drag_drop/drag_drop_controller_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,10 @@ class MockDataTransferPolicyController
MOCK_METHOD2(IsClipboardReadAllowed,
bool(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst));
MOCK_METHOD3(PasteIfAllowed,
void((const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
base::OnceCallback<void(bool)> callback)));
MOCK_METHOD3(IsDragDropAllowed,
bool(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@ bool DataTransferDlpController::IsClipboardReadAllowed(
return is_read_allowed;
}

void DataTransferDlpController::PasteIfAllowed(
const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
base::OnceCallback<void(bool)> callback) {
// TODO(crbug.com/1180169): Pass true if the user chose to proceed, otherwise
// false should be passed instead.
std::move(callback).Run(true);
}

bool DataTransferDlpController::IsDragDropAllowed(
const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DLP_DATA_TRANSFER_DLP_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_POLICY_DLP_DATA_TRANSFER_DLP_CONTROLLER_H_

#include "base/callback.h"
#include "base/strings/string16.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_clipboard_notifier.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_drag_drop_notifier.h"
Expand Down Expand Up @@ -37,6 +38,9 @@ class DataTransferDlpController : public ui::DataTransferPolicyController {
bool IsClipboardReadAllowed(
const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst) override;
void PasteIfAllowed(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
base::OnceCallback<void(bool)> callback) override;
bool IsDragDropAllowed(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
const bool is_drop) override;
Expand Down
4 changes: 4 additions & 0 deletions chrome/browser/ui/ash/clipboard_history_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,10 @@ class FakeDataTransferPolicyController
(*data_src->origin() == allowed_origin_);
}

void PasteIfAllowed(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
base::OnceCallback<void(bool)> callback) override {}

bool IsDragDropAllowed(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
const bool is_drop) override {
Expand Down
4 changes: 4 additions & 0 deletions components/exo/data_offer_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ class TestDataTransferPolicyController : ui::DataTransferPolicyController {
return true;
}

void PasteIfAllowed(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
base::OnceCallback<void(bool)> callback) override {}

bool IsDragDropAllowed(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst,
const bool is_drop) override {
Expand Down
141 changes: 87 additions & 54 deletions content/browser/renderer_host/clipboard_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@
#include "ui/base/clipboard/file_info.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/data_transfer_policy/data_transfer_policy_controller.h"
#include "ui/base/ui_base_features.h"
#include "url/gurl.h"

namespace content {

namespace {
// TODO(crbug.com/1181248): Rename to IsRendererPasteAllowed.
bool IsClipboardPasteAllowed(
const GlobalFrameRoutingId& render_frame_routing_id_) {
RenderFrameHostImpl* render_frame_host =
Expand Down Expand Up @@ -221,17 +223,17 @@ void ClipboardHostImpl::ReadText(ui::ClipboardBuffer clipboard_buffer,
}

std::string data = base::UTF16ToUTF8(result);
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer),
ui::ClipboardFormatType::GetPlainTextType(), std::move(data),
base::BindOnce(
[](base::string16 result, ReadTextCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
result.clear();
std::move(callback).Run(result);
},
std::move(result), std::move(callback)));
PasteIfPolicyAllowed(clipboard_buffer,
ui::ClipboardFormatType::GetPlainTextType(),
std::move(data),
base::BindOnce(
[](base::string16 result, ReadTextCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
result.clear();
std::move(callback).Run(result);
},
std::move(result), std::move(callback)));
}

void ClipboardHostImpl::ReadHtml(ui::ClipboardBuffer clipboard_buffer,
Expand All @@ -249,9 +251,8 @@ void ClipboardHostImpl::ReadHtml(ui::ClipboardBuffer clipboard_buffer,
&fragment_start, &fragment_end);

std::string data = base::UTF16ToUTF8(markup);
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer),
ui::ClipboardFormatType::GetHtmlType(), std::move(data),
PasteIfPolicyAllowed(
clipboard_buffer, ui::ClipboardFormatType::GetHtmlType(), std::move(data),
base::BindOnce(
[](base::string16 markup, std::string src_url_str,
uint32_t fragment_start, uint32_t fragment_end,
Expand All @@ -275,17 +276,16 @@ void ClipboardHostImpl::ReadSvg(ui::ClipboardBuffer clipboard_buffer,
clipboard_->ReadSvg(clipboard_buffer, /*data_dst=*/nullptr, &markup);

std::string data = base::UTF16ToUTF8(markup);
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer),
ui::ClipboardFormatType::GetSvgType(), std::move(data),
base::BindOnce(
[](base::string16 markup, ReadSvgCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
markup.clear();
std::move(callback).Run(std::move(markup));
},
std::move(markup), std::move(callback)));
PasteIfPolicyAllowed(clipboard_buffer, ui::ClipboardFormatType::GetSvgType(),
std::move(data),
base::BindOnce(
[](base::string16 markup, ReadSvgCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
markup.clear();
std::move(callback).Run(std::move(markup));
},
std::move(markup), std::move(callback)));
}

void ClipboardHostImpl::ReadRtf(ui::ClipboardBuffer clipboard_buffer,
Expand All @@ -299,17 +299,16 @@ void ClipboardHostImpl::ReadRtf(ui::ClipboardBuffer clipboard_buffer,
clipboard_->ReadRTF(clipboard_buffer, data_dst.get(), &result);

std::string data = result;
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer),
ui::ClipboardFormatType::GetRtfType(), std::move(data),
base::BindOnce(
[](std::string result, ReadRtfCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
result.clear();
std::move(callback).Run(result);
},
std::move(result), std::move(callback)));
PasteIfPolicyAllowed(clipboard_buffer, ui::ClipboardFormatType::GetRtfType(),
std::move(data),
base::BindOnce(
[](std::string result, ReadRtfCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
result.clear();
std::move(callback).Run(result);
},
std::move(result), std::move(callback)));
}

void ClipboardHostImpl::ReadImage(ui::ClipboardBuffer clipboard_buffer,
Expand All @@ -331,17 +330,17 @@ void ClipboardHostImpl::OnReadImage(ui::ClipboardBuffer clipboard_buffer,
std::string data =
std::string(reinterpret_cast<const char*>(bitmap.getPixels()),
bitmap.computeByteSize());
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer),
ui::ClipboardFormatType::GetBitmapType(), std::move(data),
base::BindOnce(
[](SkBitmap bitmap, ReadImageCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
bitmap.reset();
std::move(callback).Run(bitmap);
},
std::move(bitmap), std::move(callback)));
PasteIfPolicyAllowed(clipboard_buffer,
ui::ClipboardFormatType::GetBitmapType(),
std::move(data),
base::BindOnce(
[](SkBitmap bitmap, ReadImageCallback callback,
ClipboardPasteContentAllowed allowed) {
if (!allowed)
bitmap.reset();
std::move(callback).Run(bitmap);
},
std::move(bitmap), std::move(callback)));
}

void ClipboardHostImpl::ReadFiles(ui::ClipboardBuffer clipboard_buffer,
Expand Down Expand Up @@ -411,9 +410,9 @@ void ClipboardHostImpl::ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
clipboard_->ReadCustomData(clipboard_buffer, type, data_dst.get(), &result);

std::string data = base::UTF16ToUTF8(result);
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer),
ui::ClipboardFormatType::GetWebCustomDataType(), std::move(data),
PasteIfPolicyAllowed(
clipboard_buffer, ui::ClipboardFormatType::GetWebCustomDataType(),
std::move(data),
base::BindOnce(
[](base::string16 result, ReadCustomDataCallback callback,
ClipboardPasteContentAllowed allowed) {
Expand Down Expand Up @@ -463,18 +462,52 @@ void ClipboardHostImpl::CommitWrite() {
ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint());
}

void ClipboardHostImpl::PerformPasteIfContentAllowed(
uint64_t seqno,
void ClipboardHostImpl::PasteIfPolicyAllowed(
ui::ClipboardBuffer clipboard_buffer,
const ui::ClipboardFormatType& data_type,
std::string data,
IsClipboardPasteContentAllowedCallback callback) {
CleanupObsoleteRequests();

if (data.empty()) {
std::move(callback).Run(ClipboardPasteContentAllowed(true));
return;
}

auto policy_cb =
base::BindOnce(&ClipboardHostImpl::PasteIfPolicyAllowedCallback,
weak_ptr_factory_.GetWeakPtr(), clipboard_buffer,
data_type, std::move(data), std::move(callback));

if (ui::DataTransferPolicyController::HasInstance()) {
ui::DataTransferPolicyController::Get()->PasteIfAllowed(
clipboard_->GetSource(clipboard_buffer), CreateDataEndpoint().get(),
std::move(policy_cb));
return;
}
std::move(policy_cb).Run(/*is_allowed=*/true);
}

void ClipboardHostImpl::PasteIfPolicyAllowedCallback(
ui::ClipboardBuffer clipboard_buffer,
const ui::ClipboardFormatType& data_type,
std::string data,
IsClipboardPasteContentAllowedCallback callback,
bool is_allowed) {
if (is_allowed) {
PerformPasteIfContentAllowed(
clipboard_->GetSequenceNumber(clipboard_buffer), data_type,
std::move(data), std::move(callback));
} else {
// If not allowed, then don't proceed with content checks.
std::move(callback).Run(ClipboardPasteContentAllowed(false));
}
}

void ClipboardHostImpl::PerformPasteIfContentAllowed(
uint64_t seqno,
const ui::ClipboardFormatType& data_type,
std::string data,
IsClipboardPasteContentAllowedCallback callback) {
CleanupObsoleteRequests();
// Add |callback| to the callbacks associated to the sequence number, adding
// an entry to the map if one does not exist.
auto& request = is_allowed_requests_[seqno];
Expand Down
25 changes: 22 additions & 3 deletions content/browser/renderer_host/clipboard_host_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,18 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {

explicit ClipboardHostImpl(RenderFrameHost* render_frame_host);

// Performs a check to see if pasting `data` is allowed by data transfer
// policies and invokes PasteIfPolicyAllowedCallback upon completion.
// PerformPasteIfContentAllowed maybe be invoked immediately if the policy
// controller doesn't exist.
void PasteIfPolicyAllowed(ui::ClipboardBuffer clipboard_buffer,
const ui::ClipboardFormatType& data_type,
std::string data,
IsClipboardPasteContentAllowedCallback callback);

// Performs a check to see if pasting |data| is allowed and invokes |callback|
// upon completion. |callback| maybe be invoked immediately if the data has
// already been checked. |data| and |seqno| should corresponds to the same
// upon completion. |callback| may be invoked immediately if the data has
// already been checked. |data| and |seqno| should corresponds to the same
// clipboard data.
void PerformPasteIfContentAllowed(
uint64_t seqno,
Expand All @@ -110,7 +119,7 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
// - it is too old
void CleanupObsoleteRequests();

// Completion callback of PerformPasteIfContentAllowed(). Sets the allowed
// Completion callback of PerformPasteIfContentAllowed(). Sets the allowed
// status for the clipboard data corresponding to sequence number |seqno|.
void FinishPasteIfContentAllowed(uint64_t seqno,
ClipboardPasteContentAllowed allowed);
Expand Down Expand Up @@ -178,6 +187,16 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
const ui::ClipboardFormatType& data_type,
std::string data);

// Completion callback of PasteIfPolicyAllowed. If `is_allowed` is set to
// true, PerformPasteIfContentAllowed will be invoked. Otherwise `callback`
// will be invoked immediately to cancel the paste.
void PasteIfPolicyAllowedCallback(
ui::ClipboardBuffer clipboard_buffer,
const ui::ClipboardFormatType& data_type,
std::string data,
IsClipboardPasteContentAllowedCallback callback,
bool is_allowed);

void OnReadImage(ui::ClipboardBuffer clipboard_buffer,
ReadImageCallback callback,
const SkBitmap& bitmap);
Expand Down
Loading

0 comments on commit 84e6ef3

Please sign in to comment.