<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/child_process_host.h"

#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "base/waitable_event.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/plugin_messages.h"
#include "chrome/common/process_watcher.h"
#include "chrome/common/result_codes.h"
#include "chrome/installer/util/google_update_settings.h"

#if defined(OS_LINUX)
#include "base/linux_util.h"
#endif  // OS_LINUX

#if defined(OS_POSIX)
// This is defined in chrome/browser/google_update_settings_posix.cc.  It's the
// static string containing the user's unique GUID.  We send this in the crash
// report.
namespace google_update {
extern std::string posix_guid;
}  // namespace google_update
#endif  // OS_POSIX


namespace {

typedef std::list<ChildProcessHost*> ChildProcessList;

// The NotificationTask is used to notify about plugin process connection/
// disconnection. It is needed because the notifications in the
// NotificationService must happen in the main thread.
class ChildNotificationTask : public Task {
 public:
  ChildNotificationTask(
      NotificationType notification_type, ChildProcessInfo* info)
      : notification_type_(notification_type), info_(*info) { }

  virtual void Run() {
    NotificationService::current()->
        Notify(notification_type_, NotificationService::AllSources(),
               Details<ChildProcessInfo>(&info_));
  }

 private:
  NotificationType notification_type_;
  ChildProcessInfo info_;
};

}  // namespace


ChildProcessHost::ChildProcessHost(
    ProcessType type, ResourceDispatcherHost* resource_dispatcher_host)
    : Receiver(type, -1),
      ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
      resource_dispatcher_host_(resource_dispatcher_host),
      opening_channel_(false) {
  Singleton<ChildProcessList>::get()->push_back(this);
}


ChildProcessHost::~ChildProcessHost() {
  Singleton<ChildProcessList>::get()->remove(this);

  resource_dispatcher_host_->CancelRequestsForProcess(id());

  if (handle())
    ProcessWatcher::EnsureProcessTerminated(handle());
}

// static
FilePath ChildProcessHost::GetChildPath() {
  FilePath child_path;

  child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
      switches::kBrowserSubprocessPath);
  if (!child_path.empty())
    return child_path;

#if !defined(OS_MACOSX)
  // On most platforms, the child executable is the same as the current
  // executable.
  PathService::Get(base::FILE_EXE, &child_path);
#else
  // On the Mac, the child executable lives at a predefined location within
  // the app bundle's versioned directory.
  child_path = chrome::GetVersionedDirectory().
      Append(chrome::kHelperProcessExecutablePath);
#endif  // OS_MACOSX

  return child_path;
}

// static
void ChildProcessHost::SetCrashReporterCommandLine(CommandLine* command_line) {
#if defined(USE_LINUX_BREAKPAD)
  const bool unattended = (getenv("CHROME_HEADLESS") != NULL);
  if (unattended || GoogleUpdateSettings::GetCollectStatsConsent()) {
    command_line->AppendSwitchWithValue(switches::kEnableCrashReporter,
                                        ASCIIToWide(google_update::posix_guid +
                                                    "," +<commit_msg>linux: use /proc/self/exe when exec'ing ourselves<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/child_process_host.h"

#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "base/waitable_event.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/plugin_messages.h"
#include "chrome/common/process_watcher.h"
#include "chrome/common/result_codes.h"
#include "chrome/installer/util/google_update_settings.h"

#if defined(OS_LINUX)
#include "base/linux_util.h"
#endif  // OS_LINUX

#if defined(OS_POSIX)
// This is defined in chrome/browser/google_update_settings_posix.cc.  It's the
// static string containing the user's unique GUID.  We send this in the crash
// report.
namespace google_update {
extern std::string posix_guid;
}  // namespace google_update
#endif  // OS_POSIX


namespace {

typedef std::list<ChildProcessHost*> ChildProcessList;

// The NotificationTask is used to notify about plugin process connection/
// disconnection. It is needed because the notifications in the
// NotificationService must happen in the main thread.
class ChildNotificationTask : public Task {
 public:
  ChildNotificationTask(
      NotificationType notification_type, ChildProcessInfo* info)
      : notification_type_(notification_type), info_(*info) { }

  virtual void Run() {
    NotificationService::current()->
        Notify(notification_type_, NotificationService::AllSources(),
               Details<ChildProcessInfo>(&info_));
  }

 private:
  NotificationType notification_type_;
  ChildProcessInfo info_;
};

}  // namespace


ChildProcessHost::ChildProcessHost(
    ProcessType type, ResourceDispatcherHost* resource_dispatcher_host)
    : Receiver(type, -1),
      ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
      resource_dispatcher_host_(resource_dispatcher_host),
      opening_channel_(false) {
  Singleton<ChildProcessList>::get()->push_back(this);
}


ChildProcessHost::~ChildProcessHost() {
  Singleton<ChildProcessList>::get()->remove(this);

  resource_dispatcher_host_->CancelRequestsForProcess(id());

  if (handle())
    ProcessWatcher::EnsureProcessTerminated(handle());
}

// static
FilePath ChildProcessHost::GetChildPath() {
  FilePath child_path;

  child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
      switches::kBrowserSubprocessPath);
  if (!child_path.empty())
    return child_path;

#if defined(OS_LINUX)
  // Use /proc/self/exe rather than our known binary path so updates
  // can't swap out the binary from underneath us.
  child_path = FilePath("/proc/self/exe");
#elif defined(OS_MACOSX)
  // On the Mac, the child executable lives at a predefined location within
  // the app bundle's versioned directory.
  child_path = chrome::GetVersionedDirectory().
      Append(chrome::kHelperProcessExecutablePath);
#else
  // On most platforms, the child executable is the same as the current
  // executable.
  PathService::Get(base::FILE_EXE, &child_path);
#endif

  return child_path;
}

// static
void ChildProcessHost::SetCrashReporterCommandLine(CommandLine* command_line) {
#if defined(USE_LINUX_BREAKPAD)
  const bool unattended = (getenv("CHROME_HEADLESS") != NULL);
  if (unattended || GoogleUpdateSettings::GetCollectStatsConsent()) {
    command_line->AppendSwitchWithValue(switches::kEnableCrashReporter,
                                        ASCIIToWide(google_update::posix_guid +
                                                    "," +
{'fraction_non_alphanumeric': 0.10882352941176471, 'fraction_numerical': 0.0012787723785166241, 'mean_word_length': 4.65918958031838, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5545504', 'n_tokens_mistral': 2366, 'n_tokens_neox': 2283, 'n_words': 524}