Bug 571193. Move Mac OS X to UNIX filesystem code shared with Linux. Also fixes bug 506812, bug 528447, bug 530188. r=benwa sr=bsmedberg
authorJosh Aas <joshmoz@gmail.com>
Wed, 21 Jul 2010 23:25:24 -0400
changeset 48054 9c005e5d971919a6243570e31ba034a261a3c659
parent 48053 8ab6bd1f88aa62dcc4012ec804f1cb880c3bcaea
child 48055 f1bd51cdac68cf5b024f4cf1b37e3e58205bdf84
push idunknown
push userunknown
push dateunknown
reviewersbenwa, bsmedberg
bugs571193, 506812, 528447, 530188
milestone2.0b3pre
Bug 571193. Move Mac OS X to UNIX filesystem code shared with Linux. Also fixes bug 506812, bug 528447, bug 530188. r=benwa sr=bsmedberg
toolkit/xre/nsAppRunner.cpp
xpcom/io/CocoaFileUtils.h
xpcom/io/CocoaFileUtils.mm
xpcom/io/Makefile.in
xpcom/io/nsILocalFileMac.idl
xpcom/io/nsLocalFile.h
xpcom/io/nsLocalFileOSX.h
xpcom/io/nsLocalFileOSX.mm
xpcom/io/nsLocalFileUnix.cpp
xpcom/io/nsLocalFileUnix.h
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1507,32 +1507,27 @@ XRE_GetBinaryPath(const char* argv0, nsI
   if (!lfm)
     return NS_ERROR_FAILURE;
 
   // Works even if we're not bundled.
   CFBundleRef appBundle = CFBundleGetMainBundle();
   if (!appBundle)
     return NS_ERROR_FAILURE;
 
-  CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
-  if (!bundleURL)
+  CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
+  if (!executableURL)
     return NS_ERROR_FAILURE;
-
-  FSRef fileRef;
-  if (!CFURLGetFSRef(bundleURL, &fileRef)) {
-    CFRelease(bundleURL);
-    return NS_ERROR_FAILURE;
-  }
-
-  rv = lfm->InitWithFSRef(&fileRef);
-  CFRelease(bundleURL);
-
+  rv = lfm->InitWithCFURL(executableURL);
+  CFRelease(executableURL);
   if (NS_FAILED(rv))
     return rv;
 
+  // Callers expect a normalized path.
+  lfm->Normalize();
+
 #elif defined(XP_UNIX)
   struct stat fileStat;
   char exePath[MAXPATHLEN];
   char tmpPath[MAXPATHLEN];
 
   rv = NS_ERROR_FAILURE;
 
   // on unix, there is no official way to get the path of the current binary.
new file mode 100644
--- /dev/null
+++ b/xpcom/io/CocoaFileUtils.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Josh Aas <josh@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This namespace contains methods with Obj-C/Cocoa implementations. The header
+// is C/C++ for inclusion in C/C++-only files.
+
+#ifndef CocoaFileUtils_h_
+#define CocoaFileUtils_h_
+
+#include "nscore.h"
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace CocoaFileUtils {
+
+nsresult RevealFileInFinder(CFURLRef url);
+nsresult OpenURL(CFURLRef url);
+nsresult GetFileCreatorCode(CFURLRef url, OSType *creatorCode);
+nsresult SetFileCreatorCode(CFURLRef url, OSType creatorCode);
+nsresult GetFileTypeCode(CFURLRef url, OSType *typeCode);
+nsresult SetFileTypeCode(CFURLRef url, OSType typeCode);
+
+} // namespace CocoaFileUtils
+
+#endif
new file mode 100644
--- /dev/null
+++ b/xpcom/io/CocoaFileUtils.mm
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Josh Aas <josh@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CocoaFileUtils.h"
+#include <Cocoa/Cocoa.h>
+#include "nsObjCExceptions.h"
+#include "nsDebug.h"
+
+namespace CocoaFileUtils {
+
+nsresult RevealFileInFinder(CFURLRef url)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NS_ENSURE_ARG_POINTER(url);
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+  BOOL success = [[NSWorkspace sharedWorkspace] selectFile:[(NSURL*)url path] inFileViewerRootedAtPath:@""];
+  [ap release];
+
+  return (success ? NS_OK : NS_ERROR_FAILURE);
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult OpenURL(CFURLRef url)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NS_ENSURE_ARG_POINTER(url);
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+  BOOL success = [[NSWorkspace sharedWorkspace] openURL:(NSURL*)url];
+  [ap release];
+
+  return (success ? NS_OK : NS_ERROR_FAILURE);
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult GetFileCreatorCode(CFURLRef url, OSType *creatorCode)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NS_ENSURE_ARG_POINTER(url);
+  NS_ENSURE_ARG_POINTER(creatorCode);
+
+  nsresult rv = NS_ERROR_FAILURE;
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+  NSDictionary* dict = [[NSFileManager defaultManager] fileAttributesAtPath:[(NSURL*)url path] traverseLink:YES];
+  NSNumber* creatorNum = (NSNumber*)[dict objectForKey:NSFileHFSCreatorCode];
+  if (creatorNum) {
+    *creatorCode = [creatorNum unsignedLongValue];
+    rv = NS_OK;
+  }
+  [ap release];
+
+  return rv;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult SetFileCreatorCode(CFURLRef url, OSType creatorCode)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NS_ENSURE_ARG_POINTER(url);
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+  NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:creatorCode] forKey:NSFileHFSCreatorCode];
+  BOOL success = [[NSFileManager defaultManager] setAttributes:dict ofItemAtPath:[(NSURL*)url path] error:nil];
+  [ap release];
+  return (success ? NS_OK : NS_ERROR_FAILURE);
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult GetFileTypeCode(CFURLRef url, OSType *typeCode)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NS_ENSURE_ARG_POINTER(url);
+  NS_ENSURE_ARG_POINTER(typeCode);
+
+  nsresult rv = NS_ERROR_FAILURE;
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+  NSDictionary* dict = [[NSFileManager defaultManager] fileAttributesAtPath:[(NSURL*)url path] traverseLink:YES];
+  NSNumber* typeNum = (NSNumber*)[dict objectForKey:NSFileHFSTypeCode];
+  if (typeNum) {
+    *typeCode = [typeNum unsignedLongValue];
+    rv = NS_OK;
+  }
+  [ap release];
+
+  return rv;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult SetFileTypeCode(CFURLRef url, OSType typeCode)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NS_ENSURE_ARG_POINTER(url);
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+  NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:typeCode] forKey:NSFileHFSTypeCode];
+  BOOL success = [[NSFileManager defaultManager] setAttributes:dict ofItemAtPath:[(NSURL*)url path] error:nil];
+  [ap release];
+  return (success ? NS_OK : NS_ERROR_FAILURE);
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+} // namespace CocoaFileUtils
--- a/xpcom/io/Makefile.in
+++ b/xpcom/io/Makefile.in
@@ -72,35 +72,37 @@ CPPSRCS		= \
 		nsStorageStream.cpp \
 		nsStringStream.cpp \
 		nsUnicharInputStream.cpp \
 		nsIOUtil.cpp \
 		nsWildCard.cpp \
 		SpecialSystemDirectory.cpp \
 		$(NULL)
 
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+CMMSRCS		+= \
+		CocoaFileUtils.mm \
+		$(NULL)
+endif
+
 ifndef MOZ_NO_FAST_LOAD
 CPPSRCS += \
 		nsFastLoadFile.cpp \
 		nsFastLoadService.cpp \
 		$(NULL)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 CPPSRCS		+= nsLocalFileOS2.cpp
 else
-ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
-CMMSRCS		= nsLocalFileOSX.mm
-else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 CPPSRCS		+= nsLocalFileWin.cpp
 else
 CPPSRCS		+= nsLocalFileUnix.cpp
 endif # windows
-endif # mac
 endif # OS2
 
 EXPORTS		= \
 		nsAppDirectoryServiceDefs.h \
 		nsDirectoryService.h \
 		nsDirectoryServiceAtomList.h \
 		nsEscape.h \
 		nsFastLoadService.h \
@@ -113,25 +115,21 @@ EXPORTS		= \
 		nsStringStream.h \
 		nsStreamUtils.h \
 		nsWildCard.h \
 		$(NULL)			
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 EXPORTS		+= nsLocalFileOS2.h
 else
-ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
-EXPORTS		+= nsLocalFileOSX.h
-else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 EXPORTS		+= nsLocalFileWin.h
 else
 EXPORTS		+= nsLocalFileUnix.h
 endif # windows
-endif # cocoa
 endif # os2
 
 XPIDLSRCS	= \
 		nsIBinaryInputStream.idl \
 		nsIBinaryOutputStream.idl  \
 		nsIDirectoryEnumerator.idl \
 		nsIFastLoadFileControl.idl \
 		nsIFastLoadService.idl \
--- a/xpcom/io/nsILocalFileMac.idl
+++ b/xpcom/io/nsILocalFileMac.idl
@@ -45,17 +45,17 @@
 %}
 
       native OSType(OSType);
       native FSSpec(FSSpec);
       native FSRef(FSRef);
 [ptr] native FSRefPtr(FSRef);
       native CFURLRef(CFURLRef);
 
