File: launch_context.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (198 lines) | stat: -rw-r--r-- 7,345 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_LAUNCH_CONTEXT_H_
#define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_LAUNCH_CONTEXT_H_

#include <stdint.h>

#include <memory>
#include <optional>
#include <string>

#include "base/files/file_path.h"
#include "base/files/platform_file.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_WIN)
#include "base/win/object_watcher.h"
#endif

namespace base {
class CommandLine;
class TaskRunner;
}  // namespace base

namespace net {
class FileStream;
}  // namespace net

namespace extensions {

// The state for a single native messaging host process launch. Instances live
// and die on the IO thread. Asynchronous process launch is initiated via
// `Start`. A consumer may cancel an in-progress launch by deleting the instance
// on the IO thread.
class LaunchContext
#if BUILDFLAG(IS_WIN)
    : public base::win::ObjectWatcher::Delegate
#endif
{
 public:
  // `callback` is guaranteed not to be run after the returned instance is
  // destroyed.
  static std::unique_ptr<LaunchContext> Start(
      bool allow_user_level_hosts,
      bool require_native_initiated_connections,
      bool native_hosts_executables_launch_directly,
      intptr_t window_handle,
      base::FilePath profile_directory,
      std::string connect_id,
      std::string error_arg,
      GURL origin,
      std::string native_host_name,
      scoped_refptr<base::TaskRunner> background_task_runner,
      NativeProcessLauncher::LaunchedCallback callback);
#if BUILDFLAG(IS_WIN)
  ~LaunchContext() override;
#else
  ~LaunchContext();
#endif

 private:
  LaunchContext(scoped_refptr<base::TaskRunner> background_task_runner,
                NativeProcessLauncher::LaunchedCallback callback);

  base::WeakPtr<LaunchContext> GetWeakPtr() {
    return weak_ptr_factory_.GetWeakPtr();
  }

  // Returns the path to the manifest file for the native messaging host
  // `host_name`. If `allow_user_level_hosts` is false, user-level manifests are
  // ignored; otherwise, they are preferred over an all-users manifest. Returns
  // an empty path if the host with the specified name cannot be found.
  static base::FilePath FindManifest(const std::string& host_name,
                                     bool allow_user_level_hosts,
                                     std::string& error_message);

  struct ProcessState {
    ProcessState();
    ProcessState(base::Process process,
                 base::ScopedPlatformFile read_file,
                 base::ScopedPlatformFile write_file);
    ProcessState(ProcessState&& other) noexcept;
    ProcessState& operator=(ProcessState&& other) noexcept;
    ~ProcessState();

    // The child process.
    base::Process process;

    // The child's stdout.
    base::ScopedPlatformFile read_file;

    // The child's stdin.
    base::ScopedPlatformFile write_file;
  };

  // Launches the native messaging process, providing it with one end each of a
  // pair of pipes for its stdout and stdin. On Windows: if
  // `native_hosts_executables_launch_directly` is true and the host is an .exe,
  // the host is launched directly; otherwise, it is launched via cmd.exe. On
  // success, returns the launched process and the out/in pipes.
  static std::optional<ProcessState> LaunchNativeProcess(
      const base::CommandLine& command_line,
      bool native_hosts_executables_launch_directly);

  // The result of a background process launch.
  struct BackgroundLaunchResult {
    explicit BackgroundLaunchResult(NativeProcessLauncher::LaunchResult result);
    explicit BackgroundLaunchResult(ProcessState process_state);
    BackgroundLaunchResult(BackgroundLaunchResult&& other) noexcept;
    BackgroundLaunchResult& operator=(BackgroundLaunchResult&& other) noexcept;
    ~BackgroundLaunchResult();

    // The result code of the launch.
    NativeProcessLauncher::LaunchResult result;

    // The handles for the child process, present only when `result` is
    // `RESULT_SUCCESS`.
    std::optional<ProcessState> process_state;
  };

  // Reads and validates the host's manifest, forms its command line, and
  // launches it. Returns an error code or the process's handles.
  static BackgroundLaunchResult LaunchInBackground(
      bool allow_user_level_hosts,
      bool require_native_initiated_connections,
      bool native_hosts_executables_launch_directly,
      intptr_t window_handle,
      const base::FilePath& profile_directory,
      const std::string& connect_id,
      const std::string& error_arg,
      const GURL& origin,
      const std::string& native_host_name);

  // Continues processing on the IO thread following `LaunchInBackground`. If
  // the launch was cancelled (via deletion of the context), the host process
  // is terminated. Otherwise, either the caller's callback is run with the
  // failure code, or the pipes are connected.
  static void OnProcessLaunched(base::WeakPtr<LaunchContext> weak_this,
                                BackgroundLaunchResult result);

  // Connects to the host process.
  void ConnectPipes(base::ScopedPlatformFile read_file,
                    base::ScopedPlatformFile write_file);

#if BUILDFLAG(IS_WIN)
  // These methods are only needed on Windows, where an extra step is needed to
  // connect to the named pipes used for stdin/stdout of the native messaging
  // host process. The connections are established asynchronously via the IO
  // completion port monitored by the IO thread.

  // Handles the result of connecting to the host's stdout pipe.
  void OnReadStreamConnectResult(int net_error);

  // Handles the result of connecting to the host's stdin pipe.
  void OnWriteStreamConnectResult(int net_error);

  // Continues processing once a pipe has connected.
  void OnPipeConnected();

  // base::win::ObjectWatcher::Delegate:
  // Handles unexpected termination of the host process.
  void OnObjectSignaled(HANDLE object) override;
#endif  // BUILDFLAG(IS_WIN)

  // Reports success via the caller's callback, which may destroy `this`.
  void OnSuccess(base::PlatformFile read_file,
                 std::unique_ptr<net::FileStream> read_stream,
                 std::unique_ptr<net::FileStream> write_stream);

  // Reports failure via the caller's callback, which may destroy `this`.
  void OnFailure(NativeProcessLauncher::LaunchResult launch_result);

  scoped_refptr<base::TaskRunner> background_task_runner_;
  NativeProcessLauncher::LaunchedCallback callback_;
  base::Process native_process_;
#if BUILDFLAG(IS_WIN)
  std::unique_ptr<net::FileStream> read_stream_;
  std::unique_ptr<net::FileStream> write_stream_;
  base::win::ObjectWatcher process_watcher_;
  bool read_pipe_connected_ = false;
  bool write_pipe_connected_ = false;
#endif  // BUILDFLAG(IS_WIN)
  SEQUENCE_CHECKER(sequence_checker_);
  base::WeakPtrFactory<LaunchContext> weak_ptr_factory_{this};
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_LAUNCH_CONTEXT_H_