Bug 1358075 - Display friendly names for .webloc files on OSX after dragging URLs to Finder. r=mstange, a=jcristau
authorStephen A Pohl <spohl.mozilla.bugs@gmail.com>
Tue, 23 May 2017 00:23:33 -0400
changeset 396452 0c65e204f2f1231ecb6a885f33cbd6eb735b4ead
parent 396451 e2a623da5e737429d12c6697ff1814c9363a706b
child 396453 35ed9162cbe6cfc7cf2354cdba6670371ed04df7
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, jcristau
bugs1358075
milestone54.0
Bug 1358075 - Display friendly names for .webloc files on OSX after dragging URLs to Finder. r=mstange, a=jcristau
widget/cocoa/nsChildView.mm
widget/cocoa/nsClipboard.mm
widget/cocoa/nsDragService.h
widget/cocoa/nsDragService.mm
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -3233,19 +3233,19 @@ NSEvent* gLastDragMouseDownEvent = nil;
 {
   [aView registerForDraggedTypes:[NSArray arrayWithObjects:
                                     NSFilenamesPboardType,
                                     NSPasteboardTypeString,
                                     NSPasteboardTypeHTML,
                                     NSURLPboardType,
                                     kPasteboardTypeFileURLPromise,
                                     kWildcardPboardType,
-                                    kCorePboardType_url,
-                                    kCorePboardType_urld,
-                                    kCorePboardType_urln,
+                                    kPublicUrlPboardType,
+                                    kPublicUrlNamePboardType,
+                                    kUrlsWithTitlesPboardType,
                                     nil]];
 }
 
 // initWithFrame:geckoChild:
 - (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
@@ -5991,21 +5991,23 @@ provideDataForType:(NSString*)aType
     // Write everything out to the pasteboard.
     unsigned int typeCount = [pasteboardOutputDict count];
     NSMutableArray* types = [NSMutableArray arrayWithCapacity:typeCount + 1];
     [types addObjectsFromArray:[pasteboardOutputDict allKeys]];
     [types addObject:kWildcardPboardType];
     for (unsigned int k = 0; k < typeCount; k++) {
       NSString* curType = [types objectAtIndex:k];
       if ([curType isEqualToString:NSPasteboardTypeString] ||
-          [curType isEqualToString:kCorePboardType_url] ||
-          [curType isEqualToString:kCorePboardType_urld] ||
-          [curType isEqualToString:kCorePboardType_urln]) {
+          [curType isEqualToString:kPublicUrlPboardType] ||
+          [curType isEqualToString:kPublicUrlNamePboardType]) {
         [aPasteboard setString:[pasteboardOutputDict valueForKey:curType]
                        forType:curType];
+      } else if ([curType isEqualToString:kUrlsWithTitlesPboardType]) {
+        [aPasteboard setPropertyList:[pasteboardOutputDict valueForKey:curType]
+                       forType:curType];
       } else if ([curType isEqualToString:NSPasteboardTypeHTML]) {
         [aPasteboard setString:
           (nsClipboard::WrapHtmlForSystemPasteboard(
             [pasteboardOutputDict valueForKey:curType]))
                       forType:curType];
       } else if ([curType isEqualToString:NSPasteboardTypeTIFF] ||
                  [curType isEqualToString:kCustomTypesPboardType]) {
         [aPasteboard setData:[pasteboardOutputDict valueForKey:curType]
@@ -6188,27 +6190,27 @@ provideDataForType:(NSString*)aType
   [pboard declareTypes:declaredTypes owner:nil];
 
   // Write the data to the pasteboard.
   for (unsigned int i = 0; i < typeCount; i++) {
     NSString* currentKey = [declaredTypes objectAtIndex:i];
     id currentValue = [pasteboardOutputDict valueForKey:currentKey];
 
     if ([currentKey isEqualToString:NSPasteboardTypeString] ||
-        [currentKey isEqualToString:kCorePboardType_url] ||
-        [currentKey isEqualToString:kCorePboardType_urld] ||
-        [currentKey isEqualToString:kCorePboardType_urln]) {
+        [currentKey isEqualToString:kPublicUrlPboardType] ||
+        [currentKey isEqualToString:kPublicUrlNamePboardType]) {
       [pboard setString:currentValue forType:currentKey];
     } else if ([currentKey isEqualToString:NSPasteboardTypeHTML]) {
       [pboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
                 forType:currentKey];
     } else if ([currentKey isEqualToString:NSPasteboardTypeTIFF]) {
       [pboard setData:currentValue forType:currentKey];
     } else if ([currentKey isEqualToString:
-                 (NSString*)kPasteboardTypeFileURLPromise]) {
+                 (NSString*)kPasteboardTypeFileURLPromise] ||
+               [currentKey isEqualToString:kUrlsWithTitlesPboardType]) {
       [pboard setPropertyList:currentValue forType:currentKey];
     }
   }
 
   return YES;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
 }
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -115,20 +115,23 @@ nsClipboard::SetNativeClipboardData(int3
   for (unsigned int i = 0; i < outputCount; i++) {
     NSString* currentKey = [outputKeys objectAtIndex:i];
     id currentValue = [pasteboardOutputDict valueForKey:currentKey];
     if (aWhichClipboard == kFindClipboard) {
       if ([currentKey isEqualToString:NSPasteboardTypeString])
         [cocoaPasteboard setString:currentValue forType:currentKey];
     } else {
       if ([currentKey isEqualToString:NSPasteboardTypeString] ||
-          [currentKey isEqualToString:kCorePboardType_url] ||
-          [currentKey isEqualToString:kCorePboardType_urld] ||
-          [currentKey isEqualToString:kCorePboardType_urln]) {
+          [currentKey isEqualToString:kPublicUrlPboardType] ||
+          [currentKey isEqualToString:kPublicUrlNamePboardType]) {
         [cocoaPasteboard setString:currentValue forType:currentKey];
+      } else if ([currentKey isEqualToString:kUrlsWithTitlesPboardType]) {
+        [cocoaPasteboard setPropertyList:
+          [pasteboardOutputDict valueForKey:currentKey]
+                                 forType:currentKey];
       } else if ([currentKey isEqualToString:NSPasteboardTypeHTML]) {
         [cocoaPasteboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
                          forType:currentKey];
       } else {
         [cocoaPasteboard setData:currentValue forType:currentKey];
       }
     }
   }
@@ -606,45 +609,47 @@ nsClipboard::PasteboardDictFromTransfera
       uint32_t len = 0;
       nsCOMPtr<nsISupports> genericURL;
       rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericURL), &len);
       nsCOMPtr<nsISupportsString> urlObject(do_QueryInterface(genericURL));
 
       nsAutoString url;
       urlObject->GetData(url);
 
+      // The Finder doesn't like getting random binary data aka
+      // Unicode, so change it into an escaped URL containing only
+      // ASCII.
+      nsAutoCString utf8Data = NS_ConvertUTF16toUTF8(url.get(), url.Length());
+      nsAutoCString escData;
+      NS_EscapeURL(utf8Data.get(),
+                   utf8Data.Length(),
+                   esc_OnlyNonASCII|esc_AlwaysCopy,
+                   escData);
+
+      NSString* nativeURL = [NSString stringWithUTF8String:escData.get()];
+      [pasteboardOutputDict setObject:nativeURL forKey:kPublicUrlPboardType];
+
       // A newline embedded in the URL means that the form is actually URL + title.
       int32_t newlinePos = url.FindChar(char16_t('\n'));
       if (newlinePos >= 0) {
         url.Truncate(newlinePos);
 
         nsAutoString urlTitle;
         urlObject->GetData(urlTitle);
         urlTitle.Mid(urlTitle, newlinePos + 1, len - (newlinePos + 1));
 
         NSString *nativeTitle = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(urlTitle.get())
                                                               length:urlTitle.Length()];
-        // be nice to Carbon apps, normalize the receiver's contents using Form C.
-        [pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urln];
-        // Also put the title out as 'urld', since some recipients will look for that.
-        [pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urld];
+        NSArray* urlsAndTitles = @[@[nativeURL], @[nativeTitle]];
+        [pasteboardOutputDict setObject:nativeTitle
+                                 forKey:kPublicUrlNamePboardType];
+        [pasteboardOutputDict setObject:urlsAndTitles
+                                 forKey:kUrlsWithTitlesPboardType];
         [nativeTitle release];
       }
