Bug 1321321 - Ensure that we always save files with the given extension / Work-around NSSavePanel limitations when saving files with multiple extensions. r=mstange.
authorstefanh@inbox.com
Sat, 25 Feb 2017 00:34:46 +0100
changeset 373937 6fd458fdbd07be39745f0194fa54cc7d2e6f1f4b
parent 373936 343d11a33afe76e0e0e27e8188e6319319fe17ef
child 373938 0ba0e2afff976c9c3538faa54f8b0b8a1187466b
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1321321
milestone54.0a1
Bug 1321321 - Ensure that we always save files with the given extension / Work-around NSSavePanel limitations when saving files with multiple extensions. r=mstange.
widget/cocoa/nsFilePicker.mm
--- a/widget/cocoa/nsFilePicker.mm
+++ b/widget/cocoa/nsFilePicker.mm
@@ -453,33 +453,48 @@ nsFilePicker::PutLocalFile(const nsStrin
 
   // set up accessory view for file format options
   NSView* accessoryView = GetAccessoryView();
   [thePanel setAccessoryView:accessoryView];
 
   // set up default file name
   NSString* defaultFilename = [NSString stringWithCharacters:(const unichar*)inDefaultName.get() length:inDefaultName.Length()];
 
-  // set up allowed types; this prevents the extension from being selected
-  // use the UTI for the file type to allow alternate extensions (e.g., jpg vs. jpeg)
+  // Set up the allowed type. This prevents the extension from being selected.
   NSString* extension = defaultFilename.pathExtension;
   if (extension.length != 0) {
-    CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL);
-
-    if (type) {
-      thePanel.allowedFileTypes = @[(NSString*)type];
-      CFRelease(type);
-    } else {
-      // if there's no UTI for the file extension, use the extension itself.
-      thePanel.allowedFileTypes = @[extension];
-    }
+    thePanel.allowedFileTypes = @[extension];
   }
   // Allow users to change the extension.
   thePanel.allowsOtherFileTypes = YES;
 
+  // If extensions are hidden and we’re saving a file with multiple extensions,
+  // only the last extension will be hidden in the panel (".tar.gz" will become
+  // ".tar"). If the remaining extension is known, the OS will think that we're
+  // trying to add a non-default extension. To avoid the confusion, we ensure
+  // that all extensions are shown in the panel if the remaining extension is
+  // known by the OS.
+  NSString* fileName =
+    [[defaultFilename lastPathComponent] stringByDeletingPathExtension];
+  NSString* otherExtension = fileName.pathExtension;
+  if (otherExtension.length != 0) {
+    // There's another extension here. Get the UTI.
+    CFStringRef type =
+      UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
+                                            (CFStringRef)otherExtension, NULL);
+    if (type) {
+      if (!CFStringHasPrefix(type, CFSTR("dyn."))) {
+        // We have a UTI, otherwise the type would have a "dyn." prefix. Ensure
+        // extensions are shown in the panel.
+        [thePanel setExtensionHidden:NO];
+      }
+      CFRelease(type);
+    }
+  }
+
   // set up default directory
   NSString *theDir = PanelDefaultDirectory();
   if (theDir) {
     [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
   }
 
   // load the panel
   nsCocoaUtils::PrepareForNativeAppModalDialog();