// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "chrome/common/mac/app_mode_chrome_locator.h" #import #include #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/mac/app_mode_common.h" namespace app_mode { bool FindBundleById(NSString* bundle_id, base::FilePath* out_bundle) { NSWorkspace* ws = [NSWorkspace sharedWorkspace]; NSString *bundlePath = [ws absolutePathForAppBundleWithIdentifier:bundle_id]; if (!bundlePath) return false; *out_bundle = base::mac::NSStringToFilePath(bundlePath); return true; } NSString* GetVersionedPath(NSString* bundle_path, NSString* version) { return [NSString pathWithComponents:@[ bundle_path, @"Contents", @"Versions", version ]]; } bool GetChromeBundleInfo(const base::FilePath& chrome_bundle, const std::string& version_str, base::FilePath* executable_path, base::FilePath* version_path, base::FilePath* framework_shlib_path) { using base::mac::ObjCCast; NSString* cr_bundle_path = base::mac::FilePathToNSString(chrome_bundle); NSBundle* cr_bundle = [NSBundle bundleWithPath:cr_bundle_path]; if (!cr_bundle) return false; // Get versioned directory. NSString* cr_versioned_path; if (!version_str.empty()) { cr_versioned_path = GetVersionedPath(cr_bundle_path, base::SysUTF8ToNSString(version_str)); } if (version_str.empty() || !base::PathExists(base::mac::NSStringToFilePath(cr_versioned_path))) { // Read version string. NSString* cr_version = ObjCCast( [cr_bundle objectForInfoDictionaryKey:app_mode::kCrBundleVersionKey]); if (!cr_version) { // Older bundles have the Chrome version in the following key. cr_version = ObjCCast([cr_bundle objectForInfoDictionaryKey:app_mode::kCFBundleShortVersionStringKey]); } if (!cr_version) return false; cr_versioned_path = GetVersionedPath(cr_bundle_path, cr_version); } // Get the framework path. NSString* cr_bundle_exe = ObjCCast( [cr_bundle objectForInfoDictionaryKey:@"CFBundleExecutable"]); // Essentially we want chrome::kFrameworkName which looks like // "$PRODUCT_STRING Framework.framework". The library itself is at // "$PRODUCT_STRING Framework.framework/$PRODUCT_STRING Framework". Note that // $PRODUCT_STRING is not |cr_bundle_exe| because in Canary the framework is // still called "Google Chrome Framework". // However, we want the shims to be agnostic to distribution and operate based // on the data in their plist, so encode the framework names here. NSDictionary* framework_for_exe = @{ @"Chromium": @"Chromium", @"Google Chrome": @"Google Chrome", @"Google Chrome Canary": @"Google Chrome", }; NSString* framework_name = [framework_for_exe objectForKey:cr_bundle_exe]; NSString* cr_framework_shlib_path = [cr_versioned_path stringByAppendingPathComponent: [framework_name stringByAppendingString:@" Framework.framework"]]; cr_framework_shlib_path = [cr_framework_shlib_path stringByAppendingPathComponent: [framework_name stringByAppendingString:@" Framework"]]; if (!cr_bundle_exe || !cr_framework_shlib_path) return false; // A few more sanity checks. BOOL is_directory; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:cr_framework_shlib_path isDirectory:&is_directory]; if (!exists || is_directory) return false; // Everything OK, copy output parameters. *executable_path = base::mac::NSStringToFilePath([cr_bundle executablePath]); *version_path = base::mac::NSStringToFilePath(cr_versioned_path); *framework_shlib_path = base::mac::NSStringToFilePath(cr_framework_shlib_path); return true; } } // namespace app_mode