Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(408)

Side by Side Diff: remoting/host/win/worker_process_launcher.cc

Issue 10828181: [Chromoting] Moving common logic responsible for launching child processes to WorkerProcessLauncher… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "remoting/host/win/worker_process_launcher.h"
6
7 #include <windows.h>
8 #include <sddl.h>
9 #include <limits>
10
11 #include "base/base_switches.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/logging.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/process_util.h"
17 #include "base/rand_util.h"
18 #include "base/stringprintf.h"
19 #include "base/utf_string_conversions.h"
20 #include "base/win/scoped_handle.h"
21 #include "ipc/ipc_channel_proxy.h"
22 #include "ipc/ipc_message.h"
23
24 using base::win::ScopedHandle;
25
26 namespace {
27
28 // Match the pipe name prefix used by Chrome IPC channels so that the client
29 // could use Chrome IPC APIs instead of connecting manually.
30 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
31
32 } // namespace
33
34 namespace remoting {
35
36 WorkerProcessLauncher::Delegate::~Delegate() {
37 }
38
39 WorkerProcessLauncher::WorkerProcessLauncher(
40 Delegate* delegate,
41 const base::Closure& stopped_callback,
42 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
43 scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
44 : Stoppable(main_task_runner, stopped_callback),
45 delegate_(delegate),
46 main_task_runner_(main_task_runner),
47 ipc_task_runner_(ipc_task_runner) {
48 }
49
50 WorkerProcessLauncher::~WorkerProcessLauncher() {
51 DCHECK(main_task_runner_->BelongsToCurrentThread());
52 }
53
54 void WorkerProcessLauncher::Start(const std::string& pipe_sddl) {
55 DCHECK(main_task_runner_->BelongsToCurrentThread());
56 DCHECK(ipc_channel_.get() == NULL);
57 DCHECK(!pipe_.IsValid());
58 DCHECK(!process_exit_event_.IsValid());
59 DCHECK(process_watcher_.GetWatchedObject() == NULL);
60
61 std::string channel_name = GenerateRandomChannelId();
62 if (CreatePipeForIpcChannel(channel_name, pipe_sddl, &pipe_)) {
63 // Wrap the pipe into an IPC channel.
64 ipc_channel_.reset(new IPC::ChannelProxy(
65 IPC::ChannelHandle(pipe_),
66 IPC::Channel::MODE_SERVER,
67 this,
68 ipc_task_runner_));
69
70 // Launch the process and attach an object watcher to the returned process
71 // handle so that we get notified if the process terminates.
72 if (delegate_->DoLaunchProcess(channel_name, &process_exit_event_)) {
73 if (process_watcher_.StartWatching(process_exit_event_, this)) {
74 return;
75 }
76
77 delegate_->DoKillProcess(CONTROL_C_EXIT);
78 }
79 }
80
81 Stop();
82 }
83
84 void WorkerProcessLauncher::Send(IPC::Message* message) {
85 DCHECK(main_task_runner_->BelongsToCurrentThread());
86
87 ipc_channel_->Send(message);
88 }
89
90 void WorkerProcessLauncher::OnObjectSignaled(HANDLE object) {
91 DCHECK(main_task_runner_->BelongsToCurrentThread());
92 DCHECK(process_watcher_.GetWatchedObject() == NULL);
93
94 Stop();
95 }
96
97 bool WorkerProcessLauncher::OnMessageReceived(const IPC::Message& message) {
98 DCHECK(main_task_runner_->BelongsToCurrentThread());
99 DCHECK(ipc_channel_.get() != NULL);
100 DCHECK(pipe_.IsValid());
101 DCHECK(process_exit_event_.IsValid());
102
103 return delegate_->OnMessageReceived(message);
104 }
105
106 void WorkerProcessLauncher::OnChannelConnected(int32 peer_pid) {
107 DCHECK(main_task_runner_->BelongsToCurrentThread());
108 DCHECK(ipc_channel_.get() != NULL);
109 DCHECK(pipe_.IsValid());
110 DCHECK(process_exit_event_.IsValid());
111
112 // Get the actual peer's PID (i.e. reported by the OS) instead of the PID
113 // reported by the peer itself (|peer_pid|).
114 DWORD actual_peer_pid;
115 if (!GetNamedPipeClientProcessId(pipe_, &actual_peer_pid)) {
116 LOG_GETLASTERROR(ERROR) << "Failed to query the peer's PID";
117 Stop();
118 return;
119 }
120
121 delegate_->OnChannelConnected(actual_peer_pid);
122 }
123
124 void WorkerProcessLauncher::OnChannelError() {
125 DCHECK(main_task_runner_->BelongsToCurrentThread());
126 DCHECK(ipc_channel_.get() != NULL);
127 DCHECK(pipe_.IsValid());
128 DCHECK(process_exit_event_.IsValid());
129
130 Stop();
131 }
132
133 void WorkerProcessLauncher::DoStop() {
134 DCHECK(main_task_runner_->BelongsToCurrentThread());
135
136 ipc_channel_.reset();
137 pipe_.Close();
138
139 // Kill the process if it has been started already.
140 if (process_watcher_.GetWatchedObject() != NULL) {
141 delegate_->DoKillProcess(CONTROL_C_EXIT);
142 return;
143 }
144
145 DCHECK(ipc_channel_.get() == NULL);
146 DCHECK(!pipe_.IsValid());
147 DCHECK(process_watcher_.GetWatchedObject() == NULL);
148
149 process_exit_event_.Close();
150 CompleteStopping();
151 }
152
153 // Creates the server end of the Chromoting IPC channel.
154 bool WorkerProcessLauncher::CreatePipeForIpcChannel(
155 const std::string& channel_name,
156 const std::string& pipe_sddl,
157 ScopedHandle* pipe_out) {
158 // Create security descriptor for the channel.
159 SECURITY_ATTRIBUTES security_attributes;
160 security_attributes.nLength = sizeof(security_attributes);
161 security_attributes.bInheritHandle = FALSE;
162
163 ULONG security_descriptor_length = 0;
164 if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
165 UTF8ToUTF16(pipe_sddl).c_str(),
166 SDDL_REVISION_1,
167 reinterpret_cast<PSECURITY_DESCRIPTOR*>(
168 &security_attributes.lpSecurityDescriptor),
169 &security_descriptor_length)) {
170 LOG_GETLASTERROR(ERROR) <<
171 "Failed to create a security descriptor for the Chromoting IPC channel";
172 return false;
173 }
174
175 // Convert the channel name to the pipe name.
176 std::string pipe_name(kChromePipeNamePrefix);
177 pipe_name.append(channel_name);
178
179 // Create the server end of the pipe. This code should match the code in
180 // IPC::Channel with exception of passing a non-default security descriptor.
181 base::win::ScopedHandle pipe;
182 pipe.Set(CreateNamedPipe(
183 UTF8ToUTF16(pipe_name).c_str(),
184 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
185 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
186 1,
187 IPC::Channel::kReadBufferSize,
188 IPC::Channel::kReadBufferSize,
189 5000,
190 &security_attributes));
191 if (!pipe.IsValid()) {
192 LOG_GETLASTERROR(ERROR) <<
193 "Failed to create the server end of the Chromoting IPC channel";
194 LocalFree(security_attributes.lpSecurityDescriptor);
195 return false;
196 }
197
198 LocalFree(security_attributes.lpSecurityDescriptor);
199
200 *pipe_out = pipe.Pass();
201 return true;
202 }
203
204 // N.B. Copied from src/content/common/child_process_host_impl.cc
205 std::string WorkerProcessLauncher::GenerateRandomChannelId() {
206 return base::StringPrintf("%d.%p.%d",
207 base::GetCurrentProcId(), this,
208 base::RandInt(0, std::numeric_limits<int>::max()));
209 }
210
211 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698