diff options
-rw-r--r-- | chrome/browser/tab_contents/web_drop_target.cc | 6 | ||||
-rw-r--r-- | webkit/glue/webview.h | 12 | ||||
-rw-r--r-- | webkit/glue/webview_impl.cc | 41 | ||||
-rw-r--r-- | webkit/glue/webview_impl.h | 13 |
4 files changed, 62 insertions, 10 deletions
diff --git a/chrome/browser/tab_contents/web_drop_target.cc b/chrome/browser/tab_contents/web_drop_target.cc index eb740ee..f934f62 100644 --- a/chrome/browser/tab_contents/web_drop_target.cc +++ b/chrome/browser/tab_contents/web_drop_target.cc @@ -136,12 +136,6 @@ DWORD WebDropTarget::OnDragOver(IDataObject* data_object, gfx::Point(client_pt.x, client_pt.y), gfx::Point(cursor_position.x, cursor_position.y)); - // Again we don't wait on the renderer to respond, but this can lead to - // a race condition. If the renderer does not want the drop data, then - // we won't know until the response from the renderer arrives. So if a - // drop happens before the response arrives, we drop on a renderer that - // doesn't want the data. TODO(noel): fix this. - if (!is_drop_target_) return DROPEFFECT_NONE; diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h index 8f39bd31..600338f 100644 --- a/webkit/glue/webview.h +++ b/webkit/glue/webview.h @@ -191,8 +191,8 @@ class WebView : public WebWidget { // Notfies the webview that the system drag and drop operation has ended. virtual void DragSourceSystemDragEnded() = 0; - // Callback methods when a drag and drop operation is trying to drop - // something on the renderer. + // Callback methods when a drag and drop operation is trying to drop data + // on this webview. virtual bool DragTargetDragEnter( const WebKit::WebDragData& drag_data, int identity, const WebKit::WebPoint& client_point, @@ -204,8 +204,16 @@ class WebView : public WebWidget { virtual void DragTargetDrop( const WebKit::WebPoint& client_point, const WebKit::WebPoint& screen_point) = 0; + + // Helper method for drag and drop target operations: return the drag data + // identity. virtual int32 GetDragIdentity() = 0; + // Helper method for drag and drop target operations: override the default + // drop effect with either a "copy" (accept true) or "none" (accept false) + // effect. Return true on success. + virtual bool SetDropEffect(bool accept) = 0; + // Notifies the webview that autofill suggestions are available for a node. virtual void AutofillSuggestionsForNode( int64 node_id, diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 03db938..e974d44 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -363,6 +363,8 @@ WebViewImpl::WebViewImpl() ime_accept_events_(true), drag_target_dispatch_(false), drag_identity_(0), + drop_effect_(DROP_EFFECT_DEFAULT), + drop_accept_(false), autocomplete_popup_showing_(false) { // WebKit/win/WebView.cpp does the same thing, except they call the // KJS specific wrapper around this method. We need to have threading @@ -1632,11 +1634,15 @@ bool WebViewImpl::DragTargetDragEnter( webkit_glue::WebPointToIntPoint(client_point), webkit_glue::WebPointToIntPoint(screen_point), kDropTargetOperation); + + drop_effect_ = DROP_EFFECT_DEFAULT; drag_target_dispatch_ = true; DragOperation effect = page_->dragController()->dragEntered(&drag_data); drag_target_dispatch_ = false; - return effect != DragOperationNone; + if (drop_effect_ != DROP_EFFECT_DEFAULT) + return drop_accept_ = (drop_effect_ != DROP_EFFECT_NONE); + return drop_accept_ = (effect != DragOperationNone); } bool WebViewImpl::DragTargetDragOver( @@ -1649,11 +1655,15 @@ bool WebViewImpl::DragTargetDragOver( webkit_glue::WebPointToIntPoint(client_point), webkit_glue::WebPointToIntPoint(screen_point), kDropTargetOperation); + + drop_effect_ = DROP_EFFECT_DEFAULT; drag_target_dispatch_ = true; DragOperation effect = page_->dragController()->dragUpdated(&drag_data); drag_target_dispatch_ = false; - return effect != DragOperationNone; + if (drop_effect_ != DROP_EFFECT_DEFAULT) + return drop_accept_ = (drop_effect_ != DROP_EFFECT_NONE); + return drop_accept_ = (effect != DragOperationNone); } void WebViewImpl::DragTargetDragLeave() { @@ -1664,11 +1674,14 @@ void WebViewImpl::DragTargetDragLeave() { IntPoint(), IntPoint(), kDropTargetOperation); + drag_target_dispatch_ = true; page_->dragController()->dragExited(&drag_data); drag_target_dispatch_ = false; current_drag_data_ = NULL; + drop_effect_ = DROP_EFFECT_DEFAULT; + drop_accept_ = false; drag_identity_ = 0; } @@ -1677,16 +1690,31 @@ void WebViewImpl::DragTargetDrop( const WebPoint& screen_point) { DCHECK(current_drag_data_.get()); + // If this webview transitions from the "drop accepting" state to the "not + // accepting" state, then our IPC message reply indicating that may be in- + // flight, or else delayed by javascript processing in this webview. If a + // drop happens before our IPC reply has reached the browser process, then + // the browser forwards the drop to this webview. So only allow a drop to + // proceed if our webview drop_accept_ state is true. + + if (!drop_accept_) { // IPC RACE CONDITION: do not allow this drop. + DragTargetDragLeave(); + return; + } + DragData drag_data( current_drag_data_.get(), webkit_glue::WebPointToIntPoint(client_point), webkit_glue::WebPointToIntPoint(screen_point), kDropTargetOperation); + drag_target_dispatch_ = true; page_->dragController()->performDrag(&drag_data); drag_target_dispatch_ = false; current_drag_data_ = NULL; + drop_effect_ = DROP_EFFECT_DEFAULT; + drop_accept_ = false; drag_identity_ = 0; } @@ -1696,6 +1724,15 @@ int32 WebViewImpl::GetDragIdentity() { return 0; } +bool WebViewImpl::SetDropEffect(bool accept) { + if (drag_target_dispatch_) { + drop_effect_ = accept ? DROP_EFFECT_COPY : DROP_EFFECT_NONE; + return true; + } else { + return false; + } +} + SearchableFormData* WebViewImpl::CreateSearchableFormDataForFocusedNode() { if (!page_.get()) return NULL; diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 5b3565b..9080bf4 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -114,6 +114,7 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { const WebKit::WebPoint& client_point, const WebKit::WebPoint& screen_point); virtual int32 GetDragIdentity(); + virtual bool SetDropEffect(bool accept); virtual void AutofillSuggestionsForNode( int64 node_id, const std::vector<std::wstring>& suggestions, @@ -323,6 +324,18 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { // copied from the WebDropData object sent from the browser process. int32 drag_identity_; + // Valid when drag_target_dispatch_ is true. Used to override the default + // browser drop effect with the effects "copy" or "none". + enum DragTargetDropEffect { + DROP_EFFECT_DEFAULT = 0, + DROP_EFFECT_COPY, + DROP_EFFECT_NONE + } drop_effect_; + + // When true, the drag data can be dropped onto the current drop target in + // this WebView (the drop target can accept the drop). + bool drop_accept_; + // The autocomplete popup. Kept around and reused every-time new suggestions // should be shown. RefPtr<WebCore::PopupContainer> autocomplete_popup_; |