• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/files/scoped_file.h"
10 #include "base/logging.h"
11 #include "base/path_service.h"
12 #include "base/posix/eintr_wrapper.h"
13 #include "base/process/launch.h"
14 #include "build/build_config.h"
15 #include "chrome/common/chrome_paths.h"
16 
17 namespace extensions {
18 
19 namespace {
20 
FindManifestInDir(int dir_key,const std::string & host_name)21 base::FilePath FindManifestInDir(int dir_key, const std::string& host_name) {
22   base::FilePath base_path;
23   if (PathService::Get(dir_key, &base_path)) {
24     base::FilePath path = base_path.Append(host_name + ".json");
25     if (base::PathExists(path))
26       return path;
27   }
28   return base::FilePath();
29 }
30 
31 }  // namespace
32 
33 // static
FindManifest(const std::string & host_name,bool allow_user_level_hosts,std::string * error_message)34 base::FilePath NativeProcessLauncher::FindManifest(
35     const std::string& host_name,
36     bool allow_user_level_hosts,
37     std::string* error_message) {
38   base::FilePath result;
39   if (allow_user_level_hosts)
40     result = FindManifestInDir(chrome::DIR_USER_NATIVE_MESSAGING, host_name);
41   if (result.empty())
42     result = FindManifestInDir(chrome::DIR_NATIVE_MESSAGING, host_name);
43 
44   if (result.empty())
45     *error_message = "Can't find native messaging host " + host_name;
46 
47   return result;
48 }
49 
50 // static
LaunchNativeProcess(const CommandLine & command_line,base::ProcessHandle * process_handle,base::File * read_file,base::File * write_file)51 bool NativeProcessLauncher::LaunchNativeProcess(
52     const CommandLine& command_line,
53     base::ProcessHandle* process_handle,
54     base::File* read_file,
55     base::File* write_file) {
56   base::FileHandleMappingVector fd_map;
57 
58   int read_pipe_fds[2] = {0};
59   if (HANDLE_EINTR(pipe(read_pipe_fds)) != 0) {
60     LOG(ERROR) << "Bad read pipe";
61     return false;
62   }
63   base::ScopedFD read_pipe_read_fd(read_pipe_fds[0]);
64   base::ScopedFD read_pipe_write_fd(read_pipe_fds[1]);
65   fd_map.push_back(std::make_pair(read_pipe_write_fd.get(), STDOUT_FILENO));
66 
67   int write_pipe_fds[2] = {0};
68   if (HANDLE_EINTR(pipe(write_pipe_fds)) != 0) {
69     LOG(ERROR) << "Bad write pipe";
70     return false;
71   }
72   base::ScopedFD write_pipe_read_fd(write_pipe_fds[0]);
73   base::ScopedFD write_pipe_write_fd(write_pipe_fds[1]);
74   fd_map.push_back(std::make_pair(write_pipe_read_fd.get(), STDIN_FILENO));
75 
76   base::LaunchOptions options;
77   options.fds_to_remap = &fd_map;
78 
79 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
80   // Don't use no_new_privs mode, e.g. in case the host needs to use sudo.
81   options.allow_new_privs = true;
82 #endif
83 
84   if (!base::LaunchProcess(command_line, options, process_handle)) {
85     LOG(ERROR) << "Error launching process";
86     return false;
87   }
88 
89   // We will not be reading from the write pipe, nor writing from the read pipe.
90   write_pipe_read_fd.reset();
91   read_pipe_write_fd.reset();
92 
93   *read_file = base::File(read_pipe_read_fd.release());
94   *write_file = base::File(write_pipe_write_fd.release());
95 
96   return true;
97 }
98 
99 }  // namespace extensions
100