summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/web_drop_target.mm
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-15 17:17:24 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-15 17:17:24 +0000
commit7fd25315869cf0520d9dd813d407c58ff5c5508a (patch)
tree48a4d15e35b58139771f539005be3a8094553577 /chrome/browser/cocoa/web_drop_target.mm
parent8e1fae6e07bf92e9b0e6f07228c5df21fcd76232 (diff)
downloadchromium_src-7fd25315869cf0520d9dd813d407c58ff5c5508a.zip
chromium_src-7fd25315869cf0520d9dd813d407c58ff5c5508a.tar.gz
chromium_src-7fd25315869cf0520d9dd813d407c58ff5c5508a.tar.bz2
Implement drops on web view.
BUG=13155, 15657 TEST=Dragging from other applications to web view should load urls or drop text depending on where in the view the drop occurs. Same with drags from the desktop. Drags within text fields on a webpage should work. Review URL: http://codereview.chromium.org/149626 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20737 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa/web_drop_target.mm')
-rw-r--r--chrome/browser/cocoa/web_drop_target.mm209
1 files changed, 209 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/web_drop_target.mm b/chrome/browser/cocoa/web_drop_target.mm
new file mode 100644
index 0000000..8d450a6
--- /dev/null
+++ b/chrome/browser/cocoa/web_drop_target.mm
@@ -0,0 +1,209 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/cocoa/web_drop_target.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#import "third_party/mozilla/include/NSPasteboard+Utils.h"
+#include "webkit/glue/webdropdata.h"
+#include "webkit/glue/window_open_disposition.h"
+
+@implementation WebDropTarget
+
+// |contents| is the TabContents representing this tab, used to communicate
+// drag&drop messages to WebCore and handle navigation on a successful drop
+// (if necessary).
+- (id)initWithTabContents:(TabContents*)contents {
+ if ((self = [super init])) {
+ tabContents_ = contents;
+ }
+ return self;
+}
+
+// Call to set whether or not we should allow the drop. Takes effect the
+// next time |-draggingUpdated:| is called.
+- (void)setIsDropTarget:(BOOL)isDropTarget {
+ isDropTarget_ = isDropTarget;
+}
+
+// Given a point in window coordinates and a view in that window, return a
+// flipped point in the coordinate system of |view|.
+- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint
+ view:(NSView*)view {
+ DCHECK(view);
+ NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil];
+ NSRect viewFrame = [view frame];
+ viewPoint.y = viewFrame.size.height - viewPoint.y;
+ return viewPoint;
+}
+
+// Given a point in window coordinates and a view in that window, return a
+// flipped point in screen coordinates.
+- (NSPoint)flipWindowPointToScreen:(const NSPoint&)windowPoint
+ view:(NSView*)view {
+ DCHECK(view);
+ NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
+ NSScreen* screen = [[view window] screen];
+ NSRect screenFrame = [screen frame];
+ screenPoint.y = screenFrame.size.height - screenPoint.y;
+ return screenPoint;
+}
+
+// Return YES if the drop site only allows drops that would navigate. If this
+// is the case, we don't want to pass messages to the renderer because there's
+// really no point (i.e., there's nothing that cares about the mouse position or
+// entering and exiting). One example is an interstitial page (e.g., safe
+// browsing warning).
+- (BOOL)onlyAllowsNavigation {
+ return tabContents_->showing_interstitial_page();
+}
+
+// Messages to send during the tracking of a drag, ususally upon recieving
+// calls from the view system. Communicates the drag messages to WebCore.
+
+- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info
+ view:(NSView*)view {
+ // Save off the RVH so we can tell if it changes during a drag. If it does,
+ // we need to send a new enter message in draggingUpdated:.
+ currentRVH_ = tabContents_->render_view_host();
+
+ if ([self onlyAllowsNavigation]) {
+ if ([[info draggingPasteboard] containsURLData])
+ return NSDragOperationCopy;
+ return NSDragOperationNone;
+ }
+
+ // Fill out a WebDropData from pasteboard.
+ WebDropData data;
+ [self populateWebDropData:&data fromPasteboard:[info draggingPasteboard]];
+
+ // 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];
+ tabContents_->render_view_host()->DragTargetDragEnter(data,
+ gfx::Point(viewPoint.x, viewPoint.y),
+ gfx::Point(screenPoint.x, screenPoint.y));
+
+ isDropTarget_ = YES;
+
+ return NSDragOperationCopy;
+}
+
+- (void)draggingExited:(id<NSDraggingInfo>)info {
+ DCHECK(currentRVH_);
+ if (currentRVH_ != tabContents_->render_view_host())
+ return;
+
+ // Nothing to do in the interstitial case.
+
+ tabContents_->render_view_host()->DragTargetDragLeave();
+}
+
+- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
+ view:(NSView*)view {
+ DCHECK(currentRVH_);
+ if (currentRVH_ != tabContents_->render_view_host())
+ [self draggingEntered:info];
+
+ if ([self onlyAllowsNavigation]) {
+ if ([[info draggingPasteboard] containsURLData])
+ return NSDragOperationCopy;
+ return NSDragOperationNone;
+ }
+
+ // Create the appropriate mouse locations for WebCore. The draggingLocation
+ // is in window coordinates.
+ NSPoint windowPoint = [info draggingLocation];
+ NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+ NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+ tabContents_->render_view_host()->DragTargetDragOver(
+ gfx::Point(viewPoint.x, viewPoint.y),
+ gfx::Point(screenPoint.x, screenPoint.y));
+
+ if (!isDropTarget_)
+ return NSDragOperationNone;
+ return NSDragOperationCopy;
+}
+
+- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
+ view:(NSView*)view {
+ if (currentRVH_ != tabContents_->render_view_host())
+ [self draggingEntered:info];
+
+ // Check if we only allow navigation and navigate to a url on the pasteboard.
+ if ([self onlyAllowsNavigation]) {
+ NSPasteboard* pboard = [info draggingPasteboard];
+ if ([pboard containsURLData]) {
+ WebDropData data;
+ [self populateURLAndTitle:&data fromPasteboard:pboard];
+ tabContents_->OpenURL(data.url, GURL(), CURRENT_TAB,
+ PageTransition::AUTO_BOOKMARK);
+ return YES;
+ }
+ return NO;
+ }
+
+ currentRVH_ = NULL;
+
+ // 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];
+ tabContents_->render_view_host()->DragTargetDrop(
+ gfx::Point(viewPoint.x, viewPoint.y),
+ gfx::Point(screenPoint.x, screenPoint.y));
+
+ return YES;
+}
+
+// Populate the URL portion of |data|. There may be more than one, but we only
+// handle dropping the first. |data| must not be NULL. Assumes the caller has
+// already called |-containsURLData|.
+- (void)populateURLAndTitle:(WebDropData*)data
+ fromPasteboard:(NSPasteboard*)pboard {
+ DCHECK(data);
+ DCHECK([pboard containsURLData]);
+
+ // The getURLs:andTitles: will already validate URIs so we don't need to
+ // again. The arrays it returns are both of NSString's.
+ NSArray* urls = nil;
+ NSArray* titles = nil;
+ [pboard getURLs:&urls andTitles:&titles];
+ data->url = GURL([[urls objectAtIndex:0] UTF8String]);
+ data->url_title = base::SysNSStringToUTF16([titles objectAtIndex:0]);
+}
+
+// Given |data|, which should not be nil, fill it in using the contents of the
+// given pasteboard.
+- (void)populateWebDropData:(WebDropData*)data
+ fromPasteboard:(NSPasteboard*)pboard {
+ DCHECK(data);
+ DCHECK(pboard);
+ NSArray* types = [pboard types];
+
+ // Get URL.
+ if ([pboard containsURLData])
+ [self populateURLAndTitle:data fromPasteboard:pboard];
+
+ // Get plain text.
+ if ([types containsObject:NSStringPboardType]) {
+ data->plain_text =
+ base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]);
+ }
+
+ // Get HTML.
+ if ([types containsObject:NSHTMLPboardType]) {
+ data->text_html =
+ base::SysNSStringToUTF16([pboard stringForType:NSHTMLPboardType]);
+ }
+
+ // TODO(pinkerton): Get files and file contents.
+}
+
+@end