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