1*6777b538SAndroid Build Coastguard Worker// Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker#include "base/apple/foundation_util.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker#include <stddef.h> 8*6777b538SAndroid Build Coastguard Worker#include <stdlib.h> 9*6777b538SAndroid Build Coastguard Worker#include <string.h> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker#include <vector> 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker#include "base/apple/bundle_locations.h" 14*6777b538SAndroid Build Coastguard Worker#include "base/apple/osstatus_logging.h" 15*6777b538SAndroid Build Coastguard Worker#include "base/containers/adapters.h" 16*6777b538SAndroid Build Coastguard Worker#include "base/files/file_path.h" 17*6777b538SAndroid Build Coastguard Worker#include "base/logging.h" 18*6777b538SAndroid Build Coastguard Worker#include "base/notreached.h" 19*6777b538SAndroid Build Coastguard Worker#include "base/numerics/checked_math.h" 20*6777b538SAndroid Build Coastguard Worker#include "base/numerics/safe_conversions.h" 21*6777b538SAndroid Build Coastguard Worker#include "base/ranges/algorithm.h" 22*6777b538SAndroid Build Coastguard Worker#include "base/strings/string_util.h" 23*6777b538SAndroid Build Coastguard Worker#include "base/strings/sys_string_conversions.h" 24*6777b538SAndroid Build Coastguard Worker#include "build/branding_buildflags.h" 25*6777b538SAndroid Build Coastguard Worker#include "build/build_config.h" 26*6777b538SAndroid Build Coastguard Worker 27*6777b538SAndroid Build Coastguard Worker#if !BUILDFLAG(IS_IOS) 28*6777b538SAndroid Build Coastguard Worker#import <AppKit/AppKit.h> 29*6777b538SAndroid Build Coastguard Worker#endif 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Workerextern "C" { 32*6777b538SAndroid Build Coastguard WorkerCFTypeID SecKeyGetTypeID(); 33*6777b538SAndroid Build Coastguard Worker} // extern "C" 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Workernamespace base::apple { 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Workernamespace { 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Workerbool g_cached_am_i_bundled_called = false; 40*6777b538SAndroid Build Coastguard Workerbool g_cached_am_i_bundled_value = false; 41*6777b538SAndroid Build Coastguard Workerbool g_override_am_i_bundled = false; 42*6777b538SAndroid Build Coastguard Workerbool g_override_am_i_bundled_value = false; 43*6777b538SAndroid Build Coastguard Worker 44*6777b538SAndroid Build Coastguard Workerbool UncachedAmIBundled() { 45*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(IS_IOS) 46*6777b538SAndroid Build Coastguard Worker // All apps are bundled on iOS. 47*6777b538SAndroid Build Coastguard Worker return true; 48*6777b538SAndroid Build Coastguard Worker#else 49*6777b538SAndroid Build Coastguard Worker if (g_override_am_i_bundled) { 50*6777b538SAndroid Build Coastguard Worker return g_override_am_i_bundled_value; 51*6777b538SAndroid Build Coastguard Worker } 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker // Yes, this is cheap. 54*6777b538SAndroid Build Coastguard Worker return [apple::OuterBundle().bundlePath hasSuffix:@".app"]; 55*6777b538SAndroid Build Coastguard Worker#endif 56*6777b538SAndroid Build Coastguard Worker} 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker} // namespace 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Workerbool AmIBundled() { 61*6777b538SAndroid Build Coastguard Worker // If the return value is not cached, this function will return different 62*6777b538SAndroid Build Coastguard Worker // values depending on when it's called. This confuses some client code, see 63*6777b538SAndroid Build Coastguard Worker // http://crbug.com/63183 . 64*6777b538SAndroid Build Coastguard Worker if (!g_cached_am_i_bundled_called) { 65*6777b538SAndroid Build Coastguard Worker g_cached_am_i_bundled_called = true; 66*6777b538SAndroid Build Coastguard Worker g_cached_am_i_bundled_value = UncachedAmIBundled(); 67*6777b538SAndroid Build Coastguard Worker } 68*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(g_cached_am_i_bundled_value, UncachedAmIBundled()) 69*6777b538SAndroid Build Coastguard Worker << "The return value of AmIBundled() changed. This will confuse tests. " 70*6777b538SAndroid Build Coastguard Worker << "Call SetAmIBundled() override manually if your test binary " 71*6777b538SAndroid Build Coastguard Worker << "delay-loads the framework."; 72*6777b538SAndroid Build Coastguard Worker return g_cached_am_i_bundled_value; 73*6777b538SAndroid Build Coastguard Worker} 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Workervoid SetOverrideAmIBundled(bool value) { 76*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(IS_IOS) 77*6777b538SAndroid Build Coastguard Worker // It doesn't make sense not to be bundled on iOS. 78*6777b538SAndroid Build Coastguard Worker if (!value) { 79*6777b538SAndroid Build Coastguard Worker NOTREACHED(); 80*6777b538SAndroid Build Coastguard Worker } 81*6777b538SAndroid Build Coastguard Worker#endif 82*6777b538SAndroid Build Coastguard Worker g_override_am_i_bundled = true; 83*6777b538SAndroid Build Coastguard Worker g_override_am_i_bundled_value = value; 84*6777b538SAndroid Build Coastguard Worker} 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard WorkerBASE_EXPORT void ClearAmIBundledCache() { 87*6777b538SAndroid Build Coastguard Worker g_cached_am_i_bundled_called = false; 88*6777b538SAndroid Build Coastguard Worker} 89*6777b538SAndroid Build Coastguard Worker 90*6777b538SAndroid Build Coastguard Workerbool IsBackgroundOnlyProcess() { 91*6777b538SAndroid Build Coastguard Worker // This function really does want to examine NSBundle's idea of the main 92*6777b538SAndroid Build Coastguard Worker // bundle dictionary. It needs to look at the actual running .app's 93*6777b538SAndroid Build Coastguard Worker // Info.plist to access its LSUIElement property. 94*6777b538SAndroid Build Coastguard Worker @autoreleasepool { 95*6777b538SAndroid Build Coastguard Worker NSDictionary* info_dictionary = [apple::MainBundle() infoDictionary]; 96*6777b538SAndroid Build Coastguard Worker return [info_dictionary[@"LSUIElement"] boolValue] != NO; 97*6777b538SAndroid Build Coastguard Worker } 98*6777b538SAndroid Build Coastguard Worker} 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard WorkerFilePath PathForFrameworkBundleResource(const char* resource_name) { 101*6777b538SAndroid Build Coastguard Worker NSBundle* bundle = apple::FrameworkBundle(); 102*6777b538SAndroid Build Coastguard Worker NSURL* resource_url = [bundle URLForResource:@(resource_name) 103*6777b538SAndroid Build Coastguard Worker withExtension:nil]; 104*6777b538SAndroid Build Coastguard Worker return NSURLToFilePath(resource_url); 105*6777b538SAndroid Build Coastguard Worker} 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard WorkerOSType CreatorCodeForCFBundleRef(CFBundleRef bundle) { 108*6777b538SAndroid Build Coastguard Worker OSType creator = kUnknownType; 109*6777b538SAndroid Build Coastguard Worker CFBundleGetPackageInfo(bundle, /*packageType=*/nullptr, &creator); 110*6777b538SAndroid Build Coastguard Worker return creator; 111*6777b538SAndroid Build Coastguard Worker} 112*6777b538SAndroid Build Coastguard Worker 113*6777b538SAndroid Build Coastguard WorkerOSType CreatorCodeForApplication() { 114*6777b538SAndroid Build Coastguard Worker CFBundleRef bundle = CFBundleGetMainBundle(); 115*6777b538SAndroid Build Coastguard Worker if (!bundle) { 116*6777b538SAndroid Build Coastguard Worker return kUnknownType; 117*6777b538SAndroid Build Coastguard Worker } 118*6777b538SAndroid Build Coastguard Worker 119*6777b538SAndroid Build Coastguard Worker return CreatorCodeForCFBundleRef(bundle); 120*6777b538SAndroid Build Coastguard Worker} 121*6777b538SAndroid Build Coastguard Worker 122*6777b538SAndroid Build Coastguard Workerbool GetSearchPathDirectory(NSSearchPathDirectory directory, 123*6777b538SAndroid Build Coastguard Worker NSSearchPathDomainMask domain_mask, 124*6777b538SAndroid Build Coastguard Worker FilePath* result) { 125*6777b538SAndroid Build Coastguard Worker DCHECK(result); 126*6777b538SAndroid Build Coastguard Worker NSArray<NSString*>* dirs = 127*6777b538SAndroid Build Coastguard Worker NSSearchPathForDirectoriesInDomains(directory, domain_mask, YES); 128*6777b538SAndroid Build Coastguard Worker if (dirs.count < 1) { 129*6777b538SAndroid Build Coastguard Worker return false; 130*6777b538SAndroid Build Coastguard Worker } 131*6777b538SAndroid Build Coastguard Worker *result = NSStringToFilePath(dirs[0]); 132*6777b538SAndroid Build Coastguard Worker return true; 133*6777b538SAndroid Build Coastguard Worker} 134*6777b538SAndroid Build Coastguard Worker 135*6777b538SAndroid Build Coastguard Workerbool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result) { 136*6777b538SAndroid Build Coastguard Worker return GetSearchPathDirectory(directory, NSLocalDomainMask, result); 137*6777b538SAndroid Build Coastguard Worker} 138*6777b538SAndroid Build Coastguard Worker 139*6777b538SAndroid Build Coastguard Workerbool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result) { 140*6777b538SAndroid Build Coastguard Worker return GetSearchPathDirectory(directory, NSUserDomainMask, result); 141*6777b538SAndroid Build Coastguard Worker} 142*6777b538SAndroid Build Coastguard Worker 143*6777b538SAndroid Build Coastguard WorkerFilePath GetUserLibraryPath() { 144*6777b538SAndroid Build Coastguard Worker FilePath user_library_path; 145*6777b538SAndroid Build Coastguard Worker if (!GetUserDirectory(NSLibraryDirectory, &user_library_path)) { 146*6777b538SAndroid Build Coastguard Worker DLOG(WARNING) << "Could not get user library path"; 147*6777b538SAndroid Build Coastguard Worker } 148*6777b538SAndroid Build Coastguard Worker return user_library_path; 149*6777b538SAndroid Build Coastguard Worker} 150*6777b538SAndroid Build Coastguard Worker 151*6777b538SAndroid Build Coastguard WorkerFilePath GetUserDocumentPath() { 152*6777b538SAndroid Build Coastguard Worker FilePath user_document_path; 153*6777b538SAndroid Build Coastguard Worker if (!GetUserDirectory(NSDocumentDirectory, &user_document_path)) { 154*6777b538SAndroid Build Coastguard Worker DLOG(WARNING) << "Could not get user document path"; 155*6777b538SAndroid Build Coastguard Worker } 156*6777b538SAndroid Build Coastguard Worker return user_document_path; 157*6777b538SAndroid Build Coastguard Worker} 158*6777b538SAndroid Build Coastguard Worker 159*6777b538SAndroid Build Coastguard Worker// Takes a path to an (executable) binary and tries to provide the path to an 160*6777b538SAndroid Build Coastguard Worker// application bundle containing it. It takes the outermost bundle that it can 161*6777b538SAndroid Build Coastguard Worker// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app"). 162*6777b538SAndroid Build Coastguard Worker// |exec_name| - path to the binary 163*6777b538SAndroid Build Coastguard Worker// returns - path to the application bundle, or empty on error 164*6777b538SAndroid Build Coastguard WorkerFilePath GetAppBundlePath(const FilePath& exec_name) { 165*6777b538SAndroid Build Coastguard Worker const char kExt[] = ".app"; 166*6777b538SAndroid Build Coastguard Worker const size_t kExtLength = std::size(kExt) - 1; 167*6777b538SAndroid Build Coastguard Worker 168*6777b538SAndroid Build Coastguard Worker // Split the path into components. 169*6777b538SAndroid Build Coastguard Worker std::vector<std::string> components = exec_name.GetComponents(); 170*6777b538SAndroid Build Coastguard Worker 171*6777b538SAndroid Build Coastguard Worker // It's an error if we don't get any components. 172*6777b538SAndroid Build Coastguard Worker if (components.empty()) { 173*6777b538SAndroid Build Coastguard Worker return FilePath(); 174*6777b538SAndroid Build Coastguard Worker } 175*6777b538SAndroid Build Coastguard Worker 176*6777b538SAndroid Build Coastguard Worker // Don't prepend '/' to the first component. 177*6777b538SAndroid Build Coastguard Worker std::vector<std::string>::const_iterator it = components.begin(); 178*6777b538SAndroid Build Coastguard Worker std::string bundle_name = *it; 179*6777b538SAndroid Build Coastguard Worker DCHECK_GT(it->length(), 0U); 180*6777b538SAndroid Build Coastguard Worker // If the first component ends in ".app", we're already done. 181*6777b538SAndroid Build Coastguard Worker if (it->length() > kExtLength && 182*6777b538SAndroid Build Coastguard Worker !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength)) { 183*6777b538SAndroid Build Coastguard Worker return FilePath(bundle_name); 184*6777b538SAndroid Build Coastguard Worker } 185*6777b538SAndroid Build Coastguard Worker 186*6777b538SAndroid Build Coastguard Worker // The first component may be "/" or "//", etc. Only append '/' if it doesn't 187*6777b538SAndroid Build Coastguard Worker // already end in '/'. 188*6777b538SAndroid Build Coastguard Worker if (bundle_name.back() != '/') { 189*6777b538SAndroid Build Coastguard Worker bundle_name += '/'; 190*6777b538SAndroid Build Coastguard Worker } 191*6777b538SAndroid Build Coastguard Worker 192*6777b538SAndroid Build Coastguard Worker // Go through the remaining components. 193*6777b538SAndroid Build Coastguard Worker for (++it; it != components.end(); ++it) { 194*6777b538SAndroid Build Coastguard Worker DCHECK_GT(it->length(), 0U); 195*6777b538SAndroid Build Coastguard Worker 196*6777b538SAndroid Build Coastguard Worker bundle_name += *it; 197*6777b538SAndroid Build Coastguard Worker 198*6777b538SAndroid Build Coastguard Worker // If the current component ends in ".app", we're done. 199*6777b538SAndroid Build Coastguard Worker if (it->length() > kExtLength && 200*6777b538SAndroid Build Coastguard Worker !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength)) { 201*6777b538SAndroid Build Coastguard Worker return FilePath(bundle_name); 202*6777b538SAndroid Build Coastguard Worker } 203*6777b538SAndroid Build Coastguard Worker 204*6777b538SAndroid Build Coastguard Worker // Separate this component from the next one. 205*6777b538SAndroid Build Coastguard Worker bundle_name += '/'; 206*6777b538SAndroid Build Coastguard Worker } 207*6777b538SAndroid Build Coastguard Worker 208*6777b538SAndroid Build Coastguard Worker return FilePath(); 209*6777b538SAndroid Build Coastguard Worker} 210*6777b538SAndroid Build Coastguard Worker 211*6777b538SAndroid Build Coastguard Worker// Takes a path to an (executable) binary and tries to provide the path to an 212*6777b538SAndroid Build Coastguard Worker// application bundle containing it. It takes the innermost bundle that it can 213*6777b538SAndroid Build Coastguard Worker// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces 214*6777b538SAndroid Build Coastguard Worker// "/Foo/Bar.app/.../Baz.app"). 215*6777b538SAndroid Build Coastguard Worker// |exec_name| - path to the binary 216*6777b538SAndroid Build Coastguard Worker// returns - path to the application bundle, or empty on error 217*6777b538SAndroid Build Coastguard WorkerFilePath GetInnermostAppBundlePath(const FilePath& exec_name) { 218*6777b538SAndroid Build Coastguard Worker static constexpr char kExt[] = ".app"; 219*6777b538SAndroid Build Coastguard Worker static constexpr size_t kExtLength = std::size(kExt) - 1; 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker // Split the path into components. 222*6777b538SAndroid Build Coastguard Worker std::vector<std::string> components = exec_name.GetComponents(); 223*6777b538SAndroid Build Coastguard Worker 224*6777b538SAndroid Build Coastguard Worker // It's an error if we don't get any components. 225*6777b538SAndroid Build Coastguard Worker if (components.empty()) { 226*6777b538SAndroid Build Coastguard Worker return FilePath(); 227*6777b538SAndroid Build Coastguard Worker } 228*6777b538SAndroid Build Coastguard Worker 229*6777b538SAndroid Build Coastguard Worker auto app = ranges::find_if( 230*6777b538SAndroid Build Coastguard Worker Reversed(components), [](const std::string& component) -> bool { 231*6777b538SAndroid Build Coastguard Worker return component.size() > kExtLength && EndsWith(component, kExt); 232*6777b538SAndroid Build Coastguard Worker }); 233*6777b538SAndroid Build Coastguard Worker 234*6777b538SAndroid Build Coastguard Worker if (app == components.rend()) { 235*6777b538SAndroid Build Coastguard Worker return FilePath(); 236*6777b538SAndroid Build Coastguard Worker } 237*6777b538SAndroid Build Coastguard Worker 238*6777b538SAndroid Build Coastguard Worker // Remove all path components after the final ".app" extension. 239*6777b538SAndroid Build Coastguard Worker components.erase(app.base(), components.end()); 240*6777b538SAndroid Build Coastguard Worker 241*6777b538SAndroid Build Coastguard Worker std::string bundle_path; 242*6777b538SAndroid Build Coastguard Worker for (const std::string& component : components) { 243*6777b538SAndroid Build Coastguard Worker // Don't prepend a slash if this is the first component or if the 244*6777b538SAndroid Build Coastguard Worker // previous component ended with a slash, which can happen when dealing 245*6777b538SAndroid Build Coastguard Worker // with an absolute path. 246*6777b538SAndroid Build Coastguard Worker if (!bundle_path.empty() && bundle_path.back() != '/') { 247*6777b538SAndroid Build Coastguard Worker bundle_path += '/'; 248*6777b538SAndroid Build Coastguard Worker } 249*6777b538SAndroid Build Coastguard Worker 250*6777b538SAndroid Build Coastguard Worker bundle_path += component; 251*6777b538SAndroid Build Coastguard Worker } 252*6777b538SAndroid Build Coastguard Worker 253*6777b538SAndroid Build Coastguard Worker return FilePath(bundle_path); 254*6777b538SAndroid Build Coastguard Worker} 255*6777b538SAndroid Build Coastguard Worker 256*6777b538SAndroid Build Coastguard Worker#define TYPE_NAME_FOR_CF_TYPE_DEFN(TypeCF) \ 257*6777b538SAndroid Build Coastguard Worker std::string TypeNameForCFType(TypeCF##Ref) { \ 258*6777b538SAndroid Build Coastguard Worker return #TypeCF; \ 259*6777b538SAndroid Build Coastguard Worker } 260*6777b538SAndroid Build Coastguard Worker 261*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFArray) 262*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFBag) 263*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFBoolean) 264*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFData) 265*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFDate) 266*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFDictionary) 267*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFNull) 268*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFNumber) 269*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFSet) 270*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFString) 271*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFURL) 272*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CFUUID) 273*6777b538SAndroid Build Coastguard Worker 274*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CGColor) 275*6777b538SAndroid Build Coastguard Worker 276*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CTFont) 277*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(CTRun) 278*6777b538SAndroid Build Coastguard Worker 279*6777b538SAndroid Build Coastguard Worker#if !BUILDFLAG(IS_IOS) 280*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(SecAccessControl) 281*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(SecCertificate) 282*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(SecKey) 283*6777b538SAndroid Build Coastguard WorkerTYPE_NAME_FOR_CF_TYPE_DEFN(SecPolicy) 284*6777b538SAndroid Build Coastguard Worker#endif 285*6777b538SAndroid Build Coastguard Worker 286*6777b538SAndroid Build Coastguard Worker#undef TYPE_NAME_FOR_CF_TYPE_DEFN 287*6777b538SAndroid Build Coastguard Worker 288*6777b538SAndroid Build Coastguard Workerstatic const char* base_bundle_id; 289*6777b538SAndroid Build Coastguard Worker 290*6777b538SAndroid Build Coastguard Workerconst char* BaseBundleID() { 291*6777b538SAndroid Build Coastguard Worker if (base_bundle_id) { 292*6777b538SAndroid Build Coastguard Worker return base_bundle_id; 293*6777b538SAndroid Build Coastguard Worker } 294*6777b538SAndroid Build Coastguard Worker 295*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(GOOGLE_CHROME_BRANDING) 296*6777b538SAndroid Build Coastguard Worker return "com.google.Chrome"; 297*6777b538SAndroid Build Coastguard Worker#else 298*6777b538SAndroid Build Coastguard Worker return "org.chromium.Chromium"; 299*6777b538SAndroid Build Coastguard Worker#endif 300*6777b538SAndroid Build Coastguard Worker} 301*6777b538SAndroid Build Coastguard Worker 302*6777b538SAndroid Build Coastguard Workervoid SetBaseBundleID(const char* new_base_bundle_id) { 303*6777b538SAndroid Build Coastguard Worker if (new_base_bundle_id != base_bundle_id) { 304*6777b538SAndroid Build Coastguard Worker free((void*)base_bundle_id); 305*6777b538SAndroid Build Coastguard Worker base_bundle_id = new_base_bundle_id ? strdup(new_base_bundle_id) : nullptr; 306*6777b538SAndroid Build Coastguard Worker } 307*6777b538SAndroid Build Coastguard Worker} 308*6777b538SAndroid Build Coastguard Worker 309*6777b538SAndroid Build Coastguard Worker#define CF_CAST_DEFN(TypeCF) \ 310*6777b538SAndroid Build Coastguard Worker template <> \ 311*6777b538SAndroid Build Coastguard Worker TypeCF##Ref CFCast<TypeCF##Ref>(const CFTypeRef& cf_val) { \ 312*6777b538SAndroid Build Coastguard Worker if (cf_val == NULL) { \ 313*6777b538SAndroid Build Coastguard Worker return NULL; \ 314*6777b538SAndroid Build Coastguard Worker } \ 315*6777b538SAndroid Build Coastguard Worker if (CFGetTypeID(cf_val) == TypeCF##GetTypeID()) { \ 316*6777b538SAndroid Build Coastguard Worker return (TypeCF##Ref)(cf_val); \ 317*6777b538SAndroid Build Coastguard Worker } \ 318*6777b538SAndroid Build Coastguard Worker return NULL; \ 319*6777b538SAndroid Build Coastguard Worker } \ 320*6777b538SAndroid Build Coastguard Worker \ 321*6777b538SAndroid Build Coastguard Worker template <> \ 322*6777b538SAndroid Build Coastguard Worker TypeCF##Ref CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val) { \ 323*6777b538SAndroid Build Coastguard Worker TypeCF##Ref rv = CFCast<TypeCF##Ref>(cf_val); \ 324*6777b538SAndroid Build Coastguard Worker DCHECK(cf_val == NULL || rv); \ 325*6777b538SAndroid Build Coastguard Worker return rv; \ 326*6777b538SAndroid Build Coastguard Worker } 327*6777b538SAndroid Build Coastguard Worker 328*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFArray) 329*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFBag) 330*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFBoolean) 331*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFData) 332*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFDate) 333*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFDictionary) 334*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFNull) 335*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFNumber) 336*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFSet) 337*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFString) 338*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFURL) 339*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CFUUID) 340*6777b538SAndroid Build Coastguard Worker 341*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CGColor) 342*6777b538SAndroid Build Coastguard Worker 343*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CTFont) 344*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CTFontDescriptor) 345*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(CTRun) 346*6777b538SAndroid Build Coastguard Worker 347*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(SecCertificate) 348*6777b538SAndroid Build Coastguard Worker 349*6777b538SAndroid Build Coastguard Worker#if !BUILDFLAG(IS_IOS) 350*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(SecAccessControl) 351*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(SecKey) 352*6777b538SAndroid Build Coastguard WorkerCF_CAST_DEFN(SecPolicy) 353*6777b538SAndroid Build Coastguard Worker#endif 354*6777b538SAndroid Build Coastguard Worker 355*6777b538SAndroid Build Coastguard Worker#undef CF_CAST_DEFN 356*6777b538SAndroid Build Coastguard Worker 357*6777b538SAndroid Build Coastguard Workerstd::string GetValueFromDictionaryErrorMessage(CFStringRef key, 358*6777b538SAndroid Build Coastguard Worker const std::string& expected_type, 359*6777b538SAndroid Build Coastguard Worker CFTypeRef value) { 360*6777b538SAndroid Build Coastguard Worker ScopedCFTypeRef<CFStringRef> actual_type_ref( 361*6777b538SAndroid Build Coastguard Worker CFCopyTypeIDDescription(CFGetTypeID(value))); 362*6777b538SAndroid Build Coastguard Worker return "Expected value for key " + SysCFStringRefToUTF8(key) + " to be " + 363*6777b538SAndroid Build Coastguard Worker expected_type + " but it was " + 364*6777b538SAndroid Build Coastguard Worker SysCFStringRefToUTF8(actual_type_ref.get()) + " instead"; 365*6777b538SAndroid Build Coastguard Worker} 366*6777b538SAndroid Build Coastguard Worker 367*6777b538SAndroid Build Coastguard WorkerNSURL* FilePathToNSURL(const FilePath& path) { 368*6777b538SAndroid Build Coastguard Worker if (NSString* path_string = FilePathToNSString(path)) { 369*6777b538SAndroid Build Coastguard Worker return [NSURL fileURLWithPath:path_string]; 370*6777b538SAndroid Build Coastguard Worker } 371*6777b538SAndroid Build Coastguard Worker return nil; 372*6777b538SAndroid Build Coastguard Worker} 373*6777b538SAndroid Build Coastguard Worker 374*6777b538SAndroid Build Coastguard WorkerNSString* FilePathToNSString(const FilePath& path) { 375*6777b538SAndroid Build Coastguard Worker if (path.empty()) { 376*6777b538SAndroid Build Coastguard Worker return nil; 377*6777b538SAndroid Build Coastguard Worker } 378*6777b538SAndroid Build Coastguard Worker return @(path.value().c_str()); // @() does UTF8 conversion. 379*6777b538SAndroid Build Coastguard Worker} 380*6777b538SAndroid Build Coastguard Worker 381*6777b538SAndroid Build Coastguard WorkerFilePath NSStringToFilePath(NSString* str) { 382*6777b538SAndroid Build Coastguard Worker if (!str.length) { 383*6777b538SAndroid Build Coastguard Worker return FilePath(); 384*6777b538SAndroid Build Coastguard Worker } 385*6777b538SAndroid Build Coastguard Worker return FilePath(str.fileSystemRepresentation); 386*6777b538SAndroid Build Coastguard Worker} 387*6777b538SAndroid Build Coastguard Worker 388*6777b538SAndroid Build Coastguard WorkerFilePath NSURLToFilePath(NSURL* url) { 389*6777b538SAndroid Build Coastguard Worker if (!url.fileURL) { 390*6777b538SAndroid Build Coastguard Worker return FilePath(); 391*6777b538SAndroid Build Coastguard Worker } 392*6777b538SAndroid Build Coastguard Worker return NSStringToFilePath(url.path); 393*6777b538SAndroid Build Coastguard Worker} 394*6777b538SAndroid Build Coastguard Worker 395*6777b538SAndroid Build Coastguard WorkerScopedCFTypeRef<CFURLRef> FilePathToCFURL(const FilePath& path) { 396*6777b538SAndroid Build Coastguard Worker DCHECK(!path.empty()); 397*6777b538SAndroid Build Coastguard Worker 398*6777b538SAndroid Build Coastguard Worker // The function's docs promise that it does not require an NSAutoreleasePool. 399*6777b538SAndroid Build Coastguard Worker // A straightforward way to accomplish this is to use *Create* functions, 400*6777b538SAndroid Build Coastguard Worker // combined with ScopedCFTypeRef. 401*6777b538SAndroid Build Coastguard Worker const std::string& path_string = path.value(); 402*6777b538SAndroid Build Coastguard Worker ScopedCFTypeRef<CFStringRef> path_cfstring(CFStringCreateWithBytes( 403*6777b538SAndroid Build Coastguard Worker kCFAllocatorDefault, reinterpret_cast<const UInt8*>(path_string.data()), 404*6777b538SAndroid Build Coastguard Worker checked_cast<CFIndex>(path_string.length()), kCFStringEncodingUTF8, 405*6777b538SAndroid Build Coastguard Worker /*isExternalRepresentation=*/FALSE)); 406*6777b538SAndroid Build Coastguard Worker if (!path_cfstring) { 407*6777b538SAndroid Build Coastguard Worker return ScopedCFTypeRef<CFURLRef>(); 408*6777b538SAndroid Build Coastguard Worker } 409*6777b538SAndroid Build Coastguard Worker 410*6777b538SAndroid Build Coastguard Worker return ScopedCFTypeRef<CFURLRef>(CFURLCreateWithFileSystemPath( 411*6777b538SAndroid Build Coastguard Worker kCFAllocatorDefault, path_cfstring.get(), kCFURLPOSIXPathStyle, 412*6777b538SAndroid Build Coastguard Worker /*isDirectory=*/FALSE)); 413*6777b538SAndroid Build Coastguard Worker} 414*6777b538SAndroid Build Coastguard Worker 415*6777b538SAndroid Build Coastguard Workerbool CFRangeToNSRange(CFRange range, NSRange* range_out) { 416*6777b538SAndroid Build Coastguard Worker NSUInteger end; 417*6777b538SAndroid Build Coastguard Worker if (IsValueInRangeForNumericType<NSUInteger>(range.location) && 418*6777b538SAndroid Build Coastguard Worker IsValueInRangeForNumericType<NSUInteger>(range.length) && 419*6777b538SAndroid Build Coastguard Worker CheckAdd(range.location, range.length).AssignIfValid(&end) && 420*6777b538SAndroid Build Coastguard Worker IsValueInRangeForNumericType<NSUInteger>(end)) { 421*6777b538SAndroid Build Coastguard Worker *range_out = NSMakeRange(static_cast<NSUInteger>(range.location), 422*6777b538SAndroid Build Coastguard Worker static_cast<NSUInteger>(range.length)); 423*6777b538SAndroid Build Coastguard Worker return true; 424*6777b538SAndroid Build Coastguard Worker } 425*6777b538SAndroid Build Coastguard Worker return false; 426*6777b538SAndroid Build Coastguard Worker} 427*6777b538SAndroid Build Coastguard Worker 428*6777b538SAndroid Build Coastguard Worker} // namespace base::apple 429*6777b538SAndroid Build Coastguard Worker 430*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, const CFStringRef string) { 431*6777b538SAndroid Build Coastguard Worker return o << base::SysCFStringRefToUTF8(string); 432*6777b538SAndroid Build Coastguard Worker} 433*6777b538SAndroid Build Coastguard Worker 434*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, const CFErrorRef err) { 435*6777b538SAndroid Build Coastguard Worker base::apple::ScopedCFTypeRef<CFStringRef> desc(CFErrorCopyDescription(err)); 436*6777b538SAndroid Build Coastguard Worker base::apple::ScopedCFTypeRef<CFDictionaryRef> user_info( 437*6777b538SAndroid Build Coastguard Worker CFErrorCopyUserInfo(err)); 438*6777b538SAndroid Build Coastguard Worker CFStringRef errorDesc = nullptr; 439*6777b538SAndroid Build Coastguard Worker if (user_info.get()) { 440*6777b538SAndroid Build Coastguard Worker errorDesc = reinterpret_cast<CFStringRef>( 441*6777b538SAndroid Build Coastguard Worker CFDictionaryGetValue(user_info.get(), kCFErrorDescriptionKey)); 442*6777b538SAndroid Build Coastguard Worker } 443*6777b538SAndroid Build Coastguard Worker o << "Code: " << CFErrorGetCode(err) << " Domain: " << CFErrorGetDomain(err) 444*6777b538SAndroid Build Coastguard Worker << " Desc: " << desc.get(); 445*6777b538SAndroid Build Coastguard Worker if (errorDesc) { 446*6777b538SAndroid Build Coastguard Worker o << "(" << errorDesc << ")"; 447*6777b538SAndroid Build Coastguard Worker } 448*6777b538SAndroid Build Coastguard Worker return o; 449*6777b538SAndroid Build Coastguard Worker} 450*6777b538SAndroid Build Coastguard Worker 451*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, CFRange range) { 452*6777b538SAndroid Build Coastguard Worker return o << NSStringFromRange( 453*6777b538SAndroid Build Coastguard Worker NSMakeRange(static_cast<NSUInteger>(range.location), 454*6777b538SAndroid Build Coastguard Worker static_cast<NSUInteger>(range.length))); 455*6777b538SAndroid Build Coastguard Worker} 456*6777b538SAndroid Build Coastguard Worker 457*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, id obj) { 458*6777b538SAndroid Build Coastguard Worker return obj ? o << [obj description].UTF8String : o << "(nil)"; 459*6777b538SAndroid Build Coastguard Worker} 460*6777b538SAndroid Build Coastguard Worker 461*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, NSRange range) { 462*6777b538SAndroid Build Coastguard Worker return o << NSStringFromRange(range); 463*6777b538SAndroid Build Coastguard Worker} 464*6777b538SAndroid Build Coastguard Worker 465*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, SEL selector) { 466*6777b538SAndroid Build Coastguard Worker return o << NSStringFromSelector(selector); 467*6777b538SAndroid Build Coastguard Worker} 468*6777b538SAndroid Build Coastguard Worker 469*6777b538SAndroid Build Coastguard Worker#if !BUILDFLAG(IS_IOS) 470*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, NSPoint point) { 471*6777b538SAndroid Build Coastguard Worker return o << NSStringFromPoint(point); 472*6777b538SAndroid Build Coastguard Worker} 473*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, NSRect rect) { 474*6777b538SAndroid Build Coastguard Worker return o << NSStringFromRect(rect); 475*6777b538SAndroid Build Coastguard Worker} 476*6777b538SAndroid Build Coastguard Workerstd::ostream& operator<<(std::ostream& o, NSSize size) { 477*6777b538SAndroid Build Coastguard Worker return o << NSStringFromSize(size); 478*6777b538SAndroid Build Coastguard Worker} 479*6777b538SAndroid Build Coastguard Worker#endif 480