1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #import "chrome/browser/ui/cocoa/url_drop_target.h" 6 7 #include "base/basictypes.h" 8 #include "chrome/browser/ui/cocoa/drag_util.h" 9 #import "third_party/mozilla/NSPasteboard+Utils.h" 10 #include "url/gurl.h" 11 12 namespace { 13 14 // Mac WebKit uses this type, declared in 15 // WebKit/mac/History/WebURLsWithTitles.h. 16 NSString* const kCrWebURLsWithTitlesPboardType = 17 @"WebURLsWithTitlesPboardType"; 18 19 } // namespace 20 21 @interface URLDropTargetHandler(Private) 22 23 // Gets the appropriate drag operation given the |NSDraggingInfo|. 24 - (NSDragOperation)getDragOperation:(id<NSDraggingInfo>)sender; 25 26 // Tell the window controller to hide the drop indicator. 27 - (void)hideIndicator; 28 29 @end // @interface URLDropTargetHandler(Private) 30 31 @implementation URLDropTargetHandler 32 33 + (NSArray*)handledDragTypes { 34 return [NSArray arrayWithObjects:kCrWebURLsWithTitlesPboardType, 35 NSURLPboardType, 36 NSStringPboardType, 37 NSFilenamesPboardType, 38 nil]; 39 } 40 41 - (id)initWithView:(NSView<URLDropTarget>*)view { 42 if ((self = [super init])) { 43 view_ = view; 44 [view_ registerForDraggedTypes:[URLDropTargetHandler handledDragTypes]]; 45 } 46 return self; 47 } 48 49 // The following four methods implement parts of the |NSDraggingDestination| 50 // protocol, which the owner should "forward" to its |URLDropTargetHandler| 51 // (us). 52 53 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender { 54 if ([[view_ urlDropController] isUnsupportedDropData:sender]) 55 return NSDragOperationNone; 56 57 return [self getDragOperation:sender]; 58 } 59 60 - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender { 61 NSDragOperation dragOp = NSDragOperationNone; 62 BOOL showIndicator = NO; 63 // Show indicator for drag data supported for tab contents as well as for 64 // local file drags that may not be viewable in tab contents, but should 65 // still trigger hover tab selection. 66 if (![[view_ urlDropController] isUnsupportedDropData:sender]) { 67 dragOp = [self getDragOperation:sender]; 68 if (dragOp == NSDragOperationCopy) 69 showIndicator = YES; 70 } else if (!drag_util::GetFileURLFromDropData(sender).is_empty()) { 71 showIndicator = YES; 72 } 73 74 if (showIndicator) { 75 // Just tell the window controller to update the indicator. 76 NSPoint hoverPoint = [view_ convertPoint:[sender draggingLocation] 77 fromView:nil]; 78 [[view_ urlDropController] indicateDropURLsInView:view_ at:hoverPoint]; 79 } 80 return dragOp; 81 } 82 83 - (void)draggingExited:(id<NSDraggingInfo>)sender { 84 [self hideIndicator]; 85 } 86 87 - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender { 88 [self hideIndicator]; 89 90 NSPasteboard* pboard = [sender draggingPasteboard]; 91 NSArray* supportedTypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; 92 NSString* bestType = [pboard availableTypeFromArray:supportedTypes]; 93 94 NSPoint dropPoint = 95 [view_ convertPoint:[sender draggingLocation] fromView:nil]; 96 // Tell the window controller about the dropped URL(s). 97 if ([pboard containsURLData]) { 98 NSArray* urls = nil; 99 NSArray* titles; // discarded 100 [pboard getURLs:&urls andTitles:&titles convertingFilenames:YES]; 101 102 if ([urls count]) { 103 [[view_ urlDropController] dropURLs:urls inView:view_ at:dropPoint]; 104 return YES; 105 } 106 } else if (NSString* text = [pboard stringForType:bestType]) { 107 // This does not include any URLs, so treat it as plain text if we can 108 // get NSString. 109 [[view_ urlDropController] dropText:text inView:view_ at:dropPoint]; 110 return YES; 111 } 112 113 return NO; 114 } 115 116 @end // @implementation URLDropTargetHandler 117 118 @implementation URLDropTargetHandler(Private) 119 120 - (NSDragOperation)getDragOperation:(id<NSDraggingInfo>)sender { 121 NSPasteboard* pboard = [sender draggingPasteboard]; 122 NSArray *supportedTypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; 123 NSString *bestType = [pboard availableTypeFromArray:supportedTypes]; 124 if (![pboard containsURLData] && ![pboard stringForType:bestType]) 125 return NSDragOperationNone; 126 127 // Only allow the copy operation. 128 return [sender draggingSourceOperationMask] & NSDragOperationCopy; 129 } 130 131 - (void)hideIndicator { 132 [[view_ urlDropController] hideDropURLsIndicatorInView:view_]; 133 } 134 135 @end // @implementation URLDropTargetHandler(Private) 136