| 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 |