Commit 6aa07208 authored by Aya ElAttar's avatar Aya ElAttar Committed by Chromium LUCI CQ

DLP: Disallow Drop if not allowed

Changed DragDropController to:
- Cancel drop if not allowed by policy rules.
- Show CursorType::NoDrop while dragging if
the policy rules disallow the data from being
dropped.

Bug: 1139886
Change-Id: I8a12f1f4af2fa0f21d4d562d393d9f64cec39f72
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2595382Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Aya Elsayed <ayaelattar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842939}
parent 28825f1b
......@@ -23,6 +23,8 @@
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.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/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider.h"
......@@ -81,6 +83,19 @@ void DispatchGestureEndToWindow(aura::Window* window) {
}
}
bool IsDragDropAllowed(const ui::OSExchangeData* drag_data,
aura::client::DragUpdateInfo& drag_info,
bool is_drop) {
DCHECK(drag_data);
drag_info.data_endpoint.set_notify_if_restricted(is_drop);
return ui::DataTransferPolicyController::HasInstance()
? ui::DataTransferPolicyController::Get()->IsDragDropAllowed(
drag_data->GetSource(), &drag_info.data_endpoint)
: true;
}
} // namespace
class DragDropTrackerDelegate : public aura::WindowDelegate {
......@@ -464,14 +479,19 @@ void DragDropController::DragUpdate(aura::Window* target,
e.set_flags(event.flags());
ui::Event::DispatcherApi(&e).set_target(target);
drag_info = delegate->OnDragUpdated(e);
bool is_drop_allowed = IsDragDropAllowed(drag_data_.get(), drag_info,
/*is_drop=*/false);
gfx::NativeCursor cursor = ui::mojom::CursorType::kNoDrop;
if (is_drop_allowed) {
if (drag_info.drag_operation & ui::DragDropTypes::DRAG_COPY)
cursor = ui::mojom::CursorType::kCopy;
else if (drag_info.drag_operation & ui::DragDropTypes::DRAG_LINK)
cursor = ui::mojom::CursorType::kAlias;
else if (drag_info.drag_operation & ui::DragDropTypes::DRAG_MOVE)
cursor = ui::mojom::CursorType::kGrabbing;
} else {
drag_info.drag_operation = ui::DragDropTypes::DRAG_NONE;
}
Shell::Get()->cursor_manager()->SetCursor(cursor);
}
}
......@@ -506,8 +526,6 @@ void DragDropController::DragUpdate(aura::Window* target,
void DragDropController::Drop(aura::Window* target,
const ui::LocatedEvent& event) {
Shell::Get()->cursor_manager()->SetCursor(ui::mojom::CursorType::kPointer);
// We must guarantee that a target gets a OnDragEntered before Drop. WebKit
// depends on not getting a Drop without DragEnter. This behavior is
// consistent with drag/drop on other platforms.
......@@ -515,6 +533,14 @@ void DragDropController::Drop(aura::Window* target,
DragUpdate(target, event);
DCHECK(target == drag_window_);
if (!IsDragDropAllowed(drag_data_.get(), current_drag_info_,
/*is_drop=*/true)) {
DragCancel();
return;
}
Shell::Get()->cursor_manager()->SetCursor(ui::mojom::CursorType::kPointer);
aura::client::DragDropDelegate* delegate =
aura::client::GetDragDropDelegate(target);
if (delegate) {
......
......@@ -31,6 +31,7 @@
#include "ui/base/clipboard/clipboard.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/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/dragdrop/os_exchange_data.h"
......@@ -245,7 +246,8 @@ class EventTargetTestDelegate : public aura::client::DragDropDelegate {
kNotInvoked,
kDragEnteredInvoked,
kDragUpdateInvoked,
kPerformDropInvoked
kPerformDropInvoked,
kDragExitInvoked
};
explicit EventTargetTestDelegate(aura::Window* window) : window_(window) {}
......@@ -267,7 +269,11 @@ class EventTargetTestDelegate : public aura::client::DragDropDelegate {
ui::DragDropTypes::DRAG_MOVE,
ui::DataTransferEndpoint(ui::EndpointType::kDefault));
}
void OnDragExited() override { ADD_FAILURE(); }
void OnDragExited() override {
EXPECT_TRUE(State::kDragEnteredInvoked == state_ ||
State::kDragUpdateInvoked == state_);
state_ = State::kDragExitInvoked;
}
int OnPerformDrop(const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) override {
EXPECT_EQ(State::kDragUpdateInvoked, state_);
......@@ -1474,4 +1480,88 @@ TEST_F(DragDropControllerTest, ToplevelWindowDragDelegate) {
}
}
namespace {
class MockDataTransferPolicyController
: public ui::DataTransferPolicyController {
public:
MOCK_METHOD2(IsClipboardReadAllowed,
bool(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst));
MOCK_METHOD2(IsDragDropAllowed,
bool(const ui::DataTransferEndpoint* const data_src,
const ui::DataTransferEndpoint* const data_dst));
};
} // namespace
TEST_F(DragDropControllerTest, DlpAllowDragDrop) {
std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), -1,
gfx::Rect(0, 0, 100, 100)));
EventTargetTestDelegate delegate(window.get());
aura::client::SetDragDropDelegate(window.get(), &delegate);
MockDataTransferPolicyController dlp_contoller;
// Posted task will be run when the inner loop runs in StartDragAndDrop.
ui::test::EventGenerator generator(window->GetRootWindow(), window.get());
generator.PressLeftButton();
auto data(std::make_unique<ui::OSExchangeData>());
data->SetString(base::UTF8ToUTF16("I am being dragged"));
EXPECT_CALL(dlp_contoller, IsDragDropAllowed)
.Times(2)
.WillRepeatedly(::testing::Return(true));
drag_drop_controller_->StartDragAndDrop(
std::move(data), window->GetRootWindow(), window.get(), gfx::Point(5, 5),
ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse);
// For drag enter
generator.MoveMouseBy(0, 1);
// For drag update
generator.MoveMouseBy(0, 1);
// For perform drop
generator.ReleaseLeftButton();
EXPECT_EQ(EventTargetTestDelegate::State::kPerformDropInvoked,
delegate.state());
}
TEST_F(DragDropControllerTest, DlpDisallowDragDrop) {
std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), -1,
gfx::Rect(0, 0, 100, 100)));
EventTargetTestDelegate delegate(window.get());
aura::client::SetDragDropDelegate(window.get(), &delegate);
MockDataTransferPolicyController dlp_contoller;
// Posted task will be run when the inner loop runs in StartDragAndDrop.
ui::test::EventGenerator generator(window->GetRootWindow(), window.get());
generator.PressLeftButton();
auto data(std::make_unique<ui::OSExchangeData>());
data->SetString(base::UTF8ToUTF16("I am being dragged"));
EXPECT_CALL(dlp_contoller, IsDragDropAllowed)
.Times(2)
.WillRepeatedly(::testing::Return(false));
drag_drop_controller_->StartDragAndDrop(
std::move(data), window->GetRootWindow(), window.get(), gfx::Point(5, 5),
ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse);
// For drag enter
generator.MoveMouseBy(0, 1);
// For drag update
generator.MoveMouseBy(0, 1);
// For perform drop
generator.ReleaseLeftButton();
EXPECT_EQ(EventTargetTestDelegate::State::kDragExitInvoked, delegate.state());
}
} // namespace ash
......@@ -63,6 +63,9 @@ class COMPONENT_EXPORT(UI_BASE_DATA_TRANSFER_POLICY) DataTransferEndpoint {
EndpointType type() const { return type_; }
void set_notify_if_restricted(bool notify_if_restricted) {
notify_if_restricted_ = notify_if_restricted;
}
bool notify_if_restricted() const { return notify_if_restricted_; }
private:
......
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