Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / macutils.cc
1 /*
2  * libjingle
3  * Copyright 2007 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <sstream>
29
30 #include "talk/base/common.h"
31 #include "talk/base/logging.h"
32 #include "talk/base/macutils.h"
33 #include "talk/base/scoped_ptr.h"
34 #include "talk/base/stringutils.h"
35
36 namespace talk_base {
37
38 ///////////////////////////////////////////////////////////////////////////////
39
40 bool ToUtf8(const CFStringRef str16, std::string* str8) {
41   if ((NULL == str16) || (NULL == str8)) {
42     return false;
43   }
44   size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
45                                                     kCFStringEncodingUTF8) + 1;
46   scoped_ptr<char[]> buffer(new char[maxlen]);
47   if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen,
48                                      kCFStringEncodingUTF8)) {
49     return false;
50   }
51   str8->assign(buffer.get());
52   return true;
53 }
54
55 bool ToUtf16(const std::string& str8, CFStringRef* str16) {
56   if (NULL == str16) {
57     return false;
58   }
59   *str16 = CFStringCreateWithBytes(kCFAllocatorDefault,
60                                    reinterpret_cast<const UInt8*>(str8.data()),
61                                    str8.length(), kCFStringEncodingUTF8,
62                                    false);
63   return NULL != *str16;
64 }
65
66 #ifdef OSX
67 void DecodeFourChar(UInt32 fc, std::string* out) {
68   std::stringstream ss;
69   ss << '\'';
70   bool printable = true;
71   for (int i = 3; i >= 0; --i) {
72     char ch = (fc >> (8 * i)) & 0xFF;
73     if (isprint(static_cast<unsigned char>(ch))) {
74       ss << ch;
75     } else {
76       printable = false;
77       break;
78     }
79   }
80   if (printable) {
81     ss << '\'';
82   } else {
83     ss.str("");
84     ss << "0x" << std::hex << fc;
85   }
86   out->append(ss.str());
87 }
88
89 static bool GetGestalt(OSType ostype, int* value) {
90   ASSERT(NULL != value);
91   SInt32 native_value;
92   OSStatus result = Gestalt(ostype, &native_value);
93   if (noErr == result) {
94     *value = native_value;
95     return true;
96   }
97   std::string str;
98   DecodeFourChar(ostype, &str);
99   LOG_E(LS_ERROR, OS, result) << "Gestalt(" << str << ")";
100   return false;
101 }
102
103 bool GetOSVersion(int* major, int* minor, int* bugfix) {
104   ASSERT(major && minor && bugfix);
105   if (!GetGestalt(gestaltSystemVersion, major)) {
106     return false;
107   }
108   if (*major < 0x1040) {
109     *bugfix = *major & 0xF;
110     *minor = (*major >> 4) & 0xF;
111     *major = (*major >> 8);
112     return true;
113   }
114   return GetGestalt(gestaltSystemVersionMajor, major) &&
115          GetGestalt(gestaltSystemVersionMinor, minor) &&
116          GetGestalt(gestaltSystemVersionBugFix, bugfix);
117 }
118
119 MacOSVersionName GetOSVersionName() {
120   int major = 0, minor = 0, bugfix = 0;
121   if (!GetOSVersion(&major, &minor, &bugfix)) {
122     return kMacOSUnknown;
123   }
124   if (major > 10) {
125     return kMacOSNewer;
126   }
127   if ((major < 10) || (minor < 3)) {
128     return kMacOSOlder;
129   }
130   switch (minor) {
131     case 3:
132       return kMacOSPanther;
133     case 4:
134       return kMacOSTiger;
135     case 5:
136       return kMacOSLeopard;
137     case 6:
138       return kMacOSSnowLeopard;
139     case 7:
140       return kMacOSLion;
141     case 8:
142       return kMacOSMountainLion;
143     case 9:
144       return kMacOSMavericks;
145   }
146   return kMacOSNewer;
147 }
148
149 bool GetQuickTimeVersion(std::string* out) {
150   int ver;
151   if (!GetGestalt(gestaltQuickTimeVersion, &ver)) {
152     return false;
153   }
154
155   std::stringstream ss;
156   ss << std::hex << ver;
157   *out = ss.str();
158   return true;
159 }
160
161 bool RunAppleScript(const std::string& script) {
162   // TODO(thaloun): Add a .mm file that contains something like this:
163   // NSString source from script
164   // NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource:&source]
165   // if (appleScript != nil) {
166   //   [appleScript executeAndReturnError:nil]
167   //   [appleScript release]
168 #ifndef CARBON_DEPRECATED
169   ComponentInstance component = NULL;
170   AEDesc script_desc;
171   AEDesc result_data;
172   OSStatus err;
173   OSAID script_id, result_id;
174
175   AECreateDesc(typeNull, NULL, 0, &script_desc);
176   AECreateDesc(typeNull, NULL, 0, &result_data);
177   script_id = kOSANullScript;
178   result_id = kOSANullScript;
179
180   component = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
181   if (component == NULL) {
182     LOG(LS_ERROR) << "Failed opening Apple Script component";
183     return false;
184   }
185   err = AECreateDesc(typeUTF8Text, script.data(), script.size(), &script_desc);
186   if (err != noErr) {
187     CloseComponent(component);
188     LOG(LS_ERROR) << "Failed creating Apple Script description";
189     return false;
190   }
191
192   err = OSACompile(component, &script_desc, kOSAModeCanInteract, &script_id);
193   if (err != noErr) {
194     AEDisposeDesc(&script_desc);
195     if (script_id != kOSANullScript) {
196       OSADispose(component, script_id);
197     }
198     CloseComponent(component);
199     LOG(LS_ERROR) << "Error compiling Apple Script";
200     return false;
201   }
202
203   err = OSAExecute(component, script_id, kOSANullScript, kOSAModeCanInteract,
204                    &result_id);
205
206   if (err == errOSAScriptError) {
207     LOG(LS_ERROR) << "Error when executing Apple Script: " << script;
208     AECreateDesc(typeNull, NULL, 0, &result_data);
209     OSAScriptError(component, kOSAErrorMessage, typeChar, &result_data);
210     int len = AEGetDescDataSize(&result_data);
211     char* data = (char*) malloc(len);
212     if (data != NULL) {
213       err = AEGetDescData(&result_data, data, len);
214       LOG(LS_ERROR) << "Script error: " << data;
215     }
216     AEDisposeDesc(&script_desc);
217     AEDisposeDesc(&result_data);
218     return false;
219   }
220   AEDisposeDesc(&script_desc);
221   if (script_id != kOSANullScript) {
222     OSADispose(component, script_id);
223   }
224   if (result_id != kOSANullScript) {
225     OSADispose(component, result_id);
226   }
227   CloseComponent(component);
228   return true;
229 #else
230   // TODO(thaloun): Support applescripts with the NSAppleScript API.
231   return false;
232 #endif  // CARBON_DEPRECATED
233 }
234 #endif  // OSX
235
236 ///////////////////////////////////////////////////////////////////////////////
237
238 }  // namespace talk_base