Plumb origin through for drags.
This repurposes the data type used to tag drags as renderer-initiated by also using it to store the origin of the source of the drag data. Currently, opaque origins are not plumbed through end-to-end. An opaque origin will still cause the drag to be treated as renderer-tainted; however, when reading out the origin, a new unique opaque origin will be created. Bug: 1346429 Change-Id: I52467e30d590473ded1eb2dd15fb40ff8ceabb23 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4837192 Commit-Queue: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1202178}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
d4de0b3f31
commit
2cb89f90a3
chrome/browser/ui/views
content
app_shim_remote_cocoa
web_contents_ns_view_bridge.hweb_contents_ns_view_bridge.mmweb_contents_view_cocoa.hweb_contents_view_cocoa.mmweb_drag_source_mac.hweb_drag_source_mac.mm
browser
renderer_host
render_frame_host_impl.ccrender_view_host_delegate_view.hrender_view_host_unittest.ccrender_widget_host_impl.ccrender_widget_host_impl.hrender_widget_host_unittest.cc
web_contents
common
ui/base
clipboard
dragdrop
os_exchange_data.ccos_exchange_data.hos_exchange_data_provider.hos_exchange_data_provider_mac.hos_exchange_data_provider_mac.mmos_exchange_data_provider_non_backed.ccos_exchange_data_provider_non_backed.hos_exchange_data_provider_non_backed_unittest.ccos_exchange_data_provider_win.ccos_exchange_data_provider_win.hos_exchange_data_unittest.cc
x
@ -70,6 +70,7 @@
|
||||
#include "ui/gfx/geometry/point_f.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace chrome {
|
||||
namespace {
|
||||
@ -345,10 +346,12 @@ class DragStartWaiter : public aura::client::DragDropClient {
|
||||
// WaitUntilDragStart can take a long time to return (it returns only after
|
||||
// the OS decides that the drag-and-drop has ended).
|
||||
//
|
||||
// Before returning populates |text|, |html| and other parameters with data
|
||||
// that would have been passed to the OS). If the caller is not interested in
|
||||
// this data, then the corresponding argument can be null.
|
||||
void WaitUntilDragStart(std::string* text,
|
||||
// Before returning populates `source_origin`, `text`, `html` and other
|
||||
// parameters with data that would have been passed to the OS). If the caller
|
||||
// is not interested in this data, then the corresponding argument can be
|
||||
// null.
|
||||
void WaitUntilDragStart(absl::optional<url::Origin>* source_origin,
|
||||
std::string* text,
|
||||
std::string* html,
|
||||
int* operation,
|
||||
gfx::Point* location_inside_web_contents) {
|
||||
@ -357,6 +360,9 @@ class DragStartWaiter : public aura::client::DragDropClient {
|
||||
// message_loop_runner_->Quit is only called from StartDragAndDrop.
|
||||
DCHECK(drag_started_);
|
||||
|
||||
if (source_origin) {
|
||||
*source_origin = source_origin_;
|
||||
}
|
||||
if (text)
|
||||
*text = text_;
|
||||
if (html)
|
||||
@ -387,6 +393,7 @@ class DragStartWaiter : public aura::client::DragDropClient {
|
||||
drag_started_ = true;
|
||||
message_loop_runner_->Quit();
|
||||
|
||||
source_origin_ = data->GetRendererTaintedOrigin();
|
||||
std::u16string text;
|
||||
if (data->GetString(&text))
|
||||
text_ = base::UTF16ToUTF8(text);
|
||||
@ -448,6 +455,7 @@ class DragStartWaiter : public aura::client::DragDropClient {
|
||||
|
||||
// Data captured during the first intercepted StartDragAndDrop call.
|
||||
bool drag_started_;
|
||||
absl::optional<url::Origin> source_origin_;
|
||||
std::string text_;
|
||||
std::string html_;
|
||||
int operation_;
|
||||
@ -1264,12 +1272,16 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_DragStartInFrame) {
|
||||
|
||||
// Verify data being passed to the OS.
|
||||
{
|
||||
absl::optional<url::Origin> source_origin;
|
||||
std::string text;
|
||||
std::string html;
|
||||
int operation = 0;
|
||||
gfx::Point location_inside_web_contents;
|
||||
drag_start_waiter.WaitUntilDragStart(&text, &html, &operation,
|
||||
drag_start_waiter.WaitUntilDragStart(&source_origin, &text, &html,
|
||||
&operation,
|
||||
&location_inside_web_contents);
|
||||
ASSERT_TRUE(source_origin.has_value());
|
||||
EXPECT_EQ(embedded_test_server()->GetOrigin(frame_site), source_origin);
|
||||
EXPECT_EQ(embedded_test_server()->GetURL(frame_site,
|
||||
"/drag_and_drop/cors-allowed.jpg"),
|
||||
text);
|
||||
@ -1402,7 +1414,8 @@ void DragAndDropBrowserTest::DragImageBetweenFrames_Start(
|
||||
// The next step of the test (DragImageBetweenFrames_Step2) runs inside the
|
||||
// nested drag-and-drop message loop - the call below won't return until the
|
||||
// drag-and-drop has already ended.
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr);
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr);
|
||||
|
||||
DragImageBetweenFrames_Step3(&state);
|
||||
}
|
||||
@ -1634,7 +1647,8 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest,
|
||||
// The next step of the test (DragImageFromDisappearingFrame_Step2) runs
|
||||
// inside the nested drag-and-drop message loop - the call below won't return
|
||||
// until the drag-and-drop has already ended.
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr);
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr);
|
||||
|
||||
DragImageFromDisappearingFrame_Step3(&state);
|
||||
}
|
||||
@ -1748,7 +1762,8 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_CrossSiteDrag) {
|
||||
// The next step of the test (CrossSiteDrag_Step2) runs inside the
|
||||
// nested drag-and-drop message loop - the call below won't return until the
|
||||
// drag-and-drop has already ended.
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr);
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr);
|
||||
|
||||
CrossSiteDrag_Step3(&state);
|
||||
}
|
||||
@ -1886,7 +1901,8 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_CrossTabDrag) {
|
||||
// The next step of the test (CrossTabDrag_Step2) runs inside the
|
||||
// nested drag-and-drop message loop - the call below won't return until the
|
||||
// drag-and-drop has already ended.
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr);
|
||||
drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr);
|
||||
|
||||
CrossTabDrag_Step3(&state);
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ class CONTENT_EXPORT WebContentsNSViewBridge : public mojom::WebContentsNSView {
|
||||
void MakeFirstResponder() override;
|
||||
void TakeFocus(bool reverse) override;
|
||||
void StartDrag(const content::DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
uint32_t operation_mask,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& image_offset,
|
||||
|
@ -98,6 +98,7 @@ void WebContentsNSViewBridge::TakeFocus(bool reverse) {
|
||||
}
|
||||
|
||||
void WebContentsNSViewBridge::StartDrag(const content::DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
uint32_t operation_mask,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& image_offset,
|
||||
@ -105,6 +106,7 @@ void WebContentsNSViewBridge::StartDrag(const content::DropData& drop_data,
|
||||
NSPoint offset = NSPointFromCGPoint(
|
||||
gfx::PointAtOffsetFromOrigin(image_offset).ToCGPoint());
|
||||
[ns_view_ startDragWithDropData:drop_data
|
||||
sourceOrigin:source_origin
|
||||
dragOperationMask:operation_mask
|
||||
image:gfx::NSImageFromImageSkia(image)
|
||||
offset:offset
|
||||
|
@ -19,6 +19,10 @@ namespace remote_cocoa::mojom {
|
||||
class WebContentsNSViewHost;
|
||||
} // namespace remote_cocoa::mojom
|
||||
|
||||
namespace url {
|
||||
class Origin;
|
||||
}
|
||||
|
||||
@class WebDragSource;
|
||||
|
||||
CONTENT_EXPORT
|
||||
@ -40,6 +44,7 @@ CONTENT_EXPORT
|
||||
- (instancetype)initWithViewsHostableView:(ui::ViewsHostableView*)v;
|
||||
- (void)registerDragTypes;
|
||||
- (void)startDragWithDropData:(const content::DropData&)dropData
|
||||
sourceOrigin:(const url::Origin&)sourceOrigin
|
||||
dragOperationMask:(NSDragOperation)operationMask
|
||||
image:(NSImage*)image
|
||||
offset:(NSPoint)offset
|
||||
|
@ -233,6 +233,7 @@ STATIC_ASSERT_ENUM(NSDragOperationMove, ui::DragDropTypes::DRAG_MOVE);
|
||||
}
|
||||
|
||||
- (void)startDragWithDropData:(const DropData&)dropData
|
||||
sourceOrigin:(const url::Origin&)sourceOrigin
|
||||
dragOperationMask:(NSDragOperation)operationMask
|
||||
image:(NSImage*)image
|
||||
offset:(NSPoint)offset
|
||||
@ -253,6 +254,7 @@ STATIC_ASSERT_ENUM(NSDragOperationMove, ui::DragDropTypes::DRAG_MOVE);
|
||||
|
||||
_dragSource = [[WebDragSource alloc] initWithHost:_host
|
||||
dropData:dropData
|
||||
sourceOrigin:sourceOrigin
|
||||
isPrivileged:isPrivileged];
|
||||
NSDraggingItem* draggingItem =
|
||||
[[NSDraggingItem alloc] initWithPasteboardWriter:_dragSource];
|
||||
|
@ -21,6 +21,10 @@ namespace remote_cocoa::mojom {
|
||||
class WebContentsNSViewHost;
|
||||
} // namespace remote_cocoa::mojom
|
||||
|
||||
namespace url {
|
||||
class Origin;
|
||||
}
|
||||
|
||||
// A class that handles managing the data for drags from the
|
||||
// WebContentsViewCocoa.
|
||||
CONTENT_EXPORT
|
||||
@ -29,6 +33,7 @@ CONTENT_EXPORT
|
||||
// Initialize a WebDragSource object for a drag.
|
||||
- (instancetype)initWithHost:(remote_cocoa::mojom::WebContentsNSViewHost*)host
|
||||
dropData:(const content::DropData&)dropData
|
||||
sourceOrigin:(const url::Origin&)sourceOrigin
|
||||
isPrivileged:(BOOL)privileged;
|
||||
|
||||
// Call when the WebContents is gone.
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "ui/base/clipboard/clipboard_constants.h"
|
||||
#include "ui/base/clipboard/custom_data_helper.h"
|
||||
#include "ui/base/cocoa/cocoa_base_utils.h"
|
||||
#include "url/origin.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
@implementation WebDragSource {
|
||||
@ -44,6 +45,9 @@
|
||||
// The drop data.
|
||||
content::DropData _dropData;
|
||||
|
||||
// The source origin the drop data came from.
|
||||
url::Origin _sourceOrigin;
|
||||
|
||||
// Whether to mark the drag as having come from a privileged WebContents.
|
||||
BOOL _privileged;
|
||||
|
||||
@ -60,10 +64,12 @@
|
||||
|
||||
- (instancetype)initWithHost:(remote_cocoa::mojom::WebContentsNSViewHost*)host
|
||||
dropData:(const content::DropData&)dropData
|
||||
sourceOrigin:(const url::Origin&)sourceOrigin
|
||||
isPrivileged:(BOOL)privileged {
|
||||
if ((self = [super init])) {
|
||||
_host = host;
|
||||
_dropData = dropData;
|
||||
_sourceOrigin = sourceOrigin;
|
||||
_privileged = privileged;
|
||||
}
|
||||
|
||||
@ -295,9 +301,15 @@
|
||||
return [NSData dataWithBytes:pickle.data() length:pickle.size()];
|
||||
}
|
||||
|
||||
// Source origin of the drop data.
|
||||
if ([type isEqualToString:ui::kUTTypeChromiumRendererInitiatedDrag]) {
|
||||
return _sourceOrigin.opaque()
|
||||
? [NSString string]
|
||||
: base::SysUTF8ToNSString(_sourceOrigin.Serialize());
|
||||
}
|
||||
|
||||
// Flavors used to tag.
|
||||
if ([type isEqualToString:ui::kUTTypeChromiumInitiatedDrag] ||
|
||||
[type isEqualToString:ui::kUTTypeChromiumRendererInitiatedDrag] ||
|
||||
[type isEqualToString:ui::kUTTypeChromiumPrivilegedInitiatedDrag]) {
|
||||
// The type _was_ promised and someone decided to call the bluff.
|
||||
return [NSData data];
|
||||
|
@ -8818,8 +8818,9 @@ void RenderFrameHostImpl::StartDragging(
|
||||
const gfx::Rect& drag_obj_rect_in_dip,
|
||||
blink::mojom::DragEventSourceInfoPtr event_info) {
|
||||
GetRenderWidgetHost()->StartDragging(
|
||||
std::move(drag_data), drag_operations_mask, unsafe_bitmap,
|
||||
cursor_offset_in_dip, drag_obj_rect_in_dip, std::move(event_info));
|
||||
std::move(drag_data), GetLastCommittedOrigin(), drag_operations_mask,
|
||||
unsafe_bitmap, cursor_offset_in_dip, drag_obj_rect_in_dip,
|
||||
std::move(event_info));
|
||||
}
|
||||
|
||||
void RenderFrameHostImpl::CreateNewPopupWidget(
|
||||
|
@ -33,6 +33,10 @@ class OverscrollRefreshHandler;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace url {
|
||||
class Origin;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class RenderFrameHost;
|
||||
class RenderWidgetHostImpl;
|
||||
@ -80,6 +84,7 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
|
||||
// `blink::DragController::StartDrag()`.
|
||||
virtual void StartDragging(
|
||||
const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -98,6 +98,7 @@ class MockDraggingRenderViewHostDelegateView
|
||||
public:
|
||||
~MockDraggingRenderViewHostDelegateView() override {}
|
||||
void StartDragging(const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -2697,6 +2697,7 @@ void RenderWidgetHostImpl::UpdateBrowserControlsState(
|
||||
|
||||
void RenderWidgetHostImpl::StartDragging(
|
||||
blink::mojom::DragDataPtr drag_data,
|
||||
const url::Origin& source_origin,
|
||||
DragOperationsMask drag_operations_mask,
|
||||
const SkBitmap& bitmap,
|
||||
const gfx::Vector2d& cursor_offset_in_dip,
|
||||
@ -2782,8 +2783,8 @@ void RenderWidgetHostImpl::StartDragging(
|
||||
scaled_rect.Scale(scale);
|
||||
rect = gfx::ToRoundedRect(scaled_rect);
|
||||
#endif
|
||||
view->StartDragging(filtered_data, drag_operations_mask, image, offset, rect,
|
||||
*event_info, this);
|
||||
view->StartDragging(filtered_data, source_origin, drag_operations_mask, image,
|
||||
offset, rect, *event_info, this);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -909,6 +909,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
|
||||
bool animate);
|
||||
|
||||
void StartDragging(blink::mojom::DragDataPtr drag_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask drag_operations_mask,
|
||||
const SkBitmap& unsafe_bitmap,
|
||||
const gfx::Vector2d& cursor_offset_in_dip,
|
||||
|
@ -276,6 +276,7 @@ class MockRenderViewHostDelegateView : public RenderViewHostDelegateView {
|
||||
|
||||
// RenderViewHostDelegateView:
|
||||
void StartDragging(const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
@ -2139,7 +2140,7 @@ TEST_F(RenderWidgetHostTest, RendererExitedNoDrag) {
|
||||
DropDataToDragData(
|
||||
drop_data, file_system_manager, process_->GetID(),
|
||||
ChromeBlobStorageContext::GetFor(process_->GetBrowserContext())),
|
||||
drag_operation, SkBitmap(), gfx::Vector2d(), gfx::Rect(),
|
||||
url::Origin(), drag_operation, SkBitmap(), gfx::Vector2d(), gfx::Rect(),
|
||||
blink::mojom::DragEventSourceInfo::New());
|
||||
EXPECT_EQ(delegate_->mock_delegate_view()->start_dragging_count(), 1);
|
||||
|
||||
@ -2150,7 +2151,7 @@ TEST_F(RenderWidgetHostTest, RendererExitedNoDrag) {
|
||||
DropDataToDragData(
|
||||
drop_data, file_system_manager, process_->GetID(),
|
||||
ChromeBlobStorageContext::GetFor(process_->GetBrowserContext())),
|
||||
drag_operation, SkBitmap(), gfx::Vector2d(), gfx::Rect(),
|
||||
url::Origin(), drag_operation, SkBitmap(), gfx::Vector2d(), gfx::Rect(),
|
||||
blink::mojom::DragEventSourceInfo::New());
|
||||
EXPECT_EQ(delegate_->mock_delegate_view()->start_dragging_count(), 1);
|
||||
}
|
||||
|
@ -353,6 +353,7 @@ void WebContentsViewAndroid::ShowPopupMenu(
|
||||
|
||||
void WebContentsViewAndroid::StartDragging(
|
||||
const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -102,6 +102,7 @@ class WebContentsViewAndroid : public WebContentsView,
|
||||
bool allow_multiple_selection) override;
|
||||
ui::OverscrollRefreshHandler* GetOverscrollRefreshHandler() const override;
|
||||
void StartDragging(const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -252,9 +252,10 @@ const ui::ClipboardFormatType& GetFileSystemFileFormatType() {
|
||||
|
||||
// Utility to fill a ui::OSExchangeDataProvider object from DropData.
|
||||
void PrepareDragData(const DropData& drop_data,
|
||||
const url::Origin source_origin,
|
||||
ui::OSExchangeDataProvider* provider,
|
||||
WebContentsImpl* web_contents) {
|
||||
provider->MarkOriginatedFromRenderer();
|
||||
provider->MarkRendererTaintedFromOrigin(source_origin);
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Put download before file contents to prefer the download of a image over
|
||||
// its thumbnail link.
|
||||
@ -698,7 +699,15 @@ void WebContentsViewAura::SetDelegateForTesting(
|
||||
void WebContentsViewAura::PrepareDropData(
|
||||
DropData* drop_data,
|
||||
const ui::OSExchangeData& data) const {
|
||||
drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// TODO(b/256022714): Using `IsRendererTainted()` breaks the Files app. Always
|
||||
// setting this to false is currently believed to be safe-ish because ChromeOS
|
||||
// separates URL and filename metadata and does not implement the DownloadURL
|
||||
// protocol.
|
||||
drop_data->did_originate_from_renderer = false;
|
||||
#else
|
||||
drop_data->did_originate_from_renderer = data.IsRendererTainted();
|
||||
#endif
|
||||
drop_data->is_from_privileged = data.IsFromPrivileged();
|
||||
|
||||
std::u16string plain_text;
|
||||
@ -1147,6 +1156,7 @@ void WebContentsViewAura::ShowContextMenu(RenderFrameHost& render_frame_host,
|
||||
|
||||
void WebContentsViewAura::StartDragging(
|
||||
const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask operations,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
@ -1180,7 +1190,7 @@ void WebContentsViewAura::StartDragging(
|
||||
selection_controller->HideAndDisallowShowingAutomatically();
|
||||
std::unique_ptr<ui::OSExchangeDataProvider> provider =
|
||||
ui::OSExchangeDataProviderFactory::CreateProvider();
|
||||
PrepareDragData(drop_data, provider.get(), web_contents_);
|
||||
PrepareDragData(drop_data, source_origin, provider.get(), web_contents_);
|
||||
|
||||
auto data = std::make_unique<ui::OSExchangeData>(std::move(provider));
|
||||
data->SetSource(
|
||||
|
@ -39,6 +39,10 @@ class DropTargetEvent;
|
||||
class TouchSelectionController;
|
||||
}
|
||||
|
||||
namespace url {
|
||||
class Origin;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class GestureNavSimple;
|
||||
class RenderWidgetHostImpl;
|
||||
@ -211,6 +215,7 @@ class CONTENT_EXPORT WebContentsViewAura
|
||||
void ShowContextMenu(RenderFrameHost& render_frame_host,
|
||||
const ContextMenuParams& params) override;
|
||||
void StartDragging(const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask operations,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "ui/display/display_switches.h"
|
||||
#include "ui/events/base_event_utils.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
|
||||
@ -387,7 +388,7 @@ TEST_F(WebContentsViewAuraTest, MAYBE_DragDropFilesOriginateFromRenderer) {
|
||||
// Simulate the drag originating in the renderer process, in which case
|
||||
// any file data should be filtered out (anchor drag scenario) except in
|
||||
// CHROMEOS_ASH.
|
||||
data->MarkOriginatedFromRenderer();
|
||||
data->MarkRendererTaintedFromOrigin(url::Origin());
|
||||
|
||||
ui::DropTargetEvent event(*data.get(), kClientPt, kScreenPt,
|
||||
ui::DragDropTypes::DRAG_COPY);
|
||||
@ -407,7 +408,6 @@ TEST_F(WebContentsViewAuraTest, MAYBE_DragDropFilesOriginateFromRenderer) {
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// CHROMEOS_ASH always returns false for DidOriginateFromRenderer().
|
||||
ASSERT_FALSE(view->current_drag_data_->filenames.empty());
|
||||
#else
|
||||
ASSERT_TRUE(view->current_drag_data_->filenames.empty());
|
||||
@ -440,7 +440,8 @@ TEST_F(WebContentsViewAuraTest, MAYBE_DragDropFilesOriginateFromRenderer) {
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// CHROMEOS_ASH always returns false for DidOriginateFromRenderer().
|
||||
// CHROMEOS_ASH never filters out files from a drop, even if the drag
|
||||
// originated from a renderer, because otherwise, it breaks the Files app.
|
||||
ASSERT_FALSE(drop_complete_data_->drop_data.filenames.empty());
|
||||
#else
|
||||
ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty());
|
||||
@ -483,7 +484,7 @@ TEST_F(WebContentsViewAuraTest, MAYBE_DragDropImageFromRenderer) {
|
||||
data->SetFileContents(filename, file_contents);
|
||||
data->SetURL(url, url_title);
|
||||
data->SetHtml(html, GURL());
|
||||
data->MarkOriginatedFromRenderer();
|
||||
data->MarkRendererTaintedFromOrigin(url::Origin());
|
||||
|
||||
ui::DropTargetEvent event(*data.get(), kClientPt, kScreenPt,
|
||||
ui::DragDropTypes::DRAG_COPY);
|
||||
@ -642,7 +643,7 @@ TEST_F(WebContentsViewAuraTest, DragDropVirtualFilesOriginateFromRenderer) {
|
||||
|
||||
// Simulate the drag originating in the renderer process, in which case
|
||||
// any file data should be filtered out (anchor drag scenario).
|
||||
data->MarkOriginatedFromRenderer();
|
||||
data->MarkRendererTaintedFromOrigin(url::Origin());
|
||||
|
||||
ui::DropTargetEvent event(*data.get(), kClientPt, kScreenPt,
|
||||
ui::DragDropTypes::DRAG_COPY);
|
||||
@ -682,7 +683,7 @@ TEST_F(WebContentsViewAuraTest, DragDropVirtualFilesOriginateFromRenderer) {
|
||||
TEST_F(WebContentsViewAuraTest, DragDropUrlData) {
|
||||
WebContentsViewAura* view = GetView();
|
||||
auto data = std::make_unique<ui::OSExchangeData>();
|
||||
data->MarkOriginatedFromRenderer();
|
||||
data->MarkRendererTaintedFromOrigin(url::Origin());
|
||||
|
||||
const std::string url_spec = "https://www.wikipedia.org/";
|
||||
const GURL url(url_spec);
|
||||
@ -761,7 +762,8 @@ TEST_F(WebContentsViewAuraTest, StartDragging) {
|
||||
|
||||
DropData drop_data;
|
||||
drop_data.text.emplace(u"Hello World!");
|
||||
view->StartDragging(drop_data, blink::DragOperationsMask::kDragOperationNone,
|
||||
view->StartDragging(drop_data, url::Origin(),
|
||||
blink::DragOperationsMask::kDragOperationNone,
|
||||
gfx::ImageSkia(), gfx::Vector2d(), gfx::Rect(),
|
||||
blink::mojom::DragEventSourceInfo(),
|
||||
RenderWidgetHostImpl::From(rvh()->GetWidget()));
|
||||
@ -832,7 +834,8 @@ TEST_F(WebContentsViewAuraTest, StartDragFromPrivilegedWebContents) {
|
||||
view->drag_in_progress_ = true;
|
||||
|
||||
DropData drop_data;
|
||||
view->StartDragging(drop_data, blink::DragOperationsMask::kDragOperationNone,
|
||||
view->StartDragging(drop_data, url::Origin(),
|
||||
blink::DragOperationsMask::kDragOperationNone,
|
||||
gfx::ImageSkia(), gfx::Vector2d(), gfx::Rect(),
|
||||
blink::mojom::DragEventSourceInfo(),
|
||||
RenderWidgetHostImpl::From(rvh()->GetWidget()));
|
||||
|
@ -203,6 +203,7 @@ void WebContentsViewChildFrame::ShowPopupMenu(
|
||||
|
||||
void WebContentsViewChildFrame::StartDragging(
|
||||
const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
DragOperationsMask ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
@ -210,8 +211,8 @@ void WebContentsViewChildFrame::StartDragging(
|
||||
const blink::mojom::DragEventSourceInfo& event_info,
|
||||
RenderWidgetHostImpl* source_rwh) {
|
||||
if (auto* view = GetOuterDelegateView()) {
|
||||
view->StartDragging(drop_data, ops, image, cursor_offset, drag_obj_rect,
|
||||
event_info, source_rwh);
|
||||
view->StartDragging(drop_data, source_origin, ops, image, cursor_offset,
|
||||
drag_obj_rect, event_info, source_rwh);
|
||||
} else {
|
||||
web_contents_->GetOuterWebContents()->SystemDragEnded(source_rwh);
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ class WebContentsViewChildFrame : public WebContentsView,
|
||||
void ShowContextMenu(RenderFrameHost& render_frame_host,
|
||||
const ContextMenuParams& params) override;
|
||||
void StartDragging(const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_ops,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -94,6 +94,7 @@ class WebContentsViewMac : public WebContentsView,
|
||||
|
||||
// RenderViewHostDelegateView:
|
||||
void StartDragging(const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
blink::DragOperationsMask allowed_operations,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
|
@ -156,6 +156,7 @@ void WebContentsViewMac::UpdateWindowControlsOverlay(
|
||||
|
||||
void WebContentsViewMac::StartDragging(
|
||||
const DropData& drop_data,
|
||||
const url::Origin& source_origin,
|
||||
DragOperationsMask allowed_operations,
|
||||
const gfx::ImageSkia& image,
|
||||
const gfx::Vector2d& cursor_offset,
|
||||
@ -183,11 +184,11 @@ void WebContentsViewMac::StartDragging(
|
||||
// TODO(crbug.com/1302094): The param `drag_obj_rect` is unused.
|
||||
|
||||
if (remote_ns_view_) {
|
||||
remote_ns_view_->StartDrag(drop_data, mask, image, cursor_offset,
|
||||
is_privileged);
|
||||
remote_ns_view_->StartDrag(drop_data, source_origin, mask, image,
|
||||
cursor_offset, is_privileged);
|
||||
} else {
|
||||
in_process_ns_view_bridge_->StartDrag(drop_data, mask, image, cursor_offset,
|
||||
is_privileged);
|
||||
in_process_ns_view_bridge_->StartDrag(drop_data, source_origin, mask, image,
|
||||
cursor_offset, is_privileged);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "content/public/common/drop_data.h"
|
||||
#include "content/public/test/test_renderer_host.h"
|
||||
#include "testing/gtest_mac.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
@ -19,6 +20,7 @@ TEST_F(WebDragSourceMacTest, DragInvalidlyEscapedBookmarklet) {
|
||||
|
||||
WebDragSource* source = [[WebDragSource alloc] initWithHost:nullptr
|
||||
dropData:drop_data
|
||||
sourceOrigin:url::Origin()
|
||||
isPrivileged:NO];
|
||||
|
||||
// Test that asking for the data of an invalidly-escaped URL doesn't throw any
|
||||
|
@ -8,6 +8,7 @@ import "content/public/common/drop_data.mojom";
|
||||
import "mojo/public/mojom/base/file_path.mojom";
|
||||
import "ui/gfx/geometry/mojom/geometry.mojom";
|
||||
import "ui/gfx/image/mojom/image.mojom";
|
||||
import "url/mojom/origin.mojom";
|
||||
import "url/mojom/url.mojom";
|
||||
|
||||
// Interface through which a WebContentsViewMac communicates with its NSView in
|
||||
@ -42,6 +43,7 @@ interface WebContentsNSView {
|
||||
// to whether the WebContents initiating the drag is being used to implement
|
||||
// a UI surface. See `WebContentsDelegate::IsPrivileged()` for more context.
|
||||
StartDrag(content.mojom.DropData drop_data,
|
||||
url.mojom.Origin source_origin,
|
||||
uint32 operation_mask,
|
||||
gfx.mojom.ImageSkia? image,
|
||||
gfx.mojom.Vector2d image_offset,
|
||||
|
@ -91,7 +91,15 @@ COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
|
||||
extern NSString* const kUTTypeChromiumPrivilegedInitiatedDrag;
|
||||
|
||||
// Data type placed on dragging pasteboards when the drag is initiated from a
|
||||
// renderer. There is never any data associated with this type.
|
||||
// renderer. If the initiator has a tuple origin (e.g. https://example.com),
|
||||
// the data is a string representation (i.e. the result of calling
|
||||
// `url::Origin::Serialize()`). Otherwise, the initiator has an opaque origin
|
||||
// and the data is the empty string.
|
||||
//
|
||||
// This format is intentionally chosen for safer backwards compatibility with
|
||||
// previous versions of Chrome, which always set an empty string for the data.
|
||||
// When newer versions of Chrome attempt to interpret this data as an origin,
|
||||
// they will safely treat it as a unique opaque origin.
|
||||
COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
|
||||
extern NSString* const kUTTypeChromiumRendererInitiatedDrag;
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "ui/base/clipboard/clipboard_format_type.h"
|
||||
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
|
||||
#include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -27,12 +27,16 @@ OSExchangeData::OSExchangeData(std::unique_ptr<OSExchangeDataProvider> provider)
|
||||
OSExchangeData::~OSExchangeData() {
|
||||
}
|
||||
|
||||
void OSExchangeData::MarkOriginatedFromRenderer() {
|
||||
provider_->MarkOriginatedFromRenderer();
|
||||
void OSExchangeData::MarkRendererTaintedFromOrigin(const url::Origin& origin) {
|
||||
provider_->MarkRendererTaintedFromOrigin(origin);
|
||||
}
|
||||
|
||||
bool OSExchangeData::DidOriginateFromRenderer() const {
|
||||
return provider_->DidOriginateFromRenderer();
|
||||
bool OSExchangeData::IsRendererTainted() const {
|
||||
return provider_->IsRendererTainted();
|
||||
}
|
||||
|
||||
absl::optional<url::Origin> OSExchangeData::GetRendererTaintedOrigin() const {
|
||||
return provider_->GetRendererTaintedOrigin();
|
||||
}
|
||||
|
||||
void OSExchangeData::MarkAsFromPrivileged() {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/base/dragdrop/os_exchange_data_provider.h"
|
||||
|
||||
class GURL;
|
||||
@ -24,6 +25,10 @@ namespace base {
|
||||
class Pickle;
|
||||
}
|
||||
|
||||
namespace url {
|
||||
class Origin;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ClipboardFormatType;
|
||||
@ -75,11 +80,14 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData {
|
||||
const OSExchangeDataProvider& provider() const { return *provider_; }
|
||||
OSExchangeDataProvider& provider() { return *provider_; }
|
||||
|
||||
// Marks drag data as tainted if it originates from the renderer. This is used
|
||||
// to avoid granting privileges to a renderer when dragging in tainted data,
|
||||
// since it could allow potential escalation of privileges.
|
||||
void MarkOriginatedFromRenderer();
|
||||
bool DidOriginateFromRenderer() const;
|
||||
// Marks drag data as tainted by the renderer, with `origin` as the source of
|
||||
// the data. This is used to:
|
||||
// - avoid granting privileges to a renderer when dragging in tainted data,
|
||||
// since it could allow potential escalation of privileges.
|
||||
// - track the origin where the drag data came from.
|
||||
void MarkRendererTaintedFromOrigin(const url::Origin& origin);
|
||||
bool IsRendererTainted() const;
|
||||
absl::optional<url::Origin> GetRendererTaintedOrigin() const;
|
||||
|
||||
// Marks drag data as from privileged WebContents. This is used to
|
||||
// make sure non-privileged WebContents will not accept drop data from
|
||||
|
@ -13,11 +13,13 @@
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/base/clipboard/clipboard_format_type.h"
|
||||
#include "ui/base/clipboard/file_info.h"
|
||||
#include "ui/base/dragdrop/download_file_info.h"
|
||||
#include "ui/base/dragdrop/download_file_interface.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "base/functional/callback_forward.h"
|
||||
@ -48,8 +50,9 @@ class COMPONENT_EXPORT(UI_BASE_DATA_EXCHANGE) OSExchangeDataProvider {
|
||||
|
||||
virtual std::unique_ptr<OSExchangeDataProvider> Clone() const = 0;
|
||||
|
||||
virtual void MarkOriginatedFromRenderer() = 0;
|
||||
virtual bool DidOriginateFromRenderer() const = 0;
|
||||
virtual void MarkRendererTaintedFromOrigin(const url::Origin& origin) = 0;
|
||||
virtual bool IsRendererTainted() const = 0;
|
||||
virtual absl::optional<url::Origin> GetRendererTaintedOrigin() const = 0;
|
||||
|
||||
virtual void MarkAsFromPrivileged() = 0;
|
||||
virtual bool IsFromPrivileged() const = 0;
|
||||
|
@ -37,8 +37,9 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderMac
|
||||
CreateProviderWrappingPasteboard(NSPasteboard* pasteboard);
|
||||
|
||||
// Overridden from OSExchangeDataProvider:
|
||||
void MarkOriginatedFromRenderer() override;
|
||||
bool DidOriginateFromRenderer() const override;
|
||||
void MarkRendererTaintedFromOrigin(const url::Origin& origin) override;
|
||||
bool IsRendererTainted() const override;
|
||||
absl::optional<url::Origin> GetRendererTaintedOrigin() const override;
|
||||
void MarkAsFromPrivileged() override;
|
||||
bool IsFromPrivileged() const override;
|
||||
void SetString(const std::u16string& data) override;
|
||||
|
@ -135,16 +135,35 @@ OSExchangeDataProviderMac::CreateProviderWrappingPasteboard(
|
||||
return std::make_unique<WrappingProvider>(pasteboard);
|
||||
}
|
||||
|
||||
void OSExchangeDataProviderMac::MarkOriginatedFromRenderer() {
|
||||
[GetPasteboard() setData:[NSData data]
|
||||
forType:kUTTypeChromiumRendererInitiatedDrag];
|
||||
void OSExchangeDataProviderMac::MarkRendererTaintedFromOrigin(
|
||||
const url::Origin& origin) {
|
||||
NSString* string = origin.opaque()
|
||||
? [NSString string]
|
||||
: base::SysUTF8ToNSString(origin.Serialize());
|
||||
[GetPasteboard() setString:string
|
||||
forType:kUTTypeChromiumRendererInitiatedDrag];
|
||||
}
|
||||
|
||||
bool OSExchangeDataProviderMac::DidOriginateFromRenderer() const {
|
||||
bool OSExchangeDataProviderMac::IsRendererTainted() const {
|
||||
return [GetPasteboard().types
|
||||
containsObject:kUTTypeChromiumRendererInitiatedDrag];
|
||||
}
|
||||
|
||||
absl::optional<url::Origin>
|
||||
OSExchangeDataProviderMac::GetRendererTaintedOrigin() const {
|
||||
NSString* item =
|
||||
[GetPasteboard() stringForType:kUTTypeChromiumRendererInitiatedDrag];
|
||||
if (!item) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
if (0 == [item length]) {
|
||||
return url::Origin();
|
||||
}
|
||||
|
||||
return url::Origin::Create(GURL(base::SysNSStringToUTF8(item)));
|
||||
}
|
||||
|
||||
void OSExchangeDataProviderMac::MarkAsFromPrivileged() {
|
||||
[GetPasteboard() setData:[NSData data]
|
||||
forType:kUTTypeChromiumPrivilegedInitiatedDrag];
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.h"
|
||||
#include "net/base/filename_util.h"
|
||||
#include "ui/base/clipboard/clipboard_format_type.h"
|
||||
@ -33,20 +32,23 @@ std::unique_ptr<OSExchangeDataProvider> OSExchangeDataProviderNonBacked::Clone()
|
||||
return clone;
|
||||
}
|
||||
|
||||
void OSExchangeDataProviderNonBacked::MarkOriginatedFromRenderer() {
|
||||
// TODO(dcheng): Currently unneeded because ChromeOS Aura correctly separates
|
||||
// URL and filename metadata, and does not implement the DownloadURL protocol.
|
||||
#if !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
originated_from_renderer_ = true;
|
||||
#endif
|
||||
void OSExchangeDataProviderNonBacked::MarkRendererTaintedFromOrigin(
|
||||
const url::Origin& origin) {
|
||||
tainted_by_renderer_origin_ = origin;
|
||||
}
|
||||
|
||||
bool OSExchangeDataProviderNonBacked::DidOriginateFromRenderer() const {
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
return false;
|
||||
#else
|
||||
return originated_from_renderer_;
|
||||
#endif
|
||||
bool OSExchangeDataProviderNonBacked::IsRendererTainted() const {
|
||||
return tainted_by_renderer_origin_.has_value();
|
||||
}
|
||||
|
||||
absl::optional<url::Origin>
|
||||
OSExchangeDataProviderNonBacked::GetRendererTaintedOrigin() const {
|
||||
// Platform-specific implementations of OSExchangeDataProvider do not
|
||||
// roundtrip opaque origins, so match that behavior here.
|
||||
if (tainted_by_renderer_origin_ && tainted_by_renderer_origin_->opaque()) {
|
||||
return url::Origin();
|
||||
}
|
||||
return tainted_by_renderer_origin_;
|
||||
}
|
||||
|
||||
void OSExchangeDataProviderNonBacked::MarkAsFromPrivileged() {
|
||||
@ -280,10 +282,8 @@ void OSExchangeDataProviderNonBacked::CopyData(
|
||||
provider->source_ =
|
||||
source_ ? std::make_unique<DataTransferEndpoint>(*source_.get())
|
||||
: nullptr;
|
||||
provider->tainted_by_renderer_origin_ = tainted_by_renderer_origin_;
|
||||
provider->is_from_privileged_ = is_from_privileged_;
|
||||
#if !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
provider->originated_from_renderer_ = originated_from_renderer_;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -10,13 +10,14 @@
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/pickle.h"
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/base/clipboard/file_info.h"
|
||||
#include "ui/base/dragdrop/os_exchange_data_provider.h"
|
||||
#include "ui/gfx/geometry/vector2d.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
@ -41,8 +42,9 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked
|
||||
|
||||
// Overridden from OSExchangeDataProvider:
|
||||
std::unique_ptr<OSExchangeDataProvider> Clone() const override;
|
||||
void MarkOriginatedFromRenderer() override;
|
||||
bool DidOriginateFromRenderer() const override;
|
||||
void MarkRendererTaintedFromOrigin(const url::Origin& origin) override;
|
||||
bool IsRendererTainted() const override;
|
||||
absl::optional<url::Origin> GetRendererTaintedOrigin() const override;
|
||||
void MarkAsFromPrivileged() override;
|
||||
bool IsFromPrivileged() const override;
|
||||
void SetString(const std::u16string& data) override;
|
||||
@ -125,10 +127,8 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked
|
||||
std::u16string html_;
|
||||
GURL base_url_;
|
||||
|
||||
#if !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// For marking data originating from the renderer.
|
||||
bool originated_from_renderer_ = false;
|
||||
#endif
|
||||
absl::optional<url::Origin> tainted_by_renderer_origin_;
|
||||
|
||||
// For marking data originating by privileged WebContents.
|
||||
bool is_from_privileged_ = false;
|
||||
|
@ -45,9 +45,7 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) {
|
||||
original.SetFileContents(base::FilePath(kFileContentsFileName),
|
||||
std::string(kFileContents));
|
||||
original.SetHtml(kHtml, GURL(kBaseUrl));
|
||||
#if !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
original.MarkOriginatedFromRenderer();
|
||||
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
original.MarkRendererTaintedFromOrigin(url::Origin());
|
||||
GURL url("www.example.com");
|
||||
original.SetSource(std::make_unique<DataTransferEndpoint>(url));
|
||||
|
||||
@ -82,9 +80,7 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) {
|
||||
EXPECT_EQ(kHtml, copy_html);
|
||||
EXPECT_EQ(GURL(kBaseUrl), copy_base_url);
|
||||
|
||||
#if !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
EXPECT_TRUE(copy->DidOriginateFromRenderer());
|
||||
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
EXPECT_TRUE(copy->IsRendererTainted());
|
||||
|
||||
DataTransferEndpoint* data_endpoint = copy->GetSource();
|
||||
EXPECT_TRUE(data_endpoint);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "base/win/shlwapi.h"
|
||||
#include "net/base/filename_util.h"
|
||||
#include "skia/ext/skia_utils_win.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/base/clipboard/clipboard_format_type.h"
|
||||
#include "ui/base/clipboard/clipboard_util_win.h"
|
||||
@ -43,6 +44,7 @@
|
||||
#include "ui/gfx/skbitmap_operations.h"
|
||||
#include "ui/strings/grit/ui_strings.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -295,16 +297,32 @@ std::unique_ptr<OSExchangeDataProvider> OSExchangeDataProviderWin::Clone()
|
||||
return std::make_unique<OSExchangeDataProviderWin>(data_object());
|
||||
}
|
||||
|
||||
void OSExchangeDataProviderWin::MarkOriginatedFromRenderer() {
|
||||
STGMEDIUM storage = CreateStorageForString(std::string());
|
||||
void OSExchangeDataProviderWin::MarkRendererTaintedFromOrigin(
|
||||
const url::Origin& origin) {
|
||||
STGMEDIUM storage = CreateStorageForString(
|
||||
origin.opaque() ? std::string() : origin.Serialize());
|
||||
data_->contents_.push_back(DataObjectImpl::StoredDataInfo::TakeStorageMedium(
|
||||
GetRendererTaintFormatType().ToFormatEtc(), storage));
|
||||
}
|
||||
|
||||
bool OSExchangeDataProviderWin::DidOriginateFromRenderer() const {
|
||||
bool OSExchangeDataProviderWin::IsRendererTainted() const {
|
||||
return HasCustomFormat(GetRendererTaintFormatType());
|
||||
}
|
||||
|
||||
absl::optional<url::Origin>
|
||||
OSExchangeDataProviderWin::GetRendererTaintedOrigin() const {
|
||||
STGMEDIUM medium;
|
||||
FORMATETC format_etc = GetRendererTaintFormatType().ToFormatEtc();
|
||||
if (FAILED(source_object_->GetData(&format_etc, &medium))) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
base::win::ScopedHGlobal<char*> data(medium.hGlobal);
|
||||
if (data.Size() == 0) {
|
||||
return url::Origin();
|
||||
}
|
||||
return url::Origin::Create(GURL(base::StringPiece(data.get(), data.Size())));
|
||||
}
|
||||
|
||||
void OSExchangeDataProviderWin::MarkAsFromPrivileged() {
|
||||
STGMEDIUM storage = CreateStorageForString(std::string());
|
||||
data_->contents_.push_back(DataObjectImpl::StoredDataInfo::TakeStorageMedium(
|
||||
|
@ -147,8 +147,9 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderWin
|
||||
|
||||
// OSExchangeDataProvider methods.
|
||||
std::unique_ptr<OSExchangeDataProvider> Clone() const override;
|
||||
void MarkOriginatedFromRenderer() override;
|
||||
bool DidOriginateFromRenderer() const override;
|
||||
void MarkRendererTaintedFromOrigin(const url::Origin& origin) override;
|
||||
bool IsRendererTainted() const override;
|
||||
absl::optional<url::Origin> GetRendererTaintedOrigin() const override;
|
||||
void MarkAsFromPrivileged() override;
|
||||
bool IsFromPrivileged() const override;
|
||||
void SetString(const std::u16string& data) override;
|
||||
|
@ -237,4 +237,53 @@ TEST_F(OSExchangeDataTest, TestHTML) {
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(OSExchangeDataTest, NotRendererTainted) {
|
||||
const OSExchangeData copy([&] {
|
||||
OSExchangeData data;
|
||||
return data.provider().Clone();
|
||||
}());
|
||||
|
||||
EXPECT_FALSE(copy.IsRendererTainted());
|
||||
EXPECT_EQ(absl::nullopt, copy.GetRendererTaintedOrigin());
|
||||
}
|
||||
|
||||
TEST_F(OSExchangeDataTest, RendererTaintedOpaqueOrigin) {
|
||||
const url::Origin tuple_origin =
|
||||
url::Origin::Create(GURL("https://www.google.com/"));
|
||||
const url::Origin opaque_origin = tuple_origin.DeriveNewOpaqueOrigin();
|
||||
ASSERT_TRUE(opaque_origin.opaque());
|
||||
|
||||
const OSExchangeData copy([&] {
|
||||
OSExchangeData data;
|
||||
data.MarkRendererTaintedFromOrigin(opaque_origin);
|
||||
return data.provider().Clone();
|
||||
}());
|
||||
|
||||
EXPECT_TRUE(copy.IsRendererTainted());
|
||||
absl::optional<url::Origin> origin = copy.GetRendererTaintedOrigin();
|
||||
EXPECT_TRUE(origin.has_value());
|
||||
EXPECT_TRUE(origin->opaque());
|
||||
// Currently, the actual value of an opaque origin is not actually serialized
|
||||
// into OSExchangeData, so expect a random opaque origin to be read out.
|
||||
EXPECT_NE(opaque_origin, origin);
|
||||
// And there should be no precursor tuple.
|
||||
EXPECT_FALSE(origin->GetTupleOrPrecursorTupleIfOpaque().IsValid());
|
||||
}
|
||||
|
||||
TEST_F(OSExchangeDataTest, RendererTaintedTupleOrigin) {
|
||||
const url::Origin tuple_origin =
|
||||
url::Origin::Create(GURL("https://www.google.com/"));
|
||||
|
||||
const OSExchangeData copy([&] {
|
||||
OSExchangeData data;
|
||||
data.MarkRendererTaintedFromOrigin(tuple_origin);
|
||||
return data.provider().Clone();
|
||||
}());
|
||||
|
||||
EXPECT_TRUE(copy.IsRendererTainted());
|
||||
absl::optional<url::Origin> origin = copy.GetRendererTaintedOrigin();
|
||||
EXPECT_TRUE(origin.has_value());
|
||||
EXPECT_EQ(tuple_origin, origin);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -85,17 +85,35 @@ std::unique_ptr<OSExchangeDataProvider> XOSExchangeDataProvider::Clone() const {
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
void XOSExchangeDataProvider::MarkOriginatedFromRenderer() {
|
||||
format_map_.Insert(
|
||||
x11::GetAtom(kRendererTaint),
|
||||
scoped_refptr<base::RefCountedMemory>(
|
||||
base::MakeRefCounted<base::RefCountedString>(std::string())));
|
||||
void XOSExchangeDataProvider::MarkRendererTaintedFromOrigin(
|
||||
const url::Origin& origin) {
|
||||
format_map_.Insert(x11::GetAtom(kRendererTaint),
|
||||
base::MakeRefCounted<base::RefCountedString>(
|
||||
origin.opaque() ? std::string() : origin.Serialize()));
|
||||
}
|
||||
|
||||
bool XOSExchangeDataProvider::DidOriginateFromRenderer() const {
|
||||
bool XOSExchangeDataProvider::IsRendererTainted() const {
|
||||
return format_map_.find(x11::GetAtom(kRendererTaint)) != format_map_.end();
|
||||
}
|
||||
|
||||
absl::optional<url::Origin> XOSExchangeDataProvider::GetRendererTaintedOrigin()
|
||||
const {
|
||||
auto it = format_map_.find(x11::GetAtom(kRendererTaint));
|
||||
|
||||
if (it == format_map_.end()) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
ui::SelectionData data(it->first, it->second);
|
||||
std::string data_as_string;
|
||||
data.AssignTo(&data_as_string);
|
||||
if (data_as_string.empty()) {
|
||||
return url::Origin();
|
||||
}
|
||||
|
||||
return url::Origin::Create(GURL(data_as_string));
|
||||
}
|
||||
|
||||
void XOSExchangeDataProvider::MarkAsFromPrivileged() {
|
||||
format_map_.Insert(
|
||||
x11::GetAtom(kFromPrivileged),
|
||||
|
@ -62,8 +62,9 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider
|
||||
|
||||
// Overridden from OSExchangeDataProvider:
|
||||
std::unique_ptr<OSExchangeDataProvider> Clone() const override;
|
||||
void MarkOriginatedFromRenderer() override;
|
||||
bool DidOriginateFromRenderer() const override;
|
||||
void MarkRendererTaintedFromOrigin(const url::Origin& origin) override;
|
||||
bool IsRendererTainted() const override;
|
||||
absl::optional<url::Origin> GetRendererTaintedOrigin() const override;
|
||||
void MarkAsFromPrivileged() override;
|
||||
bool IsFromPrivileged() const override;
|
||||
void SetString(const std::u16string& data) override;
|
||||
|
Reference in New Issue
Block a user