diff options
author | marshall@chromium.org <marshall@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-11 15:04:47 +0000 |
---|---|---|
committer | marshall@chromium.org <marshall@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-11 15:04:47 +0000 |
commit | 090550f49c64e02bb0d819ce507e78657630ff06 (patch) | |
tree | 7376dea44d8d119dcd0b250d2338e00dd78d89c7 /content | |
parent | c6c691d6ddc6ec9ae8f23e0e6ca978d13c845e1f (diff) | |
download | chromium_src-090550f49c64e02bb0d819ce507e78657630ff06.zip chromium_src-090550f49c64e02bb0d819ce507e78657630ff06.tar.gz chromium_src-090550f49c64e02bb0d819ce507e78657630ff06.tar.bz2 |
Add a new WebContentsDelegate::CanDragEnter method. Allows applications using the Content API to selectively cancel (disallow) drag&drop operations on a per-WebContents basis. For example, applications may want to disable drag&drop completely or may want to disallow a drop based on the drag contents (only certain data types, URL formats, etc).
BUG=224440
TEST=none
Review URL: https://chromiumcodereview.appspot.com/16026010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205550 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/web_contents/web_drag_dest_gtk.cc | 22 | ||||
-rw-r--r-- | content/browser/web_contents/web_drag_dest_gtk.h | 3 | ||||
-rw-r--r-- | content/browser/web_contents/web_drag_dest_mac.h | 3 | ||||
-rw-r--r-- | content/browser/web_contents/web_drag_dest_mac.mm | 30 | ||||
-rw-r--r-- | content/browser/web_contents/web_drag_dest_win.cc | 38 | ||||
-rw-r--r-- | content/browser/web_contents/web_drag_dest_win.h | 3 | ||||
-rw-r--r-- | content/public/browser/web_contents_delegate.cc | 7 | ||||
-rw-r--r-- | content/public/browser/web_contents_delegate.h | 9 |
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() {} |