summaryrefslogtreecommitdiff
path: root/xpcom/io
diff options
context:
space:
mode:
authorBrian Smith <brian@dbsoft.org>2022-04-26 10:56:11 -0500
committerBrian Smith <brian@dbsoft.org>2022-04-26 10:56:11 -0500
commit1a31160dde95477993fb7d3aa1327b2a45f8fca8 (patch)
treef030c1903971dce5981795141374e828ff0669b4 /xpcom/io
parente764f258e2530aa172102ff091ef205cc9bd5154 (diff)
downloaduxp-1a31160dde95477993fb7d3aa1327b2a45f8fca8.tar.gz
Issue #1829 - Revert "Issue #1751 -- Remove XP_MACOSX conditionals and support files from /xpcom"
This reverts commit 1bf0734a7249eb0dc1a96d825e7310eb46cac6dc.
Diffstat (limited to 'xpcom/io')
-rw-r--r--xpcom/io/CocoaFileUtils.h34
-rw-r--r--xpcom/io/CocoaFileUtils.mm267
-rw-r--r--xpcom/io/moz.build10
-rw-r--r--xpcom/io/nsILocalFileMac.idl179
4 files changed, 490 insertions, 0 deletions
diff --git a/xpcom/io/CocoaFileUtils.h b/xpcom/io/CocoaFileUtils.h
new file mode 100644
index 0000000000..919c127162
--- /dev/null
+++ b/xpcom/io/CocoaFileUtils.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// 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 aUrl);
+nsresult OpenURL(CFURLRef aUrl);
+nsresult GetFileCreatorCode(CFURLRef aUrl, OSType* aCreatorCode);
+nsresult SetFileCreatorCode(CFURLRef aUrl, OSType aCreatorCode);
+nsresult GetFileTypeCode(CFURLRef aUrl, OSType* aTypeCode);
+nsresult SetFileTypeCode(CFURLRef aUrl, OSType aTypeCode);
+void AddOriginMetadataToFile(const CFStringRef filePath,
+ const CFURLRef sourceURL,
+ const CFURLRef referrerURL);
+void AddQuarantineMetadataToFile(const CFStringRef filePath,
+ const CFURLRef sourceURL,
+ const CFURLRef referrerURL,
+ const bool isFromWeb);
+CFURLRef GetTemporaryFolderCFURLRef();
+
+} // namespace CocoaFileUtils
+
+#endif
diff --git a/xpcom/io/CocoaFileUtils.mm b/xpcom/io/CocoaFileUtils.mm
new file mode 100644
index 0000000000..a02b82ac1d
--- /dev/null
+++ b/xpcom/io/CocoaFileUtils.mm
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CocoaFileUtils.h"
+#include "nsCocoaFeatures.h"
+#include "nsCocoaUtils.h"
+#include <Cocoa/Cocoa.h>
+#include "nsObjCExceptions.h"
+#include "nsDebug.h"
+
+// Need to cope with us using old versions of the SDK and needing this on 10.10+
+#if !defined(MAC_OS_X_VERSION_10_10) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10)
+const CFStringRef kCFURLQuarantinePropertiesKey = CFSTR("NSURLQuarantinePropertiesKey");
+#endif
+
+namespace CocoaFileUtils {
+
+nsresult RevealFileInFinder(CFURLRef url)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ if (NS_WARN_IF(!url))
+ return NS_ERROR_INVALID_ARG;
+
+ 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;
+
+ if (NS_WARN_IF(!url))
+ return NS_ERROR_INVALID_ARG;
+
+ 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;
+
+ if (NS_WARN_IF(!url) || NS_WARN_IF(!creatorCode))
+ return NS_ERROR_INVALID_ARG;
+
+ nsAutoreleasePool localPool;
+
+ NSString *resolvedPath = [[(NSURL*)url path] stringByResolvingSymlinksInPath];
+ if (!resolvedPath) {
+ return NS_ERROR_FAILURE;
+ }
+
+ NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:resolvedPath error:nil];
+ if (!dict) {
+ return NS_ERROR_FAILURE;
+ }
+
+ NSNumber* creatorNum = (NSNumber*)[dict objectForKey:NSFileHFSCreatorCode];
+ if (!creatorNum) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *creatorCode = [creatorNum unsignedLongValue];
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult SetFileCreatorCode(CFURLRef url, OSType creatorCode)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ if (NS_WARN_IF(!url))
+ return NS_ERROR_INVALID_ARG;
+
+ 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;
+
+ if (NS_WARN_IF(!url) || NS_WARN_IF(!typeCode))
+ return NS_ERROR_INVALID_ARG;
+
+ nsAutoreleasePool localPool;
+
+ NSString *resolvedPath = [[(NSURL*)url path] stringByResolvingSymlinksInPath];
+ if (!resolvedPath) {
+ return NS_ERROR_FAILURE;
+ }
+
+ NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:resolvedPath error:nil];
+ if (!dict) {
+ return NS_ERROR_FAILURE;
+ }
+
+ NSNumber* typeNum = (NSNumber*)[dict objectForKey:NSFileHFSTypeCode];
+ if (!typeNum) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *typeCode = [typeNum unsignedLongValue];
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult SetFileTypeCode(CFURLRef url, OSType typeCode)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ if (NS_WARN_IF(!url))
+ return NS_ERROR_INVALID_ARG;
+
+ 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;
+}
+
+void AddOriginMetadataToFile(const CFStringRef filePath,
+ const CFURLRef sourceURL,
+ const CFURLRef referrerURL) {
+ typedef OSStatus (*MDItemSetAttribute_type)(MDItemRef, CFStringRef, CFTypeRef);
+ static MDItemSetAttribute_type mdItemSetAttributeFunc = NULL;
+
+ static bool did_symbol_lookup = false;
+ if (!did_symbol_lookup) {
+ did_symbol_lookup = true;
+
+ CFBundleRef metadata_bundle = ::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Metadata"));
+ if (!metadata_bundle) {
+ return;
+ }
+
+ mdItemSetAttributeFunc = (MDItemSetAttribute_type)
+ ::CFBundleGetFunctionPointerForName(metadata_bundle, CFSTR("MDItemSetAttribute"));
+ }
+ if (!mdItemSetAttributeFunc) {
+ return;
+ }
+
+ MDItemRef mdItem = ::MDItemCreate(NULL, filePath);
+ if (!mdItem) {
+ return;
+ }
+
+ CFMutableArrayRef list = ::CFArrayCreateMutable(kCFAllocatorDefault, 2, NULL);
+ if (!list) {
+ ::CFRelease(mdItem);
+ return;
+ }
+
+ // The first item in the list is the source URL of the downloaded file.
+ if (sourceURL) {
+ ::CFArrayAppendValue(list, ::CFURLGetString(sourceURL));
+ }
+
+ // If the referrer is known, store that in the second position.
+ if (referrerURL) {
+ ::CFArrayAppendValue(list, ::CFURLGetString(referrerURL));
+ }
+
+ mdItemSetAttributeFunc(mdItem, kMDItemWhereFroms, list);
+
+ ::CFRelease(list);
+ ::CFRelease(mdItem);
+}
+
+void AddQuarantineMetadataToFile(const CFStringRef filePath,
+ const CFURLRef sourceURL,
+ const CFURLRef referrerURL,
+ const bool isFromWeb) {
+ CFURLRef fileURL = ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+ filePath,
+ kCFURLPOSIXPathStyle,
+ false);
+
+ // The properties key changed in 10.10:
+ CFStringRef quarantinePropKey;
+ if (nsCocoaFeatures::OnYosemiteOrLater()) {
+ quarantinePropKey = kCFURLQuarantinePropertiesKey;
+ } else {
+ quarantinePropKey = kLSItemQuarantineProperties;
+ }
+ CFDictionaryRef quarantineProps = NULL;
+ Boolean success = ::CFURLCopyResourcePropertyForKey(fileURL,
+ quarantinePropKey,
+ &quarantineProps,
+ NULL);
+
+ // If there aren't any quarantine properties then the user probably
+ // set up an exclusion and we don't need to add metadata.
+ if (!success || !quarantineProps) {
+ ::CFRelease(fileURL);
+ return;
+ }
+
+ // We don't know what to do if the props aren't a dictionary.
+ if (::CFGetTypeID(quarantineProps) != ::CFDictionaryGetTypeID()) {
+ ::CFRelease(fileURL);
+ ::CFRelease(quarantineProps);
+ return;
+ }
+
+ // Make a mutable copy of the properties.
+ CFMutableDictionaryRef mutQuarantineProps =
+ ::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, (CFDictionaryRef)quarantineProps);
+ ::CFRelease(quarantineProps);
+
+ // Add metadata that the OS couldn't infer.
+
+ if (!::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineTypeKey)) {
+ CFStringRef type = isFromWeb ? kLSQuarantineTypeWebDownload : kLSQuarantineTypeOtherDownload;
+ ::CFDictionarySetValue(mutQuarantineProps, kLSQuarantineTypeKey, type);
+ }
+
+ if (!::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineOriginURLKey) && referrerURL) {
+ ::CFDictionarySetValue(mutQuarantineProps, kLSQuarantineOriginURLKey, referrerURL);
+ }
+
+ if (!::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineDataURLKey) && sourceURL) {
+ ::CFDictionarySetValue(mutQuarantineProps, kLSQuarantineDataURLKey, sourceURL);
+ }
+
+ // Set quarantine properties on file.
+ ::CFURLSetResourcePropertyForKey(fileURL,
+ quarantinePropKey,
+ mutQuarantineProps,
+ NULL);
+
+ ::CFRelease(fileURL);
+ ::CFRelease(mutQuarantineProps);
+}
+
+CFURLRef GetTemporaryFolderCFURLRef()
+{
+ NSString* tempDir = ::NSTemporaryDirectory();
+ return tempDir == nil ? NULL : (CFURLRef)[NSURL fileURLWithPath:tempDir
+ isDirectory:YES];
+}
+
+} // namespace CocoaFileUtils
diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build
index 467d61682b..43ce517c45 100644
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -37,6 +37,11 @@ XPIDL_SOURCES += [
'nsIUnicharOutputStream.idl',
]
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ XPIDL_SOURCES += [
+ 'nsILocalFileMac.idl',
+ ]
+
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += ['nsLocalFileWin.h']
EXPORTS.mozilla += [
@@ -118,6 +123,11 @@ SOURCES += [
'FilePreferences.cpp',
]
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ SOURCES += [
+ 'CocoaFileUtils.mm',
+ ]
+
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
diff --git a/xpcom/io/nsILocalFileMac.idl b/xpcom/io/nsILocalFileMac.idl
new file mode 100644
index 0000000000..d8655449bb
--- /dev/null
+++ b/xpcom/io/nsILocalFileMac.idl
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsILocalFile.idl"
+
+%{C++
+#include <Carbon/Carbon.h>
+#include <CoreFoundation/CoreFoundation.h>
+%}
+
+ native OSType(OSType);
+ native FSSpec(FSSpec);
+ native FSRef(FSRef);
+[ptr] native FSRefPtr(FSRef);
+ native CFURLRef(CFURLRef);
+
+[scriptable, builtinclass, uuid(623eca5b-c25d-4e27-be5a-789a66c4b2f7)]
+interface nsILocalFileMac : nsILocalFile
+{
+ /**
+ * initWithCFURL
+ *
+ * Init this object with a CFURLRef
+ *
+ * NOTE: Supported only for XP_MACOSX
+ * NOTE: If the path of the CFURL is /a/b/c, at least a/b must exist beforehand.
+ *
+ * @param aCFURL the CoreFoundation URL
+ *
+ */
+ [noscript] void initWithCFURL(in CFURLRef aCFURL);
+
+ /**
+ * initWithFSRef
+ *
+ * Init this object with an FSRef
+ *
+ * NOTE: Supported only for XP_MACOSX
+ *
+ * @param aFSRef the native FSRef
+ *
+ */
+ [noscript] void initWithFSRef([const] in FSRefPtr aFSRef);
+
+ /**
+ * 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
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * NOTE: Supported only for XP_MACOSX
+ *
+ * @return
+ *
+ */
+ [noscript] CFURLRef getCFURL();
+
+ /**
+ * getFSRef
+ *
+ * Returns the FSRef of the file object.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * NOTE: Supported only for XP_MACOSX
+ *
+ * @return
+ *
+ */
+ [noscript] FSRef getFSRef();
+
+ /**
+ * getFSSpec
+ *
+ * Returns the FSSpec of the file object.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * @return
+ *
+ */
+ [noscript] FSSpec getFSSpec();
+
+ /**
+ * 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 int64_t fileSizeWithResFork;
+
+ /**
+ * fileType, creator
+ *
+ * File type and creator attributes
+ *
+ */
+ [noscript] attribute OSType fileType;
+ [noscript] attribute OSType fileCreator;
+
+ /**
+ * launchWithDoc
+ *
+ * Launch the application that this file points to with a document.
+ *
+ * @param aDocToLoad Must not be NULL. If no document, use nsIFile::launch
+ * @param aLaunchInBackground TRUE if the application should not come to the front.
+ *
+ */
+ void launchWithDoc(in nsIFile aDocToLoad, in boolean aLaunchInBackground);
+
+ /**
+ * openDocWithApp
+ *
+ * Open the document that this file points to with the given application.
+ *
+ * @param aAppToOpenWith The application with which to open the document.
+ * If NULL, the creator code of the document is used
+ * to determine the application.
+ * @param aLaunchInBackground TRUE if the application should not come to the front.
+ *
+ */
+ void openDocWithApp(in nsIFile aAppToOpenWith, in boolean aLaunchInBackground);
+
+ /**
+ * isPackage
+ *
+ * returns true if a directory is determined to be a package under Mac OS 9/X
+ *
+ */
+ boolean isPackage();
+
+ /**
+ * bundleDisplayName
+ *
+ * returns the display name of the application bundle (usually the human
+ * readable name of the application)
+ */
+ readonly attribute AString bundleDisplayName;
+
+ /**
+ * bundleIdentifier
+ *
+ * returns the identifier of the bundle
+ */
+ readonly attribute AUTF8String bundleIdentifier;
+
+ /**
+ * Last modified time of a bundle's contents (as opposed to its package
+ * directory). Our convention is to make the bundle's Info.plist file
+ * stand in for the rest of its contents -- since this file contains the
+ * bundle's version information and other identifiers. For non-bundles
+ * this is the same as lastModifiedTime.
+ */
+ readonly attribute int64_t bundleContentsLastModifiedTime;
+};
+
+%{C++
+extern "C"
+{
+NS_EXPORT nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, bool aFollowSymlinks, nsILocalFileMac** result);
+NS_EXPORT nsresult NS_NewLocalFileWithCFURL(const CFURLRef aURL, bool aFollowSymlinks, nsILocalFileMac** result);
+}
+%}