1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
6
7#include "base/command_line.h"
8#include "base/file_util.h"
9#include "base/logging.h"
10#include "base/posix/eintr_wrapper.h"
11#include "base/process/launch.h"
12
13namespace extensions {
14
15namespace {
16
17const char kNativeMessagingDirectory[] =
18#if defined(OFFICIAL_BUILD) && defined(OS_MACOSX)
19    "/Library/Google/Chrome/NativeMessagingHosts";
20#elif defined(OFFICIAL_BUILD) && !defined(OS_MACOSX)
21    "/etc/opt/chrome/native-messaging-hosts";
22#elif !defined(OFFICIAL_BUILD) && defined(OS_MACOSX)
23    "/Library/Application Support/Chromium/NativeMessagingHosts";
24#else
25    "/etc/chromium/native-messaging-hosts";
26#endif
27
28}  // namespace
29
30// static
31base::FilePath NativeProcessLauncher::FindManifest(
32    const std::string& native_host_name,
33    std::string* error_message) {
34  return base::FilePath(kNativeMessagingDirectory).Append(
35      native_host_name + ".json");
36}
37
38// static
39bool NativeProcessLauncher::LaunchNativeProcess(
40    const CommandLine& command_line,
41    base::PlatformFile* read_file,
42    base::PlatformFile* write_file) {
43  base::FileHandleMappingVector fd_map;
44
45  int read_pipe_fds[2] = {0};
46  if (HANDLE_EINTR(pipe(read_pipe_fds)) != 0) {
47    LOG(ERROR) << "Bad read pipe";
48    return false;
49  }
50  file_util::ScopedFD read_pipe_read_fd(&read_pipe_fds[0]);
51  file_util::ScopedFD read_pipe_write_fd(&read_pipe_fds[1]);
52  fd_map.push_back(std::make_pair(*read_pipe_write_fd, STDOUT_FILENO));
53
54  int write_pipe_fds[2] = {0};
55  if (HANDLE_EINTR(pipe(write_pipe_fds)) != 0) {
56    LOG(ERROR) << "Bad write pipe";
57    return false;
58  }
59  file_util::ScopedFD write_pipe_read_fd(&write_pipe_fds[0]);
60  file_util::ScopedFD write_pipe_write_fd(&write_pipe_fds[1]);
61  fd_map.push_back(std::make_pair(*write_pipe_read_fd, STDIN_FILENO));
62
63  base::LaunchOptions options;
64  options.fds_to_remap = &fd_map;
65  int process_id;
66  if (!base::LaunchProcess(command_line, options, &process_id)) {
67    LOG(ERROR) << "Error launching process";
68    return false;
69  }
70
71  // We will not be reading from the write pipe, nor writing from the read pipe.
72  write_pipe_read_fd.reset();
73  read_pipe_write_fd.reset();
74
75  *read_file = *read_pipe_read_fd.release();
76  *write_file = *write_pipe_write_fd.release();
77
78  return true;
79}
80
81}  // namespace extensions
82