diff options
Diffstat (limited to 'content/common/child_process_host.cc')
-rw-r--r-- | content/common/child_process_host.cc | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/content/common/child_process_host.cc b/content/common/child_process_host.cc index 6a14750..02a5bd6 100644 --- a/content/common/child_process_host.cc +++ b/content/common/child_process_host.cc @@ -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 @@ void ChildProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { } // static -FilePath ChildProcessHost::GetChildPath(bool allow_self) { +FilePath ChildProcessHost::GetChildPath(int flags) { FilePath child_path; child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( @@ -53,13 +100,33 @@ FilePath ChildProcessHost::GetChildPath(bool allow_self) { // 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; } |