15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/path_service.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
13bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "build/build_config.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::FilePath FindManifestInDir(int dir_key, const std::string& host_name) {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath base_path;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (PathService::Get(dir_key, &base_path)) {
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::FilePath path = base_path.Append(host_name + ".json");
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (base::PathExists(path))
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return path;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::FilePath();
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::FilePath NativeProcessLauncher::FindManifest(
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& host_name,
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool allow_user_level_hosts,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* error_message) {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath result;
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (allow_user_level_hosts)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = FindManifestInDir(chrome::DIR_USER_NATIVE_MESSAGING, host_name);
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result.empty())
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = FindManifestInDir(chrome::DIR_NATIVE_MESSAGING, host_name);
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result.empty())
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *error_message = "Can't find native messaging host " + host_name;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeProcessLauncher::LaunchNativeProcess(
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CommandLine& command_line,
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::ProcessHandle* process_handle,
5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::File* read_file,
5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::File* write_file) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FileHandleMappingVector fd_map;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int read_pipe_fds[2] = {0};
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HANDLE_EINTR(pipe(read_pipe_fds)) != 0) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Bad read pipe";
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD read_pipe_read_fd(read_pipe_fds[0]);
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD read_pipe_write_fd(read_pipe_fds[1]);
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  fd_map.push_back(std::make_pair(read_pipe_write_fd.get(), STDOUT_FILENO));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int write_pipe_fds[2] = {0};
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HANDLE_EINTR(pipe(write_pipe_fds)) != 0) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Bad write pipe";
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD write_pipe_read_fd(write_pipe_fds[0]);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD write_pipe_write_fd(write_pipe_fds[1]);
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  fd_map.push_back(std::make_pair(write_pipe_read_fd.get(), STDIN_FILENO));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::LaunchOptions options;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.fds_to_remap = &fd_map;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Don't use no_new_privs mode, e.g. in case the host needs to use sudo.
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.allow_new_privs = true;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!base::LaunchProcess(command_line, options, process_handle)) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error launching process";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will not be reading from the write pipe, nor writing from the read pipe.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_pipe_read_fd.reset();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_pipe_write_fd.reset();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  *read_file = base::File(read_pipe_read_fd.release());
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  *write_file = base::File(write_pipe_write_fd.release());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
100