Home | History | Annotate | Download | only in mac
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_MAC_FOUNDATION_UTIL_H_
      6 #define BASE_MAC_FOUNDATION_UTIL_H_
      7 
      8 #include <CoreFoundation/CoreFoundation.h>
      9 
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/base_export.h"
     14 #include "base/logging.h"
     15 #include "base/mac/scoped_cftyperef.h"
     16 
     17 #if defined(__OBJC__)
     18 #import <Foundation/Foundation.h>
     19 #else  // __OBJC__
     20 #include <CoreFoundation/CoreFoundation.h>
     21 class NSBundle;
     22 class NSString;
     23 #endif  // __OBJC__
     24 
     25 #if defined(OS_IOS)
     26 #include <CoreText/CoreText.h>
     27 #else
     28 #include <ApplicationServices/ApplicationServices.h>
     29 #endif
     30 
     31 // Adapted from NSObjCRuntime.h NS_ENUM definition (used in Foundation starting
     32 // with the OS X 10.8 SDK and the iOS 6.0 SDK).
     33 #if __has_extension(cxx_strong_enums) && \
     34     (defined(OS_IOS) || (defined(MAC_OS_X_VERSION_10_8) && \
     35                          MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8))
     36 #define CR_FORWARD_ENUM(_type, _name) enum _name : _type _name
     37 #else
     38 #define CR_FORWARD_ENUM(_type, _name) _type _name
     39 #endif
     40 
     41 // Adapted from NSPathUtilities.h and NSObjCRuntime.h.
     42 #if __LP64__ || NS_BUILD_32_LIKE_64
     43 typedef CR_FORWARD_ENUM(unsigned long, NSSearchPathDirectory);
     44 typedef unsigned long NSSearchPathDomainMask;
     45 #else
     46 typedef CR_FORWARD_ENUM(unsigned int, NSSearchPathDirectory);
     47 typedef unsigned int NSSearchPathDomainMask;
     48 #endif
     49 
     50 typedef struct OpaqueSecTrustRef* SecACLRef;
     51 typedef struct OpaqueSecTrustedApplicationRef* SecTrustedApplicationRef;
     52 
     53 namespace base {
     54 
     55 class FilePath;
     56 
     57 namespace mac {
     58 
     59 // Returns true if the application is running from a bundle
     60 BASE_EXPORT bool AmIBundled();
     61 BASE_EXPORT void SetOverrideAmIBundled(bool value);
     62 
     63 // Returns true if this process is marked as a "Background only process".
     64 BASE_EXPORT bool IsBackgroundOnlyProcess();
     65 
     66 // Returns the path to a resource within the framework bundle.
     67 BASE_EXPORT FilePath PathForFrameworkBundleResource(CFStringRef resourceName);
     68 
     69 // Returns the creator code associated with the CFBundleRef at bundle.
     70 OSType CreatorCodeForCFBundleRef(CFBundleRef bundle);
     71 
     72 // Returns the creator code associated with this application, by calling
     73 // CreatorCodeForCFBundleRef for the application's main bundle.  If this
     74 // information cannot be determined, returns kUnknownType ('????').  This
     75 // does not respect the override app bundle because it's based on CFBundle
     76 // instead of NSBundle, and because callers probably don't want the override
     77 // app bundle's creator code anyway.
     78 BASE_EXPORT OSType CreatorCodeForApplication();
     79 
     80 // Searches for directories for the given key in only the given |domain_mask|.
     81 // If found, fills result (which must always be non-NULL) with the
     82 // first found directory and returns true.  Otherwise, returns false.
     83 BASE_EXPORT bool GetSearchPathDirectory(NSSearchPathDirectory directory,
     84                                         NSSearchPathDomainMask domain_mask,
     85                                         FilePath* result);
     86 
     87 // Searches for directories for the given key in only the local domain.
     88 // If found, fills result (which must always be non-NULL) with the
     89 // first found directory and returns true.  Otherwise, returns false.
     90 BASE_EXPORT bool GetLocalDirectory(NSSearchPathDirectory directory,
     91                                    FilePath* result);
     92 
     93 // Searches for directories for the given key in only the user domain.
     94 // If found, fills result (which must always be non-NULL) with the
     95 // first found directory and returns true.  Otherwise, returns false.
     96 BASE_EXPORT bool GetUserDirectory(NSSearchPathDirectory directory,
     97                                   FilePath* result);
     98 
     99 // Returns the ~/Library directory.
    100 BASE_EXPORT FilePath GetUserLibraryPath();
    101 
    102 // Takes a path to an (executable) binary and tries to provide the path to an
    103 // application bundle containing it. It takes the outermost bundle that it can
    104 // find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
    105 //   |exec_name| - path to the binary
    106 //   returns - path to the application bundle, or empty on error
    107 BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name);
    108 
    109 #define TYPE_NAME_FOR_CF_TYPE_DECL(TypeCF) \
    110 BASE_EXPORT std::string TypeNameForCFType(TypeCF##Ref);
    111 
    112 TYPE_NAME_FOR_CF_TYPE_DECL(CFArray);
    113 TYPE_NAME_FOR_CF_TYPE_DECL(CFBag);
    114 TYPE_NAME_FOR_CF_TYPE_DECL(CFBoolean);
    115 TYPE_NAME_FOR_CF_TYPE_DECL(CFData);
    116 TYPE_NAME_FOR_CF_TYPE_DECL(CFDate);
    117 TYPE_NAME_FOR_CF_TYPE_DECL(CFDictionary);
    118 TYPE_NAME_FOR_CF_TYPE_DECL(CFNull);
    119 TYPE_NAME_FOR_CF_TYPE_DECL(CFNumber);
    120 TYPE_NAME_FOR_CF_TYPE_DECL(CFSet);
    121 TYPE_NAME_FOR_CF_TYPE_DECL(CFString);
    122 TYPE_NAME_FOR_CF_TYPE_DECL(CFURL);
    123 TYPE_NAME_FOR_CF_TYPE_DECL(CFUUID);
    124 
    125 TYPE_NAME_FOR_CF_TYPE_DECL(CGColor);
    126 
    127 TYPE_NAME_FOR_CF_TYPE_DECL(CTFont);
    128 TYPE_NAME_FOR_CF_TYPE_DECL(CTRun);
    129 
    130 #undef TYPE_NAME_FOR_CF_TYPE_DECL
    131 
    132 // Retain/release calls for memory management in C++.
    133 BASE_EXPORT void NSObjectRetain(void* obj);
    134 BASE_EXPORT void NSObjectRelease(void* obj);
    135 
    136 // CFTypeRefToNSObjectAutorelease transfers ownership of a Core Foundation
    137 // object (one derived from CFTypeRef) to the Foundation memory management
    138 // system.  In a traditional managed-memory environment, cf_object is
    139 // autoreleased and returned as an NSObject.  In a garbage-collected
    140 // environment, cf_object is marked as eligible for garbage collection.
    141 //
    142 // This function should only be used to convert a concrete CFTypeRef type to
    143 // its equivalent "toll-free bridged" NSObject subclass, for example,
    144 // converting a CFStringRef to NSString.
    145 //
    146 // By calling this function, callers relinquish any ownership claim to
    147 // cf_object.  In a managed-memory environment, the object's ownership will be
    148 // managed by the innermost NSAutoreleasePool, so after this function returns,
    149 // callers should not assume that cf_object is valid any longer than the
    150 // returned NSObject.
    151 //
    152 // Returns an id, typed here for C++'s sake as a void*.
    153 BASE_EXPORT void* CFTypeRefToNSObjectAutorelease(CFTypeRef cf_object);
    154 
    155 // Returns the base bundle ID, which can be set by SetBaseBundleID but
    156 // defaults to a reasonable string. This never returns NULL. BaseBundleID
    157 // returns a pointer to static storage that must not be freed.
    158 BASE_EXPORT const char* BaseBundleID();
    159 
    160 // Sets the base bundle ID to override the default. The implementation will
    161 // make its own copy of new_base_bundle_id.
    162 BASE_EXPORT void SetBaseBundleID(const char* new_base_bundle_id);
    163 
    164 }  // namespace mac
    165 }  // namespace base
    166 
    167 #if !defined(__OBJC__)
    168 #define OBJC_CPP_CLASS_DECL(x) class x;
    169 #else  // __OBJC__
    170 #define OBJC_CPP_CLASS_DECL(x)
    171 #endif  // __OBJC__
    172 
    173 // Convert toll-free bridged CFTypes to NSTypes and vice-versa. This does not
    174 // autorelease |cf_val|. This is useful for the case where there is a CFType in
    175 // a call that expects an NSType and the compiler is complaining about const
    176 // casting problems.
    177 // The calls are used like this:
    178 // NSString *foo = CFToNSCast(CFSTR("Hello"));
    179 // CFStringRef foo2 = NSToCFCast(@"Hello");
    180 // The macro magic below is to enforce safe casting. It could possibly have
    181 // been done using template function specialization, but template function
    182 // specialization doesn't always work intuitively,
    183 // (http://www.gotw.ca/publications/mill17.htm) so the trusty combination
    184 // of macros and function overloading is used instead.
    185 
    186 #define CF_TO_NS_CAST_DECL(TypeCF, TypeNS) \
    187 OBJC_CPP_CLASS_DECL(TypeNS) \
    188 \
    189 namespace base { \
    190 namespace mac { \
    191 BASE_EXPORT TypeNS* CFToNSCast(TypeCF##Ref cf_val); \
    192 BASE_EXPORT TypeCF##Ref NSToCFCast(TypeNS* ns_val); \
    193 } \
    194 }
    195 
    196 #define CF_TO_NS_MUTABLE_CAST_DECL(name) \
    197 CF_TO_NS_CAST_DECL(CF##name, NS##name) \
    198 OBJC_CPP_CLASS_DECL(NSMutable##name) \
    199 \
    200 namespace base { \
    201 namespace mac { \
    202 BASE_EXPORT NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val); \
    203 BASE_EXPORT CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val); \
    204 } \
    205 }
    206 
    207 // List of toll-free bridged types taken from:
    208 // http://www.cocoadev.com/index.pl?TollFreeBridged
    209 
    210 CF_TO_NS_MUTABLE_CAST_DECL(Array);
    211 CF_TO_NS_MUTABLE_CAST_DECL(AttributedString);
    212 CF_TO_NS_CAST_DECL(CFCalendar, NSCalendar);
    213 CF_TO_NS_MUTABLE_CAST_DECL(CharacterSet);
    214 CF_TO_NS_MUTABLE_CAST_DECL(Data);
    215 CF_TO_NS_CAST_DECL(CFDate, NSDate);
    216 CF_TO_NS_MUTABLE_CAST_DECL(Dictionary);
    217 CF_TO_NS_CAST_DECL(CFError, NSError);
    218 CF_TO_NS_CAST_DECL(CFLocale, NSLocale);
    219 CF_TO_NS_CAST_DECL(CFNumber, NSNumber);
    220 CF_TO_NS_CAST_DECL(CFRunLoopTimer, NSTimer);
    221 CF_TO_NS_CAST_DECL(CFTimeZone, NSTimeZone);
    222 CF_TO_NS_MUTABLE_CAST_DECL(Set);
    223 CF_TO_NS_CAST_DECL(CFReadStream, NSInputStream);
    224 CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream);
    225 CF_TO_NS_MUTABLE_CAST_DECL(String);
    226 CF_TO_NS_CAST_DECL(CFURL, NSURL);
    227 
    228 #undef CF_TO_NS_CAST_DECL
    229 #undef CF_TO_NS_MUTABLE_CAST_DECL
    230 #undef OBJC_CPP_CLASS_DECL
    231 
    232 namespace base {
    233 namespace mac {
    234 
    235 // CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more
    236 // specific CoreFoundation type. The compatibility of the passed
    237 // object is found by comparing its opaque type against the
    238 // requested type identifier. If the supplied object is not
    239 // compatible with the requested return type, CFCast<>() returns
    240 // NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer
    241 // to either variant results in NULL being returned without
    242 // triggering any DCHECK.
    243 //
    244 // Example usage:
    245 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>(
    246 //     CFArrayGetValueAtIndex(array, index));
    247 //
    248 // CFTypeRef hello = CFSTR("hello world");
    249 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>(hello);
    250 
    251 template<typename T>
    252 T CFCast(const CFTypeRef& cf_val);
    253 
    254 template<typename T>
    255 T CFCastStrict(const CFTypeRef& cf_val);
    256 
    257 #define CF_CAST_DECL(TypeCF) \
    258 template<> BASE_EXPORT TypeCF##Ref \
    259 CFCast<TypeCF##Ref>(const CFTypeRef& cf_val);\
    260 \
    261 template<> BASE_EXPORT TypeCF##Ref \
    262 CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val);
    263 
    264 CF_CAST_DECL(CFArray);
    265 CF_CAST_DECL(CFBag);
    266 CF_CAST_DECL(CFBoolean);
    267 CF_CAST_DECL(CFData);
    268 CF_CAST_DECL(CFDate);
    269 CF_CAST_DECL(CFDictionary);
    270 CF_CAST_DECL(CFNull);
    271 CF_CAST_DECL(CFNumber);
    272 CF_CAST_DECL(CFSet);
    273 CF_CAST_DECL(CFString);
    274 CF_CAST_DECL(CFURL);
    275 CF_CAST_DECL(CFUUID);
    276 
    277 CF_CAST_DECL(CGColor);
    278 
    279 CF_CAST_DECL(CTFont);
    280 CF_CAST_DECL(CTRun);
    281 
    282 CF_CAST_DECL(SecACL);
    283 CF_CAST_DECL(SecTrustedApplication);
    284 
    285 #undef CF_CAST_DECL
    286 
    287 #if defined(__OBJC__)
    288 
    289 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more
    290 // specific (NSObject-derived) type. The compatibility of the passed
    291 // object is found by checking if it's a kind of the requested type
    292 // identifier. If the supplied object is not compatible with the
    293 // requested return type, ObjCCast<>() returns nil and
    294 // ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either
    295 // variant results in nil being returned without triggering any DCHECK.
    296 //
    297 // The strict variant is useful when retrieving a value from a
    298 // collection which only has values of a specific type, e.g. an
    299 // NSArray of NSStrings. The non-strict variant is useful when
    300 // retrieving values from data that you can't fully control. For
    301 // example, a plist read from disk may be beyond your exclusive
    302 // control, so you'd only want to check that the values you retrieve
    303 // from it are of the expected types, but not crash if they're not.
    304 //
    305 // Example usage:
    306 // NSString* version = base::mac::ObjCCast<NSString>(
    307 //     [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
    308 //
    309 // NSString* str = base::mac::ObjCCastStrict<NSString>(
    310 //     [ns_arr_of_ns_strs objectAtIndex:0]);
    311 template<typename T>
    312 T* ObjCCast(id objc_val) {
    313   if ([objc_val isKindOfClass:[T class]]) {
    314     return reinterpret_cast<T*>(objc_val);
    315   }
    316   return nil;
    317 }
    318 
    319 template<typename T>
    320 T* ObjCCastStrict(id objc_val) {
    321   T* rv = ObjCCast<T>(objc_val);
    322   DCHECK(objc_val == nil || rv);
    323   return rv;
    324 }
    325 
    326 #endif  // defined(__OBJC__)
    327 
    328 // Helper function for GetValueFromDictionary to create the error message
    329 // that appears when a type mismatch is encountered.
    330 BASE_EXPORT std::string GetValueFromDictionaryErrorMessage(
    331     CFStringRef key, const std::string& expected_type, CFTypeRef value);
    332 
    333 // Utility function to pull out a value from a dictionary, check its type, and
    334 // return it. Returns NULL if the key is not present or of the wrong type.
    335 template<typename T>
    336 T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) {
    337   CFTypeRef value = CFDictionaryGetValue(dict, key);
    338   T value_specific = CFCast<T>(value);
    339 
    340   if (value && !value_specific) {
    341     std::string expected_type = TypeNameForCFType(value_specific);
    342     DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key,
    343                                                         expected_type,
    344                                                         value);
    345   }
    346 
    347   return value_specific;
    348 }
    349 
    350 // Converts |path| to an autoreleased NSString. Returns nil if |path| is empty.
    351 BASE_EXPORT NSString* FilePathToNSString(const FilePath& path);
    352 
    353 // Converts |str| to a FilePath. Returns an empty path if |str| is nil.
    354 BASE_EXPORT FilePath NSStringToFilePath(NSString* str);
    355 
    356 }  // namespace mac
    357 }  // namespace base
    358 
    359 // Stream operations for CFTypes. They can be used with NSTypes as well
    360 // by using the NSToCFCast methods above.
    361 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo");
    362 // Operator << can not be overloaded for ObjectiveC types as the compiler
    363 // can not distinguish between overloads for id with overloads for void*.
    364 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o,
    365                                             const CFErrorRef err);
    366 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o,
    367                                             const CFStringRef str);
    368 
    369 #endif  // BASE_MAC_FOUNDATION_UTIL_H_
    370