// Copyright (c) 2012 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/ui/cocoa/url_drop_target.h" #include "chrome/browser/ui/cocoa/drag_util.h" #import "third_party/mozilla/NSPasteboard+Utils.h" #include "url/gurl.h" namespace { // Mac WebKit uses this type, declared in // WebKit/mac/History/WebURLsWithTitles.h. NSString* const kCrWebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType"; } // namespace @interface URLDropTargetHandler(Private) // Gets the appropriate drag operation given the |NSDraggingInfo|. - (NSDragOperation)getDragOperation:(id)sender; // Tell the window controller to hide the drop indicator. - (void)hideIndicator; @end // @interface URLDropTargetHandler(Private) @implementation URLDropTargetHandler + (NSArray*)handledDragTypes { return [NSArray arrayWithObjects:kCrWebURLsWithTitlesPboardType, NSURLPboardType, NSStringPboardType, NSFilenamesPboardType, nil]; } - (id)initWithView:(NSView*)view { if ((self = [super init])) { view_ = view; [view_ registerForDraggedTypes:[URLDropTargetHandler handledDragTypes]]; } return self; } // The following four methods implement parts of the |NSDraggingDestination| // protocol, which the owner should "forward" to its |URLDropTargetHandler| // (us). - (NSDragOperation)draggingEntered:(id)sender { if ([[view_ urlDropController] isUnsupportedDropData:sender]) return NSDragOperationNone; return [self getDragOperation:sender]; } - (NSDragOperation)draggingUpdated:(id)sender { NSDragOperation dragOp = NSDragOperationNone; BOOL showIndicator = NO; // Show indicator for drag data supported for tab contents as well as for // local file drags that may not be viewable in tab contents, but should // still trigger hover tab selection. if (![[view_ urlDropController] isUnsupportedDropData:sender]) { dragOp = [self getDragOperation:sender]; if (dragOp == NSDragOperationCopy) showIndicator = YES; } else if (!drag_util::GetFileURLFromDropData(sender).is_empty()) { showIndicator = YES; } if (showIndicator) { // Just tell the window controller to update the indicator. NSPoint hoverPoint = [view_ convertPoint:[sender draggingLocation] fromView:nil]; [[view_ urlDropController] indicateDropURLsInView:view_ at:hoverPoint]; } return dragOp; } - (void)draggingExited:(id)sender { [self hideIndicator]; } - (BOOL)performDragOperation:(id)sender { [self hideIndicator]; NSPasteboard* pboard = [sender draggingPasteboard]; NSArray* supportedTypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; NSString* bestType = [pboard availableTypeFromArray:supportedTypes]; NSPoint dropPoint = [view_ convertPoint:[sender draggingLocation] fromView:nil]; // Tell the window controller about the dropped URL(s). if ([pboard containsURLData]) { NSArray* urls = nil; NSArray* titles; // discarded [pboard getURLs:&urls andTitles:&titles convertingFilenames:YES]; if ([urls count]) { [[view_ urlDropController] dropURLs:urls inView:view_ at:dropPoint]; return YES; } } else if (NSString* text = [pboard stringForType:bestType]) { // This does not include any URLs, so treat it as plain text if we can // get NSString. [[view_ urlDropController] dropText:text inView:view_ at:dropPoint]; return YES; } return NO; } @end // @implementation URLDropTargetHandler @implementation URLDropTargetHandler(Private) - (NSDragOperation)getDragOperation:(id)sender { NSPasteboard* pboard = [sender draggingPasteboard]; NSArray *supportedTypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; NSString *bestType = [pboard availableTypeFromArray:supportedTypes]; if (![pboard containsURLData] && ![pboard stringForType:bestType]) return NSDragOperationNone; // Only allow the copy operation. return [sender draggingSourceOperationMask] & NSDragOperationCopy; } - (void)hideIndicator { [[view_ urlDropController] hideDropURLsIndicatorInView:view_]; } @end // @implementation URLDropTargetHandler(Private)