1 // Copyright 2012 The Chromium Authors
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_APPLE_FOUNDATION_UTIL_H_
6 #define BASE_APPLE_FOUNDATION_UTIL_H_
7
8 #include <AvailabilityMacros.h>
9 #include <CoreFoundation/CoreFoundation.h>
10 #include <CoreText/CoreText.h>
11 #include <Security/Security.h>
12
13 #include <string>
14
15 #include "base/apple/scoped_cftyperef.h"
16 #include "base/base_export.h"
17 #include "base/compiler_specific.h"
18 #include "base/containers/span.h"
19 #include "base/logging.h"
20 #include "build/build_config.h"
21
22 #if defined(__OBJC__)
23 #import <Foundation/Foundation.h>
24 @class NSFont;
25 @class UIFont;
26 #endif // __OBJC__
27
28 namespace base {
29 class FilePath;
30 }
31
32 namespace base::apple {
33
34 // Returns true if the application is running from a bundle
35 BASE_EXPORT bool AmIBundled();
36 BASE_EXPORT void SetOverrideAmIBundled(bool value);
37
38 #if defined(UNIT_TEST)
39 // This is required because instantiating some tests requires checking the
40 // directory structure, which sets the AmIBundled cache state. Individual tests
41 // may or may not be bundled, and this would trip them up if the cache weren't
42 // cleared. This should not be called from individual tests, just from test
43 // instantiation code that gets a path from PathService.
44 BASE_EXPORT void ClearAmIBundledCache();
45 #endif
46
47 // Returns true if this process is marked as a "Background only process".
48 BASE_EXPORT bool IsBackgroundOnlyProcess();
49
50 // Returns the path to a resource within the framework bundle.
51 BASE_EXPORT FilePath PathForFrameworkBundleResource(const char* resource_name);
52
53 // Returns the creator code associated with the CFBundleRef at bundle.
54 OSType CreatorCodeForCFBundleRef(CFBundleRef bundle);
55
56 // Returns the creator code associated with this application, by calling
57 // CreatorCodeForCFBundleRef for the application's main bundle. If this
58 // information cannot be determined, returns kUnknownType ('????'). This
59 // does not respect the override app bundle because it's based on CFBundle
60 // instead of NSBundle, and because callers probably don't want the override
61 // app bundle's creator code anyway.
62 BASE_EXPORT OSType CreatorCodeForApplication();
63
64 #if defined(__OBJC__)
65
66 // Searches for directories for the given key in only the given |domain_mask|.
67 // If found, fills result (which must always be non-NULL) with the
68 // first found directory and returns true. Otherwise, returns false.
69 BASE_EXPORT bool GetSearchPathDirectory(NSSearchPathDirectory directory,
70 NSSearchPathDomainMask domain_mask,
71 FilePath* result);
72
73 // Searches for directories for the given key in only the local domain.
74 // If found, fills result (which must always be non-NULL) with the
75 // first found directory and returns true. Otherwise, returns false.
76 BASE_EXPORT bool GetLocalDirectory(NSSearchPathDirectory directory,
77 FilePath* result);
78
79 // Searches for directories for the given key in only the user domain.
80 // If found, fills result (which must always be non-NULL) with the
81 // first found directory and returns true. Otherwise, returns false.
82 BASE_EXPORT bool GetUserDirectory(NSSearchPathDirectory directory,
83 FilePath* result);
84
85 #endif // __OBJC__
86
87 // Returns the ~/Library directory.
88 BASE_EXPORT FilePath GetUserLibraryPath();
89
90 // Returns the ~/Documents directory.
91 BASE_EXPORT FilePath GetUserDocumentPath();
92
93 // Takes a path to an (executable) binary and tries to provide the path to an
94 // application bundle containing it. It takes the outermost bundle that it can
95 // find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
96 // |exec_name| - path to the binary
97 // returns - path to the application bundle, or empty on error
98 BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name);
99
100 // Takes a path to an (executable) binary and tries to provide the path to an
101 // application bundle containing it. It takes the innermost bundle that it can
102 // find (so for "/Foo/Bar.app/.../Baz.app/..." it produces
103 // "/Foo/Bar.app/.../Baz.app").
104 // |exec_name| - path to the binary
105 // returns - path to the application bundle, or empty on error
106 BASE_EXPORT FilePath GetInnermostAppBundlePath(const FilePath& exec_name);
107
108 #define TYPE_NAME_FOR_CF_TYPE_DECL(TypeCF) \
109 BASE_EXPORT std::string TypeNameForCFType(TypeCF##Ref)
110
111 TYPE_NAME_FOR_CF_TYPE_DECL(CFArray);
112 TYPE_NAME_FOR_CF_TYPE_DECL(CFBag);
113 TYPE_NAME_FOR_CF_TYPE_DECL(CFBoolean);
114 TYPE_NAME_FOR_CF_TYPE_DECL(CFData);
115 TYPE_NAME_FOR_CF_TYPE_DECL(CFDate);
116 TYPE_NAME_FOR_CF_TYPE_DECL(CFDictionary);
117 TYPE_NAME_FOR_CF_TYPE_DECL(CFNull);
118 TYPE_NAME_FOR_CF_TYPE_DECL(CFNumber);
119 TYPE_NAME_FOR_CF_TYPE_DECL(CFSet);
120 TYPE_NAME_FOR_CF_TYPE_DECL(CFString);
121 TYPE_NAME_FOR_CF_TYPE_DECL(CFURL);
122 TYPE_NAME_FOR_CF_TYPE_DECL(CFUUID);
123
124 TYPE_NAME_FOR_CF_TYPE_DECL(CGColor);
125
126 TYPE_NAME_FOR_CF_TYPE_DECL(CTFont);
127 TYPE_NAME_FOR_CF_TYPE_DECL(CTRun);
128
129 TYPE_NAME_FOR_CF_TYPE_DECL(SecAccessControl);
130 TYPE_NAME_FOR_CF_TYPE_DECL(SecCertificate);
131 TYPE_NAME_FOR_CF_TYPE_DECL(SecKey);
132 TYPE_NAME_FOR_CF_TYPE_DECL(SecPolicy);
133
134 #undef TYPE_NAME_FOR_CF_TYPE_DECL
135
136 // Returns the base bundle ID, which can be set by SetBaseBundleID but
137 // defaults to a reasonable string. This never returns NULL. BaseBundleID
138 // returns a pointer to static storage that must not be freed.
139 BASE_EXPORT const char* BaseBundleID();
140
141 // Sets the base bundle ID to override the default. The implementation will
142 // make its own copy of new_base_bundle_id.
143 BASE_EXPORT void SetBaseBundleID(const char* new_base_bundle_id);
144
145 // CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more specific
146 // CoreFoundation type. The compatibility of the passed object is found by
147 // comparing its opaque type against the requested type identifier. If the
148 // supplied object is not compatible with the requested return type, CFCast<>()
149 // returns null and CFCastStrict<>() will CHECK. Providing a null pointer to
150 // either variant results in null being returned without triggering any CHECK.
151 //
152 // Example usage:
153 // CFNumberRef some_number = base::apple::CFCast<CFNumberRef>(
154 // CFArrayGetValueAtIndex(array, index));
155 //
156 // CFTypeRef hello = CFSTR("hello world");
157 // CFStringRef some_string = base::apple::CFCastStrict<CFStringRef>(hello);
158
159 template <typename T>
160 T CFCast(const CFTypeRef& cf_val);
161
162 template <typename T>
163 T CFCastStrict(const CFTypeRef& cf_val);
164
165 #define CF_CAST_DECL(TypeCF) \
166 template <> \
167 BASE_EXPORT TypeCF##Ref CFCast<TypeCF##Ref>(const CFTypeRef& cf_val); \
168 \
169 template <> \
170 BASE_EXPORT TypeCF##Ref CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val)
171
172 CF_CAST_DECL(CFArray);
173 CF_CAST_DECL(CFBag);
174 CF_CAST_DECL(CFBoolean);
175 CF_CAST_DECL(CFData);
176 CF_CAST_DECL(CFDate);
177 CF_CAST_DECL(CFDictionary);
178 CF_CAST_DECL(CFNull);
179 CF_CAST_DECL(CFNumber);
180 CF_CAST_DECL(CFSet);
181 CF_CAST_DECL(CFString);
182 CF_CAST_DECL(CFURL);
183 CF_CAST_DECL(CFUUID);
184
185 CF_CAST_DECL(CGColor);
186
187 CF_CAST_DECL(CTFont);
188 CF_CAST_DECL(CTFontDescriptor);
189 CF_CAST_DECL(CTRun);
190
191 CF_CAST_DECL(SecAccessControl);
192 CF_CAST_DECL(SecCertificate);
193 CF_CAST_DECL(SecKey);
194 CF_CAST_DECL(SecPolicy);
195
196 #undef CF_CAST_DECL
197
198 #if defined(__OBJC__)
199
200 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more specific
201 // (NSObject-derived) type. The compatibility of the passed object is found by
202 // checking if it's a kind of the requested type identifier. If the supplied
203 // object is not compatible with the requested return type, ObjCCast<>() returns
204 // nil and ObjCCastStrict<>() will CHECK. Providing a nil pointer to either
205 // variant results in nil being returned without triggering any CHECK.
206 //
207 // The strict variant is useful when retrieving a value from a collection which
208 // only has values of a specific type, e.g. an NSArray of NSStrings. The
209 // non-strict variant is useful when retrieving values from data that you can't
210 // fully control. For example, a plist read from disk may be beyond your
211 // exclusive control, so you'd only want to check that the values you retrieve
212 // from it are of the expected types, but not crash if they're not.
213 //
214 // Example usage:
215 // NSString* version = base::apple::ObjCCast<NSString>(
216 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
217 //
218 // // (If it's not possible to use an NSArray<NSString>.)
219 // NSString* str = base::apple::ObjCCastStrict<NSString>(
220 // [ns_arr_of_ns_strs objectAtIndex:0]);
221 template <typename T>
ObjCCast(id objc_val)222 T* ObjCCast(id objc_val) {
223 if ([objc_val isKindOfClass:[T class]]) {
224 return reinterpret_cast<T*>(objc_val);
225 }
226 return nil;
227 }
228
229 template <typename T>
ObjCCastStrict(id objc_val)230 T* ObjCCastStrict(id objc_val) {
231 T* rv = ObjCCast<T>(objc_val);
232 CHECK(objc_val == nil || rv);
233 return rv;
234 }
235
236 #endif // defined(__OBJC__)
237
238 // Helper function for GetValueFromDictionary to create the error message
239 // that appears when a type mismatch is encountered.
240 BASE_EXPORT std::string GetValueFromDictionaryErrorMessage(
241 CFStringRef key,
242 const std::string& expected_type,
243 CFTypeRef value);
244
245 // Utility function to pull out a value from a dictionary, check its type, and
246 // return it. Returns NULL if the key is not present or of the wrong type.
247 template <typename T>
GetValueFromDictionary(CFDictionaryRef dict,CFStringRef key)248 T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) {
249 CFTypeRef value = CFDictionaryGetValue(dict, key);
250 T value_specific = CFCast<T>(value);
251
252 if (value && !value_specific) {
253 std::string expected_type = TypeNameForCFType(value_specific);
254 DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key, expected_type,
255 value);
256 }
257
258 return value_specific;
259 }
260
261 #if defined(__OBJC__)
262
263 // Converts |path| to an autoreleased NSURL. Returns nil if |path| is empty.
264 BASE_EXPORT NSURL* FilePathToNSURL(const FilePath& path);
265
266 // Converts |path| to an autoreleased NSString. Returns nil if |path| is empty.
267 BASE_EXPORT NSString* FilePathToNSString(const FilePath& path);
268
269 // Converts |str| to a FilePath. Returns an empty path if |str| is nil.
270 BASE_EXPORT FilePath NSStringToFilePath(NSString* str);
271
272 // Converts |url| to a FilePath. Returns an empty path if |url| is nil or if
273 // |url| is not of scheme "file".
274 BASE_EXPORT FilePath NSURLToFilePath(NSURL* url);
275
276 #endif // __OBJC__
277
278 // CoreFoundation versions of the above calls. These only uses manually-owned
279 // resources, so they do not depend on an NSAutoreleasePool being set up on the
280 // current thread.
281
282 // Converts |path| to a CFURLRef. Returns nil if |path| is empty.
283 BASE_EXPORT ScopedCFTypeRef<CFURLRef> FilePathToCFURL(const FilePath& path);
284
285 // Converts |path| to a CFStringRef. Returns nil if |path| is empty.
286 BASE_EXPORT ScopedCFTypeRef<CFStringRef> FilePathToCFString(
287 const FilePath& path);
288
289 // Converts |str| to a FilePath. Returns an empty path if |str| is nil.
290 BASE_EXPORT FilePath CFStringToFilePath(CFStringRef str);
291
292 // Converts |url| to a FilePath. Returns an empty path if |url| is nil or if
293 // |url| is not of scheme "file".
294 BASE_EXPORT FilePath CFURLToFilePath(CFURLRef url);
295
296 #if defined(__OBJC__)
297 // Converts |range| to an NSRange, returning the new range in |range_out|.
298 // Returns true if conversion was successful, false if the values of |range|
299 // could not be converted to NSUIntegers.
300 [[nodiscard]] BASE_EXPORT bool CFRangeToNSRange(CFRange range,
301 NSRange* range_out);
302
303 // Returns an immutable `base::span<const uint8_t>` pointing to the memory owned
304 // by `data`. Returns an empty span if `data` is nil or empty.
305 //
306 // The resulting span will be valid until the top-most autorelease pool is
307 // popped. Ensure that the span does not outlive that autorelease pool.
NSDataToSpan(NSData * data)308 inline span<const uint8_t> NSDataToSpan(NSData* data) {
309 // SAFETY: `NSData` guarantees that `bytes` is exactly `length` in size.
310 return UNSAFE_BUFFERS(
311 span(static_cast<const uint8_t*>(data.bytes), size_t{data.length}));
312 }
313
314 // Returns a mutable `base::span<uint8_t>` pointing to the memory owned by
315 // `data`. Returns an empty span if `data` is nil or empty.
316 //
317 // The resulting span will be valid until the top-most autorelease pool is
318 // popped. Ensure that the span does not outlive that autorelease pool.
NSMutableDataToSpan(NSMutableData * data)319 inline span<uint8_t> NSMutableDataToSpan(NSMutableData* data) {
320 // SAFETY: `NSMutableData` guarantees that `mutableBytes` is exactly `length`
321 // in size.
322 return UNSAFE_BUFFERS(
323 span(static_cast<uint8_t*>(data.mutableBytes), size_t{data.length}));
324 }
325
326 #endif // defined(__OBJC__)
327
328 // Returns an immutable `base::span<const uint8_t>` pointing to the memory
329 // owned by `data`. `data` must outlive the returned span.
330 // Returns an empty span if `data` is null or empty.
331 BASE_EXPORT span<const uint8_t> CFDataToSpan(CFDataRef data);
332
333 // Returns a mutable `base::span<uint8_t>` pointing to the memory
334 // owned by `data`. `data` must outlive the returned span.
335 // Returns an empty span if `data` is null or empty.
336 BASE_EXPORT span<uint8_t> CFMutableDataToSpan(CFMutableDataRef data);
337
338 } // namespace base::apple
339
340 // Stream operations for CFTypes. They can be used with Objective-C types as
341 // well by using the casting methods in base/apple/bridging.h.
342 //
343 // For example: LOG(INFO) << base::apple::NSToCFPtrCast(@"foo");
344 //
345 // operator<<() can not be overloaded for Objective-C types as the compiler
346 // cannot distinguish between overloads for id with overloads for void*.
347 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o,
348 const CFErrorRef err);
349 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o,
350 const CFStringRef str);
351 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, CFRange);
352
353 #if defined(__OBJC__)
354 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, id);
355 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSRange);
356 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, SEL);
357
358 #if BUILDFLAG(IS_MAC)
359 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSPoint);
360 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSRect);
361 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSSize);
362 #endif // IS_MAC
363
364 #endif // __OBJC__
365
366 #endif // BASE_APPLE_FOUNDATION_UTIL_H_
367