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"
15 #include "chrome/common/mac/app_mode_common.h"
19 bool FindBundleById(NSString* bundle_id, base::FilePath* out_bundle) {
20 NSWorkspace* ws = [NSWorkspace sharedWorkspace];
21 NSString *bundlePath = [ws absolutePathForAppBundleWithIdentifier:bundle_id];
25 *out_bundle = base::mac::NSStringToFilePath(bundlePath);
29 NSString* GetVersionedPath(NSString* bundle_path, NSString* version) {
31 pathWithComponents:@[ bundle_path, @"Contents", @"Versions", version ]];
34 bool GetChromeBundleInfo(const base::FilePath& chrome_bundle,
35 const std::string& version_str,
36 base::FilePath* executable_path,
37 base::FilePath* version_path,
38 base::FilePath* framework_shlib_path) {
39 using base::mac::ObjCCast;
41 NSString* cr_bundle_path = base::mac::FilePathToNSString(chrome_bundle);
42 NSBundle* cr_bundle = [NSBundle bundleWithPath:cr_bundle_path];
47 // Get versioned directory.
48 NSString* cr_versioned_path;
49 if (!version_str.empty()) {
51 GetVersionedPath(cr_bundle_path, base::SysUTF8ToNSString(version_str));
54 if (version_str.empty() ||
55 !base::PathExists(base::mac::NSStringToFilePath(cr_versioned_path))) {
56 // Read version string.
57 NSString* cr_version = ObjCCast<NSString>(
58 [cr_bundle objectForInfoDictionaryKey:app_mode::kCrBundleVersionKey]);
60 // Older bundles have the Chrome version in the following key.
61 cr_version = ObjCCast<NSString>([cr_bundle
62 objectForInfoDictionaryKey:app_mode::kCFBundleShortVersionStringKey]);
67 cr_versioned_path = GetVersionedPath(cr_bundle_path, cr_version);
70 // Get the framework path.
71 NSString* cr_bundle_exe =
73 [cr_bundle objectForInfoDictionaryKey:@"CFBundleExecutable"]);
74 // Essentially we want chrome::kFrameworkName which looks like
75 // "$PRODUCT_STRING Framework.framework". The library itself is at
76 // "$PRODUCT_STRING Framework.framework/$PRODUCT_STRING Framework". Note that
77 // $PRODUCT_STRING is not |cr_bundle_exe| because in Canary the framework is
78 // still called "Google Chrome Framework".
79 // However, we want the shims to be agnostic to distribution and operate based
80 // on the data in their plist, so encode the framework names here.
81 NSDictionary* framework_for_exe = @{
82 @"Chromium": @"Chromium",
83 @"Google Chrome": @"Google Chrome",
84 @"Google Chrome Canary": @"Google Chrome",
86 NSString* framework_name = [framework_for_exe objectForKey:cr_bundle_exe];
87 NSString* cr_framework_shlib_path =
88 [cr_versioned_path stringByAppendingPathComponent:
89 [framework_name stringByAppendingString:@" Framework.framework"]];
90 cr_framework_shlib_path =
91 [cr_framework_shlib_path stringByAppendingPathComponent:
92 [framework_name stringByAppendingString:@" Framework"]];
93 if (!cr_bundle_exe || !cr_framework_shlib_path)
96 // A few more sanity checks.
98 BOOL exists = [[NSFileManager defaultManager]
99 fileExistsAtPath:cr_framework_shlib_path
100 isDirectory:&is_directory];
101 if (!exists || is_directory)
104 // Everything OK, copy output parameters.
105 *executable_path = base::mac::NSStringToFilePath([cr_bundle executablePath]);
106 *version_path = base::mac::NSStringToFilePath(cr_versioned_path);
107 *framework_shlib_path =
108 base::mac::NSStringToFilePath(cr_framework_shlib_path);
112 } // namespace app_mode