Commit 0678253f authored by paulmeyer's avatar paulmeyer Committed by Commit bot

Prevent drag-and-drop events from firing over cross-site, same-page

frames.

This is a follow-up to https://codereview.chromium.org/2568893002/,
enabling the same behavior on Mac.

Review-Url: https://codereview.chromium.org/2580843003
Cr-Commit-Position: refs/heads/master@{#438911}
parent 08525f40
......@@ -549,6 +549,7 @@ void WebContentsViewMac::CloseTab() {
offset:(NSPoint)offset {
if (![self webContents])
return;
[dragDest_ setDragStartTrackersForProcess:sourceRWH->GetProcess()->GetID()];
dragSource_.reset([[WebDragSource alloc]
initWithContents:[self webContents]
view:self
......
......@@ -7,6 +7,7 @@
#include <memory>
#include "base/strings/string16.h"
#include "content/browser/loader/global_routing_id.h"
#include "content/common/content_export.h"
#include "content/public/common/drop_data.h"
#include "ui/gfx/geometry/point.h"
......@@ -44,6 +45,15 @@ CONTENT_EXPORT
// during a drag, we need to re-send the DragEnter message.
RenderViewHostIdentifier currentRVH_;
// Tracks the IDs of the source RenderProcessHost and RenderViewHost from
// which the current drag originated. These are set in
// -setDragStartTrackersForProcess:, and are used to ensure that drag events
// do not fire over a cross-site frame (with respect to the source frame) in
// the same page (see crbug.com/666858). See
// WebContentsViewAura::drag_start_process_id_ for additional information.
int dragStartProcessID_;
content::GlobalRoutingID dragStartViewID_;
// The data for the current drag, or NULL if none is in progress.
std::unique_ptr<content::DropData> dropData_;
......@@ -79,6 +89,14 @@ CONTENT_EXPORT
GetRenderWidgetHostAtPoint:(const NSPoint&)viewPoint
transformedPt:(gfx::Point*)transformedPt;
// Sets |dragStartProcessID_| and |dragStartViewID_|.
- (void)setDragStartTrackersForProcess:(int)processID;
// Returns whether |targetRWH| is a valid RenderWidgetHost to be dragging
// over. This enforces that same-page, cross-site drags are not allowed. See
// crbug.com/666858.
- (bool)isValidDragTarget:(content::RenderWidgetHostImpl*)targetRWH;
@end
// Public use only for unit tests.
......
......@@ -13,6 +13,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/drop_data.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
......@@ -57,6 +58,11 @@ int GetModifierFlags() {
return modifier_state;
}
content::GlobalRoutingID GetRenderViewHostID(content::RenderViewHost* rvh) {
return content::GlobalRoutingID(rvh->GetProcess()->GetID(),
rvh->GetRoutingID());
}
} // namespace
@implementation WebDragDest
......@@ -68,6 +74,9 @@ int GetModifierFlags() {
if ((self = [super init])) {
webContents_ = contents;
canceled_ = false;
dragStartProcessID_ = content::ChildProcessHost::kInvalidUniqueID;
dragStartViewID_ = content::GlobalRoutingID(
content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE);
}
return self;
}
......@@ -141,9 +150,13 @@ int GetModifierFlags() {
canceled_ = true;
return NSDragOperationNone;
}
currentRWHForDrag_ =
[self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt]
->GetWeakPtr();
content::RenderWidgetHostImpl* targetRWH =
[self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt];
if (![self isValidDragTarget:targetRWH])
return NSDragOperationNone;
currentRWHForDrag_ = targetRWH->GetWeakPtr();
// Fill out a DropData from pasteboard.
std::unique_ptr<DropData> dropData;
......@@ -224,6 +237,9 @@ int GetModifierFlags() {
content::RenderWidgetHostImpl* targetRWH =
[self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt];
if (![self isValidDragTarget:targetRWH])
return NSDragOperationNone;
// TODO(paulmeyer): The dragging delegates may now by invoked multiple times
// per drag, even without the drag ever leaving the window.
if (targetRWH != currentRWHForDrag_.get()) {
......@@ -263,6 +279,9 @@ int GetModifierFlags() {
content::RenderWidgetHostImpl* targetRWH =
[self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt];
if (![self isValidDragTarget:targetRWH])
return NO;
if (targetRWH != currentRWHForDrag_.get()) {
if (currentRWHForDrag_)
currentRWHForDrag_->DragTargetDragLeave();
......@@ -306,6 +325,17 @@ GetRenderWidgetHostAtPoint:(const NSPoint&)viewPoint
gfx::Point(viewPoint.x, viewPoint.y), transformedPt);
}
- (void)setDragStartTrackersForProcess:(int)processID {
dragStartProcessID_ = processID;
dragStartViewID_ = GetRenderViewHostID(webContents_->GetRenderViewHost());
}
- (bool)isValidDragTarget:(content::RenderWidgetHostImpl*)targetRWH {
return targetRWH->GetProcess()->GetID() == dragStartProcessID_ ||
GetRenderViewHostID(webContents_->GetRenderViewHost()) !=
dragStartViewID_;
}
// Given |data|, which should not be nil, fill it in using the contents of the
// given pasteboard. The types handled by this method should be kept in sync
// with [WebContentsViewCocoa registerDragTypes].
......
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