Commit ff03b241 authored by Aya ElAttar's avatar Aya ElAttar Committed by Commit Bot

Add tests for ClipboardDlpController

1. Changed TestClipboard to support DLP controller.
2. Added unittests to cover allowed/disallowed clipboard
read based on the DLP controller.

Bug: 1103215
Change-Id: Ibb6c7bf575dd0e514349c395fb965af203fe3b1d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2283207
Commit-Queue: Aya Elsayed <ayaelattar@google.com>
Reviewed-by: default avatarNikita Podguzov <nikitapodguzov@chromium.org>
Reviewed-by: default avatarDarwin Huang <huangdarwin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789890}
parent f4b37cb6
......@@ -23,10 +23,12 @@
#include "base/pickle.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "third_party/skia/include/core/SkBitmap.h"
......@@ -35,6 +37,8 @@
#include "third_party/skia/include/core/SkUnPreMultiply.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/clipboard_data_endpoint.h"
#include "ui/base/clipboard/clipboard_dlp_controller.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/clipboard/test/clipboard_test_util.h"
#include "ui/base/clipboard/test/test_clipboard.h"
......@@ -58,6 +62,8 @@ using testing::Contains;
namespace ui {
class MockClipboardDlpController;
template <typename ClipboardTraits>
class ClipboardTest : public PlatformTest {
public:
......@@ -88,14 +94,40 @@ class ClipboardTest : public PlatformTest {
return types;
}
void AddDlpController() {
auto dlp_controller = std::make_unique<MockClipboardDlpController>();
dlp_controller_ = dlp_controller.get();
ClipboardTest::clipboard().SetClipboardDlpController(
std::move(dlp_controller));
}
MockClipboardDlpController* dlp_controller() const { return dlp_controller_; }
private:
#if defined(USE_X11)
std::unique_ptr<PlatformEventSource> event_source_;
#endif
// Clipboard has a protected destructor, so scoped_ptr doesn't work here.
Clipboard* clipboard_ = nullptr;
// MockClipboardDlpController object is owned by ClipboardTest.
MockClipboardDlpController* dlp_controller_ = nullptr;
};
// A mock delegate for testing.
class MockClipboardDlpController : public ClipboardDlpController {
public:
MockClipboardDlpController();
~MockClipboardDlpController();
MOCK_CONST_METHOD2(IsDataReadAllowed,
bool(const ClipboardDataEndpoint* const data_src,
const ClipboardDataEndpoint* const data_dst));
};
MockClipboardDlpController::MockClipboardDlpController() = default;
MockClipboardDlpController::~MockClipboardDlpController() = default;
// Hack for tests that need to call static methods of ClipboardTest.
struct NullClipboardTraits {
static Clipboard* Create() { return nullptr; }
......@@ -1014,6 +1046,52 @@ TYPED_TEST(ClipboardTest, WriteImageEmptyParams) {
scw.WriteImage(SkBitmap());
}
// DLP is only intended to be used in Chrome OS, so the following DLP related
// tests are only run on Chrome OS.
#if defined(OS_CHROMEOS)
// Test that copy/paste would work normally if the dlp controller didn't
// restrict the clipboard data.
TYPED_TEST(ClipboardTest, DlpAllowDataRead) {
this->AddDlpController();
const base::string16 kTestText(base::UTF8ToUTF16("World"));
{
ScopedClipboardWriter writer(
ClipboardBuffer::kCopyPaste,
std::make_unique<ClipboardDataEndpoint>(GURL()));
writer.WriteText(kTestText);
}
auto* dlp_controller = this->dlp_controller();
EXPECT_CALL(*dlp_controller, IsDataReadAllowed)
.WillRepeatedly(testing::Return(true));
base::string16 read_result;
this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr, &read_result);
::testing::Mock::VerifyAndClearExpectations(dlp_controller);
EXPECT_EQ(kTestText, read_result);
}
// Test that pasting clipboard data would not work if the dlp controller
// restricted it.
TYPED_TEST(ClipboardTest, DlpDisallowDataRead) {
this->AddDlpController();
const base::string16 kTestText(base::UTF8ToUTF16("World"));
{
ScopedClipboardWriter writer(
ClipboardBuffer::kCopyPaste,
std::make_unique<ClipboardDataEndpoint>(GURL()));
writer.WriteText(kTestText);
}
auto* dlp_controller = this->dlp_controller();
EXPECT_CALL(*dlp_controller, IsDataReadAllowed)
.WillRepeatedly(testing::Return(false));
base::string16 read_result;
this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr, &read_result);
::testing::Mock::VerifyAndClearExpectations(dlp_controller);
EXPECT_EQ(base::string16(), read_result);
}
#endif // defined(OS_CHROMEOS)
} // namespace ui
#endif // UI_BASE_CLIPBOARD_CLIPBOARD_TEST_TEMPLATE_H_
......@@ -5,6 +5,8 @@
#include "ui/base/clipboard/test/test_clipboard.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversions.h"
......@@ -12,6 +14,7 @@
#include "skia/ext/skia_utils_base.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/clipboard_data_endpoint.h"
#include "ui/base/clipboard/clipboard_dlp_controller.h"
#include "ui/base/clipboard/clipboard_monitor.h"
namespace ui {
......@@ -39,15 +42,18 @@ uint64_t TestClipboard::GetSequenceNumber(ClipboardBuffer buffer) const {
return GetStore(buffer).sequence_number;
}
// TODO(crbug.com/1103215): Setting |dlp_controller| should be supported.
void TestClipboard::SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) {}
std::unique_ptr<ClipboardDlpController> dlp_controller) {
dlp_controller_ = std::move(dlp_controller);
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
bool TestClipboard::IsFormatAvailable(
const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ui::ClipboardDataEndpoint* data_dst) const {
if (dlp_controller_ && !dlp_controller_->IsDataReadAllowed(
GetStore(buffer).data_src.get(), data_dst))
return false;
#if defined(OS_LINUX)
// The linux clipboard treats the presence of text on the clipboard
// as the url format being available.
......@@ -63,13 +69,15 @@ void TestClipboard::Clear(ClipboardBuffer buffer) {
GetStore(buffer).Clear();
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
void TestClipboard::ReadAvailableTypes(
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst,
std::vector<base::string16>* types) const {
DCHECK(types);
types->clear();
if (dlp_controller_ && !dlp_controller_->IsDataReadAllowed(
GetStore(buffer).data_src.get(), data_dst))
return;
if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
data_dst))
......@@ -83,12 +91,16 @@ void TestClipboard::ReadAvailableTypes(
types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
std::vector<base::string16>
TestClipboard::ReadAvailablePlatformSpecificFormatNames(
ClipboardBuffer buffer,
const ui::ClipboardDataEndpoint* data_dst) const {
const auto& data = GetStore(buffer).data;
const DataStore& store = GetStore(buffer);
if (dlp_controller_ &&
!dlp_controller_->IsDataReadAllowed(store.data_src.get(), data_dst))
return {};
const auto& data = store.data;
std::vector<base::string16> types;
types.reserve(data.size());
for (const auto& it : data)
......@@ -113,10 +125,13 @@ TestClipboard::ReadAvailablePlatformSpecificFormatNames(
return types;
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
void TestClipboard::ReadText(ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst,
base::string16* result) const {
if (dlp_controller_ && !dlp_controller_->IsDataReadAllowed(
GetStore(buffer).data_src.get(), data_dst))
return;
std::string result8;
ReadAsciiText(buffer, data_dst, &result8);
*result = base::UTF8ToUTF16(result8);
......@@ -126,23 +141,30 @@ void TestClipboard::ReadText(ClipboardBuffer buffer,
void TestClipboard::ReadAsciiText(ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst,
std::string* result) const {
result->clear();
const DataStore& store = GetStore(buffer);
if (dlp_controller_ &&
!dlp_controller_->IsDataReadAllowed(store.data_src.get(), data_dst))
return;
result->clear();
auto it = store.data.find(ClipboardFormatType::GetPlainTextType());
if (it != store.data.end())
*result = it->second;
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
void TestClipboard::ReadHTML(ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst,
base::string16* markup,
std::string* src_url,
uint32_t* fragment_start,
uint32_t* fragment_end) const {
const DataStore& store = GetStore(buffer);
if (dlp_controller_ &&
!dlp_controller_->IsDataReadAllowed(store.data_src.get(), data_dst))
return;
markup->clear();
src_url->clear();
const DataStore& store = GetStore(buffer);
auto it = store.data.find(ClipboardFormatType::GetHtmlType());
if (it != store.data.end())
*markup = base::UTF8ToUTF16(it->second);
......@@ -151,18 +173,20 @@ void TestClipboard::ReadHTML(ClipboardBuffer buffer,
*fragment_end = base::checked_cast<uint32_t>(markup->size());
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
void TestClipboard::ReadRTF(ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst,
std::string* result) const {
result->clear();
const DataStore& store = GetStore(buffer);
if (dlp_controller_ &&
!dlp_controller_->IsDataReadAllowed(store.data_src.get(), data_dst))
return;
result->clear();
auto it = store.data.find(ClipboardFormatType::GetRtfType());
if (it != store.data.end())
*result = it->second;
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
void TestClipboard::ReadImage(ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst,
ReadImageCallback callback) const {
......@@ -180,6 +204,10 @@ void TestClipboard::ReadBookmark(const ClipboardDataEndpoint* data_dst,
base::string16* title,
std::string* url) const {
const DataStore& store = GetDefaultStore();
if (dlp_controller_ &&
!dlp_controller_->IsDataReadAllowed(store.data_src.get(), data_dst))
return;
if (url) {
auto it = store.data.find(ClipboardFormatType::GetUrlType());
if (it != store.data.end())
......@@ -189,12 +217,15 @@ void TestClipboard::ReadBookmark(const ClipboardDataEndpoint* data_dst,
*title = base::UTF8ToUTF16(store.url_title);
}
// TODO(crbug.com/1103215): |data_dst| should be supported.
void TestClipboard::ReadData(const ClipboardFormatType& format,
const ClipboardDataEndpoint* data_dst,
std::string* result) const {
result->clear();
const DataStore& store = GetDefaultStore();
if (dlp_controller_ &&
!dlp_controller_->IsDataReadAllowed(store.data_src.get(), data_dst))
return;
result->clear();
auto it = store.data.find(format);
if (it != store.data.end())
*result = it->second;
......@@ -208,7 +239,6 @@ void TestClipboard::ClearLastModifiedTime() {
last_modified_time_ = base::Time();
}
// TODO(crbug.com/1103215): |data_src| should be supported
void TestClipboard::WritePortableRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
......@@ -218,9 +248,9 @@ void TestClipboard::WritePortableRepresentations(
for (const auto& kv : objects)
DispatchPortableRepresentation(kv.first, kv.second);
default_store_buffer_ = ClipboardBuffer::kCopyPaste;
GetStore(buffer).SetDataSource(std::move(data_src));
}
// TODO(crbug.com/1103215): |data_src| should be supported
void TestClipboard::WritePlatformRepresentations(
ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
......@@ -229,6 +259,7 @@ void TestClipboard::WritePlatformRepresentations(
default_store_buffer_ = buffer;
DispatchPlatformRepresentations(std::move(platform_representations));
default_store_buffer_ = ClipboardBuffer::kCopyPaste;
GetStore(buffer).SetDataSource(std::move(data_src));
}
void TestClipboard::WriteText(const char* text_data, size_t text_len) {
......@@ -292,9 +323,31 @@ void TestClipboard::WriteData(const ClipboardFormatType& format,
GetDefaultStore().data[format] = std::string(data_data, data_len);
}
TestClipboard::DataStore::DataStore() : sequence_number(0) {}
TestClipboard::DataStore::DataStore() = default;
TestClipboard::DataStore::DataStore(const DataStore& other) {
sequence_number = other.sequence_number;
data = other.data;
url_title = other.url_title;
html_src_url = other.html_src_url;
image = other.image;
data_src = other.data_src ? std::make_unique<ClipboardDataEndpoint>(
ClipboardDataEndpoint(*(other.data_src)))
: nullptr;
}
TestClipboard::DataStore::DataStore(const DataStore& other) = default;
TestClipboard::DataStore& TestClipboard::DataStore::operator=(
const DataStore& other) {
sequence_number = other.sequence_number;
data = other.data;
url_title = other.url_title;
html_src_url = other.html_src_url;
image = other.image;
data_src = other.data_src ? std::make_unique<ClipboardDataEndpoint>(
ClipboardDataEndpoint(*(other.data_src)))
: nullptr;
return *this;
}
TestClipboard::DataStore::~DataStore() = default;
......@@ -305,6 +358,11 @@ void TestClipboard::DataStore::Clear() {
image = SkBitmap();
}
void TestClipboard::DataStore::SetDataSource(
std::unique_ptr<ClipboardDataEndpoint> data_src) {
this->data_src = std::move(data_src);
}
const TestClipboard::DataStore& TestClipboard::GetStore(
ClipboardBuffer buffer) const {
CHECK(IsSupportedClipboardBuffer(buffer));
......
......@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
......@@ -105,13 +106,16 @@ class TestClipboard : public Clipboard {
struct DataStore {
DataStore();
DataStore(const DataStore& other);
DataStore& operator=(const DataStore& other);
~DataStore();
void Clear();
uint64_t sequence_number;
void SetDataSource(std::unique_ptr<ClipboardDataEndpoint> data_src);
uint64_t sequence_number = 0;
base::flat_map<ClipboardFormatType, std::string> data;
std::string url_title;
std::string html_src_url;
SkBitmap image;
std::unique_ptr<ClipboardDataEndpoint> data_src = nullptr;
};
// The non-const versions increment the sequence number as a side effect.
......@@ -124,6 +128,8 @@ class TestClipboard : public Clipboard {
mutable base::flat_map<ClipboardBuffer, DataStore> stores_;
base::Time last_modified_time_;
std::unique_ptr<ClipboardDlpController> dlp_controller_;
DISALLOW_COPY_AND_ASSIGN(TestClipboard);
};
......
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