-
-      // The Finder doesn't like getting random binary data aka
-      // Unicode, so change it into an escaped URL containing only
-      // ASCII.
-      nsAutoCString utf8Data = NS_ConvertUTF16toUTF8(url.get(), url.Length());
-      nsAutoCString escData;
-      NS_EscapeURL(utf8Data.get(), utf8Data.Length(), esc_OnlyNonASCII|esc_AlwaysCopy, escData);
-
-      // printf("Escaped url is %s, length %d\n", escData.get(), escData.Length());
-
-      NSString *nativeURL = [NSString stringWithUTF8String:escData.get()];
-      [pasteboardOutputDict setObject:nativeURL forKey:kCorePboardType_url];
     }
     // If it wasn't a type that we recognize as exportable we don't put it on the system
     // clipboard. We'll just access it from our cached transferable when we need it.
   }
 
   return pasteboardOutputDict;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
--- a/widget/cocoa/nsDragService.h
+++ b/widget/cocoa/nsDragService.h
@@ -7,19 +7,19 @@
 #define nsDragService_h_
 
 #include "nsBaseDragService.h"
 #include "nsChildView.h"
 
 #include <Cocoa/Cocoa.h>
 
 extern NSString* const kWildcardPboardType;
-extern NSString* const kCorePboardType_url;
-extern NSString* const kCorePboardType_urld;
-extern NSString* const kCorePboardType_urln;
+extern NSString* const kPublicUrlPboardType;
+extern NSString* const kPublicUrlNamePboardType;
+extern NSString* const kUrlsWithTitlesPboardType;
 extern NSString* const kCustomTypesPboardType;
 
 class nsDragService : public nsBaseDragService
 {
 public:
   nsDragService();
 
   // nsBaseDragService
--- a/widget/cocoa/nsDragService.mm
+++ b/widget/cocoa/nsDragService.mm
@@ -42,25 +42,21 @@ extern NSPasteboard* globalDragPboard;
 extern ChildView* gLastDragView;
 extern NSEvent* gLastDragMouseDownEvent;
 extern bool gUserCancelledDrag;
 
 // This global makes the transferable array available to Cocoa's promised
 // file destination callback.
 nsIArray *gDraggedTransferables = nullptr;
 
-NSString* const kWildcardPboardType    = @"org.mozilla.MozillaWildcard";
-NSString* const kCorePboardType_url    =
-  @"org.mozilla.CorePasteboardFlavorType0x75726C20"; // 'url '  url
-NSString* const kCorePboardType_urld   =
-  @"org.mozilla.CorePasteboardFlavorType0x75726C64"; // 'urld'  desc
-NSString* const kCorePboardType_urln   =
-  @"org.mozilla.CorePasteboardFlavorType0x75726C6E"; // 'urln'  title
-NSString* const kUTTypeURLName         = @"public.url-name";
-NSString* const kCustomTypesPboardType = @"org.mozilla.custom-clipdata";
+NSString* const kWildcardPboardType       = @"org.mozilla.MozillaWildcard";
+NSString* const kPublicUrlPboardType      = @"public.url";
+NSString* const kPublicUrlNamePboardType  = @"public.url-name";
+NSString* const kUrlsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
+NSString* const kCustomTypesPboardType    = @"org.mozilla.custom-clipdata";
 
 nsDragService::nsDragService()
   : mNativeDragView(nil), mNativeDragEvent(nil), mDragImageChanged(false)
 {
   EnsureLogInitialized();
 }
 
 nsDragService::~nsDragService()
@@ -208,17 +204,17 @@ nsDragService::ConstructDragImage(nsIDOM
 bool
 nsDragService::IsValidType(NSString* availableType, bool allowFileURL)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   // Prevent exposing fileURL for non-fileURL type.
   // We need URL provided by dropped webloc file, but don't need file's URL.
   // kUTTypeFileURL is returned by [NSPasteboard availableTypeFromArray:] for
-  // kUTTypeURL, since it conforms to kUTTypeURL.
+  // kPublicUrlPboardType, since it conforms to kPublicUrlPboardType.
   if (!allowFileURL && [availableType isEqualToString:(id)kUTTypeFileURL]) {
     return false;
   }
 
   return true;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
 }
@@ -239,17 +235,17 @@ nsDragService::GetStringForType(NSPasteb
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 NSString*
 nsDragService::GetTitleForURL(NSPasteboardItem* item)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
-  NSString* name = GetStringForType(item, (const NSString*)kUTTypeURLName);
+  NSString* name = GetStringForType(item, kPublicUrlNamePboardType);
   if (name) {
     return name;
   }
 
   NSString* filePath = GetFilePath(item);
   if (filePath) {
     return [filePath lastPathComponent];
   }
@@ -481,26 +477,26 @@ nsDragService::GetData(nsITransferable* 
     }
 
     NSString* pString = nil;
     if (flavorStr.EqualsLiteral(kUnicodeMime)) {
       pString = GetStringForType(item, (const NSString*)kUTTypeUTF8PlainText);
     } else if (flavorStr.EqualsLiteral(kHTMLMime)) {
       pString = GetStringForType(item, (const NSString*)kUTTypeHTML);
     } else if (flavorStr.EqualsLiteral(kURLMime)) {
-      pString = GetStringForType(item, (const NSString*)kUTTypeURL);
+      pString = GetStringForType(item, kPublicUrlPboardType);
       if (pString) {
         NSString* title = GetTitleForURL(item);
         if (!title) {
           title = pString;
         }
         pString = [NSString stringWithFormat:@"%@\n%@", pString, title];
       }
     } else if (flavorStr.EqualsLiteral(kURLDataMime)) {
-      pString = GetStringForType(item, (const NSString*)kUTTypeURL);
+      pString = GetStringForType(item, kPublicUrlPboardType);
     } else if (flavorStr.EqualsLiteral(kURLDescriptionMime)) {
       pString = GetTitleForURL(item);
     } else if (flavorStr.EqualsLiteral(kRTFMime)) {
       pString = GetStringForType(item, (const NSString*)kUTTypeRTF);
     }
     if (pString) {
       NSData* stringData;
       if (flavorStr.EqualsLiteral(kRTFMime)) {
@@ -598,19 +594,19 @@ nsDragService::IsDataFlavorSupported(con
     type = (const NSString*)kUTTypeFileURL;
     allowFileURL = true;
   } else if (dataFlavor.EqualsLiteral(kUnicodeMime)) {
     type = (const NSString*)kUTTypeUTF8PlainText;
   } else if (dataFlavor.EqualsLiteral(kHTMLMime)) {
     type = (const NSString*)kUTTypeHTML;
   } else if (dataFlavor.EqualsLiteral(kURLMime) ||
              dataFlavor.EqualsLiteral(kURLDataMime)) {
-    type = (const NSString*)kUTTypeURL;
+    type = kPublicUrlPboardType;
   } else if (dataFlavor.EqualsLiteral(kURLDescriptionMime)) {
-    type = (const NSString*)kUTTypeURLName;
+    type = kPublicUrlNamePboardType;
   } else if (dataFlavor.EqualsLiteral(kRTFMime)) {
     type = (const NSString*)kUTTypeRTF;
   } else if (dataFlavor.EqualsLiteral(kCustomTypesMime)) {
     type = (const NSString*)kCustomTypesPboardType;
   }
 
   NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]];
   if (availableType && IsValidType(availableType, allowFileURL)) {