Skip to content

Commit

Permalink
DLP: Change clipboard data dsts to control toasts
Browse files Browse the repository at this point in the history
- Changed clipboard data endpoint destinations
to accept a new parameter to control whether to
notify the user if the clipboard is restricted
with data leak prevention policy rules.

- Updated clipboard read references with the new
parameter according to the following:
  - If the clipboard read call is because
of a user action trying to copy-paste, then a
notification should be shown.
  - Otherwise the notification shouldn't be shown
e.g. ChromePasswordManager, ClipboardAura,
checking if the paste command is enabled for
the context menu, ...etc.

Bug: 1136290
Change-Id: I9eea9bee8d027650c56ace132e34dfed1e78d2d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2452712
Commit-Queue: Aya Elsayed <ayaelattar@chromium.org>
Reviewed-by: Justin Donnelly <jdonnelly@chromium.org>
Reviewed-by: Darwin Huang <huangdarwin@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Sergey Poromov <poromov@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821668}
  • Loading branch information
ayamahmod authored and Commit Bot committed Oct 28, 2020
1 parent 9c0ee95 commit 2ae6eb2
Show file tree
Hide file tree
Showing 24 changed files with 175 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1919,8 +1919,13 @@ AutotestPrivateGetClipboardTextDataFunction::
ExtensionFunction::ResponseAction
AutotestPrivateGetClipboardTextDataFunction::Run() {
base::string16 data;
// This clipboard data read is initiated an extension API, then the user
// shouldn't see a notification if the clipboard is restricted by the rules of
// data leak prevention policy.
ui::ClipboardDataEndpoint data_dst = ui::ClipboardDataEndpoint(
ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
ui::Clipboard::GetForCurrentThread()->ReadText(
ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &data);
ui::ClipboardBuffer::kCopyPaste, &data_dst, &data);
return RespondNow(OneArgument(base::Value(data)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ bool EnterpriseClipboardDlpController::IsDataReadAllowed(

DlpRulesManager::Level level = DlpRulesManager::Level::kAllow;

if (!data_dst) {
if (!data_dst || data_dst->type() == ui::EndpointType::kDefault) {
// Passing empty URL will return restricted if there's a rule restricting
// the src against any dst (*), otherwise it will return ALLOW.
level = DlpRulesManager::Get()->IsRestrictedDestination(
Expand All @@ -72,7 +72,9 @@ bool EnterpriseClipboardDlpController::IsDataReadAllowed(
NOTREACHED();
}

if (level == DlpRulesManager::Level::kBlock) {
bool notify_on_paste = !data_dst || data_dst->notify_if_restricted();

if (level == DlpRulesManager::Level::kBlock && notify_on_paste) {
ShowBlockToast(GetToastText(data_src, data_dst));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
#include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_data_endpoint.h"
#include "ui/events/keycodes/keyboard_codes.h"
#endif

Expand Down Expand Up @@ -1290,8 +1291,12 @@ void ChromePasswordManagerClient::OnPaste() {

ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
base::string16 text;
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&text);
// Given that this clipboard data read happens in the background and not
// initiated by a user gesture, then the user shouldn't see a notification if
// the clipboard is restricted by the rules of data leak prevention policy.
ui::ClipboardDataEndpoint data_dst = ui::ClipboardDataEndpoint(
ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &data_dst, &text);
was_on_paste_called_ = true;
password_reuse_detection_manager_.OnPaste(std::move(text));
}
Expand Down
20 changes: 12 additions & 8 deletions chrome/browser/renderer_context_menu/render_view_context_menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -785,8 +785,9 @@ void RenderViewContextMenu::WriteURLToClipboard(const GURL& url) {
if (url.is_empty() || !url.is_valid())
return;

ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste,
CreateDataEndpoint());
ui::ScopedClipboardWriter scw(
ui::ClipboardBuffer::kCopyPaste,
CreateDataEndpoint(/*notify_if_restricted=*/true));
scw.WriteText(FormatURLForClipboard(url));
}

Expand Down Expand Up @@ -2696,7 +2697,8 @@ bool RenderViewContextMenu::IsPasteEnabled() const {

std::vector<base::string16> types;
ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes(
ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint().get(), &types);
ui::ClipboardBuffer::kCopyPaste,
CreateDataEndpoint(/*notify_if_restricted=*/false).get(), &types);
return !types.empty();
}

Expand All @@ -2706,7 +2708,8 @@ bool RenderViewContextMenu::IsPasteAndMatchStyleEnabled() const {

return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
ui::ClipboardFormatType::GetPlainTextType(),
ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint().get());
ui::ClipboardBuffer::kCopyPaste,
CreateDataEndpoint(/*notify_if_restricted=*/false).get());
}

bool RenderViewContextMenu::IsPrintPreviewEnabled() const {
Expand Down Expand Up @@ -2753,11 +2756,11 @@ void RenderViewContextMenu::AppendQRCodeGeneratorItem(bool for_image,
}

std::unique_ptr<ui::ClipboardDataEndpoint>
RenderViewContextMenu::CreateDataEndpoint() const {
RenderViewContextMenu::CreateDataEndpoint(bool notify_if_restricted) const {
RenderFrameHost* render_frame_host = GetRenderFrameHost();
if (render_frame_host) {
return std::make_unique<ui::ClipboardDataEndpoint>(
render_frame_host->GetLastCommittedOrigin());
render_frame_host->GetLastCommittedOrigin(), notify_if_restricted);
}
return nullptr;
}
Expand Down Expand Up @@ -2932,8 +2935,9 @@ void RenderViewContextMenu::ExecExitFullscreen() {
}

void RenderViewContextMenu::ExecCopyLinkText() {
ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste,
CreateDataEndpoint());
ui::ScopedClipboardWriter scw(
ui::ClipboardBuffer::kCopyPaste,
CreateDataEndpoint(/*notify_if_restricted=*/true));
scw.WriteText(params_.link_text);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ class RenderViewContextMenu : public RenderViewContextMenuBase {
void AppendSharedClipboardItem();
void AppendQRCodeGeneratorItem(bool for_image, bool draw_icon);

std::unique_ptr<ui::ClipboardDataEndpoint> CreateDataEndpoint() const;
std::unique_ptr<ui::ClipboardDataEndpoint> CreateDataEndpoint(
bool notify_if_restricted) const;

// Command enabled query functions.
bool IsReloadEnabled() const;
Expand Down
14 changes: 8 additions & 6 deletions chrome/browser/ui/omnibox/clipboard_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@
#include "base/strings/utf_string_conversions.h"
#include "components/omnibox/browser/omnibox_view.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_data_endpoint.h"

base::string16 GetClipboardText() {
base::string16 GetClipboardText(bool notify_if_restricted) {
// Try text format.
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
ui::ClipboardDataEndpoint data_dst = ui::ClipboardDataEndpoint(
ui::EndpointType::kDefault, notify_if_restricted);
if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
ui::ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr)) {
&data_dst)) {
base::string16 text;
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr, &text);
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &data_dst, &text);
text = text.substr(0, kMaxClipboardTextLength);
return OmniboxView::SanitizeTextForPaste(text);
}
Expand All @@ -33,9 +35,9 @@ base::string16 GetClipboardText() {
// order, we are sure to paste what the user copied.
if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetUrlType(),
ui::ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr)) {
&data_dst)) {
std::string url_str;
clipboard->ReadBookmark(nullptr, /* data_dst = */ nullptr, &url_str);
clipboard->ReadBookmark(&data_dst, nullptr, &url_str);
// pass resulting url string through GURL to normalize
GURL url(url_str);
if (url.is_valid())
Expand Down
4 changes: 3 additions & 1 deletion chrome/browser/ui/omnibox/clipboard_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ static const size_t kMaxClipboardTextLength = 500 * 1024;
// Returns the current clipboard contents as a string that can be pasted in.
// In addition to just getting CF_UNICODETEXT out, this can also extract URLs
// from bookmarks on the clipboard.
base::string16 GetClipboardText();
// If `notify_if_restricted` is set to true, a notification will be shown to
// the user if the clipboard contents can't be accessed.
base::string16 GetClipboardText(bool notify_if_restricted);

#endif // CHROME_BROWSER_UI_OMNIBOX_CLIPBOARD_UTILS_H_
17 changes: 9 additions & 8 deletions chrome/browser/ui/omnibox/clipboard_utils_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ TEST_F(ClipboardUtilsTest, GetClipboardText) {
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(kPlainText);
}
EXPECT_EQ(kPlainText, GetClipboardText());
EXPECT_EQ(kPlainText, GetClipboardText(/*notify_if_restricted=*/false));

// Can we pull a string consists of white-space?
const base::string16 kSpace6(ASCIIToUTF16(" "));
Expand All @@ -62,11 +62,11 @@ TEST_F(ClipboardUtilsTest, GetClipboardText) {
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(kSpace6);
}
EXPECT_EQ(kSpace1, GetClipboardText());
EXPECT_EQ(kSpace1, GetClipboardText(/*notify_if_restricted=*/false));

// Does an empty clipboard get empty text?
clipboard->Clear(ui::ClipboardBuffer::kCopyPaste);
EXPECT_EQ(base::string16(), GetClipboardText());
EXPECT_EQ(base::string16(), GetClipboardText(/*notify_if_restricted=*/false));

// Bookmark clipboard apparently not supported on Linux.
// See TODO on ClipboardText.BookmarkTest.
Expand All @@ -77,15 +77,16 @@ TEST_F(ClipboardUtilsTest, GetClipboardText) {
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteBookmark(kTitle, kURL);
}
EXPECT_EQ(ASCIIToUTF16(kURL), GetClipboardText());
EXPECT_EQ(ASCIIToUTF16(kURL),
GetClipboardText(/*notify_if_restricted=*/false));

// Do we pull text in preference to a bookmark?
{
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(kPlainText);
clipboard_writer.WriteBookmark(kTitle, kURL);
}
EXPECT_EQ(kPlainText, GetClipboardText());
EXPECT_EQ(kPlainText, GetClipboardText(/*notify_if_restricted=*/false));
#endif

// Do we get nothing if there is neither text nor a bookmark?
Expand All @@ -94,7 +95,7 @@ TEST_F(ClipboardUtilsTest, GetClipboardText) {
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteHTML(kMarkup, kURL);
}
EXPECT_TRUE(GetClipboardText().empty());
EXPECT_TRUE(GetClipboardText(/*notify_if_restricted=*/false).empty());
}

TEST_F(ClipboardUtilsTest, TruncateLongText) {
Expand All @@ -104,15 +105,15 @@ TEST_F(ClipboardUtilsTest, TruncateLongText) {
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(almost_long_text);
}
EXPECT_EQ(almost_long_text, GetClipboardText());
EXPECT_EQ(almost_long_text, GetClipboardText(/*notify_if_restricted=*/false));

const base::string16 long_text =
base::ASCIIToUTF16(std::string(kMaxClipboardTextLength + 1, '.'));
{
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(long_text);
}
EXPECT_EQ(almost_long_text, GetClipboardText());
EXPECT_EQ(almost_long_text, GetClipboardText(/*notify_if_restricted=*/false));
}

} // namespace
6 changes: 3 additions & 3 deletions chrome/browser/ui/search/omnibox_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ void PasteIntoOmnibox(const base::string16& text,
// from the clipboard already sanitized. The second case is needed to handle
// drag-and-drop value and it has to be sanitazed before setting it into the
// omnibox.
base::string16 text_to_paste = text.empty()
? GetClipboardText()
: omnibox_view->SanitizeTextForPaste(text);
base::string16 text_to_paste =
text.empty() ? GetClipboardText(/*notify_if_restricted=*/true)
: omnibox_view->SanitizeTextForPaste(text);

if (text_to_paste.empty())
return;
Expand Down
32 changes: 23 additions & 9 deletions chrome/browser/ui/views/omnibox/omnibox_view_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <set>
#include <utility>

#include "base/auto_reset.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/feature_list.h"
Expand Down Expand Up @@ -794,7 +795,7 @@ void OmniboxViewViews::ExecuteCommand(int command_id, int event_flags) {
switch (command_id) {
// These commands don't invoke the popup via OnBefore/AfterPossibleChange().
case IDC_PASTE_AND_GO:
model()->PasteAndGo(GetClipboardText());
model()->PasteAndGo(GetClipboardText(/*notify_if_restricted=*/true));
return;
case IDC_SHOW_FULL_URLS:
case IDC_EDIT_SEARCH_ENGINES:
Expand Down Expand Up @@ -937,7 +938,7 @@ base::string16 OmniboxViewViews::GetSelectedText() const {
}

void OmniboxViewViews::OnOmniboxPaste() {
const base::string16 text(GetClipboardText());
const base::string16 text(GetClipboardText(/*notify_if_restricted=*/true));

if (text.empty() ||
// When the fakebox is focused, ignore pasted whitespace because if the
Expand Down Expand Up @@ -1470,9 +1471,10 @@ base::string16 OmniboxViewViews::GetLabelForCommandId(int command_id) const {

// Don't paste-and-go data that was marked by its originator as confidential.
constexpr size_t kMaxSelectionTextLength = 50;
const base::string16 clipboard_text = IsClipboardDataMarkedAsConfidential()
? base::string16()
: GetClipboardText();
const base::string16 clipboard_text =
IsClipboardDataMarkedAsConfidential()
? base::string16()
: GetClipboardText(/*notify_if_restricted=*/false);

if (clipboard_text.empty())
return l10n_util::GetStringUTF16(IDS_PASTE_AND_GO_EMPTY);
Expand Down Expand Up @@ -1976,10 +1978,12 @@ void OmniboxViewViews::OnBlur() {

bool OmniboxViewViews::IsCommandIdEnabled(int command_id) const {
if (command_id == Textfield::kPaste)
return !GetReadOnly() && !GetClipboardText().empty();
return !GetReadOnly() &&
!GetClipboardText(/*notify_if_restricted=*/false).empty();
if (command_id == IDC_PASTE_AND_GO) {
return !GetReadOnly() && !IsClipboardDataMarkedAsConfidential() &&
model()->CanPasteAndGo(GetClipboardText());
model()->CanPasteAndGo(
GetClipboardText(/*notify_if_restricted=*/false));
}

// Menu item is only shown when it is valid.
Expand Down Expand Up @@ -2109,7 +2113,8 @@ bool OmniboxViewViews::IsTextEditCommandEnabled(
case ui::TextEditCommand::MOVE_DOWN:
return !GetReadOnly();
case ui::TextEditCommand::PASTE:
return !GetReadOnly() && !GetClipboardText().empty();
return !GetReadOnly() &&
!GetClipboardText(show_rejection_ui_if_any_).empty();
default:
return Textfield::IsTextEditCommandEnabled(command);
}
Expand All @@ -2121,6 +2126,8 @@ void OmniboxViewViews::ExecuteTextEditCommand(ui::TextEditCommand command) {
// here, we need to deactivate touch text selection here, too.
DestroyTouchSelection();

base::AutoReset<bool> show_rejection_ui(&show_rejection_ui_if_any_, true);

if (!IsTextEditCommandEnabled(command))
return;

Expand Down Expand Up @@ -2176,6 +2183,11 @@ bool OmniboxViewViews::HandleKeyEvent(views::Textfield* textfield,
if (event.IsUnicodeKeyCode())
return false;

// Show a notification if the clipboard is restricted by the rules of the
// data leak prevention policy. This state is used by the
// IsTextEditCommandEnabled(ui::TextEditCommand::PASTE) cases below.
base::AutoReset<bool> show_rejection_ui(&show_rejection_ui_if_any_, true);

const bool shift = event.IsShiftDown();
const bool control = event.IsControlDown();
const bool alt = event.IsAltDown() || event.IsAltGrDown();
Expand Down Expand Up @@ -2339,7 +2351,9 @@ void OmniboxViewViews::OnAfterUserAction(views::Textfield* sender) {
void OmniboxViewViews::OnAfterCutOrCopy(ui::ClipboardBuffer clipboard_buffer) {
ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread();
base::string16 selected_text;
cb->ReadText(clipboard_buffer, /* data_dst = */ nullptr, &selected_text);
ui::ClipboardDataEndpoint data_dst = ui::ClipboardDataEndpoint(
ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
cb->ReadText(clipboard_buffer, &data_dst, &selected_text);
GURL url;
bool write_url = false;
model()->AdjustTextForCopy(GetSelectedRange().GetMin(), &selected_text, &url,
Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/ui/views/omnibox/omnibox_view_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,9 @@ class OmniboxViewViews : public OmniboxView,
// and gets a tap. So we use this variable to remember focus state before tap.
bool select_all_on_gesture_tap_ = false;

// Whether the user should be notified if the clipboard is restricted.
bool show_rejection_ui_if_any_ = false;

// Keep track of the word that would be selected if URL is unelided between
// a single and double click. This is an edge case where the elided URL is
// selected. On the double click, unelision is performed in between the first
Expand Down
4 changes: 3 additions & 1 deletion components/bookmarks/browser/bookmark_node_data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,11 @@ BookmarkNodeData::~BookmarkNodeData() {
#if !defined(OS_APPLE)
// static
bool BookmarkNodeData::ClipboardContainsBookmarks() {
ui::ClipboardDataEndpoint data_dst = ui::ClipboardDataEndpoint(
ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
ui::ClipboardFormatType::GetType(kClipboardFormatString),
ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
ui::ClipboardBuffer::kCopyPaste, &data_dst);
}
#endif

Expand Down
Loading

0 comments on commit 2ae6eb2

Please sign in to comment.