-[scriptable, uuid(86D685E5-EE3F-405A-B521-446529DB82E5)]
+[scriptable, uuid(DE4C75BE-D42B-4F8C-95D9-284C83CF29A4)]
 interface nsILocalFileMac : nsILocalFile
 {
    /**
     * initWithCFURL
     *
     * Init this object with a CFURLRef
     *
     * NOTE: Supported only for XP_MACOSX
@@ -73,28 +73,16 @@ interface nsILocalFileMac : nsILocalFile
     *
     * NOTE: Supported only for XP_MACOSX
     *
     * @param   aFSRef         the native FSRef
     *
     */
   [noscript] void initWithFSRef([const] in FSRefPtr aFSRef);
 
-   /**
-    * initToAppWithCreatorCode
-    *
-    * Init this object to point to an application having the given
-    * creator code. If this app is missing, this will fail. It will first
-    * look for running application with the given creator.
-    *
-    * @param   aAppCreator     the signature of the app
-    *
-    */
-  [noscript] void initToAppWithCreatorCode(in OSType aAppCreator);
-
     /**
     * getCFURL
     *
     * Returns the CFURLRef of the file object. The caller is
     * responsible for calling CFRelease() on it.
     *
     * NOTE: Observes the state of the followLinks attribute.
     * If the file object is an alias and followLinks is TRUE, returns
@@ -144,22 +132,17 @@ interface nsILocalFileMac : nsILocalFile
     * fileSizeWithResFork
     * 
     * Returns the combined size of both the data fork and the resource
     * fork (if present) rather than just the size of the data fork
     * as returned by GetFileSize()
     *
     */
    readonly attribute PRInt64 fileSizeWithResFork;
-    
-   /**
-    * Use with SetFileType() to specify the signature of current process
-    */
-   const unsigned long CURRENT_PROCESS_CREATOR = 0x8000000;
-    
+
    /**
     * fileType, creator
     *
     * File type and creator attributes
     *
     */
    [noscript] attribute OSType fileType;
    [noscript] attribute OSType fileCreator;
--- a/xpcom/io/nsLocalFile.h
+++ b/xpcom/io/nsLocalFile.h
@@ -67,18 +67,16 @@
 // so here we will export it.  Other users should not depend
 // on this.
 
 #include <errno.h>
 #include "nsILocalFile.h"
 
 #ifdef XP_WIN
 #include "nsLocalFileWin.h"
-#elif defined(XP_MACOSX)
-#include "nsLocalFileOSX.h"
 #elif defined(XP_UNIX) || defined(XP_BEOS)
 #include "nsLocalFileUnix.h"
 #elif defined(XP_OS2)
 #include "nsLocalFileOS2.h"
 #else
 #error NOT_IMPLEMENTED
 #endif
 
deleted file mode 100644
--- a/xpcom/io/nsLocalFileOSX.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2001, 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Conrad Carlen <ccarlen@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsLocalFileMac_h_
-#define nsLocalFileMac_h_
-
-#include "nsILocalFileMac.h"
-#include "nsString.h"
-#include "nsIHashable.h"
-
-class nsDirEnumerator;
-
-// Mac OS X 10.4 does not have stat64/lstat64
-#if defined(HAVE_STAT64) && defined(HAVE_LSTAT64) && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4)
-#define STAT stat64
-#define LSTAT lstat64
-#else
-#define STAT stat
-#define LSTAT lstat
-#endif
-
-// Mac OS X 10.4 does not have statvfs64
-#if defined(HAVE_STATVFS64) && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4)
-#define STATVFS statvfs64
-#else
-#define STATVFS statvfs
-#endif
-
-// The native charset of this implementation is UTF-8. The Unicode used by the
-// Mac OS file system is decomposed, so "Native" versions of these routines will
-// always use decomposed Unicode (NFD). Their "non-Native" counterparts are 
-// intended to be simple wrappers which call the "Native" version and convert 
-// between UTF-8 and UTF-16. All the work is done on the "Native" side except
-// for the conversion to NFC (composed Unicode) done in "non-Native" getters.
-
-class NS_COM nsLocalFile : public nsILocalFileMac,
-                           public nsIHashable
-{
-  friend class nsDirEnumerator;
-    
-public:
-  NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
-
-  nsLocalFile();
-
-  static nsresult nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIFILE
-  NS_DECL_NSILOCALFILE
-  NS_DECL_NSILOCALFILEMAC
-  NS_DECL_NSIHASHABLE
-
-public:
-  static void GlobalInit();
-  static void GlobalShutdown();
-
-private:
-  ~nsLocalFile();
-
-protected:
-  nsLocalFile(const nsLocalFile& src);
-  nsresult SetBaseURL(CFURLRef aCFURLRef); // retains aCFURLRef
-  nsresult GetFSRefInternal(FSRef& aFSRef);
-  nsresult GetPathInternal(nsACString& path); // Returns path respecting mFollowLinks
-  nsresult CopyInternal(nsIFile* newParentDir,
-                        const nsAString& newName,
-                        PRBool followLinks);
-  nsresult FillStatBufferInternal(struct STAT *statBuffer);
-
-protected:
-  CFURLRef     mBaseURL; // The FS object we represent
-  char         mPath[PATH_MAX]; // POSIX path, UTF-8, NULL terminated
-  PRPackedBool mFollowLinks;
-};
-
-#endif // nsLocalFileMac_h_
deleted file mode 100644
--- a/xpcom/io/nsLocalFileOSX.mm
+++ /dev/null
@@ -1,2278 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2001, 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Conrad Carlen <ccarlen@netscape.com>
- *  Jungshik Shin <jshin@mailaps.org>
- *  Asaf Romano <mozilla.mano@sent.com>
- *  Mark Mentovai <mark@moxienet.com>
- *  Josh Aas <josh@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsLocalFile.h"
-#include "nsDirectoryServiceDefs.h"
-
-#include "nsObjCExceptions.h"
-#include "nsAutoPtr.h"
-#include "nsString.h"
-#include "nsReadableUtils.h"
-#include "nsIDirectoryEnumerator.h"
-#include "nsISimpleEnumerator.h"
-#include "nsITimelineService.h"
-#include "nsTArray.h"
-
-#include "plbase64.h"
-#include "prmem.h"
-#include "nsCRT.h"
-#include "nsHashKeys.h"
-
-#include "nsTraceRefcntImpl.h"
-
-#include <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <stdlib.h>
-#include <utime.h>
-
-#define CHECK_INIT()                            \
-    PR_BEGIN_MACRO                              \
-        if (!mBaseURL)                          \
-            return NS_ERROR_NOT_INITIALIZED;    \
-    PR_END_MACRO
-
-static nsresult MacErrorMapper(OSErr inErr);
-static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
-static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr);
-
-#pragma mark -
-#pragma mark [FSRef operator==]
-
-bool operator==(const FSRef& lhs, const FSRef& rhs)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
-  return (::FSCompareFSRefs(&lhs, &rhs) == noErr);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-#pragma mark -
-#pragma mark [StFollowLinksState]
-
-class StFollowLinksState
-{
-  public:
-    StFollowLinksState(nsLocalFile& aFile) :
-        mFile(aFile)
-    {
-        mFile.GetFollowLinks(&mSavedState);
-    }
-
-    StFollowLinksState(nsLocalFile& aFile, PRBool followLinksState) :
-        mFile(aFile)
-    {
-        mFile.GetFollowLinks(&mSavedState);
-        mFile.SetFollowLinks(followLinksState);
-    }
-
-    ~StFollowLinksState()
-    {
-        mFile.SetFollowLinks(mSavedState);
-    }
-    
-  private:
-    nsLocalFile& mFile;
-    PRBool mSavedState;
-};
-
-#pragma mark -
-#pragma mark [nsDirEnumerator]
-
-class nsDirEnumerator : public nsISimpleEnumerator,
-                        public nsIDirectoryEnumerator
-{
-    public:
-
-        NS_DECL_ISUPPORTS
-
-        nsDirEnumerator() :
-          mIterator(nsnull),
-          mFSRefsArray(nsnull),
-          mArrayCnt(0), mArrayIndex(0)
-        {
-        }
-
-        nsresult Init(nsILocalFileMac* parent) 
-        {
-          NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-          NS_ENSURE_ARG(parent);
-          
-          OSErr err;
-          nsresult rv;
-          FSRef parentRef;
-          
-          rv = parent->GetFSRef(&parentRef);
-          if (NS_FAILED(rv))
-            return rv;
-          
-          mFSRefsArray = (FSRef *)nsMemory::Alloc(sizeof(FSRef)
-                                                  * kRequestCountPerIteration);
-          if (!mFSRefsArray)
-            return NS_ERROR_OUT_OF_MEMORY;
-          
-          err = ::FSOpenIterator(&parentRef, kFSIterateFlat, &mIterator);
-          if (err != noErr)
-            return MacErrorMapper(err);
-                              
-          return NS_OK;
-
-          NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-        }
-
-        NS_IMETHOD HasMoreElements(PRBool *result) 
-        {
-          NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-          if (!mIterator || !mFSRefsArray) {
-            *result = PR_FALSE;
-            return NS_OK;
-          }
-
-          if (mNext == nsnull) {
-            if (mArrayIndex >= mArrayCnt) {
-              ItemCount actualCnt;
-              OSErr err = ::FSGetCatalogInfoBulk(mIterator,
-                                           kRequestCountPerIteration,
-                                           &actualCnt,
-                                           nsnull,
-                                           kFSCatInfoNone,
-                                           nsnull,
-                                           mFSRefsArray,
-                                           nsnull,
-                                           nsnull);
-            
-              if (err == noErr || err == errFSNoMoreItems) {
-                mArrayCnt = actualCnt;
-                mArrayIndex = 0;
-              }
-            }
-
-            if (mArrayIndex < mArrayCnt) {
-              nsRefPtr<nsLocalFile> newFile = new nsLocalFile;
-              if (!newFile)
-                return NS_ERROR_OUT_OF_MEMORY;
-              FSRef fsRef = mFSRefsArray[mArrayIndex];
-              if (NS_FAILED(newFile->InitWithFSRef(&fsRef)))
-                return NS_ERROR_FAILURE;
-              mArrayIndex++;
-              mNext = newFile;
-            } 
-          }
-
-          *result = mNext != nsnull;
-          if (!*result)
-            Close();
-
-          return NS_OK;
-
-          NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-        }
-
-        NS_IMETHOD GetNext(nsISupports **result) 
-        {
-            NS_ENSURE_ARG_POINTER(result);
-            *result = nsnull;
-
-            nsresult rv;
-            PRBool hasMore;
-            rv = HasMoreElements(&hasMore);
-            if (NS_FAILED(rv)) return rv;
-
-            *result = mNext; // might return nsnull
-            NS_IF_ADDREF(*result);
-
-            mNext = nsnull;
-            return NS_OK;
-        }
-
-        NS_IMETHOD GetNextFile(nsIFile **result)
-        {
-            *result = nsnull;
-            PRBool hasMore = PR_FALSE;
-            nsresult rv = HasMoreElements(&hasMore);
-            if (NS_FAILED(rv) || !hasMore)
-                return rv;
-            *result = mNext;
-            NS_IF_ADDREF(*result);
-            mNext = nsnull;
-            return NS_OK;
-        }
-
-        NS_IMETHOD Close()
-        {
-          NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-          if (mIterator) {
-            ::FSCloseIterator(mIterator);
-            mIterator = nsnull;
-          }
-          if (mFSRefsArray) {
-            nsMemory::Free(mFSRefsArray);
-            mFSRefsArray = nsnull;
-          }
-          return NS_OK;
-
-          NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-        }
-
-    private:
-        ~nsDirEnumerator() 
-        {
-          Close();
-        }
-
-    protected:
-        // According to Apple doc, request the number of objects
-        // per call that will fit in 4 VM pages.
-        enum {
-          kRequestCountPerIteration = ((4096 * 4) / sizeof(FSRef))
-        };
-        
-        nsCOMPtr<nsILocalFileMac>   mNext;
-        
-        FSIterator              mIterator;
-        FSRef                   *mFSRefsArray;
-        PRInt32                 mArrayCnt, mArrayIndex;
-};
-
-NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
-
-const char kPathSepChar = '/';
-
-#pragma mark -
-#pragma mark [CTORs/DTOR]
-
-nsLocalFile::nsLocalFile() :
-  mBaseURL(NULL),
-  mFollowLinks(PR_TRUE)
-{
-  mPath[0] = '\0';
-}
-
-nsLocalFile::nsLocalFile(const nsLocalFile& src) :
-  mBaseURL(NULL),
-  mFollowLinks(src.mFollowLinks)
-{
-  SetBaseURL(src.mBaseURL);
-}
-
-nsLocalFile::~nsLocalFile()
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  if (mBaseURL)
-    ::CFRelease(mBaseURL);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-#pragma mark -
-#pragma mark [nsISupports]
-
-NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
-                              nsILocalFileMac,
-                              nsILocalFile,
-                              nsIFile,
-                              nsIHashable)
-                              
-nsresult
-nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
-{
-  NS_ENSURE_ARG_POINTER(aInstancePtr);
-  NS_ENSURE_NO_AGGREGATION(outer);
-
-  nsLocalFile* inst = new nsLocalFile();
-  if (inst == NULL)
-    return NS_ERROR_OUT_OF_MEMORY;
-  
-  nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
-  if (NS_FAILED(rv))
-  {
-    delete inst;
-    return rv;
-  }
-  return NS_OK;
-}
-
-#pragma mark -
-#pragma mark [nsIFile]
-
-NS_IMETHODIMP nsLocalFile::Append(const nsAString& aNode)
-{
-  return AppendNative(NS_ConvertUTF16toUTF8(aNode));
-}
-
-NS_IMETHODIMP nsLocalFile::AppendNative(const nsACString& aNode)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  nsACString::const_iterator start, end;
-  aNode.BeginReading(start);
-  aNode.EndReading(end);
-  if (FindCharInReadable(kPathSepChar, start, end))
-    return NS_ERROR_FILE_UNRECOGNIZED_PATH;
-
-  CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
-                                  PromiseFlatCString(aNode).get(),
-                                  kCFStringEncodingUTF8);
-  if (nodeStrRef) {
-    CFURLRef newRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
-                                  mBaseURL, nodeStrRef, PR_FALSE);
-    ::CFRelease(nodeStrRef);
-    if (newRef) {
-      SetBaseURL(newRef);
-      ::CFRelease(newRef);
-      return NS_OK;
-    }
-  }
-  return NS_ERROR_FAILURE;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::Normalize()
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  char resolved_path[PATH_MAX] = "";
-  if (!realpath(mPath, resolved_path))
-      return NSRESULT_FOR_ERRNO();
-
-  // Need to know whether we're a directory to create a new CFURLRef
-  PRBool isDirectory;
-  nsresult rv = IsDirectory(&isDirectory);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = NS_ERROR_FAILURE;
-  CFStringRef pathStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
-                                                       resolved_path,
-                                                       kCFStringEncodingUTF8);
-  if (pathStrRef) {
-    CFURLRef newURLRef =
-      ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pathStrRef,
-                                      kCFURLPOSIXPathStyle, isDirectory);
-    if (newURLRef) {
-      SetBaseURL(newURLRef);
-      ::CFRelease(newURLRef);
-      rv = NS_OK;
-    }
-    ::CFRelease(pathStrRef);
-  }
-
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::Create(PRUint32 type, PRUint32 permissions)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
-    return NS_ERROR_FILE_UNKNOWN_TYPE;
-
-  CHECK_INIT();
-  
-  nsTArray<nsString> nonExtantNodes;
-  CFURLRef pathURLRef = mBaseURL;
-  FSRef pathFSRef;
-  CFStringRef leafStrRef = nsnull;
-  nsAutoTArray<UniChar, NAME_MAX> buffer;
-  Boolean success;
-  
-  // Work backwards through the path to find the last node which
-  // exists. Place the nodes which don't exist in an array and we'll
-  // create those below.
-  while ((success = ::CFURLGetFSRef(pathURLRef, &pathFSRef)) == false) {
-    leafStrRef = ::CFURLCopyLastPathComponent(pathURLRef);
-    if (!leafStrRef)
-      break;
-    CFIndex leafLen = ::CFStringGetLength(leafStrRef);
-    if (!buffer.SetLength(leafLen + 1))
-      break;
-    ::CFStringGetCharacters(leafStrRef, CFRangeMake(0, leafLen), buffer.Elements());
-    buffer[leafLen] = '\0';
-    nonExtantNodes.AppendElement(nsString(nsDependentString(buffer.Elements())));
-    ::CFRelease(leafStrRef);
-    leafStrRef = nsnull;
-    
-    // Get the parent of the leaf for the next go round
-    CFURLRef parent = ::CFURLCreateCopyDeletingLastPathComponent(NULL, pathURLRef);
-    if (!parent)
-      break;
-    if (pathURLRef != mBaseURL)
-      ::CFRelease(pathURLRef);
-    pathURLRef = parent;
-  }
-  if (pathURLRef != mBaseURL)
-    ::CFRelease(pathURLRef);
-  if (leafStrRef != nsnull)
-    ::CFRelease(leafStrRef);
-  if (!success)
-    return NS_ERROR_FAILURE;
-  PRInt32 nodesToCreate = PRInt32(nonExtantNodes.Length());
-  if (nodesToCreate == 0)
-    return NS_ERROR_FILE_ALREADY_EXISTS;
-  
-  OSErr err;    
-  nsAutoString nextNodeName;
-  for (PRInt32 i = nodesToCreate - 1; i > 0; i--) {
-    nextNodeName = nonExtantNodes[i];
-    err = ::FSCreateDirectoryUnicode(&pathFSRef,
-                                      nextNodeName.Length(),
-                                      (const UniChar *)nextNodeName.get(),
-                                      kFSCatInfoNone,
-                                      nsnull, &pathFSRef, nsnull, nsnull);
-    if (err != noErr)
-      return MacErrorMapper(err);
-  }
-  nextNodeName = nonExtantNodes[0];
-  if (type == NORMAL_FILE_TYPE) {
-    err = ::FSCreateFileUnicode(&pathFSRef,
-                                nextNodeName.Length(),
-                                (const UniChar *)nextNodeName.get(),
-                                kFSCatInfoNone,
-                                nsnull, nsnull, nsnull);
-  }
-  else {
-    err = ::FSCreateDirectoryUnicode(&pathFSRef,
-                                    nextNodeName.Length(),
-                                    (const UniChar *)nextNodeName.get(),
-                                    kFSCatInfoNone,
-                                    nsnull, nsnull, nsnull, nsnull);
-  }
-            
-  return MacErrorMapper(err);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetLeafName(nsAString& aLeafName)
-{
-  nsCAutoString nativeString;
-  nsresult rv = GetNativeLeafName(nativeString);
-  if (NS_FAILED(rv))
-    return rv;
-  CopyUTF8toUTF16NFC(nativeString, aLeafName);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::SetLeafName(const nsAString& aLeafName)
-{
-  return SetNativeLeafName(NS_ConvertUTF16toUTF8(aLeafName));
-}
-
-NS_IMETHODIMP nsLocalFile::GetNativeLeafName(nsACString& aNativeLeafName)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  nsresult rv = NS_ERROR_FAILURE;
-  CFStringRef leafStrRef = ::CFURLCopyLastPathComponent(mBaseURL);
-  if (leafStrRef) {
-    rv = CFStringReftoUTF8(leafStrRef, aNativeLeafName);
-    ::CFRelease(leafStrRef);
-  }
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::SetNativeLeafName(const nsACString& aNativeLeafName)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  nsresult rv = NS_ERROR_FAILURE;
-  CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseURL);
-  if (parentURLRef) {
-    CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
-                                    PromiseFlatCString(aNativeLeafName).get(),
-                                    kCFStringEncodingUTF8);
-
-    if (nodeStrRef) {
-      CFURLRef newURLRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
-                                    parentURLRef, nodeStrRef, PR_FALSE);
-      if (newURLRef) {
-        SetBaseURL(newURLRef);
-        ::CFRelease(newURLRef);
-        rv = NS_OK;
-      }
-      ::CFRelease(nodeStrRef);
-    }
-    ::CFRelease(parentURLRef);
-  }
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString& newName)
-{
-  return CopyInternal(newParentDir, newName, PR_FALSE);
-}
-
-NS_IMETHODIMP nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString& newName)
-{
-  return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_FALSE);
-}
-
-NS_IMETHODIMP nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString& newName)
-{
-  return CopyInternal(newParentDir, newName, PR_TRUE);
-}
-
-NS_IMETHODIMP nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString& newName)
-{
-  return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_TRUE);
-}
-
-NS_IMETHODIMP nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString& newName)
-{
-  return MoveToNative(newParentDir, NS_ConvertUTF16toUTF8(newName));
-}
-
-NS_IMETHODIMP nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString& newName)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  StFollowLinksState followLinks(*this, PR_FALSE);
-
-  PRBool isDirectory;
-  nsresult rv = IsDirectory(&isDirectory);
-  if (NS_FAILED(rv))
-    return rv;
-
-  // Build the destination path.
-  nsCOMPtr<nsIFile> parentDir = newParentDir;
-  if (!parentDir) {
-    if (newName.IsEmpty())
-      return NS_ERROR_INVALID_ARG;
-    rv = GetParent(getter_AddRefs(parentDir));
-    if (NS_FAILED(rv))
-      return rv;   
-  }
-  else {
-    PRBool exists;
-    rv = parentDir->Exists(&exists);
-    if (NS_FAILED(rv))
-      return rv;
-    if (!exists) {
-      rv = parentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
-      if (NS_FAILED(rv))
-        return rv;
-    }
-  }
-
-  nsCAutoString destPath;
-  rv = parentDir->GetNativePath(destPath);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (!newName.IsEmpty())
-    destPath.Append(NS_LITERAL_CSTRING("/") + newName);
-  else {
-    nsCAutoString leafName;
-    rv = GetNativeLeafName(leafName);
-    if (NS_FAILED(rv))
-      return rv;
-    destPath.Append(NS_LITERAL_CSTRING("/") + leafName);
-  }
-
-  // Perform the move.
-  if (rename(mPath, destPath.get()) != 0) {
-    if (errno == EXDEV) {
-      // Can't move across volume (device) boundaries.  Copy and remove.
-      rv = CopyToNative(parentDir, newName);
-      if (NS_SUCCEEDED(rv)) {
-        // Permit removal failure.
-        Remove(PR_TRUE);
-      }
-    }
-    else
-      rv = NSRESULT_FOR_ERRNO();
-
-    if (NS_FAILED(rv))
-      return rv;
-  }
-
-  // Update |this| to refer to the moved file.
-  CFURLRef newBaseRef =
-   ::CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)destPath.get(),
-                                             destPath.Length(), isDirectory);
-  if (!newBaseRef)
-    return NS_ERROR_FAILURE;
-  SetBaseURL(newBaseRef);
-  ::CFRelease(newBaseRef);
-
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::Remove(PRBool recursive)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  // if we're a symlink, never remove target
-  StFollowLinksState followLinks(*this, PR_FALSE);
-
-  PRBool isDirectory;
-  nsresult rv = IsDirectory(&isDirectory);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (recursive && isDirectory) {
-    CFURLRef urlRef;
-    rv = GetCFURL(&urlRef);
-    if (NS_SUCCEEDED(rv) && urlRef) {
-      NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-      BOOL removeSuccess = [[NSFileManager defaultManager] removeFileAtPath:[(NSURL*)urlRef path] handler:nil];
-      [ap release];
-      ::CFRelease(urlRef);
-      rv = removeSuccess ? NS_OK : NS_ERROR_FAILURE;
-    }
-  }
-  else {
-    int status;
-    if (isDirectory)
-      status = rmdir(mPath);
-    else
-      status = unlink(mPath);
-
-    if (status != 0)
-      rv = NSRESULT_FOR_ERRNO();
-  }
-
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-// Only send back permissions bits: maybe we want to send back the whole
-// mode_t to permit checks against other file types?
-#define NORMALIZE_PERMS(mode)    ((mode)& (S_IRWXU | S_IRWXG | S_IRWXO))
-
-NS_IMETHODIMP nsLocalFile::GetPermissions(PRUint32 *aPermissions)
-{
-  NS_ENSURE_ARG_POINTER(aPermissions);
-
-  CHECK_INIT();
-
-  struct STAT buf;
-  nsresult rv = FillStatBufferInternal(&buf);
-  if (NS_FAILED(rv))
-    return NSRESULT_FOR_ERRNO();
-
-  *aPermissions = NORMALIZE_PERMS(buf.st_mode);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::SetPermissions(PRUint32 aPermissions)
-{
-  CHECK_INIT();
-
-  if (chmod(mPath, aPermissions) < 0)
-    return NSRESULT_FOR_ERRNO();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
-{
-    NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissionsOfLink)
-{
-    NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
-{
-  NS_ENSURE_ARG_POINTER(aLastModifiedTime);
-
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-
-  PRFileInfo64 info;
-  if (PR_GetFileInfo64(path.get(), &info) != PR_SUCCESS)
-    return NSRESULT_FOR_ERRNO();
-  PRInt64 modTime = PRInt64(info.modifyTime);
-  if (modTime == 0)
-    *aLastModifiedTime = 0;
-  else
-    *aLastModifiedTime = modTime / PRInt64(PR_USEC_PER_MSEC);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
-{
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-
-  int result;
-  if (aLastModifiedTime != 0) {
-    struct STAT statBuf;
-    nsresult rv = FillStatBufferInternal(&statBuf);
-    if (NS_FAILED(rv))
-      return rv;
-
-    struct utimbuf ut;
-    ut.actime = statBuf.st_atime;
-
-    // convert milliseconds to seconds since the unix epoch
-    ut.modtime = (time_t)(PRFloat64(aLastModifiedTime) / PR_MSEC_PER_SEC);
-    result = utime(path.get(), &ut);
-  } else {
-    result = utime(path.get(), nsnull);
-  }
-  return NSRESULT_FOR_RETURN(result);
-}
-
-NS_IMETHODIMP nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTimeOfLink)
-{
-  NS_ENSURE_ARG(aLastModifiedTimeOfLink);
-
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-
-  struct STAT sbuf;
-  if (LSTAT(path.get(), &sbuf) == -1)
-    return NSRESULT_FOR_ERRNO();
-  *aLastModifiedTimeOfLink = PRInt64(sbuf.st_mtime) * PRInt64(PR_MSEC_PER_SEC);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTimeOfLink)
-{
-  return SetLastModifiedTime(aLastModifiedTimeOfLink);
-}
-
-NS_IMETHODIMP nsLocalFile::GetFileSize(PRInt64 *aFileSize)
-{
-  NS_ENSURE_ARG_POINTER(aFileSize);
-  *aFileSize = 0;
-
-  struct STAT buf;
-  nsresult rv = FillStatBufferInternal(&buf);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (!S_ISDIR(buf.st_mode))
-    *aFileSize = (PRInt64)buf.st_size;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::SetFileSize(PRInt64 aFileSize)
-{
-  CHECK_INIT();
-
-  off_t size = (off_t)aFileSize;
-  if (truncate(mPath, size) == -1)
-    return NSRESULT_FOR_ERRNO();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSizeOfLink)
-{
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(aFileSizeOfLink);
-  
-  StFollowLinksState followLinks(*this, PR_FALSE);
-  return GetFileSize(aFileSizeOfLink);
-}
-
-NS_IMETHODIMP nsLocalFile::GetTarget(nsAString& aTarget)
-{
-  nsCAutoString nativeString;
-  nsresult rv = GetNativeTarget(nativeString);
-  if (NS_FAILED(rv))
-    return rv;
-  CopyUTF8toUTF16NFC(nativeString, aTarget);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetNativeTarget(nsACString& aNativeTarget)
-{
-  CHECK_INIT();
-
-  aNativeTarget.Truncate();
-  
-  struct STAT symStat;
-  if (LSTAT(mPath, &symStat) == -1)
-    return NSRESULT_FOR_ERRNO();
-  
-  if (!S_ISLNK(symStat.st_mode))
-    return NS_ERROR_FILE_INVALID_PATH;
-  
-  PRInt32 size = (PRInt32)symStat.st_size;
-  char *target = (char *)nsMemory::Alloc(size + 1);
-  if (!target)
-    return NS_ERROR_OUT_OF_MEMORY;
-  
-  if (readlink(mPath, target, (size_t)size) < 0) {
-    nsMemory::Free(target);
-    return NSRESULT_FOR_ERRNO();
-  }
-  target[size] = '\0';
-  
-  nsresult rv = NS_OK;
-  nsCOMPtr<nsIFile> self(this);
-  PRInt32 maxLinks = 40;
-  while (PR_TRUE) {
-    if (maxLinks-- == 0) {
-      rv = NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
-      break;
-    }
-    
-    if (target[0] != '/') {
-      nsCOMPtr<nsIFile> parent;
-      if (NS_FAILED(rv = self->GetParent(getter_AddRefs(parent))))
-        break;
-      nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(parent, &rv));
-      if (NS_FAILED(rv))
-        break;
-      if (NS_FAILED(rv = localFile->AppendRelativeNativePath(nsDependentCString(target))))
-        break;
-      if (NS_FAILED(rv = localFile->GetNativePath(aNativeTarget)))
-        break;
-      self = parent;
-    } else {
-      aNativeTarget = target;
-    }
-    
-    const nsPromiseFlatCString &flatRetval = PromiseFlatCString(aNativeTarget);
-    
-    // Any failure in testing the current target we'll just interpret
-    // as having reached our destiny.
-    if (LSTAT(flatRetval.get(), &symStat) == -1)
-      break;
-    
-    // And of course we're done if it isn't a symlink.
-    if (!S_ISLNK(symStat.st_mode))
-      break;
-    
-    PRInt32 newSize = (PRInt32)symStat.st_size;
-    if (newSize > size) {
-      char *newTarget = (char *)nsMemory::Realloc(target, newSize + 1);
-      if (!newTarget) {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-        break;
-      }
-      target = newTarget;
-      size = newSize;
-    }
-    
-    PRInt32 linkLen = readlink(flatRetval.get(), target, size);
-    if (linkLen == -1) {
-      rv = NSRESULT_FOR_ERRNO();
-      break;
-    }
-    target[linkLen] = '\0';
-  }
-  
-  nsMemory::Free(target);
-  
-  if (NS_FAILED(rv))
-    aNativeTarget.Truncate();
-  return rv;  
-}
-
-NS_IMETHODIMP nsLocalFile::GetPath(nsAString& aPath)
-{
-  nsCAutoString nativeString;
-  nsresult rv = GetNativePath(nativeString);
-  if (NS_FAILED(rv))
-    return rv;
-  CopyUTF8toUTF16NFC(nativeString, aPath);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetNativePath(nsACString& aNativePath)
-{
-  CHECK_INIT();
-
-  aNativePath.Assign(mPath);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::Exists(PRBool *_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  struct STAT buf;
-  *_retval = (STAT(mPath, &buf) == 0);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::IsWritable(PRBool *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-  // don't bother resolving, this always traverses symbolic links
-  *_retval = (PRBool)[[NSFileManager defaultManager] isWritableFileAtPath:[(NSURL*)mBaseURL path]];
-  [ap release];
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::IsReadable(PRBool *_retval)
-{
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  PRUint32 permissions;
-  nsresult rv = GetPermissions(&permissions);
-  if (NS_FAILED(rv))
-    return rv;
-  *_retval = ((permissions & S_IRUSR) != 0);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::IsExecutable(PRBool *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-  
-  FSRef fsRef;
-  nsresult rv = GetFSRefInternal(fsRef);
-  if (NS_FAILED(rv))
-    return rv;
-    
-  LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
-  LSItemInfoRecord theInfo;
-  if (::LSCopyItemInfoForRef(&fsRef, theInfoRequest, &theInfo) == noErr) {
-    if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
-    *_retval = PR_TRUE;
-  }
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::IsHidden(PRBool *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  // If the leaf name begins with a '.', consider it invisible
-  nsAutoString name;
-  nsresult rv = GetLeafName(name);
-  if (NS_FAILED(rv))
-    return rv;
-  if (name.Length() >= 1 && Substring(name, 0, 1).EqualsLiteral("."))
-    *_retval = PR_TRUE;
-
-  LSItemInfoRecord itemInfo;
-  LSCopyItemInfoForURL(mBaseURL, kLSRequestBasicFlagsOnly, &itemInfo);
-  *_retval = !!(itemInfo.flags & kLSItemInfoIsInvisible);
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::IsDirectory(PRBool *_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  struct STAT buf;
-  nsresult rv = FillStatBufferInternal(&buf);
-  if (NS_FAILED(rv))
-    return rv;
-
-  *_retval = S_ISDIR(buf.st_mode);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::IsFile(PRBool *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  struct STAT buf;
-  nsresult rv = FillStatBufferInternal(&buf);
-  if (NS_FAILED(rv))
-    return rv;
-
-  *_retval = S_ISREG(buf.st_mode);
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::IsSymlink(PRBool *_retval)
-{
-  CHECK_INIT();
-
-  NS_ENSURE_ARG(_retval);
-  *_retval = PR_FALSE;
-
-  struct stat symStat;
-  if (lstat(mPath, &symStat) < 0)
-    return NSRESULT_FOR_ERRNO();
-  *_retval = S_ISLNK(symStat.st_mode);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::IsSpecial(PRBool *_retval)
-{
-  NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP nsLocalFile::Clone(nsIFile **_retval)
-{
-    // Just copy-construct ourselves
-    *_retval = new nsLocalFile(*this);
-    if (!*_retval)
-      return NS_ERROR_OUT_OF_MEMORY;
-
-    NS_ADDREF(*_retval);
-    
-    return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
-{
-  NS_ENSURE_ARG(inFile);
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  nsCAutoString inPath;
-  nsresult rv = inFile->GetNativePath(inPath);
-  if (NS_FAILED(rv))
-    return rv;
-
-  *_retval = !strcmp(mPath, inPath.get());
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
-{
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PR_FALSE;
-
-  PRBool isDir;
-  nsresult rv = IsDirectory(&isDir);
-  if (NS_FAILED(rv))
-    return rv;
-  if (!isDir)
-    return NS_OK;     // must be a dir to contain someone
-
-  nsCAutoString thisPath, inPath;
-  if (NS_FAILED(GetNativePath(thisPath)) || NS_FAILED(inFile->GetNativePath(inPath)))
-    return NS_ERROR_FAILURE;
-  size_t thisPathLen = thisPath.Length();
-  if ((inPath.Length() > thisPathLen + 1) && (strncasecmp(thisPath.get(), inPath.get(), thisPathLen) == 0)) {
-    // Now make sure that the |inFile|'s path has a separator at thisPathLen,
-    // and there's at least one more character after that.
-    if (inPath[thisPathLen] == kPathSepChar)
-      *_retval = PR_TRUE;
-  }  
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetParent(nsIFile * *aParent)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(aParent);
-  *aParent = nsnull;
-
-  CHECK_INIT();
-
-  // If it can be determined without error that a file does not
-  // have a parent, return nsnull for the parent and NS_OK as the result.
-  // See bug 133617.
-  nsresult rv = NS_OK;
-  CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseURL);
-  if (parentURLRef) {
-    // If the parent path is longer than file's path then 
-    // CFURLCreateCopyDeletingLastPathComponent must have simply added
-    // two dots at the end - in this case indicate that there is no parent.
-    // See bug 332389.
-    CFStringRef path = ::CFURLGetString(mBaseURL);
-    CFStringRef newPath = ::CFURLGetString(parentURLRef);
-    if (::CFStringGetLength(newPath) < ::CFStringGetLength(path)) {
-      rv = NS_ERROR_FAILURE;
-      nsRefPtr<nsLocalFile> newFile = new nsLocalFile;
-      if (newFile) {
-        rv = newFile->InitWithCFURL(parentURLRef);
-        if (NS_SUCCEEDED(rv)) {
-          NS_ADDREF(*aParent = newFile);
-          rv = NS_OK;
-        }
-      }
-    }
-    ::CFRelease(parentURLRef);
-  }
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **aDirectoryEntries)
-{
-  NS_ENSURE_ARG_POINTER(aDirectoryEntries);
-  *aDirectoryEntries = nsnull;
-
-  nsresult rv;
-  PRBool isDir;
-  rv = IsDirectory(&isDir);
-  if (NS_FAILED(rv)) 
-    return rv;
-  if (!isDir)
-    return NS_ERROR_FILE_NOT_DIRECTORY;
-
-  nsDirEnumerator* dirEnum = new nsDirEnumerator;
-  if (dirEnum == nsnull)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(dirEnum);
-  rv = dirEnum->Init(this);
-  if (NS_FAILED(rv)) {
-    NS_RELEASE(dirEnum);
-    return rv;
-  }
-  *aDirectoryEntries = dirEnum;
-  
-  return NS_OK;
-}
-
-#pragma mark -
-#pragma mark [nsILocalFile]
-
-NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString& filePath)
-{
-  return InitWithNativePath(NS_ConvertUTF16toUTF8(filePath));
-}
-
-NS_IMETHODIMP nsLocalFile::InitWithNativePath(const nsACString& filePath)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  nsCAutoString fixedPath;
-  if (Substring(filePath, 0, 2).EqualsLiteral("~/")) {
-    nsCOMPtr<nsIFile> homeDir;
-    nsCAutoString homePath;
-    nsresult rv = NS_GetSpecialDirectory(NS_OS_HOME_DIR,
-                                        getter_AddRefs(homeDir));
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = homeDir->GetNativePath(homePath);
-    NS_ENSURE_SUCCESS(rv, rv);
-    
-    fixedPath = homePath + Substring(filePath, 1, filePath.Length() - 1);
-  }
-  else if (filePath.IsEmpty() || filePath.First() != '/')
-    return NS_ERROR_FILE_UNRECOGNIZED_PATH;
-  else
-    fixedPath.Assign(filePath);
-
-  // A path with consecutive '/'s which are not between
-  // nodes crashes CFURLGetFSRef(). Consecutive '/'s which
-  // are between actual nodes are OK. So, convert consecutive
-  // '/'s to a single one.
-  fixedPath.ReplaceSubstring("//", "/");
-
-  // On 10.2, huge paths also crash CFURLGetFSRef()
-  if (fixedPath.Length() > PATH_MAX)
-    return NS_ERROR_FILE_NAME_TOO_LONG;
-
-  CFStringRef pathAsCFString;
-  CFURLRef pathAsCFURL;
-
-  pathAsCFString = ::CFStringCreateWithCString(nsnull, fixedPath.get(), kCFStringEncodingUTF8);
-  if (!pathAsCFString)
-    return NS_ERROR_FAILURE;
-  pathAsCFURL = ::CFURLCreateWithFileSystemPath(nsnull, pathAsCFString, kCFURLPOSIXPathStyle, PR_FALSE);
-  if (!pathAsCFURL) {
-    ::CFRelease(pathAsCFString);
-    return NS_ERROR_FAILURE;
-  }
-  SetBaseURL(pathAsCFURL);
-  ::CFRelease(pathAsCFURL);
-  ::CFRelease(pathAsCFString);
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::InitWithFile(nsILocalFile *aFile)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG(aFile);
-  
-  nsCOMPtr<nsILocalFileMac> aFileMac(do_QueryInterface(aFile));
-  if (!aFileMac)
-    return NS_ERROR_UNEXPECTED;
-  CFURLRef urlRef;
-  nsresult rv = aFileMac->GetCFURL(&urlRef);
-  if (NS_FAILED(rv))
-    return rv;
-  rv = InitWithCFURL(urlRef);
-  ::CFRelease(urlRef);
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
-{
-  NS_ENSURE_ARG_POINTER(aFollowLinks);
-  
-  *aFollowLinks = mFollowLinks;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
-{
-  mFollowLinks = aFollowLinks;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-    
-  *_retval = PR_Open(path.get(), flags, mode);
-  if (! *_retval)
-    return NS_ErrorAccordingToNSPR();
-
-  if (flags & DELETE_ON_CLOSE) {
-    PR_Delete(path.get());
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::OpenANSIFileDesc(const char *mode, FILE **_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-    
-  *_retval = fopen(path.get(), mode);
-  if (! *_retval)
-    return NS_ERROR_FAILURE;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::Load(PRLibrary **_retval)
-{
-  CHECK_INIT();
-
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  NS_TIMELINE_START_TIMER("PR_LoadLibrary");
-
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-
-#ifdef NS_BUILD_REFCNT_LOGGING
-  nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
-#endif
-
-  *_retval = PR_LoadLibrary(path.get());
-
-#ifdef NS_BUILD_REFCNT_LOGGING
-  nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
-#endif
-
-  NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
-  NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", path.get());
-
-  if (!*_retval)
-    return NS_ERROR_FAILURE;
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(aDiskSpaceAvailable);
-
-  nsCAutoString path;
-  nsresult rv = GetPathInternal(path);
-  if (NS_FAILED(rv))
-    return rv;
-
-  struct STATVFS fs_buf;
-  if (STATVFS(path.get(), &fs_buf) < 0)
-    return NS_ERROR_FAILURE;
-  // minus one block for fuzz
-  *aDiskSpaceAvailable = (PRInt64)fs_buf.f_frsize * (fs_buf.f_bavail - 1);
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::AppendRelativePath(const nsAString& relativeFilePath)
-{
-  return AppendRelativeNativePath(NS_ConvertUTF16toUTF8(relativeFilePath));
-}
-
-NS_IMETHODIMP nsLocalFile::AppendRelativeNativePath(const nsACString& relativeFilePath)
-{  
-  if (relativeFilePath.IsEmpty())
-    return NS_OK;
-  // No leading '/' 
-  if (relativeFilePath.First() == '/')
-    return NS_ERROR_FILE_UNRECOGNIZED_PATH;
-
-  // Parse the nodes and call Append() for each
-  nsACString::const_iterator nodeBegin, pathEnd;
-  relativeFilePath.BeginReading(nodeBegin);
-  relativeFilePath.EndReading(pathEnd);
-  nsACString::const_iterator nodeEnd(nodeBegin);
-  
-  while (nodeEnd != pathEnd) {
-    FindCharInReadable(kPathSepChar, nodeEnd, pathEnd);
-    nsresult rv = AppendNative(Substring(nodeBegin, nodeEnd));
-    if (NS_FAILED(rv))
-      return rv;
-    if (nodeEnd != pathEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
-      ++nodeEnd;
-    nodeBegin = nodeEnd;
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::GetPersistentDescriptor(nsACString& aPersistentDescriptor)
-{
-  return GetNativePath(aPersistentDescriptor);
-}
-
-NS_IMETHODIMP nsLocalFile::SetPersistentDescriptor(const nsACString& aPersistentDescriptor)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  if (aPersistentDescriptor.IsEmpty())
-    return NS_ERROR_INVALID_ARG;
-
-  // Support pathnames as user-supplied descriptors if they begin with '/'
-  // or '~'.  These characters do not collide with the base64 set used for
-  // encoding alias records.
-  char first = aPersistentDescriptor.First();
-  if (first == '/' || first == '~')
-    return InitWithNativePath(aPersistentDescriptor);
-
-  nsresult rv = NS_OK;
-  
-  PRUint32 dataSize = aPersistentDescriptor.Length();    
-  char* decodedData = PL_Base64Decode(PromiseFlatCString(aPersistentDescriptor).get(), dataSize, nsnull);
-  if (!decodedData) {
-    NS_ERROR("SetPersistentDescriptor was given bad data");
-    return NS_ERROR_FAILURE;
-  }
-  
-  // Cast to an alias record and resolve.
-  AliasRecord aliasHeader = *(AliasPtr)decodedData;
-  PRInt32 aliasSize = ::GetAliasSizeFromPtr(&aliasHeader);
-  if (aliasSize > ((PRInt32)dataSize * 3) / 4) { // be paranoid about having too few data
-    PR_Free(decodedData);
-    return NS_ERROR_FAILURE;
-  }
-  
-  // Move the now-decoded data into the Handle.
-  // The size of the decoded data is 3/4 the size of the encoded data. See plbase64.h
-  Handle  newHandle = nsnull;
-  if (::PtrToHand(decodedData, &newHandle, aliasSize) != noErr)
-    rv = NS_ERROR_OUT_OF_MEMORY;
-  PR_Free(decodedData);
-  if (NS_FAILED(rv))
-    return rv;
-
-  Boolean changed;
-  FSRef resolvedFSRef;
-  OSErr err = ::FSResolveAlias(nsnull, (AliasHandle)newHandle, &resolvedFSRef, &changed);
-    
-  rv = MacErrorMapper(err);
-  DisposeHandle(newHandle);
-  if (NS_FAILED(rv))
-    return rv;
- 
-  return InitWithFSRef(&resolvedFSRef);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::Reveal()
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  BOOL success = NO;
-
-  CFURLRef urlRef;
-  if (NS_SUCCEEDED(GetCFURL(&urlRef)) && urlRef) {
-    NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-    success = [[NSWorkspace sharedWorkspace] selectFile:[(NSURL*)urlRef path] inFileViewerRootedAtPath:@""];
-    [ap release];
-
-    ::CFRelease(urlRef);
-  }
-
-  return (success ? NS_OK : NS_ERROR_FAILURE);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::Launch()
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  BOOL success = NO;
-
-  CFURLRef urlRef;
-  if (NS_SUCCEEDED(GetCFURL(&urlRef)) && urlRef) {
-    NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-    success = [[NSWorkspace sharedWorkspace] openURL:(NSURL*)urlRef];
-    [ap release];
-
-    ::CFRelease(urlRef);
-  }
-
-  return (success ? NS_OK : NS_ERROR_FAILURE);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-#pragma mark -
-#pragma mark [nsILocalFileMac]
-
-NS_IMETHODIMP nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
-{
-  NS_ENSURE_ARG(aCFURL);
-  
-  SetBaseURL(aCFURL);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsLocalFile::InitWithFSRef(const FSRef *aFSRef)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG(aFSRef);
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  CFURLRef newURLRef = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aFSRef);
-  if (newURLRef) {
-    SetBaseURL(newURLRef);
-    ::CFRelease(newURLRef);
-    rv = NS_OK;
-  }
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  FSRef fsRef;
-  OSErr err = ::LSFindApplicationForInfo(aAppCreator, nsnull, nsnull, &fsRef, nsnull);
-  if (err != noErr)
-    return MacErrorMapper(err);
-  return InitWithFSRef(&fsRef);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetCFURL(CFURLRef *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  if (mFollowLinks) {
-    nsCAutoString nativePath;
-    nsresult rv = GetNativeTarget(nativePath);
-    if (NS_SUCCEEDED(rv)) {
-      // This is a symlink if we can get a target path.
-      // We can assume this is not a directory if we know it is a symlink.
-      // I'll say this anyway because it is so dangerous: Do not call IsDirectory
-      // here because that ultimately ends up calling GetCFURL and you get a loop.
-      CFURLRef targetURL = ::CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
-                                                                     (UInt8*)nativePath.BeginWriting(),
-                                                                     nativePath.Length(),
-                                                                     false);
-      if (!targetURL)
-        return NS_ERROR_FAILURE;
-      *_retval = targetURL;
-      return NS_OK;
-    }
-  }
-
-  ::CFRetain(mBaseURL);
-  *_retval = mBaseURL;
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetFSRef(FSRef *_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-  return GetFSRefInternal(*_retval);
-}
-
-NS_IMETHODIMP nsLocalFile::GetFSSpec(FSSpec *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(_retval);
-  CHECK_INIT();
-
-  FSRef fsRef;
-  nsresult rv = GetFSRefInternal(fsRef);
-  if (NS_SUCCEEDED(rv)) {
-    OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNone, nsnull, nsnull, _retval, nsnull);
-    return MacErrorMapper(err); 
-  }
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSizeWithResFork)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(aFileSizeWithResFork);
-  
-  FSRef fsRef;
-  nsresult rv = GetFSRefInternal(fsRef);
-  if (NS_FAILED(rv))
-    return rv;
-      
-  FSCatalogInfo catalogInfo;
-  OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoDataSizes + kFSCatInfoRsrcSizes,
-                                 &catalogInfo, nsnull, nsnull, nsnull);
-  if (err != noErr)
-    return MacErrorMapper(err);
-    
-  *aFileSizeWithResFork = catalogInfo.dataLogicalSize + catalogInfo.rsrcLogicalSize;
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetFileType(OSType *aFileType)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(aFileType);
-
-  CHECK_INIT();
-  
-  nsresult rv = NS_ERROR_FAILURE;
-
-  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-  NSDictionary* dict = [[NSFileManager defaultManager] fileAttributesAtPath:[(NSURL*)mBaseURL path] traverseLink:YES];
-  NSNumber* typeNum = (NSNumber*)[dict objectForKey:NSFileHFSTypeCode];
-  if (typeNum) {
-    *aFileType = [typeNum unsignedLongValue];
-    rv = NS_OK;
-  }
-  [ap release];
-
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::SetFileType(OSType aFileType)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-  NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:aFileType] forKey:NSFileHFSTypeCode];
-  BOOL success = [[NSFileManager defaultManager] changeFileAttributes:dict atPath:[(NSURL*)mBaseURL path]];
-  [ap release];
-  return (success ? NS_OK : NS_ERROR_FAILURE);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::GetFileCreator(OSType *aFileCreator)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG_POINTER(aFileCreator);
-
-  CHECK_INIT();
-
-  nsresult rv = NS_ERROR_FAILURE;
-
-  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-  NSDictionary* dict = [[NSFileManager defaultManager] fileAttributesAtPath:[(NSURL*)mBaseURL path] traverseLink:YES];
-  id creatorNum = (NSNumber*)[dict objectForKey:NSFileHFSCreatorCode];
-  if (creatorNum) {
-    *aFileCreator = [creatorNum unsignedLongValue];
-    rv = NS_OK;
-  }
-  [ap release];
-
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::SetFileCreator(OSType aFileCreator)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
-  NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:aFileCreator] forKey:NSFileHFSCreatorCode];
-  BOOL success = [[NSFileManager defaultManager] changeFileAttributes:dict atPath:[(NSURL*)mBaseURL path]];
-  [ap release];
-  return (success ? NS_OK : NS_ERROR_FAILURE);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::LaunchWithDoc(nsILocalFile *aDocToLoad, PRBool aLaunchInBackground)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  PRBool isExecutable;
-  nsresult rv = IsExecutable(&isExecutable);
-  if (NS_FAILED(rv))
-    return rv;
-  if (!isExecutable)
-    return NS_ERROR_FILE_EXECUTION_FAILED;
-
-  FSRef appFSRef, docFSRef;
-  rv = GetFSRefInternal(appFSRef);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (aDocToLoad) {
-    nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
-    rv = macDoc->GetFSRef(&docFSRef);
-    if (NS_FAILED(rv))
-      return rv;
-  }
-  
-  LSLaunchFlags       theLaunchFlags = kLSLaunchDefaults;
-  LSLaunchFSRefSpec   thelaunchSpec;
-
-  if (aLaunchInBackground)
-    theLaunchFlags |= kLSLaunchDontSwitch;
-  memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
-
-  thelaunchSpec.appRef = &appFSRef;
-  if (aDocToLoad) {
-    thelaunchSpec.numDocs = 1;
-    thelaunchSpec.itemRefs = &docFSRef;
-  }
-  thelaunchSpec.launchFlags = theLaunchFlags;
-
-  OSErr err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
-  if (err != noErr)
-    return MacErrorMapper(err);
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::OpenDocWithApp(nsILocalFile *aAppToOpenWith, PRBool aLaunchInBackground)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  nsresult rv;
-  OSErr err;
-
-  FSRef docFSRef, appFSRef;
-  rv = GetFSRefInternal(docFSRef);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (aAppToOpenWith) {
-    nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
-    if (!appFileMac)
-      return rv;
-
-    PRBool isExecutable;
-    rv = appFileMac->IsExecutable(&isExecutable);
-    if (NS_FAILED(rv))
-      return rv;
-    if (!isExecutable)
-      return NS_ERROR_FILE_EXECUTION_FAILED;
-    
-    rv = appFileMac->GetFSRef(&appFSRef);
-    if (NS_FAILED(rv))
-      return rv;
-  }
-  else {
-    OSType  fileCreator;
-    rv = GetFileCreator(&fileCreator);
-    if (NS_FAILED(rv))
-      return rv;
-
-    err = ::LSFindApplicationForInfo(fileCreator, nsnull, nsnull, &appFSRef, nsnull);
-    if (err != noErr)
-      return MacErrorMapper(err);
-  }
-  
-  LSLaunchFlags       theLaunchFlags = kLSLaunchDefaults;
-  LSLaunchFSRefSpec   thelaunchSpec;
-
-  if (aLaunchInBackground)
-  theLaunchFlags |= kLSLaunchDontSwitch;
-  memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
-
-  thelaunchSpec.appRef = &appFSRef;
-  thelaunchSpec.numDocs = 1;
-  thelaunchSpec.itemRefs = &docFSRef;
-  thelaunchSpec.launchFlags = theLaunchFlags;
-
-  err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
-  if (err != noErr)
-    return MacErrorMapper(err);
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsLocalFile::IsPackage(PRBool *_retval)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG(_retval);
-  *_retval = PR_FALSE;
-  
-  CFURLRef urlRef;
-  if (NS_SUCCEEDED(GetCFURL(&urlRef)) && urlRef) {
-    *_retval = [[NSWorkspace sharedWorkspace] isFilePackageAtPath:[(NSURL *)urlRef path]];
-    ::CFRelease(urlRef);
-    
-    return NS_OK;
-  }
-  
-  return NS_ERROR_FAILURE;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsLocalFile::GetBundleDisplayName(nsAString& outBundleName)
-{
-  PRBool isPackage = PR_FALSE;
-  nsresult rv = IsPackage(&isPackage);
-  if (NS_FAILED(rv) || !isPackage)
-    return NS_ERROR_FAILURE;
-  
-  nsAutoString name;
-  rv = GetLeafName(name);
-  if (NS_FAILED(rv))
-    return rv;
-  
-  PRInt32 length = name.Length();
-  if (Substring(name, length - 4, length).EqualsLiteral(".app")) {
-    // 4 characters in ".app"
-    outBundleName = Substring(name, 0, length - 4);
-  }
-  else
-    outBundleName = name;
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsLocalFile::GetBundleIdentifier(nsACString& outBundleIdentifier)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  nsresult rv = NS_ERROR_FAILURE;
-
-  CFURLRef urlRef;
-  if (NS_SUCCEEDED(GetCFURL(&urlRef))) {
-    CFBundleRef bundle = ::CFBundleCreate(NULL, urlRef);
-    if (bundle) {
-      CFStringRef bundleIdentifier = ::CFBundleGetIdentifier(bundle);
-      if (bundleIdentifier)
-        rv = CFStringReftoUTF8(bundleIdentifier, outBundleIdentifier);
-
-      ::CFRelease(bundle);
-    }
-    ::CFRelease(urlRef);
-  }
-
-  return rv;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-#pragma mark -
-#pragma mark [Protected Methods]
-
-nsresult nsLocalFile::SetBaseURL(CFURLRef aCFURLRef)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ENSURE_ARG(aCFURLRef);
-
-  ::CFRetain(aCFURLRef);
-  if (mBaseURL)
-    ::CFRelease(mBaseURL);
-  mBaseURL = aCFURLRef;
-
-  if (!::CFURLGetFileSystemRepresentation(mBaseURL, NO, (UInt8*)mPath, PATH_MAX))
-    return NS_ERROR_FAILURE;
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult nsLocalFile::GetFSRefInternal(FSRef& aFSRef)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  return (::CFURLGetFSRef(mBaseURL, &aFSRef) ? NS_OK : NS_ERROR_FAILURE);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult nsLocalFile::GetPathInternal(nsACString& path)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  CFURLRef urlRef;
-  nsresult rv = GetCFURL(&urlRef);
-  if (NS_FAILED(rv))
-    return rv;
-
-  path.SetLength(PATH_MAX);
-  if (path.Length() != (unsigned int)PATH_MAX) {
-    ::CFRelease(urlRef);
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  Boolean gotPath = ::CFURLGetFileSystemRepresentation(urlRef, true, (UInt8*)path.BeginWriting(), PATH_MAX);
-  ::CFRelease(urlRef);
-
-  return (gotPath ? NS_OK : NS_ERROR_FAILURE);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult nsLocalFile::CopyInternal(nsIFile* aParentDir,
-                                   const nsAString& newName,
-                                   PRBool followLinks)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  CHECK_INIT();
-
-  StFollowLinksState srcFollowState(*this, followLinks);
-
-  nsresult rv;
-  OSErr err;
-  FSRef srcFSRef;
-
-  rv = GetFSRefInternal(srcFSRef);
-  if (NS_FAILED(rv))
-    return rv;
-
-  nsCOMPtr<nsIFile> newParentDir = aParentDir;
-
-  if (!newParentDir) {
-    if (newName.IsEmpty())
-      return NS_ERROR_INVALID_ARG;
-    rv = GetParent(getter_AddRefs(newParentDir));
-    if (NS_FAILED(rv))
-      return rv;    
-  }
-
-  // If newParentDir does not exist, create it
-  PRBool exists;
-  rv = newParentDir->Exists(&exists);
-  if (NS_FAILED(rv))
-    return rv;
-  if (!exists) {
-    rv = newParentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
-    if (NS_FAILED(rv))
-      return rv;
-  }
-
-  FSRef destFSRef;
-  nsCOMPtr<nsILocalFileMac> newParentDirMac(do_QueryInterface(newParentDir));
-  if (!newParentDirMac)
-    return NS_ERROR_NO_INTERFACE;
-  rv = newParentDirMac->GetFSRef(&destFSRef);
-  if (NS_FAILED(rv))
-    return rv;
-
-  CFStringRef destNameStr = NULL;
-  if (newName.Length() > 0) {
-    destNameStr = ::CFStringCreateWithCharacters(kCFAllocatorDefault,
-                                                 PromiseFlatString(newName).get(),
-                                                 newName.Length());
-  }
-  err = ::FSCopyObjectSync(&srcFSRef, &destFSRef, destNameStr, NULL, kFSFileOperationDefaultOptions);
-  if (destNameStr)
-    ::CFRelease(destNameStr);
-
-  return MacErrorMapper(err);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult nsLocalFile::FillStatBufferInternal(struct STAT *statBuffer)
-{
-  CHECK_INIT();
-
-  if (STAT(mPath, statBuffer) == -1) {
-    if (LSTAT(mPath, statBuffer) == -1)
-      return NSRESULT_FOR_ERRNO();
-  }
-
-  return NS_OK;
-}
-
-// nsIHashable
-
-NS_IMETHODIMP
-nsLocalFile::Equals(nsIHashable* aOther, PRBool *aResult)
-{
-  nsCOMPtr<nsIFile> otherFile(do_QueryInterface(aOther));
-  if (!otherFile) {
-    *aResult = PR_FALSE;
-    return NS_OK;
-  }
-
-  return Equals(otherFile, aResult);
-}
-
-NS_IMETHODIMP
-nsLocalFile::GetHashCode(PRUint32 *aResult)
-{
-    NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-    CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseURL, kCFURLPOSIXPathStyle);
-    nsCAutoString path;
-    CFStringReftoUTF8(pathStrRef, path);
-    ::CFRelease(pathStrRef);
-    *aResult = HashString(path);
-    return NS_OK;
-
-    NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-#pragma mark -
-#pragma mark [Global Functions]
-
-void nsLocalFile::GlobalInit()
-{
-}
-
-void nsLocalFile::GlobalShutdown()
-{
-}
-
-nsresult NS_NewLocalFile(const nsAString& path, PRBool followLinks, nsILocalFile* *result)
-{
-    nsLocalFile* file = new nsLocalFile;
-    if (file == nsnull)
-        return NS_ERROR_OUT_OF_MEMORY;
-    NS_ADDREF(file);
-
-    file->SetFollowLinks(followLinks);
-
-    if (!path.IsEmpty()) {
-        nsresult rv = file->InitWithPath(path);
-        if (NS_FAILED(rv)) {
-            NS_RELEASE(file);
-            return rv;
-        }
-    }
-    *result = file;
-    return NS_OK;
-}
-
-nsresult NS_NewNativeLocalFile(const nsACString& path, PRBool followLinks, nsILocalFile **result)
-{
-    return NS_NewLocalFile(NS_ConvertUTF8toUTF16(path), followLinks, result);
-}
-
-nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowLinks, nsILocalFileMac** result)
-{
-    nsLocalFile* file = new nsLocalFile();
-    if (file == nsnull)
-        return NS_ERROR_OUT_OF_MEMORY;
-    NS_ADDREF(file);
-
-    file->SetFollowLinks(aFollowLinks);
-
-    nsresult rv = file->InitWithFSRef(aFSRef);
-    if (NS_FAILED(rv)) {
-        NS_RELEASE(file);
-        return rv;
-    }
-    *result = file;
-    return NS_OK;
-}
-
-nsresult NS_NewLocalFileWithCFURL(const CFURLRef aURL, PRBool aFollowLinks, nsILocalFileMac** result)
-{
-  nsLocalFile* file = new nsLocalFile();
-  if (file == nsnull)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(file);
-
-  file->SetFollowLinks(aFollowLinks);
-
-  nsresult rv = file->InitWithCFURL(aURL);
-  if (NS_FAILED(rv)) {
-    NS_RELEASE(file);
-    return rv;
-  }
-  *result = file;
-  return NS_OK;
-}
-
-#pragma mark -
-#pragma mark [Static Functions]
-
-static nsresult MacErrorMapper(OSErr inErr)
-{
-    nsresult outErr;
-    
-    switch (inErr)
-    {
-        case noErr:
-            outErr = NS_OK;
-            break;
-
-        case fnfErr:
-        case afpObjectNotFound:
-        case afpDirNotFound:
-            outErr = NS_ERROR_FILE_NOT_FOUND;
-            break;
-
-        case dupFNErr:
-        case afpObjectExists:
-            outErr = NS_ERROR_FILE_ALREADY_EXISTS;
-            break;
-        
-        case dskFulErr:
-        case afpDiskFull:
-            outErr = NS_ERROR_FILE_DISK_FULL;
-            break;
-        
-        case fLckdErr:
-        case afpVolLocked:
-            outErr = NS_ERROR_FILE_IS_LOCKED;
-            break;
-        
-        case afpAccessDenied:
-            outErr = NS_ERROR_FILE_ACCESS_DENIED;
-            break;
-
-        case afpDirNotEmpty:
-            outErr = NS_ERROR_FILE_DIR_NOT_EMPTY;
-            break;
-            
-        // Can't find good map for some
-        case bdNamErr:
-            outErr = NS_ERROR_FAILURE;
-            break;
-
-        default:    
-            outErr = NS_ERROR_FAILURE;
-            break;
-    }
-    return outErr;
-}
-
-// Convert a UTF-8 string to a UTF-16 string while normalizing to
-// Normalization Form C (composed Unicode). We need this because
-// Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode)
-// while most other OS', server-side programs usually expect NFC.
-static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc);
-
-  // The number of 16bit code units in a UTF-16 string will never be
-  // larger than the number of bytes in the corresponding UTF-8 string.
-  CFMutableStringRef inStr = ::CFStringCreateMutable(NULL, inFlatSrc.Length());
-
-  if (!inStr) {
-    CopyUTF8toUTF16(aSrc, aResult);
-    return;
-  }
-
-  ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8);
-
-  ::CFStringNormalize(inStr, kCFStringNormalizationFormC);
-
-  CFIndex length = ::CFStringGetLength(inStr);
-  const UniChar* chars = ::CFStringGetCharactersPtr(inStr);
-
-  if (chars) {
-    aResult.Assign(chars, length);
-  }
-  else {
-    nsAutoTArray<UniChar, PATH_MAX> buffer;
-    if (!buffer.SetLength(length)) {
-      CopyUTF8toUTF16(aSrc, aResult);
-    }
-    else {
-      ::CFStringGetCharacters(inStr, ::CFRangeMake(0, length), buffer.Elements());
-      aResult.Assign(buffer.Elements(), length);
-    }
-  }
-  ::CFRelease(inStr);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  // first see if the conversion would succeed and find the length of the result
-  CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef);
-  CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
-                                              kCFStringEncodingUTF8, 0, PR_FALSE,
-                                              NULL, 0, &usedBufLen);
-  if (charsConverted == inStrLen) {
-    // all characters converted, do the actual conversion
-    aOutStr.SetLength(usedBufLen);
-    if (aOutStr.Length() != (unsigned int)usedBufLen)
-      return NS_ERROR_OUT_OF_MEMORY;
-    UInt8 *buffer = (UInt8*)aOutStr.BeginWriting();
-    ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), kCFStringEncodingUTF8,
-                       0, false, buffer, usedBufLen, &usedBufLen);
-    return NS_OK;
-  }
-  return NS_ERROR_FAILURE;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
--- a/xpcom/io/nsLocalFileUnix.cpp
+++ b/xpcom/io/nsLocalFileUnix.cpp
@@ -41,17 +41,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
- * Implementation of nsIFile for ``Unixy'' systems.
+ * Implementation of nsIFile for "unixy" systems.
  */
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <utime.h>
@@ -87,16 +87,21 @@
 #include "nsISimpleEnumerator.h"
 #include "nsITimelineService.h"
 
 #ifdef MOZ_WIDGET_GTK2
 #include "nsIGIOService.h"
 #include "nsIGnomeVFSService.h"
 #endif
 
+#ifdef XP_MACOSX
+#include <Carbon/Carbon.h>
+#include "CocoaFileUtils.h"
+#endif
+
 #if (MOZ_PLATFORM_MAEMO == 5)
 #include <glib.h>
 #include <hildon-uri.h>
 #include <hildon-mime.h>
 #include <libosso.h>
 #endif
 
 #ifdef ANDROID
@@ -255,20 +260,28 @@ nsLocalFile::nsLocalFile()
 {
 }
 
 nsLocalFile::nsLocalFile(const nsLocalFile& other)
   : mPath(other.mPath)
 {
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile,
+#ifdef XP_MACOSX
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
+                              nsILocalFileMac,
+                              nsILocalFile,
                               nsIFile,
+                              nsIHashable)
+#else
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile,
                               nsILocalFile,
+                              nsIFile,
                               nsIHashable)
+#endif
 
 nsresult
 nsLocalFile::nsLocalFileConstructor(nsISupports *outer, 
                                     const nsIID &aIID,
                                     void **aInstancePtr)
 {
     NS_ENSURE_ARG_POINTER(aInstancePtr);
     NS_ENSURE_NO_AGGREGATION(outer);
@@ -1282,29 +1295,29 @@ nsLocalFile::GetDiskSpaceAvailable(PRInt
 
 }
 
 NS_IMETHODIMP
 nsLocalFile::GetParent(nsIFile **aParent)
 {
     CHECK_mPath();
     NS_ENSURE_ARG_POINTER(aParent);
-    *aParent       = nsnull;
+    *aParent = nsnull;
 
     // if '/' we are at the top of the volume, return null
     if (mPath.Equals("/"))
         return  NS_OK;
  
     // <brendan, after jband> I promise to play nice
     char *buffer   = mPath.BeginWriting(),
          *slashp   = buffer;
 
     // find the last significant slash in buffer
     slashp = strrchr(buffer, '/');
-    NS_ASSERTION(slashp, "non-canonical mPath?");
+    NS_ASSERTION(slashp, "non-canonical path?");
     if (!slashp)
         return NS_ERROR_FILE_INVALID_PATH;
 
     // for the case where we are at '/'
     if (slashp == buffer)
         slashp++;
 
     // temporarily terminate buffer at the last significant slash
@@ -1635,17 +1648,16 @@ nsLocalFile::GetNativeTarget(nsACString 
 
     nsMemory::Free(target);
 
     if (NS_FAILED(rv))
         _retval.Truncate();
     return rv;
 }
 
-/* attribute PRBool followLinks; */
 NS_IMETHODIMP
 nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
 {
     *aFollowLinks = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1768,16 +1780,24 @@ nsLocalFile::Reveal()
         if (NS_FAILED(parentDir->GetNativePath(dirPath)))
             return NS_ERROR_FAILURE;
 
         if (giovfs)
             return giovfs->ShowURIForInput(dirPath);
         else 
             return gnomevfs->ShowURIForInput(dirPath);        
     }
+#elif defined(XP_MACOSX)
+    CFURLRef url;
+    if (NS_SUCCEEDED(GetCFURL(&url))) {
+      nsresult rv = CocoaFileUtils::RevealFileInFinder(url);
+      ::CFRelease(url);
+      return rv;
+    }
+    return NS_ERROR_FAILURE;
 #else
     return NS_ERROR_FAILURE;
 #endif
 }
 
 NS_IMETHODIMP
 nsLocalFile::Launch()
 {
@@ -1818,30 +1838,40 @@ nsLocalFile::Launch()
     nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1", &rv));
     if (NS_SUCCEEDED(rv))
         rv = mimeService->GetTypeFromFile(this, type);
 
     nsDependentCString fileUri = NS_LITERAL_CSTRING("file://");
     fileUri.Append(mPath);
     mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
     return bridge->OpenUriExternal(fileUri, type) ? NS_OK : NS_ERROR_FAILURE;
+#elif defined(XP_MACOSX)
+    CFURLRef url;
+    if (NS_SUCCEEDED(GetCFURL(&url))) {
+        nsresult rv = CocoaFileUtils::OpenURL(url);
+        ::CFRelease(url);
+        return rv;
+    }
+    return NS_ERROR_FAILURE;
 #else
     return NS_ERROR_FAILURE;
 #endif
 }
 #endif
 
 nsresult
 NS_NewNativeLocalFile(const nsACString &path, PRBool followSymlinks, nsILocalFile **result)
 {
     nsLocalFile *file = new nsLocalFile();
     if (!file)
         return NS_ERROR_OUT_OF_MEMORY;
     NS_ADDREF(file);
 
+    file->SetFollowLinks(followSymlinks);
+
     if (!path.IsEmpty()) {
         nsresult rv = file->InitWithNativePath(path);
         if (NS_FAILED(rv)) {
             NS_RELEASE(file);
             return rv;
         }
     }
     *result = file;
@@ -1969,8 +1999,441 @@ void
 nsLocalFile::GlobalInit()
 {
 }
 
 void
 nsLocalFile::GlobalShutdown()
 {
 }
+
+// nsILocalFileMac
+
+#ifdef XP_MACOSX
+
+static nsresult MacErrorMapper(OSErr inErr)
+{
+  nsresult outErr;
+
+  switch (inErr)
+  {
+    case noErr:
+      outErr = NS_OK;
+      break;
+
+    case fnfErr:
+    case afpObjectNotFound:
+    case afpDirNotFound:
+      outErr = NS_ERROR_FILE_NOT_FOUND;
+      break;
+
+    case dupFNErr:
+    case afpObjectExists:
+      outErr = NS_ERROR_FILE_ALREADY_EXISTS;
+      break;
+
+    case dskFulErr:
+    case afpDiskFull:
+      outErr = NS_ERROR_FILE_DISK_FULL;
+      break;
+
+    case fLckdErr:
+    case afpVolLocked:
+      outErr = NS_ERROR_FILE_IS_LOCKED;
+      break;
+
+    case afpAccessDenied:
+      outErr = NS_ERROR_FILE_ACCESS_DENIED;
+      break;
+
+    case afpDirNotEmpty:
+      outErr = NS_ERROR_FILE_DIR_NOT_EMPTY;
+      break;
+
+    // Can't find good map for some
+    case bdNamErr:
+      outErr = NS_ERROR_FAILURE;
+      break;
+
+    default:
+      outErr = NS_ERROR_FAILURE;
+      break;
+  }
+
+  return outErr;
+}
+
+static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr)
+{
+  // first see if the conversion would succeed and find the length of the result
+  CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef);
+  CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+                                              kCFStringEncodingUTF8, 0, PR_FALSE,
+                                              NULL, 0, &usedBufLen);
+  if (charsConverted == inStrLen) {
+    // all characters converted, do the actual conversion
+    aOutStr.SetLength(usedBufLen);
+    if (aOutStr.Length() != (unsigned int)usedBufLen)
+      return NS_ERROR_OUT_OF_MEMORY;
+    UInt8 *buffer = (UInt8*)aOutStr.BeginWriting();
+    ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), kCFStringEncodingUTF8,
+                       0, false, buffer, usedBufLen, &usedBufLen);
+    return NS_OK;
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
+{
+  UInt8 path[PATH_MAX];
+  if (::CFURLGetFileSystemRepresentation(aCFURL, false, path, PATH_MAX)) {
+    nsDependentCString nativePath((char*)path);
+    return InitWithNativePath(nativePath);
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithFSRef(const FSRef *aFSRef)
+{
+  NS_ENSURE_ARG(aFSRef);
+
+  CFURLRef newURLRef = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aFSRef);
+  if (newURLRef) {
+    nsresult rv = InitWithCFURL(newURLRef);
+    ::CFRelease(newURLRef);
+    return rv;
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetCFURL(CFURLRef *_retval)
+{
+  CHECK_mPath();
+
+  PRBool isDir;
+  IsDirectory(&isDir);
+  *_retval = ::CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
+                                                       (UInt8*)mPath.get(),
+                                                       mPath.Length(),
+                                                       isDir);
+
+  return (*_retval ? NS_OK : NS_ERROR_FAILURE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFSRef(FSRef *_retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+
+  nsresult rv = NS_ERROR_FAILURE;
+
+  CFURLRef url = NULL;
+  if (NS_SUCCEEDED(GetCFURL(&url))) {
+    if (::CFURLGetFSRef(url, _retval)) {
+      rv = NS_OK;
+    }
+    ::CFRelease(url);
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFSSpec(FSSpec *_retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+
+  FSRef fsRef;
+  nsresult rv = GetFSRef(&fsRef);
+  if (NS_SUCCEEDED(rv)) {
+    OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNone, nsnull, nsnull, _retval, nsnull);
+    return MacErrorMapper(err);
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSizeWithResFork)
+{
+  NS_ENSURE_ARG_POINTER(aFileSizeWithResFork);
+
+  FSRef fsRef;
+  nsresult rv = GetFSRef(&fsRef);
+  if (NS_FAILED(rv))
+    return rv;
+
+  FSCatalogInfo catalogInfo;
+  OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoDataSizes + kFSCatInfoRsrcSizes,
+                                 &catalogInfo, nsnull, nsnull, nsnull);
+  if (err != noErr)
+    return MacErrorMapper(err);
+
+  *aFileSizeWithResFork = catalogInfo.dataLogicalSize + catalogInfo.rsrcLogicalSize;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileType(OSType *aFileType)
+{
+  CFURLRef url;
+  if (NS_SUCCEEDED(GetCFURL(&url))) {
+    nsresult rv = CocoaFileUtils::GetFileTypeCode(url, aFileType);
+    ::CFRelease(url);
+    return rv;
+  }
+  return NS_ERROR_FAILURE;
+}
+  
+NS_IMETHODIMP
+nsLocalFile::SetFileType(OSType aFileType)
+{
+  CFURLRef url;
+  if (NS_SUCCEEDED(GetCFURL(&url))) {
+    nsresult rv = CocoaFileUtils::SetFileTypeCode(url, aFileType);
+    ::CFRelease(url);
+    return rv;
+  }
+  return NS_ERROR_FAILURE;
+}
+  
+NS_IMETHODIMP
+nsLocalFile::GetFileCreator(OSType *aFileCreator)
+{
+  CFURLRef url;
+  if (NS_SUCCEEDED(GetCFURL(&url))) {
+    nsresult rv = CocoaFileUtils::GetFileCreatorCode(url, aFileCreator);
+    ::CFRelease(url);
+    return rv;
+  }
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFileCreator(OSType aFileCreator)
+{
+  CFURLRef url;
+  if (NS_SUCCEEDED(GetCFURL(&url))) {
+    nsresult rv = CocoaFileUtils::SetFileCreatorCode(url, aFileCreator);
+    ::CFRelease(url);
+    return rv;
+  }
+  return NS_ERROR_FAILURE;
+}
+  
+NS_IMETHODIMP
+nsLocalFile::LaunchWithDoc(nsILocalFile *aDocToLoad, PRBool aLaunchInBackground)
+{    
+  PRBool isExecutable;
+  nsresult rv = IsExecutable(&isExecutable);
+  if (NS_FAILED(rv))
+    return rv;
+  if (!isExecutable)
+    return NS_ERROR_FILE_EXECUTION_FAILED;
+
+  FSRef appFSRef, docFSRef;
+  rv = GetFSRef(&appFSRef);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (aDocToLoad) {
+    nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
+    rv = macDoc->GetFSRef(&docFSRef);
+    if (NS_FAILED(rv))
+      return rv;
+  }
+
+  LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+  LSLaunchFSRefSpec thelaunchSpec;
+
+  if (aLaunchInBackground)
+    theLaunchFlags |= kLSLaunchDontSwitch;
+  memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+  thelaunchSpec.appRef = &appFSRef;
+  if (aDocToLoad) {
+    thelaunchSpec.numDocs = 1;
+    thelaunchSpec.itemRefs = &docFSRef;
+  }
+  thelaunchSpec.launchFlags = theLaunchFlags;
+
+  OSErr err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+  if (err != noErr)
+    return MacErrorMapper(err);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenDocWithApp(nsILocalFile *aAppToOpenWith, PRBool aLaunchInBackground)
+{
+  FSRef docFSRef;
+  nsresult rv = GetFSRef(&docFSRef);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (!aAppToOpenWith) {
+    OSErr err = ::LSOpenFSRef(&docFSRef, NULL);
+    return MacErrorMapper(err);
+  }
+
+  nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
+  if (!appFileMac)
+    return rv;
+
+  PRBool isExecutable;
+  rv = appFileMac->IsExecutable(&isExecutable);
+  if (NS_FAILED(rv))
+    return rv;
+  if (!isExecutable)
+    return NS_ERROR_FILE_EXECUTION_FAILED;
+
+  FSRef appFSRef;
+  rv = appFileMac->GetFSRef(&appFSRef);
+  if (NS_FAILED(rv))
+    return rv;
+
+  LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+  LSLaunchFSRefSpec thelaunchSpec;
+
+  if (aLaunchInBackground)
+    theLaunchFlags |= kLSLaunchDontSwitch;
+  memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+  thelaunchSpec.appRef = &appFSRef;
+  thelaunchSpec.numDocs = 1;
+  thelaunchSpec.itemRefs = &docFSRef;
+  thelaunchSpec.launchFlags = theLaunchFlags;
+
+  OSErr err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+  if (err != noErr)
+    return MacErrorMapper(err);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsPackage(PRBool *_retval)
+{
+  NS_ENSURE_ARG(_retval);
+  *_retval = PR_FALSE;
+
+  CFURLRef url;
+  nsresult rv = GetCFURL(&url);
+  if (NS_FAILED(rv))
+    return rv;
+
+  LSItemInfoRecord info;
+  OSStatus status = ::LSCopyItemInfoForURL(url, kLSRequestBasicFlagsOnly, &info);
+
+  ::CFRelease(url);
+
+  if (status != noErr) {
+    return NS_ERROR_FAILURE;
+  }
+
+  *_retval = !!(info.flags & kLSItemInfoIsPackage);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetBundleDisplayName(nsAString& outBundleName)
+{
+  PRBool isPackage = PR_FALSE;
+  nsresult rv = IsPackage(&isPackage);
+  if (NS_FAILED(rv) || !isPackage)
+    return NS_ERROR_FAILURE;
+
+  nsAutoString name;
+  rv = GetLeafName(name);
+  if (NS_FAILED(rv))
+    return rv;
+
+  PRInt32 length = name.Length();
+  if (Substring(name, length - 4, length).EqualsLiteral(".app")) {
+    // 4 characters in ".app"
+    outBundleName = Substring(name, 0, length - 4);
+  }
+  else {
+    outBundleName = name;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetBundleIdentifier(nsACString& outBundleIdentifier)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+
+  CFURLRef urlRef;
+  if (NS_SUCCEEDED(GetCFURL(&urlRef))) {
+    CFBundleRef bundle = ::CFBundleCreate(NULL, urlRef);
+    if (bundle) {
+      CFStringRef bundleIdentifier = ::CFBundleGetIdentifier(bundle);
+      if (bundleIdentifier)
+        rv = CFStringReftoUTF8(bundleIdentifier, outBundleIdentifier);
+      ::CFRelease(bundle);
+    }
+    ::CFRelease(urlRef);
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+  NS_ENSURE_ARG(aFile);
+
+  nsCAutoString nativePath;
+  nsresult rv = aFile->GetNativePath(nativePath);
+  if (NS_FAILED(rv))
+    return rv;
+
+  return InitWithNativePath(nativePath);
+}
+
+nsresult
+NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowLinks, nsILocalFileMac** result)
+{
+  nsLocalFile* file = new nsLocalFile();
+  if (file == nsnull)
+    return NS_ERROR_OUT_OF_MEMORY;
+  NS_ADDREF(file);
+
+  file->SetFollowLinks(aFollowLinks);
+
+  nsresult rv = file->InitWithFSRef(aFSRef);
+  if (NS_FAILED(rv)) {
+    NS_RELEASE(file);
+    return rv;
+  }
+  *result = file;
+  return NS_OK;
+}
+
+nsresult
+NS_NewLocalFileWithCFURL(const CFURLRef aURL, PRBool aFollowLinks, nsILocalFileMac** result)
+{
+  nsLocalFile* file = new nsLocalFile();
+  if (!file)
+    return NS_ERROR_OUT_OF_MEMORY;
+  NS_ADDREF(file);
+
+  file->SetFollowLinks(aFollowLinks);
+
+  nsresult rv = file->InitWithCFURL(aURL);
+  if (NS_FAILED(rv)) {
+    NS_RELEASE(file);
+    return rv;
+  }
+  *result = file;
+  return NS_OK;
+}
+
+#endif
--- a/xpcom/io/nsLocalFileUnix.h
+++ b/xpcom/io/nsLocalFileUnix.h
@@ -48,16 +48,19 @@
 #include <sys/types.h>
 #include <unistd.h>
 
 #include "nscore.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsIHashable.h"
 #include "nsIClassInfoImpl.h"
+#ifdef XP_MACOSX
+#include "nsILocalFileMac.h"
+#endif
 
 /** 
  *  we need these for statfs()
  */
 #ifdef HAVE_SYS_STATVFS_H
     #if defined(__osf__) && defined(__DECCXX)
         extern "C" int statvfs(const char *, struct statvfs *);
     #endif
@@ -96,49 +99,50 @@
     #define LSTAT lstat64
     #define HAVE_STATS64 1
 #else
     #define STAT stat
     #define LSTAT lstat
 #endif
 
 
-class NS_COM nsLocalFile : public nsILocalFile,
+class NS_COM nsLocalFile :
+#ifdef XP_MACOSX
+                           public nsILocalFileMac,
+#else
+                           public nsILocalFile,
+#endif
                            public nsIHashable
 {
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
     
     nsLocalFile();
 
     static nsresult nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
 
-    // nsISupports
     NS_DECL_ISUPPORTS
-
-    // nsIFile
     NS_DECL_NSIFILE
-
-    // nsILocalFile
     NS_DECL_NSILOCALFILE
-
-    // nsIHashable
+#ifdef XP_MACOSX
+    NS_DECL_NSILOCALFILEMAC
+#endif
     NS_DECL_NSIHASHABLE
 
 public:
     static void GlobalInit();
     static void GlobalShutdown();
 
 private:
     nsLocalFile(const nsLocalFile& other);
     ~nsLocalFile() {}
 
 protected:
-// This stat cache holds the *last stat* - it does not invalidate.
-// Call "FillStatCache" whenever you want to stat our file.
+    // This stat cache holds the *last stat* - it does not invalidate.
+    // Call "FillStatCache" whenever you want to stat our file.
     struct STAT  mCachedStat;
     nsCString    mPath;
 
     void LocateNativeLeafName(nsACString::const_iterator &,
                               nsACString::const_iterator &);
 
     nsresult CopyDirectoryTo(nsIFile *newParent);
     nsresult CreateAllAncestors(PRUint32 permissions);