1 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 //! Core Foundation Bundle Type
11
12 use core_foundation_sys::base::kCFAllocatorDefault;
13 pub use core_foundation_sys::bundle::*;
14 use core_foundation_sys::url::kCFURLPOSIXPathStyle;
15 use std::path::PathBuf;
16
17 use base::{CFType, TCFType};
18 use url::CFURL;
19 use dictionary::CFDictionary;
20 use std::os::raw::c_void;
21 use string::CFString;
22
23 declare_TCFType!{
24 /// A Bundle type.
25 CFBundle, CFBundleRef
26 }
27 impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID);
28
29 impl CFBundle {
new(bundleURL: CFURL) -> Option<CFBundle>30 pub fn new(bundleURL: CFURL) -> Option<CFBundle> {
31 unsafe {
32 let bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundleURL.as_concrete_TypeRef());
33 if bundle_ref.is_null() {
34 None
35 } else {
36 Some(TCFType::wrap_under_create_rule(bundle_ref))
37 }
38 }
39 }
40
bundle_with_identifier(identifier: CFString) -> Option<CFBundle>41 pub fn bundle_with_identifier(identifier: CFString) -> Option<CFBundle> {
42 unsafe {
43 let bundle_ref = CFBundleGetBundleWithIdentifier(identifier.as_concrete_TypeRef());
44 if bundle_ref.is_null() {
45 None
46 } else {
47 Some(TCFType::wrap_under_get_rule(bundle_ref))
48 }
49 }
50 }
51
function_pointer_for_name(&self, function_name: CFString) -> *const c_void52 pub fn function_pointer_for_name(&self, function_name: CFString) -> *const c_void {
53 unsafe {
54 CFBundleGetFunctionPointerForName(self.as_concrete_TypeRef(),
55 function_name.as_concrete_TypeRef())
56 }
57 }
58
main_bundle() -> CFBundle59 pub fn main_bundle() -> CFBundle {
60 unsafe {
61 let bundle_ref = CFBundleGetMainBundle();
62 TCFType::wrap_under_get_rule(bundle_ref)
63 }
64 }
65
info_dictionary(&self) -> CFDictionary<CFString, CFType>66 pub fn info_dictionary(&self) -> CFDictionary<CFString, CFType> {
67 unsafe {
68 let info_dictionary = CFBundleGetInfoDictionary(self.0);
69 TCFType::wrap_under_get_rule(info_dictionary)
70 }
71 }
72
executable_url(&self) -> Option<CFURL>73 pub fn executable_url(&self) -> Option<CFURL> {
74 unsafe {
75 let exe_url = CFBundleCopyExecutableURL(self.0);
76 if exe_url.is_null() {
77 None
78 } else {
79 Some(TCFType::wrap_under_create_rule(exe_url))
80 }
81 }
82 }
83
84 /// Bundle's own location
bundle_url(&self) -> Option<CFURL>85 pub fn bundle_url(&self) -> Option<CFURL> {
86 unsafe {
87 let bundle_url = CFBundleCopyBundleURL(self.0);
88 if bundle_url.is_null() {
89 None
90 } else {
91 Some(TCFType::wrap_under_create_rule(bundle_url))
92 }
93 }
94 }
95
96 /// Bundle's own location
path(&self) -> Option<PathBuf>97 pub fn path(&self) -> Option<PathBuf> {
98 let url = self.bundle_url()?;
99 Some(PathBuf::from(url.get_file_system_path(kCFURLPOSIXPathStyle).to_string()))
100 }
101
102 /// Bundle's resources location
bundle_resources_url(&self) -> Option<CFURL>103 pub fn bundle_resources_url(&self) -> Option<CFURL> {
104 unsafe {
105 let bundle_url = CFBundleCopyResourcesDirectoryURL(self.0);
106 if bundle_url.is_null() {
107 None
108 } else {
109 Some(TCFType::wrap_under_create_rule(bundle_url))
110 }
111 }
112 }
113
114 /// Bundle's resources location
resources_path(&self) -> Option<PathBuf>115 pub fn resources_path(&self) -> Option<PathBuf> {
116 let url = self.bundle_resources_url()?;
117 Some(PathBuf::from(url.get_file_system_path(kCFURLPOSIXPathStyle).to_string()))
118 }
119
private_frameworks_url(&self) -> Option<CFURL>120 pub fn private_frameworks_url(&self) -> Option<CFURL> {
121 unsafe {
122 let fw_url = CFBundleCopyPrivateFrameworksURL(self.0);
123 if fw_url.is_null() {
124 None
125 } else {
126 Some(TCFType::wrap_under_create_rule(fw_url))
127 }
128 }
129 }
130
shared_support_url(&self) -> Option<CFURL>131 pub fn shared_support_url(&self) -> Option<CFURL> {
132 unsafe {
133 let fw_url = CFBundleCopySharedSupportURL(self.0);
134 if fw_url.is_null() {
135 None
136 } else {
137 Some(TCFType::wrap_under_create_rule(fw_url))
138 }
139 }
140 }
141 }
142
143
144 #[test]
safari_executable_url()145 fn safari_executable_url() {
146 use string::CFString;
147 use url::{CFURL, kCFURLPOSIXPathStyle};
148
149 let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
150 let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
151 let cfurl_executable = CFBundle::new(cfurl_path)
152 .expect("Safari not present")
153 .executable_url();
154 assert!(cfurl_executable.is_some());
155 assert_eq!(cfurl_executable
156 .unwrap()
157 .absolute()
158 .get_file_system_path(kCFURLPOSIXPathStyle)
159 .to_string(),
160 "/Applications/Safari.app/Contents/MacOS/Safari");
161 }
162
163 #[test]
safari_private_frameworks_url()164 fn safari_private_frameworks_url() {
165 use string::CFString;
166 use url::{CFURL, kCFURLPOSIXPathStyle};
167
168 let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
169 let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
170 let cfurl_executable = CFBundle::new(cfurl_path)
171 .expect("Safari not present")
172 .private_frameworks_url();
173 assert!(cfurl_executable.is_some());
174 assert_eq!(cfurl_executable
175 .unwrap()
176 .absolute()
177 .get_file_system_path(kCFURLPOSIXPathStyle)
178 .to_string(),
179 "/Applications/Safari.app/Contents/Frameworks");
180 }
181
182 #[test]
non_existant_bundle()183 fn non_existant_bundle() {
184 use string::CFString;
185 use url::{CFURL, kCFURLPOSIXPathStyle};
186
187 let cfstr_path = CFString::from_static_string("/usr/local/foo");
188 let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
189 assert!(CFBundle::new(cfurl_path).is_none());
190 }
191