OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // On Mac, shortcuts can't have command-line arguments. Instead, produce small | 5 // On Mac, shortcuts can't have command-line arguments. Instead, produce small |
6 // app bundles which locate the Chromium framework and load it, passing the | 6 // app bundles which locate the Chromium framework and load it, passing the |
7 // appropriate data. This is the code for such an app bundle. It should be kept | 7 // appropriate data. This is the code for such an app bundle. It should be kept |
8 // minimal and do as little work as possible (with as much work done on | 8 // minimal and do as little work as possible (with as much work done on |
9 // framework side as possible). | 9 // framework side as possible). |
10 | 10 |
11 #include <dlfcn.h> | 11 #include <dlfcn.h> |
12 | 12 |
13 #include <CoreFoundation/CoreFoundation.h> | 13 #include <CoreFoundation/CoreFoundation.h> |
14 #import <Foundation/Foundation.h> | 14 #import <Foundation/Foundation.h> |
15 | 15 |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/file_util.h" | 17 #include "base/file_util.h" |
18 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/mac/foundation_util.h" | 20 #include "base/mac/foundation_util.h" |
21 #include "base/mac/launch_services_util.h" | 21 #include "base/mac/launch_services_util.h" |
22 #include "base/mac/scoped_nsautorelease_pool.h" | 22 #include "base/mac/scoped_nsautorelease_pool.h" |
23 #include "base/process/launch.h" | |
23 #include "base/strings/sys_string_conversions.h" | 24 #include "base/strings/sys_string_conversions.h" |
25 #include "chrome/common/chrome_switches.h" | |
24 #import "chrome/common/mac/app_mode_chrome_locator.h" | 26 #import "chrome/common/mac/app_mode_chrome_locator.h" |
25 #include "chrome/common/mac/app_mode_common.h" | 27 #include "chrome/common/mac/app_mode_common.h" |
26 | 28 |
27 namespace { | 29 namespace { |
28 | 30 |
29 typedef int (*StartFun)(const app_mode::ChromeAppModeInfo*); | 31 typedef int (*StartFun)(const app_mode::ChromeAppModeInfo*); |
30 | 32 |
31 int LoadFrameworkAndStart(app_mode::ChromeAppModeInfo* info) { | 33 int LoadFrameworkAndStart(app_mode::ChromeAppModeInfo* info) { |
32 using base::SysNSStringToUTF8; | 34 using base::SysNSStringToUTF8; |
33 using base::SysNSStringToUTF16; | 35 using base::SysNSStringToUTF16; |
(...skipping 26 matching lines...) Expand all Loading... | |
60 if (!found_bundle) { | 62 if (!found_bundle) { |
61 // If no such bundle path exists, try to search by bundle ID. | 63 // If no such bundle path exists, try to search by bundle ID. |
62 if (!app_mode::FindBundleById(cr_bundle_id, &cr_bundle_path)) { | 64 if (!app_mode::FindBundleById(cr_bundle_id, &cr_bundle_path)) { |
63 // TODO(jeremy): Display UI to allow user to manually locate the Chrome | 65 // TODO(jeremy): Display UI to allow user to manually locate the Chrome |
64 // bundle. | 66 // bundle. |
65 LOG(FATAL) << "Failed to locate bundle by identifier"; | 67 LOG(FATAL) << "Failed to locate bundle by identifier"; |
66 } | 68 } |
67 } | 69 } |
68 | 70 |
69 // ** 2: Read information from the Chrome bundle. | 71 // ** 2: Read information from the Chrome bundle. |
72 base::FilePath executable_path; | |
70 base::string16 raw_version_str; | 73 base::string16 raw_version_str; |
71 base::FilePath version_path; | 74 base::FilePath version_path; |
72 base::FilePath framework_shlib_path; | 75 base::FilePath framework_shlib_path; |
73 if (!app_mode::GetChromeBundleInfo(cr_bundle_path, &raw_version_str, | 76 if (!app_mode::GetChromeBundleInfo(cr_bundle_path, |
74 &version_path, &framework_shlib_path)) { | 77 &executable_path, |
78 &raw_version_str, | |
79 &version_path, | |
80 &framework_shlib_path)) { | |
75 LOG(FATAL) << "Couldn't ready Chrome bundle info"; | 81 LOG(FATAL) << "Couldn't ready Chrome bundle info"; |
76 } | 82 } |
77 base::FilePath app_mode_bundle_path = | 83 base::FilePath app_mode_bundle_path = |
78 base::mac::NSStringToFilePath([app_bundle bundlePath]); | 84 base::mac::NSStringToFilePath([app_bundle bundlePath]); |
79 | 85 |
80 // ** 3: Fill in ChromeAppModeInfo. | 86 // ** 3: Fill in ChromeAppModeInfo. |
81 info->chrome_outer_bundle_path = cr_bundle_path; | 87 info->chrome_outer_bundle_path = cr_bundle_path; |
82 info->chrome_versioned_path = version_path; | 88 info->chrome_versioned_path = version_path; |
83 info->app_mode_bundle_path = app_mode_bundle_path; | 89 info->app_mode_bundle_path = app_mode_bundle_path; |
84 | 90 |
(...skipping 23 matching lines...) Expand all Loading... | |
108 void* cr_dylib = dlopen(framework_shlib_path.value().c_str(), RTLD_LAZY); | 114 void* cr_dylib = dlopen(framework_shlib_path.value().c_str(), RTLD_LAZY); |
109 if (cr_dylib) { | 115 if (cr_dylib) { |
110 // Find the entry point. | 116 // Find the entry point. |
111 ChromeAppModeStart = (StartFun)dlsym(cr_dylib, "ChromeAppModeStart"); | 117 ChromeAppModeStart = (StartFun)dlsym(cr_dylib, "ChromeAppModeStart"); |
112 if (!ChromeAppModeStart) | 118 if (!ChromeAppModeStart) |
113 LOG(ERROR) << "Couldn't get entry point: " << dlerror(); | 119 LOG(ERROR) << "Couldn't get entry point: " << dlerror(); |
114 } else { | 120 } else { |
115 LOG(ERROR) << "Couldn't load framework: " << dlerror(); | 121 LOG(ERROR) << "Couldn't load framework: " << dlerror(); |
116 } | 122 } |
117 | 123 |
118 if (ChromeAppModeStart) { | 124 if (ChromeAppModeStart) |
119 return ChromeAppModeStart(info); | 125 return ChromeAppModeStart(info); |
120 } else { | 126 |
121 LOG(ERROR) << "Loading Chrome failed, launching with command line."; | 127 LOG(ERROR) << "Loading Chrome failed, launching Chrome with command line"; |
122 // Launch Chrome instead and have it update this app_mode_loader bundle. | 128 CommandLine command_line(executable_path); |
123 CommandLine command_line(CommandLine::NO_PROGRAM); | 129 if (CommandLine::ForCurrentProcess()->HasSwitch( |
130 app_mode::kLaunchedByChromeProcessId) || | |
131 info->app_mode_id == app_mode::kAppListModeId) { | |
132 // Pass --app-shim-error to have Chrome rebuild this shim. | |
124 command_line.AppendSwitchPath(app_mode::kAppShimError, | 133 command_line.AppendSwitchPath(app_mode::kAppShimError, |
125 app_mode_bundle_path); | 134 app_mode_bundle_path); |
126 if (!base::mac::OpenApplicationWithPath( | 135 } else { |
127 cr_bundle_path, command_line, kLSLaunchDefaults, NULL)) { | 136 // If the shim was launched directly (instead of by Chrome), first ask |
128 LOG(ERROR) << "Could not launch Chrome from: " << cr_bundle_path.value(); | 137 // Chrome to launch the app. Chrome will launch the shim again, the same |
129 return 1; | 138 // error will occur and be handled above. This approach allows the app to be |
130 } | 139 // started without blocking on fixing the shim and guarantees that the |
140 // profile is loaded when Chrome receives --app-shim-error. | |
141 command_line.AppendSwitchPath(switches::kProfileDirectory, | |
142 info->profile_dir); | |
143 command_line.AppendSwitchASCII(switches::kAppId, info->app_mode_id); | |
144 } | |
145 // Launch the executable directly since base::mac::OpenApplicationWithPath | |
146 // uses LSOpenApplication which doesn't pass command line arguments if the | |
147 // application is already running. | |
148 if (!base::LaunchProcess(command_line, base::LaunchOptions(), NULL)) { | |
149 LOG(ERROR) << "Could not launch Chrome: " | |
150 << command_line.GetCommandLineString(); | |
151 return 1; | |
152 } | |
131 | 153 |
132 return 0; | 154 return 0; |
133 } | |
134 } | 155 } |
135 | 156 |
136 } // namespace | 157 } // namespace |
137 | 158 |
138 __attribute__((visibility("default"))) | 159 __attribute__((visibility("default"))) |
139 int main(int argc, char** argv) { | 160 int main(int argc, char** argv) { |
161 CommandLine::Init(argc, argv); | |
140 app_mode::ChromeAppModeInfo info; | 162 app_mode::ChromeAppModeInfo info; |
141 | 163 |
142 // Hard coded info parameters. | 164 // Hard coded info parameters. |
143 info.major_version = app_mode::kCurrentChromeAppModeInfoMajorVersion; | 165 info.major_version = app_mode::kCurrentChromeAppModeInfoMajorVersion; |
144 info.minor_version = app_mode::kCurrentChromeAppModeInfoMinorVersion; | 166 info.minor_version = app_mode::kCurrentChromeAppModeInfoMinorVersion; |
tapted
2014/05/06 07:13:24
we should increment this again, for the bulk updat
jackhou1
2014/05/06 08:38:17
Done.
| |
145 info.argc = argc; | 167 info.argc = argc; |
146 info.argv = argv; | 168 info.argv = argv; |
147 | 169 |
148 // Exit instead of returning to avoid the the removal of |main()| from stack | 170 // Exit instead of returning to avoid the the removal of |main()| from stack |
149 // backtraces under tail call optimization. | 171 // backtraces under tail call optimization. |
150 exit(LoadFrameworkAndStart(&info)); | 172 exit(LoadFrameworkAndStart(&info)); |
151 } | 173 } |
OLD | NEW |