OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/win/scoped_handle.h" | 8 #include "base/win/scoped_handle.h" |
9 #include "ipc/ipc_channel.h" | 9 #include "ipc/ipc_channel.h" |
10 #include "ipc/ipc_channel_proxy.h" | 10 #include "ipc/ipc_channel_proxy.h" |
11 #include "ipc/ipc_listener.h" | 11 #include "ipc/ipc_listener.h" |
12 #include "ipc/ipc_message.h" | 12 #include "ipc/ipc_message.h" |
13 #include "remoting/base/auto_thread_task_runner.h" | 13 #include "remoting/base/auto_thread_task_runner.h" |
14 #include "remoting/host/host_exit_codes.h" | 14 #include "remoting/host/host_exit_codes.h" |
| 15 #include "remoting/host/win/launch_process_with_token.h" |
15 #include "remoting/host/win/worker_process_launcher.h" | 16 #include "remoting/host/win/worker_process_launcher.h" |
16 #include "remoting/host/worker_process_ipc_delegate.h" | 17 #include "remoting/host/worker_process_ipc_delegate.h" |
17 #include "testing/gmock_mutant.h" | 18 #include "testing/gmock_mutant.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 | 21 |
21 using base::win::ScopedHandle; | 22 using base::win::ScopedHandle; |
22 using testing::_; | 23 using testing::_; |
23 using testing::AnyNumber; | 24 using testing::AnyNumber; |
24 using testing::CreateFunctor; | 25 using testing::CreateFunctor; |
25 using testing::DoAll; | 26 using testing::DoAll; |
26 using testing::Expectation; | 27 using testing::Expectation; |
27 using testing::Invoke; | 28 using testing::Invoke; |
28 using testing::Return; | 29 using testing::Return; |
29 using testing::ReturnPointee; | 30 using testing::ReturnPointee; |
30 | 31 |
31 namespace remoting { | 32 namespace remoting { |
32 | 33 |
33 namespace { | 34 namespace { |
34 | 35 |
35 const char kIpcSecurityDescriptor[] = "D:(A;;GA;;;AU)"; | 36 const char kIpcSecurityDescriptor[] = "D:(A;;GA;;;AU)"; |
36 | 37 |
37 class MockProcessLauncherDelegate | 38 class MockProcessLauncherDelegate |
38 : public WorkerProcessLauncher::Delegate { | 39 : public WorkerProcessLauncher::Delegate { |
39 public: | 40 public: |
40 MockProcessLauncherDelegate() {} | 41 MockProcessLauncherDelegate() {} |
41 virtual ~MockProcessLauncherDelegate() {} | 42 virtual ~MockProcessLauncherDelegate() {} |
42 | 43 |
| 44 // IPC::Sender implementation. |
| 45 MOCK_METHOD1(Send, bool(IPC::Message*)); |
| 46 |
43 // WorkerProcessLauncher::Delegate implementation | 47 // WorkerProcessLauncher::Delegate implementation |
44 MOCK_METHOD0(GetExitCode, DWORD()); | 48 MOCK_METHOD0(GetExitCode, DWORD()); |
45 MOCK_METHOD1(KillProcess, void(DWORD)); | 49 MOCK_METHOD1(KillProcess, void(DWORD)); |
46 MOCK_METHOD2(LaunchProcess, bool(const std::string&, ScopedHandle*)); | 50 MOCK_METHOD2(LaunchProcess, bool(IPC::Listener*, ScopedHandle*)); |
47 | 51 |
48 private: | 52 private: |
49 DISALLOW_COPY_AND_ASSIGN(MockProcessLauncherDelegate); | 53 DISALLOW_COPY_AND_ASSIGN(MockProcessLauncherDelegate); |
50 }; | 54 }; |
51 | 55 |
52 class MockIpcDelegate | 56 class MockIpcDelegate |
53 : public WorkerProcessIpcDelegate { | 57 : public WorkerProcessIpcDelegate { |
54 public: | 58 public: |
55 MockIpcDelegate() {} | 59 MockIpcDelegate() {} |
56 virtual ~MockIpcDelegate() {} | 60 virtual ~MockIpcDelegate() {} |
(...skipping 17 matching lines...) Expand all Loading... |
74 virtual ~WorkerProcessLauncherTest(); | 78 virtual ~WorkerProcessLauncherTest(); |
75 | 79 |
76 virtual void SetUp() OVERRIDE; | 80 virtual void SetUp() OVERRIDE; |
77 virtual void TearDown() OVERRIDE; | 81 virtual void TearDown() OVERRIDE; |
78 | 82 |
79 // IPC::Listener implementation | 83 // IPC::Listener implementation |
80 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | 84 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
81 | 85 |
82 // WorkerProcessLauncher::Delegate mocks | 86 // WorkerProcessLauncher::Delegate mocks |
83 void KillProcess(DWORD exit_code); | 87 void KillProcess(DWORD exit_code); |
84 bool LaunchProcess(const std::string& channel_name, | 88 bool LaunchProcess(IPC::Listener* delegate, |
85 ScopedHandle* process_exit_event_out); | 89 ScopedHandle* process_exit_event_out); |
86 bool LaunchProcessAndConnect(const std::string& channel_name, | 90 bool LaunchProcessAndConnect(IPC::Listener* delegate, |
87 ScopedHandle* process_exit_event_out); | 91 ScopedHandle* process_exit_event_out); |
88 | 92 |
89 void ConnectTo(const std::string& channel_name); | 93 void ConnectChannel(); |
90 void Disconnect(); | 94 void DisconnectChannel(); |
91 | 95 |
92 // Starts the worker. | 96 // Starts the worker. |
93 void StartWorker(); | 97 void StartWorker(); |
94 | 98 |
95 // Stops the worker. | 99 // Stops the worker. |
96 void StopWorker(); | 100 void StopWorker(); |
97 | 101 |
98 // Quits |message_loop_|. | 102 // Quits |message_loop_|. |
99 void QuitMainMessageLoop(); | 103 void QuitMainMessageLoop(); |
100 | 104 |
101 protected: | 105 protected: |
102 MessageLoop message_loop_; | 106 MessageLoop message_loop_; |
103 scoped_refptr<AutoThreadTaskRunner> task_runner_; | 107 scoped_refptr<AutoThreadTaskRunner> task_runner_; |
104 | 108 |
105 // Exit code of the worker process. | 109 // Exit code of the worker process. |
106 DWORD exit_code_; | 110 DWORD exit_code_; |
107 | 111 |
108 MockIpcDelegate ipc_delegate_; | 112 MockIpcDelegate ipc_delegate_; |
109 scoped_ptr<MockProcessLauncherDelegate> launcher_delegate_; | 113 scoped_ptr<MockProcessLauncherDelegate> launcher_delegate_; |
110 | 114 |
111 // Client end of the IPC channel. | 115 // The name of the IPC channel. |
112 scoped_ptr<IPC::ChannelProxy> ipc_channel_; | 116 std::string channel_name_; |
| 117 |
| 118 // Client and server ends of the IPC channel. |
| 119 scoped_ptr<IPC::ChannelProxy> channel_client_; |
| 120 scoped_ptr<IPC::ChannelProxy> channel_server_; |
113 | 121 |
114 // The worker process launcher. | 122 // The worker process launcher. |
115 scoped_ptr<WorkerProcessLauncher> launcher_; | 123 scoped_ptr<WorkerProcessLauncher> launcher_; |
116 | 124 |
117 // The event signalling termination of the worker process. | 125 // The event signalling termination of the worker process. |
118 ScopedHandle process_exit_event_; | 126 ScopedHandle process_exit_event_; |
119 }; | 127 }; |
120 | 128 |
121 | 129 |
122 WorkerProcessLauncherTest::WorkerProcessLauncherTest() | 130 WorkerProcessLauncherTest::WorkerProcessLauncherTest() |
123 : message_loop_(MessageLoop::TYPE_IO) { | 131 : message_loop_(MessageLoop::TYPE_IO) { |
124 } | 132 } |
125 | 133 |
126 WorkerProcessLauncherTest::~WorkerProcessLauncherTest() { | 134 WorkerProcessLauncherTest::~WorkerProcessLauncherTest() { |
127 } | 135 } |
128 | 136 |
129 void WorkerProcessLauncherTest::SetUp() { | 137 void WorkerProcessLauncherTest::SetUp() { |
130 task_runner_ = new AutoThreadTaskRunner( | 138 task_runner_ = new AutoThreadTaskRunner( |
131 message_loop_.message_loop_proxy(), | 139 message_loop_.message_loop_proxy(), |
132 base::Bind(&WorkerProcessLauncherTest::QuitMainMessageLoop, | 140 base::Bind(&WorkerProcessLauncherTest::QuitMainMessageLoop, |
133 base::Unretained(this))); | 141 base::Unretained(this))); |
134 | 142 |
135 exit_code_ = STILL_ACTIVE; | 143 exit_code_ = STILL_ACTIVE; |
136 | 144 |
137 // Set up process launcher delegate | 145 // Set up process launcher delegate |
138 launcher_delegate_.reset(new MockProcessLauncherDelegate()); | 146 launcher_delegate_.reset(new MockProcessLauncherDelegate()); |
| 147 EXPECT_CALL(*launcher_delegate_, Send(_)) |
| 148 .Times(AnyNumber()) |
| 149 .WillRepeatedly(Return(false)); |
139 EXPECT_CALL(*launcher_delegate_, GetExitCode()) | 150 EXPECT_CALL(*launcher_delegate_, GetExitCode()) |
140 .Times(AnyNumber()) | 151 .Times(AnyNumber()) |
141 .WillRepeatedly(ReturnPointee(&exit_code_)); | 152 .WillRepeatedly(ReturnPointee(&exit_code_)); |
142 EXPECT_CALL(*launcher_delegate_, KillProcess(_)) | 153 EXPECT_CALL(*launcher_delegate_, KillProcess(_)) |
143 .Times(AnyNumber()) | 154 .Times(AnyNumber()) |
144 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::KillProcess)); | 155 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::KillProcess)); |
145 | 156 |
146 // Set up IPC delegate. | 157 // Set up IPC delegate. |
147 EXPECT_CALL(ipc_delegate_, OnMessageReceived(_)) | 158 EXPECT_CALL(ipc_delegate_, OnMessageReceived(_)) |
148 .Times(AnyNumber()) | 159 .Times(AnyNumber()) |
149 .WillRepeatedly(Return(false)); | 160 .WillRepeatedly(Return(false)); |
150 } | 161 } |
151 | 162 |
152 void WorkerProcessLauncherTest::TearDown() { | 163 void WorkerProcessLauncherTest::TearDown() { |
153 } | 164 } |
154 | 165 |
155 bool WorkerProcessLauncherTest::OnMessageReceived(const IPC::Message& message) { | 166 bool WorkerProcessLauncherTest::OnMessageReceived(const IPC::Message& message) { |
156 return false; | 167 return false; |
157 } | 168 } |
158 | 169 |
159 void WorkerProcessLauncherTest::KillProcess(DWORD exit_code) { | 170 void WorkerProcessLauncherTest::KillProcess(DWORD exit_code) { |
160 exit_code_ = exit_code; | 171 exit_code_ = exit_code; |
161 BOOL result = SetEvent(process_exit_event_); | 172 BOOL result = SetEvent(process_exit_event_); |
162 EXPECT_TRUE(result); | 173 EXPECT_TRUE(result); |
163 } | 174 } |
164 | 175 |
165 bool WorkerProcessLauncherTest::LaunchProcess( | 176 bool WorkerProcessLauncherTest::LaunchProcess( |
166 const std::string& channel_name, | 177 IPC::Listener* delegate, |
167 ScopedHandle* process_exit_event_out) { | |
168 return LaunchProcessAndConnect("", process_exit_event_out); | |
169 } | |
170 | |
171 bool WorkerProcessLauncherTest::LaunchProcessAndConnect( | |
172 const std::string& channel_name, | |
173 ScopedHandle* process_exit_event_out) { | 178 ScopedHandle* process_exit_event_out) { |
174 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); | 179 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); |
175 if (!process_exit_event_.IsValid()) | 180 if (!process_exit_event_.IsValid()) |
176 return false; | 181 return false; |
177 | 182 |
178 if (!channel_name.empty()) { | 183 channel_name_ = GenerateIpcChannelName(this); |
179 task_runner_->PostTask( | 184 if (!CreateIpcChannel(channel_name_, kIpcSecurityDescriptor, task_runner_, |
180 FROM_HERE, | 185 delegate, &channel_server_)) { |
181 base::Bind(&WorkerProcessLauncherTest::ConnectTo, | 186 return false; |
182 base::Unretained(this), | |
183 channel_name)); | |
184 } | 187 } |
185 | 188 |
186 exit_code_ = STILL_ACTIVE; | 189 exit_code_ = STILL_ACTIVE; |
187 return DuplicateHandle(GetCurrentProcess(), | 190 return DuplicateHandle(GetCurrentProcess(), |
188 process_exit_event_, | 191 process_exit_event_, |
189 GetCurrentProcess(), | 192 GetCurrentProcess(), |
190 process_exit_event_out->Receive(), | 193 process_exit_event_out->Receive(), |
191 0, | 194 0, |
192 FALSE, | 195 FALSE, |
193 DUPLICATE_SAME_ACCESS) != FALSE; | 196 DUPLICATE_SAME_ACCESS) != FALSE; |
194 } | 197 } |
195 | 198 |
196 void WorkerProcessLauncherTest::ConnectTo(const std::string& channel_name) { | 199 bool WorkerProcessLauncherTest::LaunchProcessAndConnect( |
197 ipc_channel_.reset(new IPC::ChannelProxy( | 200 IPC::Listener* delegate, |
198 IPC::ChannelHandle(channel_name), | 201 ScopedHandle* process_exit_event_out) { |
| 202 if (!LaunchProcess(delegate, process_exit_event_out)) |
| 203 return false; |
| 204 |
| 205 task_runner_->PostTask( |
| 206 FROM_HERE, |
| 207 base::Bind(&WorkerProcessLauncherTest::ConnectChannel, |
| 208 base::Unretained(this))); |
| 209 return true; |
| 210 } |
| 211 |
| 212 void WorkerProcessLauncherTest::ConnectChannel() { |
| 213 channel_client_.reset(new IPC::ChannelProxy( |
| 214 IPC::ChannelHandle(channel_name_), |
199 IPC::Channel::MODE_CLIENT, | 215 IPC::Channel::MODE_CLIENT, |
200 this, | 216 this, |
201 task_runner_)); | 217 task_runner_)); |
202 } | 218 } |
203 | 219 |
204 void WorkerProcessLauncherTest::Disconnect() { | 220 void WorkerProcessLauncherTest::DisconnectChannel() { |
205 ipc_channel_.reset(); | 221 channel_client_.reset(); |
206 } | 222 } |
207 | 223 |
208 void WorkerProcessLauncherTest::StartWorker() { | 224 void WorkerProcessLauncherTest::StartWorker() { |
209 launcher_.reset(new WorkerProcessLauncher(task_runner_, | 225 launcher_.reset(new WorkerProcessLauncher( |
210 task_runner_, | 226 task_runner_, launcher_delegate_.Pass(), &ipc_delegate_)); |
211 launcher_delegate_.Pass(), | |
212 &ipc_delegate_, | |
213 kIpcSecurityDescriptor)); | |
214 } | 227 } |
215 | 228 |
216 void WorkerProcessLauncherTest::StopWorker() { | 229 void WorkerProcessLauncherTest::StopWorker() { |
217 launcher_.reset(); | 230 launcher_.reset(); |
218 Disconnect(); | 231 DisconnectChannel(); |
| 232 channel_name_.clear(); |
| 233 channel_server_.reset(); |
219 task_runner_ = NULL; | 234 task_runner_ = NULL; |
220 } | 235 } |
221 | 236 |
222 void WorkerProcessLauncherTest::QuitMainMessageLoop() { | 237 void WorkerProcessLauncherTest::QuitMainMessageLoop() { |
223 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 238 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
224 } | 239 } |
225 | 240 |
226 TEST_F(WorkerProcessLauncherTest, Start) { | 241 TEST_F(WorkerProcessLauncherTest, Start) { |
227 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _)) | 242 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _)) |
228 .Times(1) | 243 .Times(1) |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 // the worker process to be restarted. | 302 // the worker process to be restarted. |
288 TEST_F(WorkerProcessLauncherTest, DropIpcChannel) { | 303 TEST_F(WorkerProcessLauncherTest, DropIpcChannel) { |
289 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _)) | 304 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _)) |
290 .Times(2) | 305 .Times(2) |
291 .WillRepeatedly(Invoke( | 306 .WillRepeatedly(Invoke( |
292 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); | 307 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
293 | 308 |
294 Expectation first_connect = | 309 Expectation first_connect = |
295 EXPECT_CALL(ipc_delegate_, OnChannelConnected()) | 310 EXPECT_CALL(ipc_delegate_, OnChannelConnected()) |
296 .Times(2) | 311 .Times(2) |
297 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::Disconnect)) | 312 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::DisconnectChannel)) |
298 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker)); | 313 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker)); |
299 | 314 |
300 EXPECT_CALL(ipc_delegate_, OnPermanentError()) | 315 EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
301 .Times(0); | 316 .Times(0); |
302 | 317 |
303 StartWorker(); | 318 StartWorker(); |
304 message_loop_.Run(); | 319 message_loop_.Run(); |
305 | 320 |
306 EXPECT_EQ(exit_code_, CONTROL_C_EXIT); | 321 EXPECT_EQ(exit_code_, CONTROL_C_EXIT); |
307 } | 322 } |
(...skipping 18 matching lines...) Expand all Loading... |
326 .Times(1) | 341 .Times(1) |
327 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker)); | 342 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker)); |
328 | 343 |
329 StartWorker(); | 344 StartWorker(); |
330 message_loop_.Run(); | 345 message_loop_.Run(); |
331 | 346 |
332 EXPECT_EQ(exit_code_, kInvalidHostConfigurationExitCode); | 347 EXPECT_EQ(exit_code_, kInvalidHostConfigurationExitCode); |
333 } | 348 } |
334 | 349 |
335 } // namespace remoting | 350 } // namespace remoting |
OLD | NEW |