Commit ba513453 authored by Andrew Xu's avatar Andrew Xu Committed by Commit Bot

[Multipaste] Support DLP

This CL handles the clipboard data with the restricted access from the
multipaste menu. It implements the following things:
(1) Disable the menu item whose clipboard history data should not
be accessed through the multipaste menu.
(2) The disabled menu item should have different UI appearance.

Bug: 1106847
Change-Id: I4c58cc898a3f529a928787d6ef378eaa49f5871a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2409736Reviewed-by: default avatarDavid Vallet <dvallet@chromium.org>
Reviewed-by: default avatarDarwin Huang <huangdarwin@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarDavid Black <dmblack@google.com>
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809185}
parent 296b36f2
......@@ -8,6 +8,7 @@
#include "ash/clipboard/clipboard_history_util.h"
#include "ash/clipboard/views/clipboard_history_item_view.h"
#include "ash/public/cpp/clipboard_image_model_factory.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/controls/menu/menu_item_view.h"
......@@ -16,7 +17,6 @@
#include "ui/views/controls/menu/submenu_view.h"
namespace ash {
// static
std::unique_ptr<ClipboardHistoryMenuModelAdapter>
ClipboardHistoryMenuModelAdapter::Create(
......@@ -39,6 +39,17 @@ void ClipboardHistoryMenuModelAdapter::Run(const gfx::Rect& anchor_rect) {
int command_id = ClipboardHistoryUtil::kFirstItemCommandId;
for (const auto& item : clipboard_history_->GetItems()) {
model_->AddItem(command_id, base::string16());
// Enable or disable the command depending on whether its corresponding
// clipboard history item is allowed to read or not.
const auto* dlp_controller =
ui::Clipboard::GetForCurrentThread()->GetClipboardDlpController();
model_->SetEnabledAt(model_->GetIndexOfCommandId(command_id),
dlp_controller
? dlp_controller->IsDataReadAllowed(
item.data().source(), /*data_dst=*/nullptr)
: true);
item_snapshots_.emplace(command_id, item);
++command_id;
}
......@@ -103,6 +114,12 @@ gfx::Rect ClipboardHistoryMenuModelAdapter::GetMenuBoundsInScreenForTest()
return root_view_->GetSubmenu()->GetBoundsInScreen();
}
const views::MenuItemView*
ClipboardHistoryMenuModelAdapter::GetMenuItemViewAtForTest(int index) const {
DCHECK(root_view_);
return root_view_->GetSubmenu()->GetMenuItemAt(index);
}
ClipboardHistoryMenuModelAdapter::ClipboardHistoryMenuModelAdapter(
std::unique_ptr<ui::SimpleMenuModel> model,
base::RepeatingClosure menu_closed_callback,
......
......@@ -69,6 +69,8 @@ class ASH_EXPORT ClipboardHistoryMenuModelAdapter : views::MenuModelAdapter {
// Returns menu bounds in screen coordinates.
gfx::Rect GetMenuBoundsInScreenForTest() const;
const views::MenuItemView* GetMenuItemViewAtForTest(int index) const;
private:
ClipboardHistoryMenuModelAdapter(
std::unique_ptr<ui::SimpleMenuModel> model,
......
......@@ -13,6 +13,7 @@
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
......@@ -49,14 +50,14 @@ class FadeImageView : public views::ImageView,
public ClipboardHistoryResourceManager::Observer {
public:
FadeImageView(const ClipboardHistoryItem& clipboard_history_item,
const ClipboardHistoryResourceManager* resource_manager)
const ClipboardHistoryResourceManager* resource_manager,
float opacity)
: views::ImageView(),
resource_manager_(resource_manager),
clipboard_history_item_(clipboard_history_item) {
clipboard_history_item_(clipboard_history_item),
opacity_(opacity) {
resource_manager_->AddObserver(this);
SetImage(*(resource_manager_->GetImageModel(clipboard_history_item_)
.GetImage()
.ToImageSkia()));
SetImageFromModel();
}
FadeImageView(const FadeImageView& rhs) = delete;
......@@ -94,9 +95,7 @@ class FadeImageView : public views::ImageView,
case FadeAnimationState::kFadeOut:
DCHECK_EQ(0.0f, layer()->opacity());
animation_state_ = FadeAnimationState::kFadeIn;
SetImage(*(resource_manager_->GetImageModel(clipboard_history_item_)
.GetImage()
.ToImageSkia()));
SetImageFromModel();
{
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
settings.AddObserver(this);
......@@ -111,6 +110,19 @@ class FadeImageView : public views::ImageView,
}
}
void SetImageFromModel() {
const gfx::ImageSkia& image =
*(resource_manager_->GetImageModel(clipboard_history_item_)
.GetImage()
.ToImageSkia());
if (opacity_ != 1.f) {
SetImage(
gfx::ImageSkiaOperations::CreateTransparentImage(image, opacity_));
} else {
SetImage(image);
}
}
// The different animation states possible when transitioning from one
// gfx::ImageSkia to the next.
enum class FadeAnimationState {
......@@ -127,6 +139,9 @@ class FadeImageView : public views::ImageView,
// The ClipboardHistoryItem represented by this class.
const ClipboardHistoryItem clipboard_history_item_;
// The opacity of the image content.
const float opacity_;
};
} // namespace
......@@ -205,12 +220,17 @@ ClipboardHistoryBitmapItemView::BuildImageView() {
ClipboardHistoryUtil::CalculateMainFormat(clipboard_history_item_.data())
.value()) {
case ui::ClipboardInternalFormat::kHtml:
return std::make_unique<FadeImageView>(clipboard_history_item_,
resource_manager_);
return std::make_unique<FadeImageView>(
clipboard_history_item_, resource_manager_, GetContentsOpacity());
case ui::ClipboardInternalFormat::kBitmap: {
auto image_view = std::make_unique<views::ImageView>();
image_view->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(
clipboard_history_item_.data().bitmap()));
gfx::ImageSkia bitmap_image = gfx::ImageSkia::CreateFrom1xBitmap(
clipboard_history_item_.data().bitmap());
if (GetContentsOpacity() != 1.f) {
bitmap_image = gfx::ImageSkiaOperations::CreateTransparentImage(
bitmap_image, GetContentsOpacity());
}
image_view->SetImage(bitmap_image);
return image_view;
}
default:
......
......@@ -26,6 +26,9 @@
namespace {
// The opacity of the disabled item view.
constexpr float kDisabledAlpha = 0.38f;
// The insets within the contents view.
constexpr gfx::Insets kContentsInsets(/*vertical=*/4, /*horizontal=*/16);
......@@ -182,6 +185,10 @@ void ClipboardHistoryItemView::OnSelectionChanged() {
main_button_->SchedulePaint();
}
float ClipboardHistoryItemView::GetContentsOpacity() const {
return container_->GetEnabled() ? 1.f : kDisabledAlpha;
}
gfx::Size ClipboardHistoryItemView::CalculatePreferredSize() const {
const int preferred_width =
views::MenuConfig::instance().touchable_menu_width;
......@@ -194,7 +201,9 @@ void ClipboardHistoryItemView::ButtonPressed(views::Button* sender,
const int command_id = sender == contents_view_->delete_button()
? ClipboardHistoryUtil::kDeleteCommandId
: container_->GetCommand();
container_->GetDelegate()->ExecuteCommand(command_id, event.flags());
views::MenuDelegate* delegate = container_->GetDelegate();
DCHECK(delegate->IsCommandEnabled(command_id));
delegate->ExecuteCommand(command_id, event.flags());
}
} // namespace ash
......@@ -90,6 +90,10 @@ class ClipboardHistoryItemView : public views::View,
// Creates the contents view.
virtual std::unique_ptr<ContentsView> CreateContentsView() = 0;
// Returns the opacity of the menu item view's contents depending on the
// enabled state.
float GetContentsOpacity() const;
private:
// views::View:
gfx::Size CalculatePreferredSize() const override;
......
......@@ -83,6 +83,8 @@ ClipboardHistoryTextItemView::CreateContentsView() {
label->SetFontList(views::MenuConfig::instance().font_list);
label->SetMultiLine(false);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
label->SetEnabledColor(
SkColorSetA(SK_ColorBLACK, 0xFF * GetContentsOpacity()));
layout->SetFlexForView(label, /*flex_weights=*/1);
contents_view->InstallDeleteButton();
......
......@@ -29,6 +29,12 @@ void HeadlessClipboard::SetClipboardDlpController(
NOTIMPLEMENTED();
}
const ui::ClipboardDlpController* HeadlessClipboard::GetClipboardDlpController()
const {
NOTIMPLEMENTED();
return nullptr;
}
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
bool HeadlessClipboard::IsFormatAvailable(
......
......@@ -28,6 +28,7 @@ class HeadlessClipboard : public ui::Clipboard {
uint64_t GetSequenceNumber(ui::ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ui::ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(
const ui::ClipboardFormatType& format,
ui::ClipboardBuffer buffer,
......
......@@ -113,6 +113,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
virtual void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) = 0;
// Returns the data leak prevention controller. This function will be used
// only on Chrome OS.
virtual const ClipboardDlpController* GetClipboardDlpController() const = 0;
// Tests whether the clipboard contains a certain format.
// TODO(crbug.com/1103614): Update |data_dst| in all references to its
// appropriate ClipboardDataEndpoint for web-originates uses.
......
......@@ -375,6 +375,12 @@ void ClipboardAndroid::SetClipboardDlpController(
NOTIMPLEMENTED();
}
const ui::ClipboardDlpController* ClipboardAndroid::GetClipboardDlpController()
const {
NOTIMPLEMENTED();
return nullptr;
}
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
bool ClipboardAndroid::IsFormatAvailable(
......
......@@ -61,6 +61,7 @@ class ClipboardAndroid : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst) const override;
......
......@@ -33,6 +33,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst) const override;
......
......@@ -75,6 +75,12 @@ void ClipboardMac::SetClipboardDlpController(
NOTIMPLEMENTED();
}
const ui::ClipboardDlpController* ClipboardMac::GetClipboardDlpController()
const {
NOTIMPLEMENTED();
return nullptr;
}
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
bool ClipboardMac::IsFormatAvailable(
......
......@@ -251,6 +251,10 @@ class ClipboardInternal {
return dlp_controller_->IsDataReadAllowed(GetData()->source(), data_dst);
}
const ClipboardDlpController* dlp_controller() const {
return dlp_controller_.get();
}
private:
// True if the ClipboardData has format |format|.
bool HasFormat(ClipboardInternalFormat format) const {
......@@ -403,6 +407,12 @@ void ClipboardNonBacked::SetClipboardDlpController(
clipboard_internal_->SetDlpController(std::move(dlp_controller));
}
const ClipboardDlpController* ClipboardNonBacked::GetClipboardDlpController()
const {
DCHECK(CalledOnValidThread());
return clipboard_internal_->dlp_controller();
}
uint64_t ClipboardNonBacked::GetSequenceNumber(ClipboardBuffer buffer) const {
DCHECK(CalledOnValidThread());
return clipboard_internal_->sequence_number();
......
......@@ -49,6 +49,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
void OnPreShutdown() override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ClipboardDlpController* GetClipboardDlpController() const override;
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
......
......@@ -353,6 +353,12 @@ void ClipboardOzone::SetClipboardDlpController(
NOTIMPLEMENTED();
}
const ui::ClipboardDlpController* ClipboardOzone::GetClipboardDlpController()
const {
NOTIMPLEMENTED();
return nullptr;
}
// TODO(crbug.com/1103194): |data_dst| should be supported.
bool ClipboardOzone::IsFormatAvailable(
const ClipboardFormatType& format,
......
......@@ -28,6 +28,7 @@ class ClipboardOzone : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst) const override;
......
......@@ -251,6 +251,12 @@ void ClipboardWin::SetClipboardDlpController(
NOTIMPLEMENTED();
}
const ui::ClipboardDlpController* ClipboardWin::GetClipboardDlpController()
const {
NOTIMPLEMENTED();
return nullptr;
}
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
bool ClipboardWin::IsFormatAvailable(
......
......@@ -38,6 +38,7 @@ class ClipboardWin : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst) const override;
......
......@@ -501,6 +501,12 @@ void ClipboardX11::SetClipboardDlpController(
NOTIMPLEMENTED();
}
const ui::ClipboardDlpController* ClipboardX11::GetClipboardDlpController()
const {
NOTIMPLEMENTED();
return nullptr;
}
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
bool ClipboardX11::IsFormatAvailable(
......
......@@ -27,6 +27,7 @@ class ClipboardX11 : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst) const override;
......
......@@ -47,6 +47,11 @@ void TestClipboard::SetClipboardDlpController(
dlp_controller_ = std::move(dlp_controller);
}
const ui::ClipboardDlpController* TestClipboard::GetClipboardDlpController()
const {
return dlp_controller_.get();
}
bool TestClipboard::IsFormatAvailable(
const ClipboardFormatType& format,
ClipboardBuffer buffer,
......
......@@ -38,6 +38,7 @@ class TestClipboard : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
void SetClipboardDlpController(
std::unique_ptr<ClipboardDlpController> dlp_controller) override;
const ui::ClipboardDlpController* GetClipboardDlpController() const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const ClipboardDataEndpoint* data_dst) const override;
......
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