OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "chrome/browser/mac/relauncher.h" | 5 #include "chrome/browser/mac/relauncher.h" |
6 | 6 |
7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
8 #include <AvailabilityMacros.h> | 8 #include <AvailabilityMacros.h> |
9 #include <dlfcn.h> | 9 #include <dlfcn.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <sys/event.h> | 11 #include <sys/event.h> |
12 #include <sys/time.h> | 12 #include <sys/time.h> |
13 #include <sys/types.h> | 13 #include <sys/types.h> |
14 #include <unistd.h> | 14 #include <unistd.h> |
15 | 15 |
16 #include <string> | 16 #include <string> |
17 #include <vector> | 17 #include <vector> |
18 | 18 |
19 #include "base/basictypes.h" | 19 #include "base/basictypes.h" |
20 #include "base/eintr_wrapper.h" | 20 #include "base/eintr_wrapper.h" |
21 #include "base/file_util.h" | 21 #include "base/file_util.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "base/mac/mac_util.h" | 23 #include "base/mac/mac_util.h" |
24 #include "base/mac/scoped_cftyperef.h" | 24 #include "base/mac/scoped_cftyperef.h" |
25 #include "base/path_service.h" | 25 #include "base/path_service.h" |
26 #include "base/process_util.h" | 26 #include "base/process_util.h" |
27 #include "base/stringprintf.h" | 27 #include "base/stringprintf.h" |
28 #include "base/sys_string_conversions.h" | 28 #include "base/sys_string_conversions.h" |
| 29 #include "chrome/browser/mac/install_from_dmg.h" |
29 #include "chrome/common/chrome_switches.h" | 30 #include "chrome/common/chrome_switches.h" |
30 #include "content/common/content_paths.h" | 31 #include "content/common/content_paths.h" |
31 #include "content/common/content_switches.h" | 32 #include "content/common/content_switches.h" |
32 #include "content/common/main_function_params.h" | 33 #include "content/common/main_function_params.h" |
33 | 34 |
34 // RTLD_MAIN_ONLY is supported as of Mac OS X 10.5, but <dlfcn.h> does not | 35 // RTLD_MAIN_ONLY is supported as of Mac OS X 10.5, but <dlfcn.h> does not |
35 // define it in the 10.5 SDK. It is present in the 10.6 SDK and is documented | 36 // define it in the 10.5 SDK. It is present in the 10.6 SDK and is documented |
36 // as working on 10.5 and later. The source code for the version of dyld that | 37 // as working on 10.5 and later. The source code for the version of dyld that |
37 // shipped in 10.5, dyld-95.3/src/dyldAPIs.cpp, confirms that this feature is | 38 // shipped in 10.5, dyld-95.3/src/dyldAPIs.cpp, confirms that this feature is |
38 // supported. Provide a fallback definition here. | 39 // supported. Provide a fallback definition here. |
39 #if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5 // 10.5 SDK | 40 #if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5 // 10.5 SDK |
40 #define RTLD_MAIN_ONLY ((void*)-5) // Search main executable only. | 41 #define RTLD_MAIN_ONLY ((void*)-5) // Search main executable only. |
41 #endif | 42 #endif |
42 | 43 |
43 namespace mac_relauncher { | 44 namespace mac_relauncher { |
44 | 45 |
| 46 const char* const kRelauncherDMGDeviceArg = "--dmg-device="; |
| 47 |
45 namespace { | 48 namespace { |
46 | 49 |
47 // The "magic" file descriptor that the relauncher process' write side of the | 50 // The "magic" file descriptor that the relauncher process' write side of the |
48 // pipe shows up on. Chosen to avoid conflicting with stdin, stdout, and | 51 // pipe shows up on. Chosen to avoid conflicting with stdin, stdout, and |
49 // stderr. | 52 // stderr. |
50 const int kRelauncherSyncFD = STDERR_FILENO + 1; | 53 const int kRelauncherSyncFD = STDERR_FILENO + 1; |
51 | 54 |
52 // The argument separating arguments intended for the relauncher process from | 55 // The argument separating arguments intended for the relauncher process from |
53 // those intended for the relaunched process. "---" is chosen instead of "--" | 56 // those intended for the relaunched process. "---" is chosen instead of "--" |
54 // because CommandLine interprets "--" as meaning "end of switches", but | 57 // because CommandLine interprets "--" as meaning "end of switches", but |
(...skipping 29 matching lines...) Expand all Loading... |
84 // so this is safe even if the relaunch is the result of an update having | 87 // so this is safe even if the relaunch is the result of an update having |
85 // been applied. In fact, it's safer than using the updated version of the | 88 // been applied. In fact, it's safer than using the updated version of the |
86 // helper process, because there's no guarantee that the updated version's | 89 // helper process, because there's no guarantee that the updated version's |
87 // relauncher implementation will be compatible with the running version's. | 90 // relauncher implementation will be compatible with the running version's. |
88 FilePath child_path; | 91 FilePath child_path; |
89 if (!PathService::Get(content::CHILD_PROCESS_EXE, &child_path)) { | 92 if (!PathService::Get(content::CHILD_PROCESS_EXE, &child_path)) { |
90 LOG(ERROR) << "No CHILD_PROCESS_EXE"; | 93 LOG(ERROR) << "No CHILD_PROCESS_EXE"; |
91 return false; | 94 return false; |
92 } | 95 } |
93 | 96 |
94 return RelaunchAppWithHelper(child_path.value(), args); | 97 std::vector<std::string> relauncher_args; |
| 98 return RelaunchAppWithHelper(child_path.value(), relauncher_args, args); |
95 } | 99 } |
96 | 100 |
97 bool RelaunchAppWithHelper(const std::string& helper, | 101 bool RelaunchAppWithHelper(const std::string& helper, |
| 102 const std::vector<std::string>& relauncher_args, |
98 const std::vector<std::string>& args) { | 103 const std::vector<std::string>& args) { |
99 std::vector<std::string> relaunch_args; | 104 std::vector<std::string> relaunch_args; |
100 relaunch_args.push_back(helper); | 105 relaunch_args.push_back(helper); |
101 relaunch_args.push_back(RelauncherTypeArg()); | 106 relaunch_args.push_back(RelauncherTypeArg()); |
102 | 107 |
103 // If this application isn't in the foreground, the relaunched one shouldn't | 108 // If this application isn't in the foreground, the relaunched one shouldn't |
104 // be either. | 109 // be either. |
105 if (!base::mac::AmIForeground()) { | 110 if (!base::mac::AmIForeground()) { |
106 relaunch_args.push_back(kRelauncherBackgroundArg); | 111 relaunch_args.push_back(kRelauncherBackgroundArg); |
107 } | 112 } |
108 | 113 |
| 114 relaunch_args.insert(relaunch_args.end(), |
| 115 relauncher_args.begin(), relauncher_args.end()); |
| 116 |
109 relaunch_args.push_back(kRelauncherArgSeparator); | 117 relaunch_args.push_back(kRelauncherArgSeparator); |
110 | 118 |
111 // When using the CommandLine interface, -psn_ may have been rewritten as | 119 // When using the CommandLine interface, -psn_ may have been rewritten as |
112 // --psn_. Look for both. | 120 // --psn_. Look for both. |
113 const char alt_psn_arg[] = "--psn_"; | 121 const char alt_psn_arg[] = "--psn_"; |
114 for (size_t index = 0; index < args.size(); ++index) { | 122 for (size_t index = 0; index < args.size(); ++index) { |
115 // Strip any -psn_ arguments, as they apply to a specific process. | 123 // Strip any -psn_ arguments, as they apply to a specific process. |
116 if (args[index].compare(0, strlen(kPSNArg), kPSNArg) != 0 && | 124 if (args[index].compare(0, strlen(kPSNArg), kPSNArg) != 0 && |
117 args[index].compare(0, strlen(alt_psn_arg), alt_psn_arg) != 0) { | 125 args[index].compare(0, strlen(alt_psn_arg), alt_psn_arg) != 0) { |
118 relaunch_args.push_back(args[index]); | 126 relaunch_args.push_back(args[index]); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 CFArrayCreateMutable(NULL, argc - 4, &kCFTypeArrayCallBacks)); | 296 CFArrayCreateMutable(NULL, argc - 4, &kCFTypeArrayCallBacks)); |
289 if (!relaunch_args) { | 297 if (!relaunch_args) { |
290 LOG(ERROR) << "CFArrayCreateMutable"; | 298 LOG(ERROR) << "CFArrayCreateMutable"; |
291 return 1; | 299 return 1; |
292 } | 300 } |
293 | 301 |
294 // Figure out what to execute, what arguments to pass it, and whether to | 302 // Figure out what to execute, what arguments to pass it, and whether to |
295 // start it in the background. | 303 // start it in the background. |
296 bool background = false; | 304 bool background = false; |
297 bool in_relaunch_args = false; | 305 bool in_relaunch_args = false; |
| 306 std::string dmg_bsd_device_name; |
298 bool seen_relaunch_executable = false; | 307 bool seen_relaunch_executable = false; |
299 std::string relaunch_executable; | 308 std::string relaunch_executable; |
300 const std::string relauncher_arg_separator(kRelauncherArgSeparator); | 309 const std::string relauncher_arg_separator(kRelauncherArgSeparator); |
301 for (int argv_index = 2; argv_index < argc; ++argv_index) { | 310 for (int argv_index = 2; argv_index < argc; ++argv_index) { |
302 const std::string arg(argv[argv_index]); | 311 const std::string arg(argv[argv_index]); |
303 | 312 |
304 // Strip any -psn_ arguments, as they apply to a specific process. | 313 // Strip any -psn_ arguments, as they apply to a specific process. |
305 if (arg.compare(0, strlen(kPSNArg), kPSNArg) == 0) { | 314 if (arg.compare(0, strlen(kPSNArg), kPSNArg) == 0) { |
306 continue; | 315 continue; |
307 } | 316 } |
308 | 317 |
309 if (!in_relaunch_args) { | 318 if (!in_relaunch_args) { |
310 if (arg == relauncher_arg_separator) { | 319 if (arg == relauncher_arg_separator) { |
311 in_relaunch_args = true; | 320 in_relaunch_args = true; |
312 } else if (arg == kRelauncherBackgroundArg) { | 321 } else if (arg == kRelauncherBackgroundArg) { |
313 background = true; | 322 background = true; |
| 323 } else if (arg.compare(0, strlen(kRelauncherDMGDeviceArg), |
| 324 kRelauncherDMGDeviceArg) == 0) { |
| 325 dmg_bsd_device_name.assign(arg.substr(strlen(kRelauncherDMGDeviceArg))); |
314 } | 326 } |
315 } else { | 327 } else { |
316 if (!seen_relaunch_executable) { | 328 if (!seen_relaunch_executable) { |
317 // The first argument after kRelauncherBackgroundArg is the path to | 329 // The first argument after kRelauncherBackgroundArg is the path to |
318 // the executable file or .app bundle directory. The Launch Services | 330 // the executable file or .app bundle directory. The Launch Services |
319 // interface wants this separate from the rest of the arguments. In | 331 // interface wants this separate from the rest of the arguments. In |
320 // the relaunched process, this path will still be visible at argv[0]. | 332 // the relaunched process, this path will still be visible at argv[0]. |
321 relaunch_executable.assign(arg); | 333 relaunch_executable.assign(arg); |
322 seen_relaunch_executable = true; | 334 seen_relaunch_executable = true; |
323 } else { | 335 } else { |
(...skipping 29 matching lines...) Expand all Loading... |
353 relaunch_args, | 365 relaunch_args, |
354 NULL // initialEvent | 366 NULL // initialEvent |
355 }; | 367 }; |
356 | 368 |
357 OSStatus err = LSOpenApplication(&ls_parameters, NULL); | 369 OSStatus err = LSOpenApplication(&ls_parameters, NULL); |
358 if (err != noErr) { | 370 if (err != noErr) { |
359 LOG(ERROR) << "LSOpenApplication: " << err; | 371 LOG(ERROR) << "LSOpenApplication: " << err; |
360 return 1; | 372 return 1; |
361 } | 373 } |
362 | 374 |
| 375 // The application should have relaunched (or is in the process of |
| 376 // relaunching). From this point on, only clean-up tasks should occur, and |
| 377 // failures are tolerable. |
| 378 |
| 379 if (!dmg_bsd_device_name.empty()) { |
| 380 EjectAndTrashDiskImage(dmg_bsd_device_name); |
| 381 } |
| 382 |
363 return 0; | 383 return 0; |
364 } | 384 } |
365 | 385 |
366 } // namespace internal | 386 } // namespace internal |
367 | 387 |
368 } // namespace mac_relauncher | 388 } // namespace mac_relauncher |
OLD | NEW |