summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/web_contents/web_drag_dest_gtk.cc22
-rw-r--r--content/browser/web_contents/web_drag_dest_gtk.h3
-rw-r--r--content/browser/web_contents/web_drag_dest_mac.h3
-rw-r--r--content/browser/web_contents/web_drag_dest_mac.mm30
-rw-r--r--content/browser/web_contents/web_drag_dest_win.cc38
-rw-r--r--content/browser/web_contents/web_drag_dest_win.h3
-rw-r--r--content/public/browser/web_contents_delegate.cc7
-rw-r--r--content/public/browser/web_contents_delegate.h9
8 files changed, 100 insertions, 15 deletions
diff --git a/content/browser/web_contents/web_drag_dest_gtk.cc b/content/browser/web_contents/web_drag_dest_gtk.cc
index 8d6c668..d34526e 100644
--- a/content/browser/web_contents/web_drag_dest_gtk.cc
+++ b/content/browser/web_contents/web_drag_dest_gtk.cc
@@ -13,6 +13,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/drag_utils_gtk.h"
#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/url_constants.h"
#include "net/base/net_util.h"
@@ -53,6 +54,7 @@ WebDragDestGtk::WebDragDestGtk(WebContents* web_contents, GtkWidget* widget)
context_(NULL),
data_requests_(0),
delegate_(NULL),
+ canceled_(false),
method_factory_(this) {
gtk_drag_dest_set(widget, static_cast<GtkDestDefaults>(0),
NULL, 0,
@@ -143,6 +145,9 @@ gboolean WebDragDestGtk::OnDragMotion(GtkWidget* sender,
time);
}
} else if (data_requests_ == 0) {
+ if (canceled_)
+ return FALSE;
+
GetRenderViewHost()->DragTargetDragOver(
ui::ClientPoint(widget_),
ui::ScreenPoint(widget_),
@@ -236,6 +241,20 @@ void WebDragDestGtk::OnDragDataReceived(
}
}
+ if (data_requests_ == 0) {
+ // Give the delegate an opportunity to cancel the drag.
+ canceled_ = !web_contents_->GetDelegate()->CanDragEnter(
+ web_contents_,
+ *drop_data_,
+ GdkDragActionToWebDragOp(context->actions));
+ if (canceled_) {
+ drag_over_time_ = time;
+ UpdateDragStatus(WebDragOperationNone);
+ drop_data_.reset();
+ return;
+ }
+ }
+
// For CHROME_BOOKMARK_ITEM, we have to handle the case where the drag source
// doesn't have any data available for us. In this case we try to synthesize a
// URL bookmark.
@@ -274,6 +293,9 @@ void WebDragDestGtk::OnDragLeave(GtkWidget* sender, GdkDragContext* context,
// as an enter.
context_ = NULL;
+ if (canceled_)
+ return;
+
// Sometimes we get a drag-leave event before getting a drag-data-received
// event. In that case, we don't want to bother the renderer with a
// DragLeave event.
diff --git a/content/browser/web_contents/web_drag_dest_gtk.h b/content/browser/web_contents/web_drag_dest_gtk.h
index 7975fb6..1e0c8ad 100644
--- a/content/browser/web_contents/web_drag_dest_gtk.h
+++ b/content/browser/web_contents/web_drag_dest_gtk.h
@@ -101,6 +101,9 @@ class CONTENT_EXPORT WebDragDestGtk {
// A delegate that can receive drag information about drag events.
WebDragDestDelegate* delegate_;
+ // True if the drag has been canceled.
+ bool canceled_;
+
base::WeakPtrFactory<WebDragDestGtk> method_factory_;
DISALLOW_COPY_AND_ASSIGN(WebDragDestGtk);
diff --git a/content/browser/web_contents/web_drag_dest_mac.h b/content/browser/web_contents/web_drag_dest_mac.h
index 1fef383..3d4cbe5 100644
--- a/content/browser/web_contents/web_drag_dest_mac.h
+++ b/content/browser/web_contents/web_drag_dest_mac.h
@@ -41,6 +41,9 @@ CONTENT_EXPORT
// The data for the current drag, or NULL if none is in progress.
scoped_ptr<WebDropData> dropData_;
+
+ // True if the drag has been canceled.
+ bool canceled_;
}
// |contents| is the WebContentsImpl representing this tab, used to communicate
diff --git a/content/browser/web_contents/web_drag_dest_mac.mm b/content/browser/web_contents/web_drag_dest_mac.mm
index ba4cc26..b1dde18 100644
--- a/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/content/browser/web_contents/web_drag_dest_mac.mm
@@ -9,6 +9,7 @@
#include "base/strings/sys_string_conversions.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#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"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
@@ -44,6 +45,7 @@ int GetModifierFlags() {
- (id)initWithWebContentsImpl:(WebContentsImpl*)contents {
if ((self = [super init])) {
webContents_ = contents;
+ canceled_ = false;
}
return self;
}
@@ -103,6 +105,22 @@ int GetModifierFlags() {
// we need to send a new enter message in draggingUpdated:.
currentRVH_ = webContents_->GetRenderViewHost();
+ // Fill out a WebDropData from pasteboard.
+ scoped_ptr<WebDropData> dropData;
+ dropData.reset(new WebDropData());
+ [self populateWebDropData:dropData.get()
+ fromPasteboard:[info draggingPasteboard]];
+
+ NSDragOperation mask = [info draggingSourceOperationMask];
+
+ // Give the delegate an opportunity to cancel the drag.
+ canceled_ = !webContents_->GetDelegate()->CanDragEnter(
+ webContents_,
+ *dropData,
+ static_cast<WebDragOperationsMask>(mask));
+ if (canceled_)
+ return NSDragOperationNone;
+
if ([self onlyAllowsNavigation]) {
if ([[info draggingPasteboard] containsURLData])
return NSDragOperationCopy;
@@ -114,17 +132,13 @@ int GetModifierFlags() {
delegate_->OnDragEnter();
}
- // Fill out a WebDropData from pasteboard.
- dropData_.reset(new WebDropData());
- [self populateWebDropData:dropData_.get()
- fromPasteboard:[info draggingPasteboard]];
+ dropData_.swap(dropData);
// Create the appropriate mouse locations for WebCore. The draggingLocation
// is in window coordinates. Both need to be flipped.
NSPoint windowPoint = [info draggingLocation];
NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
- NSDragOperation mask = [info draggingSourceOperationMask];
webContents_->GetRenderViewHost()->DragTargetDragEnter(
*dropData_,
gfx::Point(viewPoint.x, viewPoint.y),
@@ -143,6 +157,9 @@ int GetModifierFlags() {
if (currentRVH_ != webContents_->GetRenderViewHost())
return;
+ if (canceled_)
+ return;
+
if ([self onlyAllowsNavigation])
return;
@@ -159,6 +176,9 @@ int GetModifierFlags() {
if (currentRVH_ != webContents_->GetRenderViewHost())
[self draggingEntered:info view:view];
+ if (canceled_)
+ return NSDragOperationNone;
+
if ([self onlyAllowsNavigation]) {
if ([[info draggingPasteboard] containsURLData])
return NSDragOperationCopy;
diff --git a/content/browser/web_contents/web_drag_dest_win.cc b/content/browser/web_contents/web_drag_dest_win.cc
index fb86f08..2e10183 100644
--- a/content/browser/web_contents/web_drag_dest_win.cc
+++ b/content/browser/web_contents/web_drag_dest_win.cc
@@ -11,6 +11,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_drag_utils_win.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_util.h"
@@ -140,7 +141,8 @@ WebDragDest::WebDragDest(HWND source_hwnd, WebContents* web_contents)
current_rvh_(NULL),
drag_cursor_(WebDragOperationNone),
interstitial_drop_target_(new InterstitialDropTarget(web_contents)),
- delegate_(NULL) {
+ delegate_(NULL),
+ canceled_(false) {
}
WebDragDest::~WebDragDest() {
@@ -152,6 +154,24 @@ DWORD WebDragDest::OnDragEnter(IDataObject* data_object,
DWORD effects) {
current_rvh_ = web_contents_->GetRenderViewHost();
+ // TODO(tc): PopulateWebDropData can be slow depending on what is in the
+ // IDataObject. Maybe we can do this in a background thread.
+ scoped_ptr<WebDropData> drop_data;
+ drop_data.reset(new WebDropData());
+ PopulateWebDropData(data_object, drop_data.get());
+
+ if (drop_data->url.is_empty())
+ ui::OSExchangeDataProviderWin::GetPlainTextURL(data_object,
+ &drop_data->url);
+
+ // Give the delegate an opportunity to cancel the drag.
+ canceled_ = !web_contents_->GetDelegate()->CanDragEnter(
+ web_contents_,
+ *drop_data,
+ WinDragOpMaskToWebDragOpMask(effects));
+ if (canceled_)
+ return DROPEFFECT_NONE;
+
if (delegate_)
delegate_->DragInitialize(web_contents_);
@@ -161,15 +181,7 @@ DWORD WebDragDest::OnDragEnter(IDataObject* data_object,
if (web_contents_->ShowingInterstitialPage())
return interstitial_drop_target_->OnDragEnter(data_object, effects);
- // TODO(tc): PopulateWebDropData can be slow depending on what is in the
- // IDataObject. Maybe we can do this in a background thread.
- drop_data_.reset(new WebDropData());
- PopulateWebDropData(data_object, drop_data_.get());
-
- if (drop_data_->url.is_empty())
- ui::OSExchangeDataProviderWin::GetPlainTextURL(data_object,
- &drop_data_->url);
-
+ drop_data_.swap(drop_data);
drag_cursor_ = WebDragOperationNone;
POINT client_pt = cursor_position;
@@ -196,6 +208,9 @@ DWORD WebDragDest::OnDragOver(IDataObject* data_object,
if (current_rvh_ != web_contents_->GetRenderViewHost())
OnDragEnter(data_object, key_state, cursor_position, effects);
+ if (canceled_)
+ return DROPEFFECT_NONE;
+
if (web_contents_->ShowingInterstitialPage())
return interstitial_drop_target_->OnDragOver(data_object, effects);
@@ -218,6 +233,9 @@ void WebDragDest::OnDragLeave(IDataObject* data_object) {
if (current_rvh_ != web_contents_->GetRenderViewHost())
return;
+ if (canceled_)
+ return;
+
if (web_contents_->ShowingInterstitialPage()) {
interstitial_drop_target_->OnDragLeave(data_object);
} else {
diff --git a/content/browser/web_contents/web_drag_dest_win.h b/content/browser/web_contents/web_drag_dest_win.h
index fb2ea17..5e8f024 100644
--- a/content/browser/web_contents/web_drag_dest_win.h
+++ b/content/browser/web_contents/web_drag_dest_win.h
@@ -78,6 +78,9 @@ class CONTENT_EXPORT WebDragDest : public ui::DropTargetWin {
// The data for the current drag, or NULL if |context_| is NULL.
scoped_ptr<WebDropData> drop_data_;
+ // True if the drag has been canceled.
+ bool canceled_;
+
DISALLOW_COPY_AND_ASSIGN(WebDragDest);
};
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 6026328..a9299c8 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -110,6 +110,13 @@ bool WebContentsDelegate::PreHandleKeyboardEvent(
return false;
}
+bool WebContentsDelegate::CanDragEnter(
+ WebContents* source,
+ const WebDropData& data,
+ WebKit::WebDragOperationsMask operations_allowed) {
+ return true;
+}
+
bool WebContentsDelegate::OnGoToEntryOffset(int offset) {
return true;
}
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 8e4f794..492cae7 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -16,6 +16,7 @@
#include "content/public/common/media_stream_request.h"
#include "content/public/common/page_transition_types.h"
#include "content/public/common/window_container_type.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/native_widget_types.h"
@@ -23,6 +24,7 @@
#include "ui/gfx/vector2d.h"
class GURL;
+struct WebDropData;
namespace base {
class FilePath;
@@ -266,6 +268,13 @@ class CONTENT_EXPORT WebContentsDelegate {
virtual void HandleGestureBegin() {}
virtual void HandleGestureEnd() {}
+ // Called when an external drag event enters the web contents window. Return
+ // true to allow dragging and dropping on the web contents window or false to
+ // cancel the operation. This method is used by Chromium Embedded Framework.
+ virtual bool CanDragEnter(WebContents* source,
+ const WebDropData& data,
+ WebKit::WebDragOperationsMask operations_allowed);
+
// Render view drag n drop ended.
virtual void DragEnded() {}