Home | History | Annotate | Download | only in base
      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: " << std::string(data, len);
    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