OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/bind_helpers.h" | 6 #include "base/bind_helpers.h" |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/memory/weak_ptr.h" | |
11 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
12 #include "base/process.h" | 11 #include "base/process.h" |
13 #include "base/process_util.h" | 12 #include "base/process_util.h" |
14 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
15 #include "ipc/ipc_channel.h" | 14 #include "ipc/ipc_channel.h" |
16 #include "ipc/ipc_channel_proxy.h" | 15 #include "ipc/ipc_channel_proxy.h" |
17 #include "ipc/ipc_listener.h" | 16 #include "ipc/ipc_listener.h" |
18 #include "ipc/ipc_message.h" | 17 #include "ipc/ipc_message.h" |
19 #include "ipc/ipc_platform_file.h" | 18 #include "ipc/ipc_platform_file.h" |
20 #include "media/video/capture/screen/screen_capturer_fake.h" | 19 #include "media/video/capture/screen/screen_capturer_fake.h" |
21 #include "media/video/capture/screen/screen_capturer_mock_objects.h" | 20 #include "media/video/capture/screen/screen_capturer_mock_objects.h" |
22 #include "remoting/base/auto_thread.h" | 21 #include "remoting/base/auto_thread.h" |
23 #include "remoting/base/auto_thread_task_runner.h" | 22 #include "remoting/base/auto_thread_task_runner.h" |
| 23 #include "remoting/base/constants.h" |
24 #include "remoting/host/chromoting_messages.h" | 24 #include "remoting/host/chromoting_messages.h" |
25 #include "remoting/host/desktop_process.h" | 25 #include "remoting/host/desktop_process.h" |
26 #include "remoting/host/desktop_session_connector.h" | 26 #include "remoting/host/desktop_session_connector.h" |
27 #include "remoting/host/desktop_session_proxy.h" | 27 #include "remoting/host/desktop_session_proxy.h" |
28 #include "remoting/host/host_mock_objects.h" | 28 #include "remoting/host/host_mock_objects.h" |
29 #include "remoting/host/ipc_desktop_environment.h" | 29 #include "remoting/host/ipc_desktop_environment.h" |
30 #include "remoting/protocol/protocol_mock_objects.h" | 30 #include "remoting/protocol/protocol_mock_objects.h" |
31 #include "testing/gmock/include/gmock/gmock.h" | 31 #include "testing/gmock/include/gmock/gmock.h" |
32 #include "testing/gtest/include/gtest/gtest.h" | 32 #include "testing/gtest/include/gtest/gtest.h" |
| 33 #include "third_party/skia/include/core/SkRegion.h" |
33 | 34 |
34 using testing::_; | 35 using testing::_; |
35 using testing::AnyNumber; | 36 using testing::AnyNumber; |
| 37 using testing::AtLeast; |
36 using testing::Return; | 38 using testing::Return; |
37 | 39 |
38 namespace remoting { | 40 namespace remoting { |
39 | 41 |
40 namespace { | 42 namespace { |
41 | 43 |
| 44 // Receives messages sent from the network process to the daemon. |
| 45 class FakeDaemonSender : public IPC::Sender { |
| 46 public: |
| 47 FakeDaemonSender() {} |
| 48 virtual ~FakeDaemonSender() {} |
| 49 |
| 50 // IPC::Sender implementation. |
| 51 virtual bool Send(IPC::Message* message) OVERRIDE; |
| 52 |
| 53 MOCK_METHOD1(ConnectTerminal, void(int)); |
| 54 MOCK_METHOD1(DisconnectTerminal, void(int)); |
| 55 |
| 56 private: |
| 57 void OnMessageReceived(const IPC::Message& message); |
| 58 |
| 59 DISALLOW_COPY_AND_ASSIGN(FakeDaemonSender); |
| 60 }; |
| 61 |
| 62 // Receives messages sent from the desktop process to the daemon. |
42 class MockDaemonListener : public IPC::Listener { | 63 class MockDaemonListener : public IPC::Listener { |
43 public: | 64 public: |
44 MockDaemonListener() {} | 65 MockDaemonListener() {} |
45 virtual ~MockDaemonListener() {} | 66 virtual ~MockDaemonListener() {} |
46 | 67 |
47 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | 68 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
48 | 69 |
49 MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit)); | 70 MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit)); |
50 MOCK_METHOD1(OnChannelConnected, void(int32)); | 71 MOCK_METHOD1(OnChannelConnected, void(int32)); |
51 MOCK_METHOD0(OnChannelError, void()); | 72 MOCK_METHOD0(OnChannelError, void()); |
52 | 73 |
53 private: | 74 private: |
54 DISALLOW_COPY_AND_ASSIGN(MockDaemonListener); | 75 DISALLOW_COPY_AND_ASSIGN(MockDaemonListener); |
55 }; | 76 }; |
56 | 77 |
| 78 bool FakeDaemonSender::Send(IPC::Message* message) { |
| 79 OnMessageReceived(*message); |
| 80 delete message; |
| 81 return true; |
| 82 } |
| 83 |
| 84 void FakeDaemonSender::OnMessageReceived(const IPC::Message& message) { |
| 85 bool handled = true; |
| 86 IPC_BEGIN_MESSAGE_MAP(FakeDaemonSender, message) |
| 87 IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_ConnectTerminal, |
| 88 ConnectTerminal) |
| 89 IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_DisconnectTerminal, |
| 90 DisconnectTerminal) |
| 91 IPC_MESSAGE_UNHANDLED(handled = false) |
| 92 IPC_END_MESSAGE_MAP() |
| 93 |
| 94 EXPECT_TRUE(handled); |
| 95 } |
| 96 |
57 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) { | 97 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) { |
58 bool handled = true; | 98 bool handled = true; |
59 IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message) | 99 IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message) |
60 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached, | 100 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached, |
61 OnDesktopAttached) | 101 OnDesktopAttached) |
62 IPC_MESSAGE_UNHANDLED(handled = false) | 102 IPC_MESSAGE_UNHANDLED(handled = false) |
63 IPC_END_MESSAGE_MAP() | 103 IPC_END_MESSAGE_MAP() |
64 | 104 |
65 EXPECT_TRUE(handled); | 105 EXPECT_TRUE(handled); |
66 return handled; | 106 return handled; |
67 } | 107 } |
68 | 108 |
69 } // namespace | 109 } // namespace |
70 | 110 |
71 class IpcDesktopEnvironmentTest | 111 class IpcDesktopEnvironmentTest : public testing::Test { |
72 : public testing::Test, | |
73 public DesktopSessionConnector { | |
74 public: | 112 public: |
75 IpcDesktopEnvironmentTest(); | 113 IpcDesktopEnvironmentTest(); |
76 virtual ~IpcDesktopEnvironmentTest(); | 114 virtual ~IpcDesktopEnvironmentTest(); |
77 | 115 |
78 virtual void SetUp() OVERRIDE; | 116 virtual void SetUp() OVERRIDE; |
79 | 117 |
80 // DesktopSessionConnector implementation. | 118 void ConnectTerminal(int terminal_id); |
81 virtual void ConnectTerminal( | 119 void DisconnectTerminal(int terminal_id); |
82 scoped_refptr<DesktopSessionProxy> desktop_session_proxy) OVERRIDE; | |
83 virtual void DisconnectTerminal( | |
84 scoped_refptr<DesktopSessionProxy> desktop_session_proxy) OVERRIDE; | |
85 virtual void OnDesktopSessionAgentAttached( | |
86 int terminal_id, | |
87 base::ProcessHandle desktop_process, | |
88 IPC::PlatformFileForTransit desktop_pipe) OVERRIDE; | |
89 virtual void OnTerminalDisconnected(int terminal_id) OVERRIDE; | |
90 | 120 |
91 // Creates a DesktopEnvironment with a fake media::ScreenCapturer, to mock | 121 // Creates a DesktopEnvironment with a fake media::ScreenCapturer, to mock |
92 // DesktopEnvironmentFactory::Create(). | 122 // DesktopEnvironmentFactory::Create(). |
93 DesktopEnvironment* CreateDesktopEnvironment(); | 123 DesktopEnvironment* CreateDesktopEnvironment(); |
94 | 124 |
95 // Creates a dummy EventExecutor, to mock | 125 // Creates a dummy EventExecutor, to mock |
96 // DesktopEnvironment::CreateEventExecutor(). | 126 // DesktopEnvironment::CreateEventExecutor(). |
97 EventExecutor* CreateEventExecutor(); | 127 EventExecutor* CreateEventExecutor(); |
98 | 128 |
99 // Creates a fake media::ScreenCapturer, to mock | 129 // Creates a fake media::ScreenCapturer, to mock |
100 // DesktopEnvironment::CreateVideoCapturer(). | 130 // DesktopEnvironment::CreateVideoCapturer(). |
101 media::ScreenCapturer* CreateVideoCapturer(); | 131 media::ScreenCapturer* CreateVideoCapturer(); |
102 | 132 |
103 void DeleteDesktopEnvironment(); | 133 void DeleteDesktopEnvironment(); |
104 | 134 |
| 135 // Forwards |event| to |clipboard_stub_|. |
| 136 void ReflectClipboardEvent(const protocol::ClipboardEvent& event); |
| 137 |
105 protected: | 138 protected: |
| 139 // Creates and starts an instance of desktop process object. |
| 140 void CreateDesktopProcess(); |
| 141 |
| 142 // Destroys the desktop process object created by CreateDesktopProcess(). |
| 143 void DestoyDesktopProcess(); |
| 144 |
106 void OnDisconnectCallback(); | 145 void OnDisconnectCallback(); |
107 | 146 |
108 // Invoked when ChromotingDesktopDaemonMsg_DesktopAttached message is | 147 // Invoked when ChromotingDesktopDaemonMsg_DesktopAttached message is |
109 // received. | 148 // received. |
110 void OnDesktopAttached(IPC::PlatformFileForTransit desktop_pipe); | 149 void OnDesktopAttached(IPC::PlatformFileForTransit desktop_pipe); |
111 | 150 |
112 // Invoked when the daemon-to-desktop channel is closed. | |
113 void OnDesktopSessionClosed(); | |
114 | |
115 // The main message loop. | 151 // The main message loop. |
116 MessageLoop message_loop_; | 152 MessageLoop message_loop_; |
117 | 153 |
118 // Runs until |desktop_session_proxy_| is connected to the desktop. | 154 // Runs until |desktop_session_proxy_| is connected to the desktop. |
119 base::RunLoop setup_run_loop_; | 155 scoped_ptr<base::RunLoop> setup_run_loop_; |
120 | 156 |
121 // Runs until there are references to |task_runner_|. | 157 // Runs until there are references to |task_runner_|. |
122 base::RunLoop main_run_loop_; | 158 base::RunLoop main_run_loop_; |
123 | 159 |
124 scoped_refptr<AutoThreadTaskRunner> task_runner_; | 160 scoped_refptr<AutoThreadTaskRunner> task_runner_; |
| 161 scoped_refptr<AutoThreadTaskRunner> io_task_runner_; |
125 | 162 |
126 // Factory for weak pointers to DesktopSessionConnector interface. | 163 // Clipboard stub that receives clipboard events from the desktop process. |
127 base::WeakPtrFactory<DesktopSessionConnector> connector_factory_; | 164 protocol::ClipboardStub* clipboard_stub_; |
128 | 165 |
129 // The daemons's end of the daemon-to-desktop channel. | 166 // The daemons's end of the daemon-to-desktop channel. |
130 scoped_ptr<IPC::ChannelProxy> daemon_channel_; | 167 scoped_ptr<IPC::ChannelProxy> desktop_channel_; |
131 | 168 |
132 // Name of the daemon-to-desktop channel. | 169 // Name of the daemon-to-desktop channel. |
133 std::string daemon_channel_name_; | 170 std::string desktop_channel_name_; |
134 | 171 |
135 // Delegate that is passed to |daemon_channel_|. | 172 // Delegate that is passed to |desktop_channel_|. |
136 MockDaemonListener daemon_listener_; | 173 MockDaemonListener desktop_listener_; |
137 | 174 |
138 scoped_ptr<IpcDesktopEnvironment> desktop_environment_; | 175 FakeDaemonSender daemon_channel_; |
139 | 176 |
140 // Event executor created by |desktop_environment_|. | 177 scoped_ptr<IpcDesktopEnvironmentFactory> desktop_environment_factory_; |
| 178 scoped_ptr<DesktopEnvironment> desktop_environment_; |
| 179 |
| 180 // The IPC event executor. |
141 scoped_ptr<EventExecutor> event_executor_; | 181 scoped_ptr<EventExecutor> event_executor_; |
142 | 182 |
143 // Screen capturer created by |desktop_environment_|. | 183 // The IPC screen capturer. |
144 scoped_ptr<media::ScreenCapturer> video_capturer_; | 184 scoped_ptr<media::ScreenCapturer> video_capturer_; |
145 | 185 |
146 // Represents the desktop process running in a user session. | 186 // Represents the desktop process running in a user session. |
147 scoped_ptr<DesktopProcess> desktop_process_; | 187 scoped_ptr<DesktopProcess> desktop_process_; |
148 | 188 |
149 // Points to the DesktopSessionProxy instance created by | 189 // Event executor owned by |desktop_process_|. |
150 // IpdDesktopEnvironment. | 190 MockEventExecutor* remote_event_executor_; |
151 scoped_refptr<DesktopSessionProxy> desktop_session_proxy_; | 191 |
| 192 // The last |terminal_id| passed to ConnectTermina(); |
| 193 int terminal_id_; |
152 | 194 |
153 media::MockScreenCapturerDelegate screen_capturer_delegate_; | 195 media::MockScreenCapturerDelegate screen_capturer_delegate_; |
154 }; | 196 }; |
155 | 197 |
156 IpcDesktopEnvironmentTest::IpcDesktopEnvironmentTest() | 198 IpcDesktopEnvironmentTest::IpcDesktopEnvironmentTest() |
157 : message_loop_(MessageLoop::TYPE_UI), | 199 : message_loop_(MessageLoop::TYPE_UI), |
158 connector_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 200 clipboard_stub_(NULL), |
| 201 remote_event_executor_(NULL), |
| 202 terminal_id_(-1) { |
159 } | 203 } |
160 | 204 |
161 IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() { | 205 IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() { |
162 } | 206 } |
163 | 207 |
164 void IpcDesktopEnvironmentTest::SetUp() { | 208 void IpcDesktopEnvironmentTest::SetUp() { |
165 // Arrange to run |message_loop_| until no components depend on it. | 209 // Arrange to run |message_loop_| until no components depend on it. |
166 task_runner_ = new AutoThreadTaskRunner( | 210 task_runner_ = new AutoThreadTaskRunner( |
167 message_loop_.message_loop_proxy(), main_run_loop_.QuitClosure()); | 211 message_loop_.message_loop_proxy(), main_run_loop_.QuitClosure()); |
168 | 212 |
169 scoped_refptr<AutoThreadTaskRunner> io_task_runner = | 213 io_task_runner_ = AutoThread::CreateWithType("IPC thread", task_runner_, |
170 AutoThread::CreateWithType("IPC thread", task_runner_, | 214 MessageLoop::TYPE_IO); |
171 MessageLoop::TYPE_IO); | 215 |
| 216 setup_run_loop_.reset(new base::RunLoop()); |
172 | 217 |
173 // Set expectation that the DaemonProcess will send DesktopAttached message | 218 // Set expectation that the DaemonProcess will send DesktopAttached message |
174 // once it is ready. | 219 // once it is ready. |
175 EXPECT_CALL(daemon_listener_, OnChannelConnected(_)); | 220 EXPECT_CALL(desktop_listener_, OnChannelConnected(_)) |
176 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_)) | 221 .Times(AnyNumber()); |
177 .WillOnce(Invoke(this, &IpcDesktopEnvironmentTest::OnDesktopAttached)); | 222 EXPECT_CALL(desktop_listener_, OnDesktopAttached(_)) |
178 EXPECT_CALL(daemon_listener_, OnChannelError()) | 223 .Times(AnyNumber()) |
| 224 .WillRepeatedly(Invoke(this, |
| 225 &IpcDesktopEnvironmentTest::OnDesktopAttached)); |
| 226 EXPECT_CALL(desktop_listener_, OnChannelError()) |
179 .Times(AnyNumber()) | 227 .Times(AnyNumber()) |
180 .WillOnce(Invoke(this, | 228 .WillOnce(Invoke(this, |
181 &IpcDesktopEnvironmentTest::OnDesktopSessionClosed)); | 229 &IpcDesktopEnvironmentTest::DestoyDesktopProcess)); |
182 | 230 |
183 // Create the daemon end of the daemon-to-desktop channel. | 231 // Intercept requests to connect and disconnect a terminal. |
184 daemon_channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID(); | 232 EXPECT_CALL(daemon_channel_, ConnectTerminal(_)) |
185 daemon_channel_.reset(new IPC::ChannelProxy( | 233 .Times(AnyNumber()) |
186 IPC::ChannelHandle(daemon_channel_name_), | 234 .WillRepeatedly(Invoke(this, |
187 IPC::Channel::MODE_SERVER, | 235 &IpcDesktopEnvironmentTest::ConnectTerminal)); |
188 &daemon_listener_, | 236 EXPECT_CALL(daemon_channel_, DisconnectTerminal(_)) |
189 io_task_runner)); | 237 .Times(AnyNumber()) |
| 238 .WillRepeatedly(Invoke(this, |
| 239 &IpcDesktopEnvironmentTest::DisconnectTerminal)); |
190 | 240 |
191 // Create an IpcDesktopEnvironment instance. | 241 // Create a desktop environment instance. |
192 desktop_environment_.reset(new IpcDesktopEnvironment( | 242 desktop_environment_factory_.reset(new IpcDesktopEnvironmentFactory( |
193 task_runner_, io_task_runner, "user@domain/rest-of-jid", | 243 task_runner_, io_task_runner_, &daemon_channel_)); |
| 244 desktop_environment_ = desktop_environment_factory_->Create( |
| 245 "user@domain/rest-of-jid", |
194 base::Bind(&IpcDesktopEnvironmentTest::OnDisconnectCallback, | 246 base::Bind(&IpcDesktopEnvironmentTest::OnDisconnectCallback, |
195 base::Unretained(this)), | 247 base::Unretained(this))); |
196 connector_factory_.GetWeakPtr())); | |
197 | 248 |
198 // Create the event executor. | 249 // Create the event executor. |
199 event_executor_ = | 250 event_executor_ = |
200 desktop_environment_->CreateEventExecutor(task_runner_, task_runner_); | 251 desktop_environment_->CreateEventExecutor(task_runner_, task_runner_); |
201 | 252 |
202 // Create the screen capturer. | 253 // Create the screen capturer. |
203 video_capturer_ = | 254 video_capturer_ = |
204 desktop_environment_->CreateVideoCapturer(task_runner_, task_runner_); | 255 desktop_environment_->CreateVideoCapturer(task_runner_, task_runner_); |
205 } | 256 } |
206 | 257 |
207 void IpcDesktopEnvironmentTest::ConnectTerminal( | 258 void IpcDesktopEnvironmentTest::ConnectTerminal(int terminal_id) { |
208 scoped_refptr<DesktopSessionProxy> desktop_session_proxy) { | 259 EXPECT_NE(terminal_id_, terminal_id); |
209 EXPECT_TRUE(!desktop_process_); | |
210 EXPECT_TRUE(!desktop_session_proxy_.get()); | |
211 EXPECT_TRUE(task_runner_.get()); | |
212 | 260 |
213 desktop_session_proxy_ = desktop_session_proxy; | 261 terminal_id_ = terminal_id; |
214 | 262 CreateDesktopProcess(); |
215 // Create and start the desktop process. | |
216 desktop_process_.reset(new DesktopProcess(task_runner_, | |
217 daemon_channel_name_)); | |
218 | |
219 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory( | |
220 new MockDesktopEnvironmentFactory()); | |
221 EXPECT_CALL(*desktop_environment_factory, CreatePtr()) | |
222 .Times(AnyNumber()) | |
223 .WillRepeatedly(Invoke( | |
224 this, &IpcDesktopEnvironmentTest::CreateDesktopEnvironment)); | |
225 EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture()) | |
226 .Times(AnyNumber()) | |
227 .WillRepeatedly(Return(false)); | |
228 | |
229 // TODO(alexeypa): Fix DesktopProcess to use the desktop environment | |
230 // to create the disconnect window instead of directly calling | |
231 // DisconnectWindow::Create(). This will take care of "Uninteresting mock | |
232 // function call" warnings printed when DisconnectWindow::Show() and | |
233 // DisconnectWindow::Hide() are called. | |
234 EXPECT_TRUE(desktop_process_->Start( | |
235 desktop_environment_factory.PassAs<DesktopEnvironmentFactory>())); | |
236 } | 263 } |
237 | 264 |
238 void IpcDesktopEnvironmentTest::DisconnectTerminal( | 265 void IpcDesktopEnvironmentTest::DisconnectTerminal(int terminal_id) { |
239 scoped_refptr<DesktopSessionProxy> desktop_session_proxy) { | 266 EXPECT_EQ(terminal_id_, terminal_id); |
240 EXPECT_TRUE(desktop_session_proxy_.get()); | |
241 EXPECT_EQ(desktop_session_proxy_.get(), desktop_session_proxy.get()); | |
242 | 267 |
243 desktop_session_proxy_ = NULL; | 268 // The IPC desktop environment is fully destroyed now. Release the remaining |
244 } | 269 // task runners. |
245 | 270 desktop_environment_factory_.reset(); |
246 void IpcDesktopEnvironmentTest::OnDesktopSessionAgentAttached( | |
247 int terminal_id, | |
248 base::ProcessHandle desktop_process, | |
249 IPC::PlatformFileForTransit desktop_pipe) { | |
250 NOTIMPLEMENTED(); | |
251 } | |
252 | |
253 void IpcDesktopEnvironmentTest::OnTerminalDisconnected(int terminal_id) { | |
254 NOTIMPLEMENTED(); | |
255 } | 271 } |
256 | 272 |
257 DesktopEnvironment* IpcDesktopEnvironmentTest::CreateDesktopEnvironment() { | 273 DesktopEnvironment* IpcDesktopEnvironmentTest::CreateDesktopEnvironment() { |
258 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment(); | 274 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment(); |
259 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr(_)) | 275 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr(_)) |
260 .Times(0); | 276 .Times(0); |
261 EXPECT_CALL(*desktop_environment, CreateEventExecutorPtr(_, _)) | 277 EXPECT_CALL(*desktop_environment, CreateEventExecutorPtr(_, _)) |
262 .Times(AnyNumber()) | 278 .Times(AnyNumber()) |
263 .WillRepeatedly( | 279 .WillRepeatedly( |
264 InvokeWithoutArgs(this, | 280 InvokeWithoutArgs(this, |
265 &IpcDesktopEnvironmentTest::CreateEventExecutor)); | 281 &IpcDesktopEnvironmentTest::CreateEventExecutor)); |
266 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr(_, _)) | 282 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr(_, _)) |
267 .Times(AnyNumber()) | 283 .Times(AnyNumber()) |
268 .WillRepeatedly( | 284 .WillRepeatedly( |
269 InvokeWithoutArgs(this, | 285 InvokeWithoutArgs(this, |
270 &IpcDesktopEnvironmentTest::CreateVideoCapturer)); | 286 &IpcDesktopEnvironmentTest::CreateVideoCapturer)); |
271 | 287 |
| 288 // Let tests know that the remote desktop environment is created. |
| 289 message_loop_.PostTask(FROM_HERE, setup_run_loop_->QuitClosure()); |
| 290 |
272 return desktop_environment; | 291 return desktop_environment; |
273 } | 292 } |
274 | 293 |
275 EventExecutor* IpcDesktopEnvironmentTest::CreateEventExecutor() { | 294 EventExecutor* IpcDesktopEnvironmentTest::CreateEventExecutor() { |
276 MockEventExecutor* event_executor = new MockEventExecutor(); | 295 EXPECT_TRUE(remote_event_executor_ == NULL); |
277 EXPECT_CALL(*event_executor, StartPtr(_)); | 296 remote_event_executor_ = new MockEventExecutor(); |
278 return event_executor; | 297 |
| 298 EXPECT_CALL(*remote_event_executor_, StartPtr(_)); |
| 299 return remote_event_executor_; |
279 } | 300 } |
280 | 301 |
281 media::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() { | 302 media::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() { |
282 return new media::ScreenCapturerFake(); | 303 return new media::ScreenCapturerFake(); |
283 } | 304 } |
284 | 305 |
285 void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() { | 306 void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() { |
286 desktop_environment_.reset(); | |
287 event_executor_.reset(); | 307 event_executor_.reset(); |
288 video_capturer_.reset(); | 308 video_capturer_.reset(); |
| 309 |
| 310 // Trigger DisconnectTerminal(). |
| 311 desktop_environment_.reset(); |
| 312 } |
| 313 |
| 314 void IpcDesktopEnvironmentTest::ReflectClipboardEvent( |
| 315 const protocol::ClipboardEvent& event) { |
| 316 clipboard_stub_->InjectClipboardEvent(event); |
| 317 } |
| 318 |
| 319 void IpcDesktopEnvironmentTest::CreateDesktopProcess() { |
| 320 EXPECT_TRUE(task_runner_); |
| 321 EXPECT_TRUE(io_task_runner_); |
| 322 |
| 323 // Create the daemon end of the daemon-to-desktop channel. |
| 324 desktop_channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID(); |
| 325 desktop_channel_.reset(new IPC::ChannelProxy( |
| 326 IPC::ChannelHandle(desktop_channel_name_), |
| 327 IPC::Channel::MODE_SERVER, |
| 328 &desktop_listener_, |
| 329 io_task_runner_)); |
| 330 |
| 331 // Create and start the desktop process. |
| 332 desktop_process_.reset(new DesktopProcess(task_runner_, |
| 333 desktop_channel_name_)); |
| 334 |
| 335 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory( |
| 336 new MockDesktopEnvironmentFactory()); |
| 337 EXPECT_CALL(*desktop_environment_factory, CreatePtr()) |
| 338 .Times(AnyNumber()) |
| 339 .WillRepeatedly(Invoke( |
| 340 this, &IpcDesktopEnvironmentTest::CreateDesktopEnvironment)); |
| 341 EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture()) |
| 342 .Times(AnyNumber()) |
| 343 .WillRepeatedly(Return(false)); |
| 344 |
| 345 // TODO(alexeypa): Fix DesktopProcess to use the desktop environment |
| 346 // to create the disconnect window instead of directly calling |
| 347 // DisconnectWindow::Create(). This will take care of "Uninteresting mock |
| 348 // function call" warnings printed when DisconnectWindow::Show() and |
| 349 // DisconnectWindow::Hide() are called. |
| 350 EXPECT_TRUE(desktop_process_->Start( |
| 351 desktop_environment_factory.PassAs<DesktopEnvironmentFactory>())); |
| 352 } |
| 353 |
| 354 void IpcDesktopEnvironmentTest::DestoyDesktopProcess() { |
| 355 desktop_channel_.reset(); |
| 356 if (desktop_process_) { |
| 357 desktop_process_->OnChannelError(); |
| 358 desktop_process_.reset(); |
| 359 } |
| 360 remote_event_executor_ = NULL; |
289 } | 361 } |
290 | 362 |
291 void IpcDesktopEnvironmentTest::OnDisconnectCallback() { | 363 void IpcDesktopEnvironmentTest::OnDisconnectCallback() { |
292 NOTIMPLEMENTED(); | 364 DeleteDesktopEnvironment(); |
293 } | 365 } |
294 | 366 |
295 void IpcDesktopEnvironmentTest::OnDesktopAttached( | 367 void IpcDesktopEnvironmentTest::OnDesktopAttached( |
296 IPC::PlatformFileForTransit desktop_pipe) { | 368 IPC::PlatformFileForTransit desktop_pipe) { |
| 369 |
297 // Instruct DesktopSessionProxy to connect to the network-to-desktop pipe. | 370 // Instruct DesktopSessionProxy to connect to the network-to-desktop pipe. |
298 EXPECT_TRUE(desktop_session_proxy_->AttachToDesktop( | 371 desktop_environment_factory_->OnDesktopSessionAgentAttached( |
299 base::GetCurrentProcessHandle(), desktop_pipe)); | 372 terminal_id_, base::GetCurrentProcessHandle(), desktop_pipe); |
300 | |
301 // Let the test know that |desktop_session_proxy_| is attahced to the desktop. | |
302 setup_run_loop_.Quit(); | |
303 } | 373 } |
304 | 374 |
305 void IpcDesktopEnvironmentTest::OnDesktopSessionClosed() { | 375 // Runs until the desktop is attached and exits immediately after that. |
306 daemon_channel_.reset(); | |
307 desktop_process_.reset(); | |
308 } | |
309 | |
310 TEST_F(IpcDesktopEnvironmentTest, Basic) { | 376 TEST_F(IpcDesktopEnvironmentTest, Basic) { |
311 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( | 377 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
312 new protocol::MockClipboardStub()); | 378 new protocol::MockClipboardStub()); |
313 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) | 379 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
| 380 .Times(0); |
| 381 |
| 382 // Start the event executor and screen capturer. |
| 383 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
| 384 |
| 385 // Run the message loop until the desktop is attached. |
| 386 setup_run_loop_->Run(); |
| 387 |
| 388 // Event executor should receive no events. |
| 389 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 390 .Times(0); |
| 391 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 392 .Times(0); |
| 393 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 394 .Times(0); |
| 395 |
| 396 // Stop the test. |
| 397 DeleteDesktopEnvironment(); |
| 398 |
| 399 task_runner_ = NULL; |
| 400 io_task_runner_ = NULL; |
| 401 main_run_loop_.Run(); |
| 402 } |
| 403 |
| 404 // Tests that the video capturer receives a frame over IPC. |
| 405 TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) { |
| 406 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
| 407 new protocol::MockClipboardStub()); |
| 408 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
| 409 .Times(0); |
| 410 |
| 411 // Start the event executor and screen capturer. |
| 412 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
| 413 video_capturer_->Start(&screen_capturer_delegate_); |
| 414 |
| 415 // Run the message loop until the desktop is attached. |
| 416 setup_run_loop_->Run(); |
| 417 |
| 418 // Event executor should receive no events. |
| 419 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 420 .Times(0); |
| 421 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 422 .Times(0); |
| 423 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 424 .Times(0); |
| 425 |
| 426 // Stop the test when the first frame is captured. |
| 427 EXPECT_CALL(screen_capturer_delegate_, OnCaptureCompleted(_)) |
| 428 .WillOnce(InvokeWithoutArgs( |
| 429 this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); |
| 430 |
| 431 // Capture a single frame. |
| 432 video_capturer_->CaptureFrame(); |
| 433 |
| 434 task_runner_ = NULL; |
| 435 io_task_runner_ = NULL; |
| 436 main_run_loop_.Run(); |
| 437 } |
| 438 |
| 439 // Tests that attaching to a new desktop works. |
| 440 TEST_F(IpcDesktopEnvironmentTest, Reattach) { |
| 441 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
| 442 new protocol::MockClipboardStub()); |
| 443 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
314 .Times(0); | 444 .Times(0); |
315 | 445 |
316 // Start the event executor and screen capturer. | 446 // Start the event executor and screen capturer. |
317 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); | 447 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
318 video_capturer_->Start(&screen_capturer_delegate_); | 448 video_capturer_->Start(&screen_capturer_delegate_); |
319 | 449 |
320 // Run the message loop until the desktop is attached. | 450 // Run the message loop until the desktop is attached. |
321 setup_run_loop_.Run(); | 451 setup_run_loop_->Run(); |
| 452 |
| 453 // Create and start a new desktop process object. |
| 454 setup_run_loop_.reset(new base::RunLoop()); |
| 455 DestoyDesktopProcess(); |
| 456 CreateDesktopProcess(); |
| 457 setup_run_loop_->Run(); |
| 458 |
| 459 // Event executor should receive no events. |
| 460 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 461 .Times(0); |
| 462 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 463 .Times(0); |
| 464 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 465 .Times(0); |
322 | 466 |
323 // Stop the test. | 467 // Stop the test. |
324 DeleteDesktopEnvironment(); | 468 DeleteDesktopEnvironment(); |
325 | 469 |
326 task_runner_ = NULL; | 470 task_runner_ = NULL; |
| 471 io_task_runner_ = NULL; |
327 main_run_loop_.Run(); | 472 main_run_loop_.Run(); |
328 } | 473 } |
329 | 474 |
330 TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) { | 475 // Tests InvalidateRegion(). |
| 476 TEST_F(IpcDesktopEnvironmentTest, InvalidateRegion) { |
331 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( | 477 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
332 new protocol::MockClipboardStub()); | 478 new protocol::MockClipboardStub()); |
333 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) | 479 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
334 .Times(0); | 480 .Times(0); |
335 | 481 |
336 // Start the event executor and screen capturer. | 482 // Start the event executor and screen capturer. |
337 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); | 483 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
338 video_capturer_->Start(&screen_capturer_delegate_); | 484 video_capturer_->Start(&screen_capturer_delegate_); |
339 | 485 |
340 // Run the message loop until the desktop is attached. | 486 // Run the message loop until the desktop is attached. |
341 setup_run_loop_.Run(); | 487 setup_run_loop_->Run(); |
| 488 |
| 489 // Event executor should receive no events. |
| 490 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 491 .Times(0); |
| 492 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 493 .Times(0); |
| 494 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 495 .Times(0); |
342 | 496 |
343 // Stop the test when the first frame is captured. | 497 // Stop the test when the first frame is captured. |
344 EXPECT_CALL(screen_capturer_delegate_, OnCaptureCompleted(_)) | 498 EXPECT_CALL(screen_capturer_delegate_, OnCaptureCompleted(_)) |
345 .WillOnce(InvokeWithoutArgs( | 499 .WillOnce(InvokeWithoutArgs( |
346 this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); | 500 this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); |
347 | 501 |
| 502 // Invalidate a region that is larger than the screen. |
| 503 SkIRect horizontal_rect = SkIRect::MakeXYWH( |
| 504 -100, |
| 505 media::ScreenCapturerFake::kHeight / 4, |
| 506 media::ScreenCapturerFake::kWidth + 200, |
| 507 media::ScreenCapturerFake::kHeight / 2); |
| 508 SkIRect vertical_rect = SkIRect::MakeXYWH( |
| 509 media::ScreenCapturerFake::kWidth / 4, |
| 510 -100, |
| 511 media::ScreenCapturerFake::kWidth / 2, |
| 512 media::ScreenCapturerFake::kHeight + 200); |
| 513 |
| 514 SkRegion invalid_region; |
| 515 invalid_region.op(horizontal_rect, SkRegion::kUnion_Op); |
| 516 invalid_region.op(vertical_rect, SkRegion::kUnion_Op); |
| 517 video_capturer_->InvalidateRegion(invalid_region); |
| 518 |
348 // Capture a single frame. | 519 // Capture a single frame. |
349 video_capturer_->CaptureFrame(); | 520 video_capturer_->CaptureFrame(); |
350 | 521 |
351 task_runner_ = NULL; | 522 task_runner_ = NULL; |
| 523 io_task_runner_ = NULL; |
352 main_run_loop_.Run(); | 524 main_run_loop_.Run(); |
353 } | 525 } |
354 | 526 |
| 527 // Tests injection of clipboard events. |
| 528 TEST_F(IpcDesktopEnvironmentTest, InjectClipboardEvent) { |
| 529 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
| 530 new protocol::MockClipboardStub()); |
| 531 clipboard_stub_ = clipboard_stub.get(); |
| 532 |
| 533 // Stop the test when a clipboard event is received from the desktop process. |
| 534 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
| 535 .Times(1) |
| 536 .WillOnce(InvokeWithoutArgs( |
| 537 this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); |
| 538 |
| 539 // Start the event executor and screen capturer. |
| 540 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
| 541 video_capturer_->Start(&screen_capturer_delegate_); |
| 542 |
| 543 // Run the message loop until the desktop is attached. |
| 544 setup_run_loop_->Run(); |
| 545 |
| 546 // Expect a single clipboard event. |
| 547 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 548 .Times(1) |
| 549 .WillOnce(Invoke(this, |
| 550 &IpcDesktopEnvironmentTest::ReflectClipboardEvent)); |
| 551 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 552 .Times(0); |
| 553 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 554 .Times(0); |
| 555 |
| 556 // Send a clipboard event. |
| 557 protocol::ClipboardEvent event; |
| 558 event.set_mime_type(kMimeTypeTextUtf8); |
| 559 event.set_data("a"); |
| 560 event_executor_->InjectClipboardEvent(event); |
| 561 |
| 562 task_runner_ = NULL; |
| 563 io_task_runner_ = NULL; |
| 564 main_run_loop_.Run(); |
| 565 } |
| 566 |
| 567 // Tests injection of key events. |
| 568 TEST_F(IpcDesktopEnvironmentTest, InjectKeyEvent) { |
| 569 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
| 570 new protocol::MockClipboardStub()); |
| 571 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
| 572 .Times(0); |
| 573 |
| 574 // Start the event executor and screen capturer. |
| 575 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
| 576 video_capturer_->Start(&screen_capturer_delegate_); |
| 577 |
| 578 // Run the message loop until the desktop is attached. |
| 579 setup_run_loop_->Run(); |
| 580 |
| 581 // Expect a single key event. |
| 582 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 583 .Times(0); |
| 584 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 585 .Times(AtLeast(1)) |
| 586 .WillRepeatedly(InvokeWithoutArgs( |
| 587 this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); |
| 588 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 589 .Times(0); |
| 590 |
| 591 // Send a key event. |
| 592 protocol::KeyEvent event; |
| 593 event.set_usb_keycode(0x070004); |
| 594 event.set_pressed(true); |
| 595 event_executor_->InjectKeyEvent(event); |
| 596 |
| 597 task_runner_ = NULL; |
| 598 io_task_runner_ = NULL; |
| 599 main_run_loop_.Run(); |
| 600 } |
| 601 |
| 602 // Tests injection of mouse events. |
| 603 TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) { |
| 604 scoped_ptr<protocol::MockClipboardStub> clipboard_stub( |
| 605 new protocol::MockClipboardStub()); |
| 606 EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_)) |
| 607 .Times(0); |
| 608 |
| 609 // Start the event executor and screen capturer. |
| 610 event_executor_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>()); |
| 611 video_capturer_->Start(&screen_capturer_delegate_); |
| 612 |
| 613 // Run the message loop until the desktop is attached. |
| 614 setup_run_loop_->Run(); |
| 615 |
| 616 // Expect a single mouse event. |
| 617 EXPECT_CALL(*remote_event_executor_, InjectClipboardEvent(_)) |
| 618 .Times(0); |
| 619 EXPECT_CALL(*remote_event_executor_, InjectKeyEvent(_)) |
| 620 .Times(0); |
| 621 EXPECT_CALL(*remote_event_executor_, InjectMouseEvent(_)) |
| 622 .Times(1) |
| 623 .WillOnce(InvokeWithoutArgs( |
| 624 this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); |
| 625 |
| 626 // Send a mouse event. |
| 627 protocol::MouseEvent event; |
| 628 event.set_x(0); |
| 629 event.set_y(0); |
| 630 event_executor_->InjectMouseEvent(event); |
| 631 |
| 632 task_runner_ = NULL; |
| 633 io_task_runner_ = NULL; |
| 634 main_run_loop_.Run(); |
| 635 } |
| 636 |
355 } // namespace remoting | 637 } // namespace remoting |
OLD | NEW |