Index: content/common/child_process_host.cc |
=================================================================== |
--- content/common/child_process_host.cc (revision 97969) |
+++ content/common/child_process_host.cc (working copy) |
@@ -6,6 +6,7 @@ |
#include "base/command_line.h" |
#include "base/file_path.h" |
+#include "base/logging.h" |
#include "base/metrics/histogram.h" |
#include "base/path_service.h" |
#include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
@@ -19,6 +20,52 @@ |
#include "base/linux_util.h" |
#endif // OS_LINUX |
+#if defined(OS_MACOSX) |
+namespace { |
+ |
+// Given |path| identifying a Mac-style child process executable path, adjusts |
+// it to correspond to |feature|. For a child process path such as |
+// ".../Chromium Helper.app/Contents/MacOS/Chromium Helper", the transformed |
+// path for feature "NP" would be |
+// ".../Chromium Helper NP.app/Contents/MacOS/Chromium Helper NP". The new |
+// path is returned. |
+FilePath TransformPathForFeature(const FilePath& path, |
+ const std::string& feature) { |
+ std::string basename = path.BaseName().value(); |
+ |
+ FilePath macos_path = path.DirName(); |
+ const char kMacOSName[] = "MacOS"; |
+ DCHECK_EQ(kMacOSName, macos_path.BaseName().value()); |
+ |
+ FilePath contents_path = macos_path.DirName(); |
+ const char kContentsName[] = "Contents"; |
+ DCHECK_EQ(kContentsName, contents_path.BaseName().value()); |
+ |
+ FilePath helper_app_path = contents_path.DirName(); |
+ const char kAppExtension[] = ".app"; |
+ std::string basename_app = basename; |
+ basename_app.append(kAppExtension); |
+ DCHECK_EQ(basename_app, helper_app_path.BaseName().value()); |
+ |
+ FilePath root_path = helper_app_path.DirName(); |
+ |
+ std::string new_basename = basename; |
+ new_basename.append(1, ' '); |
+ new_basename.append(feature); |
+ std::string new_basename_app = new_basename; |
+ new_basename_app.append(kAppExtension); |
+ |
+ FilePath new_path = root_path.Append(new_basename_app) |
+ .Append(kContentsName) |
+ .Append(kMacOSName) |
+ .Append(new_basename); |
+ |
+ return new_path; |
+} |
+ |
+} // namespace |
+#endif // OS_MACOSX |
+ |
ChildProcessHost::ChildProcessHost() |
: ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)), |
opening_channel_(false) { |
@@ -39,7 +86,7 @@ |
} |
// static |
-FilePath ChildProcessHost::GetChildPath(bool allow_self) { |
+FilePath ChildProcessHost::GetChildPath(int flags) { |
FilePath child_path; |
child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
@@ -53,13 +100,33 @@ |
// When running under Valgrind, forking /proc/self/exe ends up forking the |
// Valgrind executable, which then crashes. However, it's almost safe to |
// assume that the updates won't happen while testing with Valgrind tools. |
- if (allow_self && !RunningOnValgrind()) |
+ if (flags & CHILD_ALLOW_SELF && !RunningOnValgrind()) |
return FilePath("/proc/self/exe"); |
#endif |
// On most platforms, the child executable is the same as the current |
// executable. |
PathService::Get(content::CHILD_PROCESS_EXE, &child_path); |
+ |
+#if defined(OS_MACOSX) |
+ DCHECK(!(flags & CHILD_NO_PIE && flags & CHILD_ALLOW_HEAP_EXECUTION)); |
+ |
+ // If needed, choose an executable with special flags set that inform the |
+ // kernel to enable or disable specific optional process-wide features. |
+ if (flags & CHILD_NO_PIE) { |
+ // "NP" is "No PIE". This results in Chromium Helper NP.app or |
+ // Google Chrome Helper NP.app. |
+ child_path = TransformPathForFeature(child_path, "NP"); |
+ } else if (flags & CHILD_ALLOW_HEAP_EXECUTION) { |
+ // "EH" is "Executable Heap". A non-executable heap is only available to |
+ // 32-bit processes on Mac OS X 10.7. Most code can and should run with a |
+ // non-executable heap, but the "EH" feature is provided to allow code |
+ // intolerant of a non-executable heap to work properly on 10.7. This |
+ // results in Chromium Helper EH.app or Google Chrome Helper EH.app. |
+ child_path = TransformPathForFeature(child_path, "EH"); |
+ } |
+#endif |
+ |
return child_path; |
} |