OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 | |
15 #include "util/mac/launchd.h" | |
16 | |
17 #import <Foundation/Foundation.h> | |
18 | |
19 #include "base/mac/foundation_util.h" | |
20 #include "base/mac/scoped_launch_data.h" | |
21 #include "base/mac/scoped_cftyperef.h" | |
22 #include "base/strings/sys_string_conversions.h" | |
23 | |
24 namespace crashpad { | |
25 | |
26 launch_data_t CFPropertyToLaunchData(CFPropertyListRef property_cf) { | |
27 // This function mixes Foundation and Core Foundation access to property list | |
28 // elements according to which is more convenient and correct for any specific | |
29 // task. | |
30 | |
31 launch_data_t data_launch = NULL; | |
32 CFTypeID type_id_cf = CFGetTypeID(property_cf); | |
33 | |
34 if (type_id_cf == CFDictionaryGetTypeID()) { | |
35 NSDictionary* dictionary_ns = base::mac::CFToNSCast( | |
36 base::mac::CFCastStrict<CFDictionaryRef>(property_cf)); | |
37 base::mac::ScopedLaunchData dictionary_launch( | |
38 launch_data_alloc(LAUNCH_DATA_DICTIONARY)); | |
39 | |
40 for (NSString* key in dictionary_ns) { | |
41 if (![key isKindOfClass:[NSString class]]) { | |
42 return NULL; | |
43 } | |
44 | |
45 CFPropertyListRef value_cf = | |
46 static_cast<CFPropertyListRef>([dictionary_ns objectForKey:key]); | |
47 launch_data_t value_launch = CFPropertyToLaunchData(value_cf); | |
48 if (!value_launch) { | |
49 return NULL; | |
50 } | |
51 | |
52 launch_data_dict_insert( | |
53 dictionary_launch, value_launch, [key UTF8String]); | |
54 } | |
55 | |
56 data_launch = dictionary_launch.release(); | |
57 | |
58 } else if (type_id_cf == CFArrayGetTypeID()) { | |
59 NSArray* array_ns = | |
60 base::mac::CFToNSCast(base::mac::CFCastStrict<CFArrayRef>(property_cf)); | |
61 base::mac::ScopedLaunchData array_launch( | |
62 launch_data_alloc(LAUNCH_DATA_ARRAY)); | |
63 size_t index = 0; | |
64 | |
65 for (id element_ns in array_ns) { | |
66 CFPropertyListRef element_cf = static_cast<CFPropertyListRef>(element_ns); | |
67 launch_data_t element_launch = CFPropertyToLaunchData(element_cf); | |
68 if (!element_launch) { | |
69 return NULL; | |
70 } | |
71 | |
72 launch_data_array_set_index(array_launch, element_launch, index++); | |
73 } | |
74 | |
75 data_launch = array_launch.release(); | |
76 | |
77 } else if (type_id_cf == CFNumberGetTypeID()) { | |
78 CFNumberRef number_cf = base::mac::CFCastStrict<CFNumberRef>(property_cf); | |
79 NSNumber* number_ns = base::mac::CFToNSCast(number_cf); | |
80 switch (CFNumberGetType(number_cf)) { | |
81 case kCFNumberSInt8Type: | |
82 case kCFNumberSInt16Type: | |
83 case kCFNumberSInt32Type: | |
84 case kCFNumberSInt64Type: | |
85 case kCFNumberCharType: | |
86 case kCFNumberShortType: | |
87 case kCFNumberIntType: | |
88 case kCFNumberLongType: | |
89 case kCFNumberLongLongType: | |
90 case kCFNumberCFIndexType: | |
91 case kCFNumberNSIntegerType: { | |
92 data_launch = launch_data_new_integer([number_ns longLongValue]); | |
93 break; | |
94 } | |
95 | |
96 case kCFNumberFloat32Type: | |
97 case kCFNumberFloat64Type: | |
98 case kCFNumberFloatType: | |
99 case kCFNumberDoubleType: { | |
100 data_launch = launch_data_new_real([number_ns doubleValue]); | |
101 break; | |
102 } | |
103 | |
104 default: { return NULL; } | |
105 } | |
106 | |
107 } else if (type_id_cf == CFBooleanGetTypeID()) { | |
108 CFBooleanRef boolean_cf = | |
109 base::mac::CFCastStrict<CFBooleanRef>(property_cf); | |
110 data_launch = launch_data_new_bool(CFBooleanGetValue(boolean_cf)); | |
111 | |
112 } else if (type_id_cf == CFStringGetTypeID()) { | |
113 NSString* string_ns = base::mac::CFToNSCast( | |
114 base::mac::CFCastStrict<CFStringRef>(property_cf)); | |
115 | |
116 // -fileSystemRepresentation might be more correct than -UTF8String, because | |
117 // these strings can hold paths. The analogous function in launchctl, | |
118 // CF2launch_data (10.9.2 launchd-842.90.1/support/launchctl.c), uses UTF-8 | |
119 // instead of filesystem encoding, so do the same here. Note that there’s | |
120 // another occurrence of -UTF8String above, used for dictionary keys. | |
121 data_launch = launch_data_new_string([string_ns UTF8String]); | |
122 | |
123 } else if (type_id_cf == CFDataGetTypeID()) { | |
124 NSData* data_ns = | |
125 base::mac::CFToNSCast(base::mac::CFCastStrict<CFDataRef>(property_cf)); | |
126 data_launch = launch_data_new_opaque([data_ns bytes], [data_ns length]); | |
127 } else { | |
128 base::ScopedCFTypeRef<CFStringRef> type_name_cf( | |
129 CFCopyTypeIDDescription(type_id_cf)); | |
130 DLOG(ERROR) << "unable to convert CFTypeID " << type_id_cf << " (" | |
131 << base::SysCFStringRefToUTF8(type_name_cf) << ")"; | |
132 } | |
133 | |
134 return data_launch; | |
135 } | |
136 | |
137 } // namespace crashpad | |
OLD | NEW |