1 /* 2 * Copyright 2007 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <sstream> 12 13 #include "webrtc/base/common.h" 14 #include "webrtc/base/logging.h" 15 #include "webrtc/base/macutils.h" 16 #include "webrtc/base/scoped_ptr.h" 17 #include "webrtc/base/stringutils.h" 18 19 namespace rtc { 20 21 /////////////////////////////////////////////////////////////////////////////// 22 23 bool ToUtf8(const CFStringRef str16, std::string* str8) { 24 if ((NULL == str16) || (NULL == str8)) { 25 return false; 26 } 27 size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16), 28 kCFStringEncodingUTF8) + 1; 29 scoped_ptr<char[]> buffer(new char[maxlen]); 30 if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen, 31 kCFStringEncodingUTF8)) { 32 return false; 33 } 34 str8->assign(buffer.get()); 35 return true; 36 } 37 38 bool ToUtf16(const std::string& str8, CFStringRef* str16) { 39 if (NULL == str16) { 40 return false; 41 } 42 *str16 = CFStringCreateWithBytes(kCFAllocatorDefault, 43 reinterpret_cast<const UInt8*>(str8.data()), 44 str8.length(), kCFStringEncodingUTF8, 45 false); 46 return NULL != *str16; 47 } 48 49 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) 50 void DecodeFourChar(UInt32 fc, std::string* out) { 51 std::stringstream ss; 52 ss << '\''; 53 bool printable = true; 54 for (int i = 3; i >= 0; --i) { 55 char ch = (fc >> (8 * i)) & 0xFF; 56 if (isprint(static_cast<unsigned char>(ch))) { 57 ss << ch; 58 } else { 59 printable = false; 60 break; 61 } 62 } 63 if (printable) { 64 ss << '\''; 65 } else { 66 ss.str(""); 67 ss << "0x" << std::hex << fc; 68 } 69 out->append(ss.str()); 70 } 71 72 static bool GetGestalt(OSType ostype, int* value) { 73 ASSERT(NULL != value); 74 SInt32 native_value; 75 OSStatus result = Gestalt(ostype, &native_value); 76 if (noErr == result) { 77 *value = native_value; 78 return true; 79 } 80 std::string str; 81 DecodeFourChar(ostype, &str); 82 LOG_E(LS_ERROR, OS, result) << "Gestalt(" << str << ")"; 83 return false; 84 } 85 86 bool GetOSVersion(int* major, int* minor, int* bugfix) { 87 ASSERT(major && minor && bugfix); 88 if (!GetGestalt(gestaltSystemVersion, major)) { 89 return false; 90 } 91 if (*major < 0x1040) { 92 *bugfix = *major & 0xF; 93 *minor = (*major >> 4) & 0xF; 94 *major = (*major >> 8); 95 return true; 96 } 97 return GetGestalt(gestaltSystemVersionMajor, major) && 98 GetGestalt(gestaltSystemVersionMinor, minor) && 99 GetGestalt(gestaltSystemVersionBugFix, bugfix); 100 } 101 102 MacOSVersionName GetOSVersionName() { 103 int major = 0, minor = 0, bugfix = 0; 104 if (!GetOSVersion(&major, &minor, &bugfix)) { 105 return kMacOSUnknown; 106 } 107 if (major > 10) { 108 return kMacOSNewer; 109 } 110 if ((major < 10) || (minor < 3)) { 111 return kMacOSOlder; 112 } 113 switch (minor) { 114 case 3: 115 return kMacOSPanther; 116 case 4: 117 return kMacOSTiger; 118 case 5: 119 return kMacOSLeopard; 120 case 6: 121 return kMacOSSnowLeopard; 122 case 7: 123 return kMacOSLion; 124 case 8: 125 return kMacOSMountainLion; 126 case 9: 127 return kMacOSMavericks; 128 } 129 return kMacOSNewer; 130 } 131 132 bool GetQuickTimeVersion(std::string* out) { 133 int ver; 134 if (!GetGestalt(gestaltQuickTimeVersion, &ver)) { 135 return false; 136 } 137 138 std::stringstream ss; 139 ss << std::hex << ver; 140 *out = ss.str(); 141 return true; 142 } 143 144 bool RunAppleScript(const std::string& script) { 145 // TODO(thaloun): Add a .mm file that contains something like this: 146 // NSString source from script 147 // NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource:&source] 148 // if (appleScript != nil) { 149 // [appleScript executeAndReturnError:nil] 150 // [appleScript release] 151 #ifndef CARBON_DEPRECATED 152 ComponentInstance component = NULL; 153 AEDesc script_desc; 154 AEDesc result_data; 155 OSStatus err; 156 OSAID script_id, result_id; 157 158 AECreateDesc(typeNull, NULL, 0, &script_desc); 159 AECreateDesc(typeNull, NULL, 0, &result_data); 160 script_id = kOSANullScript; 161 result_id = kOSANullScript; 162 163 component = OpenDefaultComponent(kOSAComponentType, typeAppleScript); 164 if (component == NULL) { 165 LOG(LS_ERROR) << "Failed opening Apple Script component"; 166 return false; 167 } 168 err = AECreateDesc(typeUTF8Text, script.data(), script.size(), &script_desc); 169 if (err != noErr) { 170 CloseComponent(component); 171 LOG(LS_ERROR) << "Failed creating Apple Script description"; 172 return false; 173 } 174 175 err = OSACompile(component, &script_desc, kOSAModeCanInteract, &script_id); 176 if (err != noErr) { 177 AEDisposeDesc(&script_desc); 178 if (script_id != kOSANullScript) { 179 OSADispose(component, script_id); 180 } 181 CloseComponent(component); 182 LOG(LS_ERROR) << "Error compiling Apple Script"; 183 return false; 184 } 185 186 err = OSAExecute(component, script_id, kOSANullScript, kOSAModeCanInteract, 187 &result_id); 188 189 if (err == errOSAScriptError) { 190 LOG(LS_ERROR) << "Error when executing Apple Script: " << script; 191 AECreateDesc(typeNull, NULL, 0, &result_data); 192 OSAScriptError(component, kOSAErrorMessage, typeChar, &result_data); 193 int len = AEGetDescDataSize(&result_data); 194 char* data = (char*) malloc(len); 195 if (data != NULL) { 196 err = AEGetDescData(&result_data, data, len); 197 LOG(LS_ERROR) << "Script error: " << data; 198 } 199 AEDisposeDesc(&script_desc); 200 AEDisposeDesc(&result_data); 201 return false; 202 } 203 AEDisposeDesc(&script_desc); 204 if (script_id != kOSANullScript) { 205 OSADispose(component, script_id); 206 } 207 if (result_id != kOSANullScript) { 208 OSADispose(component, result_id); 209 } 210 CloseComponent(component); 211 return true; 212 #else 213 // TODO(thaloun): Support applescripts with the NSAppleScript API. 214 return false; 215 #endif // CARBON_DEPRECATED 216 } 217 #endif // WEBRTC_MAC && !defined(WEBRTC_IOS) 218 219 /////////////////////////////////////////////////////////////////////////////// 220 221 } // namespace rtc 222