1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/common/mac/app_mode_chrome_locator.h"
7 #import <AppKit/AppKit.h>
8 #include <CoreFoundation/CoreFoundation.h>
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/mac/foundation_util.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "chrome/common/chrome_constants.h"
18 bool FindBundleById(NSString* bundle_id, base::FilePath* out_bundle) {
19 NSWorkspace* ws = [NSWorkspace sharedWorkspace];
20 NSString *bundlePath = [ws absolutePathForAppBundleWithIdentifier:bundle_id];
24 *out_bundle = base::mac::NSStringToFilePath(bundlePath);
28 NSString* GetVersionedPath(NSString* bundle_path, NSString* version) {
30 pathWithComponents:@[ bundle_path, @"Contents", @"Versions", version ]];
33 bool GetChromeBundleInfo(const base::FilePath& chrome_bundle,
34 const std::string& version_str,
35 base::FilePath* executable_path,
36 base::FilePath* version_path,
37 base::FilePath* framework_shlib_path) {
38 using base::mac::ObjCCast;
40 NSString* cr_bundle_path = base::mac::FilePathToNSString(chrome_bundle);
41 NSBundle* cr_bundle = [NSBundle bundleWithPath:cr_bundle_path];
46 // Get versioned directory.
47 NSString* cr_versioned_path;
48 if (!version_str.empty()) {
50 GetVersionedPath(cr_bundle_path, base::SysUTF8ToNSString(version_str));
53 if (version_str.empty() ||
54 !base::PathExists(base::mac::NSStringToFilePath(cr_versioned_path))) {
55 // Read version string.
56 NSString* cr_version = ObjCCast<NSString>(
57 [cr_bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
61 cr_versioned_path = GetVersionedPath(cr_bundle_path, cr_version);
64 // Get the framework path.
65 NSString* cr_bundle_exe =
67 [cr_bundle objectForInfoDictionaryKey:@"CFBundleExecutable"]);
68 // Essentially we want chrome::kFrameworkName which looks like
69 // "$PRODUCT_STRING Framework.framework". The library itself is at
70 // "$PRODUCT_STRING Framework.framework/$PRODUCT_STRING Framework". Note that
71 // $PRODUCT_STRING is not |cr_bundle_exe| because in Canary the framework is
72 // still called "Google Chrome Framework".
73 // However, we want the shims to be agnostic to distribution and operate based
74 // on the data in their plist, so encode the framework names here.
75 NSDictionary* framework_for_exe = @{
76 @"Chromium": @"Chromium",
77 @"Google Chrome": @"Google Chrome",
78 @"Google Chrome Canary": @"Google Chrome",
80 NSString* framework_name = [framework_for_exe objectForKey:cr_bundle_exe];
81 NSString* cr_framework_shlib_path =
82 [cr_versioned_path stringByAppendingPathComponent:
83 [framework_name stringByAppendingString:@" Framework.framework"]];
84 cr_framework_shlib_path =
85 [cr_framework_shlib_path stringByAppendingPathComponent:
86 [framework_name stringByAppendingString:@" Framework"]];
87 if (!cr_bundle_exe || !cr_framework_shlib_path)
90 // A few more sanity checks.
92 BOOL exists = [[NSFileManager defaultManager]
93 fileExistsAtPath:cr_framework_shlib_path
94 isDirectory:&is_directory];
95 if (!exists || is_directory)
98 // Everything OK, copy output parameters.
99 *executable_path = base::mac::NSStringToFilePath([cr_bundle executablePath]);
100 *version_path = base::mac::NSStringToFilePath(cr_versioned_path);
101 *framework_shlib_path =
102 base::mac::NSStringToFilePath(cr_framework_shlib_path);
106 } // namespace app_mode