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