15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/foundation_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/bundle_locations.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_logging.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/sys_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_IOS)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFTypeID SecACLGetTypeID();
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFTypeID SecTrustedApplicationGetTypeID();
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)Boolean _CFIsObjC(CFTypeID typeID, CFTypeRef obj);
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // extern "C"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mac {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool g_override_am_i_bundled = false;
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool g_override_am_i_bundled_value = false;
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool UncachedAmIBundled() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS)
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // All apps are bundled on iOS.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_override_am_i_bundled)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return g_override_am_i_bundled_value;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Yes, this is cheap.
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return [[base::mac::OuterBundle() bundlePath] hasSuffix:@".app"];
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AmIBundled() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the return value is not cached, this function will return different
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values depending on when it's called. This confuses some client code, see
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/63183 .
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool result = UncachedAmIBundled();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(result, UncachedAmIBundled())
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "The return value of AmIBundled() changed. This will confuse tests. "
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Call SetAmIBundled() override manually if your test binary "
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "delay-loads the framework.";
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetOverrideAmIBundled(bool value) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It doesn't make sense not to be bundled on iOS.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_override_am_i_bundled = true;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_override_am_i_bundled_value = value;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsBackgroundOnlyProcess() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function really does want to examine NSBundle's idea of the main
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bundle dictionary.  It needs to look at the actual running .app's
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Info.plist to access its LSUIElement property.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSDictionary* info_dictionary = [base::mac::MainBundle() infoDictionary];
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [[info_dictionary objectForKey:@"LSUIElement"] boolValue] != NO;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath PathForFrameworkBundleResource(CFStringRef resourceName) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSBundle* bundle = base::mac::FrameworkBundle();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSString* resourcePath = [bundle pathForResource:(NSString*)resourceName
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            ofType:nil];
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NSStringToFilePath(resourcePath);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSType CreatorCodeForCFBundleRef(CFBundleRef bundle) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSType creator = kUnknownType;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFBundleGetPackageInfo(bundle, NULL, &creator);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return creator;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSType CreatorCodeForApplication() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFBundleRef bundle = CFBundleGetMainBundle();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bundle)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kUnknownType;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreatorCodeForCFBundleRef(bundle);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetSearchPathDirectory(NSSearchPathDirectory directory,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            NSSearchPathDomainMask domain_mask,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            FilePath* result) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* dirs =
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NSSearchPathForDirectoriesInDomains(directory, domain_mask, YES);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ([dirs count] < 1) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = NSStringToFilePath([dirs objectAtIndex:0]);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetSearchPathDirectory(directory, NSLocalDomainMask, result);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetSearchPathDirectory(directory, NSUserDomainMask, result);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath GetUserLibraryPath() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath user_library_path;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetUserDirectory(NSLibraryDirectory, &user_library_path)) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Could not get user library path";
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return user_library_path;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Takes a path to an (executable) binary and tries to provide the path to an
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// application bundle containing it. It takes the outermost bundle that it can
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   |exec_name| - path to the binary
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   returns - path to the application bundle, or empty on error
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath GetAppBundlePath(const FilePath& exec_name) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kExt[] = ".app";
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kExtLength = arraysize(kExt) - 1;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Split the path into components.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> components;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exec_name.GetComponents(&components);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's an error if we don't get any components.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!components.size())
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FilePath();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't prepend '/' to the first component.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string>::const_iterator it = components.begin();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string bundle_name = *it;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(it->length(), 0U);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the first component ends in ".app", we're already done.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it->length() > kExtLength &&
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength))
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FilePath(bundle_name);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first component may be "/" or "//", etc. Only append '/' if it doesn't
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already end in '/'.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bundle_name[bundle_name.length() - 1] != '/')
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bundle_name += '/';
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Go through the remaining components.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (++it; it != components.end(); ++it) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GT(it->length(), 0U);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bundle_name += *it;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the current component ends in ".app", we're done.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->length() > kExtLength &&
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FilePath(bundle_name);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Separate this component from the next one.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bundle_name += '/';
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FilePath();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TYPE_NAME_FOR_CF_TYPE_DEFN(TypeCF) \
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TypeNameForCFType(TypeCF##Ref) { \
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return #TypeCF; \
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFArray);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFBag);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFBoolean);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFData);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFDate);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFDictionary);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFNull);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFNumber);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFSet);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFString);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFURL);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CFUUID);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CGColor);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CTFont);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TYPE_NAME_FOR_CF_TYPE_DEFN(CTRun);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef TYPE_NAME_FOR_CF_TYPE_DEFN
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSObjectRetain(void* obj) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id<NSObject> nsobj = static_cast<id<NSObject> >(obj);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [nsobj retain];
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSObjectRelease(void* obj) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id<NSObject> nsobj = static_cast<id<NSObject> >(obj);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [nsobj release];
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* CFTypeRefToNSObjectAutorelease(CFTypeRef cf_object) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When GC is on, NSMakeCollectable marks cf_object for GC and autorelease
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is a no-op.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the traditional GC-less environment, NSMakeCollectable is a no-op,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and cf_object is autoreleased, balancing out the caller's ownership claim.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NSMakeCollectable returns nil when used on a NULL object.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [NSMakeCollectable(cf_object) autorelease];
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* base_bundle_id;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BaseBundleID() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base_bundle_id) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base_bundle_id;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "com.google.Chrome";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "org.chromium.Chromium";
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetBaseBundleID(const char* new_base_bundle_id) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_base_bundle_id != base_bundle_id) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free((void*)base_bundle_id);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base_bundle_id = new_base_bundle_id ? strdup(new_base_bundle_id) : NULL;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Definitions for the corresponding CF_TO_NS_CAST_DECL macros in
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// foundation_util.h.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CF_TO_NS_CAST_DEFN(TypeCF, TypeNS) \
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TypeNS* CFToNSCast(TypeCF##Ref cf_val) { \
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TypeNS* ns_val = \
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<TypeNS*>(reinterpret_cast<const TypeNS*>(cf_val)); \
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ns_val; \
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} \
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TypeCF##Ref NSToCFCast(TypeNS* ns_val) { \
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TypeCF##Ref cf_val = reinterpret_cast<TypeCF##Ref>(ns_val); \
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cf_val; \
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CF_TO_NS_MUTABLE_CAST_DEFN(name) \
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CF##name, NS##name) \
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val) { \
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSMutable##name* ns_val = reinterpret_cast<NSMutable##name*>(cf_val); \
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ns_val; \
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} \
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val) { \
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFMutable##name##Ref cf_val = \
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<CFMutable##name##Ref>(ns_val); \
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cf_val; \
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(Array);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(AttributedString);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFCalendar, NSCalendar);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(CharacterSet);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(Data);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFDate, NSDate);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(Dictionary);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFError, NSError);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFLocale, NSLocale);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFNumber, NSNumber);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFRunLoopTimer, NSTimer);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFTimeZone, NSTimeZone);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(Set);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFReadStream, NSInputStream);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFWriteStream, NSOutputStream);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_MUTABLE_CAST_DEFN(String);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CFURL, NSURL);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if defined(OS_IOS)
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)CF_TO_NS_CAST_DEFN(CTFont, UIFont);
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#else
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The NSFont/CTFont toll-free bridging is broken when it comes to type
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// checking, so do some special-casing.
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// http://www.openradar.me/15341349 rdar://15341349
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)NSFont* CFToNSCast(CTFontRef cf_val) {
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NSFont* ns_val =
3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const_cast<NSFont*>(reinterpret_cast<const NSFont*>(cf_val));
3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!cf_val ||
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         CTFontGetTypeID() == CFGetTypeID(cf_val) ||
3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         (_CFIsObjC(CTFontGetTypeID(), cf_val) &&
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          [ns_val isKindOfClass:NSClassFromString(@"NSFont")]));
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return ns_val;
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)CTFontRef NSToCFCast(NSFont* ns_val) {
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CTFontRef cf_val = reinterpret_cast<CTFontRef>(ns_val);
3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!cf_val ||
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         CTFontGetTypeID() == CFGetTypeID(cf_val) ||
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         [ns_val isKindOfClass:NSClassFromString(@"NSFont")]);
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return cf_val;
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef CF_TO_NS_CAST_DEFN
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef CF_TO_NS_MUTABLE_CAST_DEFN
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CF_CAST_DEFN(TypeCF) \
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> TypeCF##Ref \
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFCast<TypeCF##Ref>(const CFTypeRef& cf_val) { \
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cf_val == NULL) { \
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL; \
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } \
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CFGetTypeID(cf_val) == TypeCF##GetTypeID()) { \
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (TypeCF##Ref)(cf_val); \
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } \
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL; \
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} \
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> TypeCF##Ref \
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val) { \
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TypeCF##Ref rv = CFCast<TypeCF##Ref>(cf_val); \
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(cf_val == NULL || rv); \
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv; \
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFArray);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFBag);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFBoolean);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFData);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFDate);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFDictionary);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFNull);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFNumber);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFSet);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFString);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFURL);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CFUUID);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CGColor);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(CTRun);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if defined(OS_IOS)
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)CF_CAST_DEFN(CTFont);
3601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#else
3611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The NSFont/CTFont toll-free bridging is broken when it comes to type
3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// checking, so do some special-casing.
3631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// http://www.openradar.me/15341349 rdar://15341349
3641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)template<> CTFontRef
3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)CFCast<CTFontRef>(const CFTypeRef& cf_val) {
3661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (cf_val == NULL) {
3671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return NULL;
3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (CFGetTypeID(cf_val) == CTFontGetTypeID()) {
3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return (CTFontRef)(cf_val);
3711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!_CFIsObjC(CTFontGetTypeID(), cf_val))
3741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return NULL;
3751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  id<NSObject> ns_val = reinterpret_cast<id>(const_cast<void*>(cf_val));
3771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if ([ns_val isKindOfClass:NSClassFromString(@"NSFont")]) {
3781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return (CTFontRef)(cf_val);
3791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return NULL;
3811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)template<> CTFontRef
3841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)CFCastStrict<CTFontRef>(const CFTypeRef& cf_val) {
3851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CTFontRef rv = CFCast<CTFontRef>(cf_val);
3861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(cf_val == NULL || rv);
3871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return rv;
3881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif
3901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_IOS)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(SecACL);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CF_CAST_DEFN(SecTrustedApplication);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef CF_CAST_DEFN
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetValueFromDictionaryErrorMessage(
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CFStringRef key, const std::string& expected_type, CFTypeRef value) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCFTypeRef<CFStringRef> actual_type_ref(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFCopyTypeIDDescription(CFGetTypeID(value)));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "Expected value for key " +
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SysCFStringRefToUTF8(key) +
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " to be " +
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_type +
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " but it was " +
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SysCFStringRefToUTF8(actual_type_ref) +
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " instead";
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSString* FilePathToNSString(const FilePath& path) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path.empty())
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return nil;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [NSString stringWithUTF8String:path.value().c_str()];
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath NSStringToFilePath(NSString* str) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![str length])
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FilePath();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FilePath([str fileSystemRepresentation]);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace mac
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator<<(std::ostream& o, const CFStringRef string) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return o << base::SysCFStringRefToUTF8(string);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator<<(std::ostream& o, const CFErrorRef err) {
431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFStringRef> desc(CFErrorCopyDescription(err));
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFDictionaryRef> user_info(CFErrorCopyUserInfo(err));
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef errorDesc = NULL;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (user_info.get()) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errorDesc = reinterpret_cast<CFStringRef>(
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CFDictionaryGetValue(user_info.get(), kCFErrorDescriptionKey));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  o << "Code: " << CFErrorGetCode(err)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " Domain: " << CFErrorGetDomain(err)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " Desc: " << desc.get();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if(errorDesc) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    o << "(" << errorDesc << ")";
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return o;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
446