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 "remoting/host/desktop_session_proxy.h" | 5 #include "remoting/host/desktop_session_proxy.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/platform_file.h" | 9 #include "base/platform_file.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
11 #include "ipc/ipc_channel_proxy.h" | 11 #include "ipc/ipc_channel_proxy.h" |
12 #include "ipc/ipc_message_macros.h" | 12 #include "ipc/ipc_message_macros.h" |
13 #include "remoting/capturer/capture_data.h" | 13 #include "remoting/capturer/capture_data.h" |
14 #include "remoting/host/audio_capturer.h" | 14 #include "remoting/host/audio_capturer.h" |
15 #include "remoting/host/chromoting_messages.h" | 15 #include "remoting/host/chromoting_messages.h" |
16 #include "remoting/host/client_session.h" | 16 #include "remoting/host/client_session.h" |
17 #include "remoting/host/ipc_audio_capturer.h" | 17 #include "remoting/host/ipc_audio_capturer.h" |
| 18 #include "remoting/host/ipc_event_executor.h" |
18 #include "remoting/host/ipc_video_frame_capturer.h" | 19 #include "remoting/host/ipc_video_frame_capturer.h" |
19 #include "remoting/proto/audio.pb.h" | 20 #include "remoting/proto/audio.pb.h" |
20 #include "remoting/proto/control.pb.h" | 21 #include "remoting/proto/control.pb.h" |
21 #include "remoting/proto/event.pb.h" | 22 #include "remoting/proto/event.pb.h" |
22 | 23 |
23 #if defined(OS_WIN) | 24 #if defined(OS_WIN) |
24 #include "base/win/scoped_handle.h" | 25 #include "base/win/scoped_handle.h" |
25 #endif // defined(OS_WIN) | 26 #endif // defined(OS_WIN) |
26 | 27 |
27 namespace remoting { | 28 namespace remoting { |
28 | 29 |
29 DesktopSessionProxy::DesktopSessionProxy( | 30 DesktopSessionProxy::DesktopSessionProxy( |
30 scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner, | |
31 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 31 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
32 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner) | 32 const std::string& client_jid, |
33 : audio_capture_task_runner_(audio_capture_task_runner), | 33 const base::Closure& disconnect_callback) |
34 caller_task_runner_(caller_task_runner), | 34 : caller_task_runner_(caller_task_runner), |
35 video_capture_task_runner_(video_capture_task_runner), | 35 client_jid_(client_jid), |
| 36 disconnect_callback_(disconnect_callback), |
36 audio_capturer_(NULL), | 37 audio_capturer_(NULL), |
37 pending_capture_frame_requests_(0), | 38 pending_capture_frame_requests_(0), |
38 video_capturer_(NULL) { | 39 video_capturer_(NULL) { |
39 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 40 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 41 DCHECK(!client_jid_.empty()); |
| 42 DCHECK(!disconnect_callback_.is_null()); |
| 43 } |
| 44 |
| 45 scoped_ptr<AudioCapturer> DesktopSessionProxy::CreateAudioCapturer( |
| 46 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner) { |
| 47 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 48 DCHECK(!audio_capture_task_runner_.get()); |
| 49 |
| 50 audio_capture_task_runner_ = audio_task_runner; |
| 51 return scoped_ptr<AudioCapturer>(new IpcAudioCapturer(this)); |
| 52 } |
| 53 |
| 54 scoped_ptr<EventExecutor> DesktopSessionProxy::CreateEventExecutor( |
| 55 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, |
| 56 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
| 57 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 58 |
| 59 return scoped_ptr<EventExecutor>(new IpcEventExecutor(this)); |
| 60 } |
| 61 |
| 62 scoped_ptr<VideoFrameCapturer> DesktopSessionProxy::CreateVideoCapturer( |
| 63 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, |
| 64 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { |
| 65 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 66 DCHECK(!video_capture_task_runner_.get()); |
| 67 |
| 68 video_capture_task_runner_ = capture_task_runner; |
| 69 return scoped_ptr<VideoFrameCapturer>(new IpcVideoFrameCapturer(this)); |
40 } | 70 } |
41 | 71 |
42 bool DesktopSessionProxy::OnMessageReceived(const IPC::Message& message) { | 72 bool DesktopSessionProxy::OnMessageReceived(const IPC::Message& message) { |
43 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 73 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
44 | 74 |
45 bool handled = true; | 75 bool handled = true; |
46 IPC_BEGIN_MESSAGE_MAP(DesktopSessionProxy, message) | 76 IPC_BEGIN_MESSAGE_MAP(DesktopSessionProxy, message) |
47 IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_AudioPacket, | 77 IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_AudioPacket, |
48 OnAudioPacket) | 78 OnAudioPacket) |
49 IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CaptureCompleted, | 79 IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CaptureCompleted, |
(...skipping 18 matching lines...) Expand all Loading... |
68 | 98 |
69 VLOG(1) << "IPC: network <- desktop (" << peer_pid << ")"; | 99 VLOG(1) << "IPC: network <- desktop (" << peer_pid << ")"; |
70 } | 100 } |
71 | 101 |
72 void DesktopSessionProxy::OnChannelError() { | 102 void DesktopSessionProxy::OnChannelError() { |
73 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 103 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
74 | 104 |
75 DetachFromDesktop(); | 105 DetachFromDesktop(); |
76 } | 106 } |
77 | 107 |
78 void DesktopSessionProxy::Initialize(const std::string& client_jid, | |
79 const base::Closure& disconnect_callback) { | |
80 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | |
81 DCHECK(client_jid_.empty()); | |
82 DCHECK(!client_jid.empty()); | |
83 DCHECK(disconnect_callback_.is_null()); | |
84 DCHECK(!disconnect_callback.is_null()); | |
85 | |
86 client_jid_ = client_jid; | |
87 disconnect_callback_ = disconnect_callback; | |
88 } | |
89 | |
90 bool DesktopSessionProxy::AttachToDesktop( | 108 bool DesktopSessionProxy::AttachToDesktop( |
91 IPC::PlatformFileForTransit desktop_process, | 109 IPC::PlatformFileForTransit desktop_process, |
92 IPC::PlatformFileForTransit desktop_pipe) { | 110 IPC::PlatformFileForTransit desktop_pipe) { |
93 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 111 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
94 DCHECK(!client_jid_.empty()); | 112 DCHECK(!client_jid_.empty()); |
95 DCHECK(!desktop_channel_); | 113 DCHECK(!desktop_channel_); |
96 DCHECK(!disconnect_callback_.is_null()); | 114 DCHECK(!disconnect_callback_.is_null()); |
97 | 115 |
98 #if defined(OS_WIN) | 116 #if defined(OS_WIN) |
99 // On Windows: |desktop_process| is a valid handle, but |desktop_pipe| needs | 117 // On Windows: |desktop_process| is a valid handle, but |desktop_pipe| needs |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 | 166 |
149 shared_buffers_.clear(); | 167 shared_buffers_.clear(); |
150 | 168 |
151 // Generate fake responses to keep the video capturer in sync. | 169 // Generate fake responses to keep the video capturer in sync. |
152 while (pending_capture_frame_requests_) { | 170 while (pending_capture_frame_requests_) { |
153 --pending_capture_frame_requests_; | 171 --pending_capture_frame_requests_; |
154 PostCaptureCompleted(scoped_refptr<CaptureData>()); | 172 PostCaptureCompleted(scoped_refptr<CaptureData>()); |
155 } | 173 } |
156 } | 174 } |
157 | 175 |
| 176 void DesktopSessionProxy::StartAudioCapturer(IpcAudioCapturer* audio_capturer) { |
| 177 DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); |
| 178 DCHECK(audio_capturer_ == NULL); |
| 179 |
| 180 audio_capturer_ = audio_capturer; |
| 181 } |
| 182 |
| 183 void DesktopSessionProxy::StopAudioCapturer() { |
| 184 DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); |
| 185 |
| 186 audio_capturer_ = NULL; |
| 187 } |
| 188 |
| 189 void DesktopSessionProxy::InvalidateRegion(const SkRegion& invalid_region) { |
| 190 if (!caller_task_runner_->BelongsToCurrentThread()) { |
| 191 caller_task_runner_->PostTask( |
| 192 FROM_HERE, base::Bind(&DesktopSessionProxy::InvalidateRegion, this, |
| 193 invalid_region)); |
| 194 return; |
| 195 } |
| 196 |
| 197 std::vector<SkIRect> invalid_rects; |
| 198 for (SkRegion::Iterator i(invalid_region); !i.done(); i.next()) |
| 199 invalid_rects.push_back(i.rect()); |
| 200 |
| 201 SendToDesktop( |
| 202 new ChromotingNetworkDesktopMsg_InvalidateRegion(invalid_rects)); |
| 203 } |
| 204 |
| 205 void DesktopSessionProxy::CaptureFrame() { |
| 206 if (!caller_task_runner_->BelongsToCurrentThread()) { |
| 207 caller_task_runner_->PostTask( |
| 208 FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this)); |
| 209 return; |
| 210 } |
| 211 |
| 212 ++pending_capture_frame_requests_; |
| 213 SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame()); |
| 214 } |
| 215 |
| 216 void DesktopSessionProxy::StartVideoCapturer( |
| 217 IpcVideoFrameCapturer* video_capturer) { |
| 218 DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); |
| 219 DCHECK(video_capturer_ == NULL); |
| 220 |
| 221 video_capturer_ = video_capturer; |
| 222 } |
| 223 |
| 224 void DesktopSessionProxy::StopVideoCapturer() { |
| 225 DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); |
| 226 |
| 227 video_capturer_ = NULL; |
| 228 } |
| 229 |
158 void DesktopSessionProxy::DisconnectSession() { | 230 void DesktopSessionProxy::DisconnectSession() { |
159 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 231 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
160 | 232 |
161 // Disconnect the client session if it hasn't been disconnected yet. | 233 // Disconnect the client session if it hasn't been disconnected yet. |
162 disconnect_callback_.Run(); | 234 disconnect_callback_.Run(); |
163 } | 235 } |
164 | 236 |
165 void DesktopSessionProxy::InjectClipboardEvent( | 237 void DesktopSessionProxy::InjectClipboardEvent( |
166 const protocol::ClipboardEvent& event) { | 238 const protocol::ClipboardEvent& event) { |
167 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 239 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 new ChromotingNetworkDesktopMsg_InjectMouseEvent(serialized_event)); | 274 new ChromotingNetworkDesktopMsg_InjectMouseEvent(serialized_event)); |
203 } | 275 } |
204 | 276 |
205 void DesktopSessionProxy::StartEventExecutor( | 277 void DesktopSessionProxy::StartEventExecutor( |
206 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 278 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
207 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 279 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
208 | 280 |
209 client_clipboard_ = client_clipboard.Pass(); | 281 client_clipboard_ = client_clipboard.Pass(); |
210 } | 282 } |
211 | 283 |
212 void DesktopSessionProxy::InvalidateRegion(const SkRegion& invalid_region) { | |
213 if (!caller_task_runner_->BelongsToCurrentThread()) { | |
214 caller_task_runner_->PostTask( | |
215 FROM_HERE, base::Bind(&DesktopSessionProxy::InvalidateRegion, this, | |
216 invalid_region)); | |
217 return; | |
218 } | |
219 | |
220 std::vector<SkIRect> invalid_rects; | |
221 for (SkRegion::Iterator i(invalid_region); !i.done(); i.next()) | |
222 invalid_rects.push_back(i.rect()); | |
223 | |
224 SendToDesktop( | |
225 new ChromotingNetworkDesktopMsg_InvalidateRegion(invalid_rects)); | |
226 } | |
227 | |
228 void DesktopSessionProxy::CaptureFrame() { | |
229 if (!caller_task_runner_->BelongsToCurrentThread()) { | |
230 caller_task_runner_->PostTask( | |
231 FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this)); | |
232 return; | |
233 } | |
234 | |
235 ++pending_capture_frame_requests_; | |
236 SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame()); | |
237 } | |
238 | |
239 void DesktopSessionProxy::StartAudioCapturer(IpcAudioCapturer* audio_capturer) { | |
240 DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); | |
241 DCHECK(audio_capturer_ == NULL); | |
242 | |
243 audio_capturer_ = audio_capturer; | |
244 } | |
245 | |
246 void DesktopSessionProxy::StopAudioCapturer() { | |
247 DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); | |
248 | |
249 audio_capturer_ = NULL; | |
250 } | |
251 | |
252 void DesktopSessionProxy::StartVideoCapturer( | |
253 IpcVideoFrameCapturer* video_capturer) { | |
254 DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); | |
255 DCHECK(video_capturer_ == NULL); | |
256 | |
257 video_capturer_ = video_capturer; | |
258 } | |
259 | |
260 void DesktopSessionProxy::StopVideoCapturer() { | |
261 DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); | |
262 | |
263 video_capturer_ = NULL; | |
264 } | |
265 | |
266 DesktopSessionProxy::~DesktopSessionProxy() { | 284 DesktopSessionProxy::~DesktopSessionProxy() { |
267 } | 285 } |
268 | 286 |
269 scoped_refptr<SharedBuffer> DesktopSessionProxy::GetSharedBuffer(int id) { | 287 scoped_refptr<SharedBuffer> DesktopSessionProxy::GetSharedBuffer(int id) { |
270 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 288 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
271 | 289 |
272 SharedBuffers::const_iterator i = shared_buffers_.find(id); | 290 SharedBuffers::const_iterator i = shared_buffers_.find(id); |
273 if (i != shared_buffers_.end()) { | 291 if (i != shared_buffers_.end()) { |
274 return i->second; | 292 return i->second; |
275 } else { | 293 } else { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 const MouseCursorShape& cursor_shape) { | 391 const MouseCursorShape& cursor_shape) { |
374 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 392 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
375 PostCursorShape( | 393 PostCursorShape( |
376 scoped_ptr<MouseCursorShape>(new MouseCursorShape(cursor_shape))); | 394 scoped_ptr<MouseCursorShape>(new MouseCursorShape(cursor_shape))); |
377 } | 395 } |
378 | 396 |
379 void DesktopSessionProxy::OnInjectClipboardEvent( | 397 void DesktopSessionProxy::OnInjectClipboardEvent( |
380 const std::string& serialized_event) { | 398 const std::string& serialized_event) { |
381 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 399 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
382 | 400 |
383 protocol::ClipboardEvent event; | 401 if (client_clipboard_) { |
384 if (!event.ParseFromString(serialized_event)) { | 402 protocol::ClipboardEvent event; |
385 LOG(ERROR) << "Failed to parse protocol::ClipboardEvent."; | 403 if (!event.ParseFromString(serialized_event)) { |
386 return; | 404 LOG(ERROR) << "Failed to parse protocol::ClipboardEvent."; |
| 405 return; |
| 406 } |
| 407 |
| 408 client_clipboard_->InjectClipboardEvent(event); |
387 } | 409 } |
388 | |
389 client_clipboard_->InjectClipboardEvent(event); | |
390 } | 410 } |
391 | 411 |
392 void DesktopSessionProxy::PostAudioPacket(scoped_ptr<AudioPacket> packet) { | 412 void DesktopSessionProxy::PostAudioPacket(scoped_ptr<AudioPacket> packet) { |
393 if (!audio_capture_task_runner_->BelongsToCurrentThread()) { | 413 if (!audio_capture_task_runner_->BelongsToCurrentThread()) { |
394 audio_capture_task_runner_->PostTask( | 414 audio_capture_task_runner_->PostTask( |
395 FROM_HERE, base::Bind(&DesktopSessionProxy::PostAudioPacket, | 415 FROM_HERE, base::Bind(&DesktopSessionProxy::PostAudioPacket, |
396 this, base::Passed(&packet))); | 416 this, base::Passed(&packet))); |
397 return; | 417 return; |
398 } | 418 } |
399 | 419 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 451 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
432 | 452 |
433 if (desktop_channel_) { | 453 if (desktop_channel_) { |
434 desktop_channel_->Send(message); | 454 desktop_channel_->Send(message); |
435 } else { | 455 } else { |
436 delete message; | 456 delete message; |
437 } | 457 } |
438 } | 458 } |
439 | 459 |
440 } // namespace remoting | 460 } // namespace remoting |
OLD | NEW |