xref: /aosp_15_r20/external/cronet/base/apple/bridging.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2021 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_APPLE_BRIDGING_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_APPLE_BRIDGING_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <CoreText/CoreText.h>
9*6777b538SAndroid Build Coastguard Worker #import <Foundation/Foundation.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/apple/scoped_cftyperef.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/types/always_false.h"
15*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
18*6777b538SAndroid Build Coastguard Worker #import <UIKit/UIKit.h>
19*6777b538SAndroid Build Coastguard Worker #endif
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
22*6777b538SAndroid Build Coastguard Worker #import <AppKit/AppKit.h>
23*6777b538SAndroid Build Coastguard Worker #endif
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker // These functions convert pointers of bridged CFTypes to NSTypes and
26*6777b538SAndroid Build Coastguard Worker // vice-versa. They come in two flavors: those that transfer ownership
27*6777b538SAndroid Build Coastguard Worker // (`OwnershipCast`) and those that just convert the pointer (`PtrCast`).
28*6777b538SAndroid Build Coastguard Worker //
29*6777b538SAndroid Build Coastguard Worker // Examples:
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // Ownership transference (as in `CFBridgingRetain`/`Release`):
32*6777b538SAndroid Build Coastguard Worker //   CFStringRef cf_string = CFStringCreateWithCString(...);
33*6777b538SAndroid Build Coastguard Worker //   NSString* ns_string = CFToNSOwnershipCast(cf_string);
34*6777b538SAndroid Build Coastguard Worker //   // At this point, `cf_string` does not need releasing.
35*6777b538SAndroid Build Coastguard Worker //
36*6777b538SAndroid Build Coastguard Worker //   NSString* ns_string = [[NSString alloc] initWithString:...];
37*6777b538SAndroid Build Coastguard Worker //   CFStringRef cf_string = NSToCFOwnershipCast(ns_string);
38*6777b538SAndroid Build Coastguard Worker //   // At this point, `cf_string` must be released.
39*6777b538SAndroid Build Coastguard Worker //
40*6777b538SAndroid Build Coastguard Worker // Pointer conversion (as in `__bridge`):
41*6777b538SAndroid Build Coastguard Worker //   // `cf_data` is some `CFDataRef` from somewhere.
42*6777b538SAndroid Build Coastguard Worker //   NSImage* ns_image = [[NSImage alloc] initWithData:CFToNSPtrCast(cf_data)];
43*6777b538SAndroid Build Coastguard Worker //
44*6777b538SAndroid Build Coastguard Worker //   // `ns_data` is some `NSData *` from somewhere.
45*6777b538SAndroid Build Coastguard Worker //   SecKeyRef sec_key = SecKeyCreateFromData(..., NSToCFPtrCast(ns_data), ...);
46*6777b538SAndroid Build Coastguard Worker //
47*6777b538SAndroid Build Coastguard Worker // The reason to use these functions (rather than using `__bridge` and
48*6777b538SAndroid Build Coastguard Worker // `CFBridgingRetain`/`Release`) is because they are type-safe. The OS-provided
49*6777b538SAndroid Build Coastguard Worker // bridging calls do not type check, while these calls do the appropriate type
50*6777b538SAndroid Build Coastguard Worker // checking via the magic of macros.
51*6777b538SAndroid Build Coastguard Worker //
52*6777b538SAndroid Build Coastguard Worker // Implementation note: Why not templates? Type checking in Core Foundation
53*6777b538SAndroid Build Coastguard Worker // involves functions named in a specific pattern, and only macro token pasting
54*6777b538SAndroid Build Coastguard Worker // works for this purpose.
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker #define CF_TO_NS_CAST_IMPL(TypeCF, TypeNS)                                  \
57*6777b538SAndroid Build Coastguard Worker   namespace base::apple {                                                   \
58*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT TypeNS* _Nullable CFToNSOwnershipCast(                 \
59*6777b538SAndroid Build Coastguard Worker       TypeCF##Ref CF_CONSUMED _Nullable cf_val) {                           \
60*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val));          \
61*6777b538SAndroid Build Coastguard Worker     return (__bridge_transfer TypeNS*)cf_val;                               \
62*6777b538SAndroid Build Coastguard Worker   }                                                                         \
63*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT CF_RETURNS_RETAINED                                    \
64*6777b538SAndroid Build Coastguard Worker       TypeCF##Ref _Nullable NSToCFOwnershipCast(TypeNS* _Nullable ns_val) { \
65*6777b538SAndroid Build Coastguard Worker     TypeCF##Ref cf_val = (__bridge_retained TypeCF##Ref)ns_val;             \
66*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val));          \
67*6777b538SAndroid Build Coastguard Worker     return cf_val;                                                          \
68*6777b538SAndroid Build Coastguard Worker   }                                                                         \
69*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT TypeNS* _Nullable CFToNSPtrCast(                       \
70*6777b538SAndroid Build Coastguard Worker       TypeCF##Ref _Nullable cf_val) {                                       \
71*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val));          \
72*6777b538SAndroid Build Coastguard Worker     return (__bridge TypeNS*)cf_val;                                        \
73*6777b538SAndroid Build Coastguard Worker   }                                                                         \
74*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT TypeCF##Ref _Nullable NSToCFPtrCast(                   \
75*6777b538SAndroid Build Coastguard Worker       TypeNS* _Nullable ns_val) {                                           \
76*6777b538SAndroid Build Coastguard Worker     TypeCF##Ref cf_val = (__bridge TypeCF##Ref)ns_val;                      \
77*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val));          \
78*6777b538SAndroid Build Coastguard Worker     return cf_val;                                                          \
79*6777b538SAndroid Build Coastguard Worker   }                                                                         \
80*6777b538SAndroid Build Coastguard Worker   }
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker #define CF_TO_NS_MUTABLE_CAST_IMPL(name)                                 \
83*6777b538SAndroid Build Coastguard Worker   CF_TO_NS_CAST_IMPL(CF##name, NS##name)                                 \
84*6777b538SAndroid Build Coastguard Worker   namespace base::apple {                                                \
85*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT NSMutable##name* _Nullable CFToNSOwnershipCast(     \
86*6777b538SAndroid Build Coastguard Worker       CFMutable##name##Ref CF_CONSUMED _Nullable cf_val) {               \
87*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val));     \
88*6777b538SAndroid Build Coastguard Worker     return (__bridge_transfer NSMutable##name*)cf_val;                   \
89*6777b538SAndroid Build Coastguard Worker   }                                                                      \
90*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT CF_RETURNS_RETAINED                                 \
91*6777b538SAndroid Build Coastguard Worker       CFMutable##name##Ref _Nullable NSToCFOwnershipCast(                \
92*6777b538SAndroid Build Coastguard Worker           NSMutable##name* _Nullable ns_val) {                           \
93*6777b538SAndroid Build Coastguard Worker     CFMutable##name##Ref cf_val =                                        \
94*6777b538SAndroid Build Coastguard Worker         (__bridge_retained CFMutable##name##Ref)ns_val;                  \
95*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val));     \
96*6777b538SAndroid Build Coastguard Worker     return cf_val;                                                       \
97*6777b538SAndroid Build Coastguard Worker   }                                                                      \
98*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT NSMutable##name* _Nullable CFToNSPtrCast(           \
99*6777b538SAndroid Build Coastguard Worker       CFMutable##name##Ref _Nullable cf_val) {                           \
100*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val));     \
101*6777b538SAndroid Build Coastguard Worker     return (__bridge NSMutable##name*)cf_val;                            \
102*6777b538SAndroid Build Coastguard Worker   }                                                                      \
103*6777b538SAndroid Build Coastguard Worker   inline BASE_EXPORT CFMutable##name##Ref _Nullable NSToCFPtrCast(       \
104*6777b538SAndroid Build Coastguard Worker       NSMutable##name* _Nullable ns_val) {                               \
105*6777b538SAndroid Build Coastguard Worker     CFMutable##name##Ref cf_val = (__bridge CFMutable##name##Ref)ns_val; \
106*6777b538SAndroid Build Coastguard Worker     DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val));     \
107*6777b538SAndroid Build Coastguard Worker     return cf_val;                                                       \
108*6777b538SAndroid Build Coastguard Worker   }                                                                      \
109*6777b538SAndroid Build Coastguard Worker   }
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker // List of toll-free bridged types taken from:
112*6777b538SAndroid Build Coastguard Worker // https://web.archive.org/web/20111124025525/http://www.cocoadev.com/index.pl?TollFreeBridged
113*6777b538SAndroid Build Coastguard Worker // https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html#//apple_ref/doc/uid/TP40010677-SW4
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker // Foundation
116*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(Array)
CF_TO_NS_MUTABLE_CAST_IMPL(AttributedString)117*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(AttributedString)
118*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFCalendar, NSCalendar)
119*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(CharacterSet)
120*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(Data)
121*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFDate, NSDate)
122*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(Dictionary)
123*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFError, NSError)
124*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFLocale, NSLocale)
125*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFNumber, NSNumber)
126*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFRunLoopTimer, NSTimer)
127*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFTimeZone, NSTimeZone)
128*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(Set)
129*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFReadStream, NSInputStream)
130*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFWriteStream, NSOutputStream)
131*6777b538SAndroid Build Coastguard Worker CF_TO_NS_MUTABLE_CAST_IMPL(String)
132*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CFURL, NSURL)
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker // AppKit / UIKit
135*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
136*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CTFont, UIFont)
137*6777b538SAndroid Build Coastguard Worker #else
138*6777b538SAndroid Build Coastguard Worker CF_TO_NS_CAST_IMPL(CTFont, NSFont)
139*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_IOS)
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker #undef CF_TO_NS_CAST_IMPL
142*6777b538SAndroid Build Coastguard Worker #undef CF_TO_NS_MUTABLE_CAST_IMPL
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker namespace base::apple {
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker template <typename CFT>
147*6777b538SAndroid Build Coastguard Worker id _Nullable CFToNSOwnershipCast(ScopedCFTypeRef<CFT>) {
148*6777b538SAndroid Build Coastguard Worker   static_assert(
149*6777b538SAndroid Build Coastguard Worker       AlwaysFalse<CFT>,
150*6777b538SAndroid Build Coastguard Worker       "Error: Do not pass a ScopedCFTypeRef to CFToNSOwnershipCast. "
151*6777b538SAndroid Build Coastguard Worker       "Call .release() on the ScopedCFTypeRef and pass the result in.");
152*6777b538SAndroid Build Coastguard Worker   return nil;
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker }  // namespace base::apple
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker #endif  // BASE_APPLE_BRIDGING_H_
158