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/process_util.h" | 10 #include "base/process_util.h" |
| 11 #include "base/memory/shared_memory.h" |
11 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
12 #include "ipc/ipc_channel_proxy.h" | 13 #include "ipc/ipc_channel_proxy.h" |
13 #include "ipc/ipc_message_macros.h" | 14 #include "ipc/ipc_message_macros.h" |
14 #include "media/video/capture/screen/screen_capture_data.h" | |
15 #include "remoting/base/capabilities.h" | 15 #include "remoting/base/capabilities.h" |
16 #include "remoting/host/chromoting_messages.h" | 16 #include "remoting/host/chromoting_messages.h" |
17 #include "remoting/host/client_session.h" | 17 #include "remoting/host/client_session.h" |
18 #include "remoting/host/client_session_control.h" | 18 #include "remoting/host/client_session_control.h" |
19 #include "remoting/host/desktop_session_connector.h" | 19 #include "remoting/host/desktop_session_connector.h" |
20 #include "remoting/host/ipc_audio_capturer.h" | 20 #include "remoting/host/ipc_audio_capturer.h" |
21 #include "remoting/host/ipc_input_injector.h" | 21 #include "remoting/host/ipc_input_injector.h" |
22 #include "remoting/host/ipc_screen_controls.h" | 22 #include "remoting/host/ipc_screen_controls.h" |
23 #include "remoting/host/ipc_video_frame_capturer.h" | 23 #include "remoting/host/ipc_video_frame_capturer.h" |
24 #include "remoting/proto/audio.pb.h" | 24 #include "remoting/proto/audio.pb.h" |
25 #include "remoting/proto/control.pb.h" | 25 #include "remoting/proto/control.pb.h" |
26 #include "remoting/proto/event.pb.h" | 26 #include "remoting/proto/event.pb.h" |
| 27 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 28 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" |
| 29 #include "third_party/webrtc/modules/desktop_capture/shared_memory.h" |
27 | 30 |
28 #if defined(OS_WIN) | 31 #if defined(OS_WIN) |
29 #include "base/win/scoped_handle.h" | 32 #include "base/win/scoped_handle.h" |
30 #endif // defined(OS_WIN) | 33 #endif // defined(OS_WIN) |
31 | 34 |
| 35 const bool kReadOnly = true; |
32 const char kSendInitialResolution[] = "sendInitialResolution"; | 36 const char kSendInitialResolution[] = "sendInitialResolution"; |
33 | 37 |
34 namespace remoting { | 38 namespace remoting { |
35 | 39 |
| 40 class DesktopSessionProxy::IpcSharedBufferCore |
| 41 : public base::RefCountedThreadSafe<IpcSharedBufferCore> { |
| 42 public: |
| 43 IpcSharedBufferCore(int id, |
| 44 base::SharedMemoryHandle handle, |
| 45 base::ProcessHandle process, |
| 46 size_t size) |
| 47 : id_(id), |
| 48 #if defined(OS_WIN) |
| 49 shared_memory_(handle, kReadOnly, process), |
| 50 #else // !defined(OS_WIN) |
| 51 shared_memory_(handle, kReadOnly), |
| 52 #endif // !defined(OS_WIN) |
| 53 size_(size) { |
| 54 if (!shared_memory_.Map(size)) { |
| 55 LOG(ERROR) << "Failed to map a shared buffer: id=" << id |
| 56 #if defined(OS_WIN) |
| 57 << ", handle=" << handle |
| 58 #else |
| 59 << ", handle.fd=" << handle.fd |
| 60 #endif |
| 61 << ", size=" << size; |
| 62 } |
| 63 } |
| 64 |
| 65 int id() { return id_; } |
| 66 size_t size() { return size_; } |
| 67 void* memory() { return shared_memory_.memory(); } |
| 68 webrtc::SharedMemory::Handle handle() { |
| 69 #if defined(OS_WIN) |
| 70 return shared_memory_.handle(); |
| 71 #else |
| 72 return shared_memory_.handle().fd; |
| 73 #endif |
| 74 } |
| 75 |
| 76 private: |
| 77 virtual ~IpcSharedBufferCore() {} |
| 78 friend class base::RefCountedThreadSafe<IpcSharedBufferCore>; |
| 79 |
| 80 int id_; |
| 81 base::SharedMemory shared_memory_; |
| 82 size_t size_; |
| 83 |
| 84 DISALLOW_COPY_AND_ASSIGN(IpcSharedBufferCore); |
| 85 }; |
| 86 |
| 87 class DesktopSessionProxy::IpcSharedBuffer : public webrtc::SharedMemory { |
| 88 public: |
| 89 IpcSharedBuffer(scoped_refptr<IpcSharedBufferCore> core) |
| 90 : SharedMemory(core->memory(), core->size(), |
| 91 core->handle(), core->id()), |
| 92 core_(core) { |
| 93 } |
| 94 |
| 95 private: |
| 96 scoped_refptr<IpcSharedBufferCore> core_; |
| 97 |
| 98 DISALLOW_COPY_AND_ASSIGN(IpcSharedBuffer); |
| 99 }; |
| 100 |
36 DesktopSessionProxy::DesktopSessionProxy( | 101 DesktopSessionProxy::DesktopSessionProxy( |
37 scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner, | 102 scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner, |
38 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 103 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
39 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | 104 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
40 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner, | 105 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner, |
41 base::WeakPtr<ClientSessionControl> client_session_control, | 106 base::WeakPtr<ClientSessionControl> client_session_control, |
42 base::WeakPtr<DesktopSessionConnector> desktop_session_connector, | 107 base::WeakPtr<DesktopSessionConnector> desktop_session_connector, |
43 bool virtual_terminal) | 108 bool virtual_terminal) |
44 : audio_capture_task_runner_(audio_capture_task_runner), | 109 : audio_capture_task_runner_(audio_capture_task_runner), |
45 caller_task_runner_(caller_task_runner), | 110 caller_task_runner_(caller_task_runner), |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 if (desktop_process_ != base::kNullProcessHandle) { | 273 if (desktop_process_ != base::kNullProcessHandle) { |
209 base::CloseProcessHandle(desktop_process_); | 274 base::CloseProcessHandle(desktop_process_); |
210 desktop_process_ = base::kNullProcessHandle; | 275 desktop_process_ = base::kNullProcessHandle; |
211 } | 276 } |
212 | 277 |
213 shared_buffers_.clear(); | 278 shared_buffers_.clear(); |
214 | 279 |
215 // Generate fake responses to keep the video capturer in sync. | 280 // Generate fake responses to keep the video capturer in sync. |
216 while (pending_capture_frame_requests_) { | 281 while (pending_capture_frame_requests_) { |
217 --pending_capture_frame_requests_; | 282 --pending_capture_frame_requests_; |
218 PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>()); | 283 PostCaptureCompleted(scoped_ptr<webrtc::DesktopFrame>()); |
219 } | 284 } |
220 } | 285 } |
221 | 286 |
222 void DesktopSessionProxy::SetAudioCapturer( | 287 void DesktopSessionProxy::SetAudioCapturer( |
223 const base::WeakPtr<IpcAudioCapturer>& audio_capturer) { | 288 const base::WeakPtr<IpcAudioCapturer>& audio_capturer) { |
224 DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); | 289 DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); |
225 | 290 |
226 audio_capturer_ = audio_capturer; | 291 audio_capturer_ = audio_capturer; |
227 } | 292 } |
228 | 293 |
229 void DesktopSessionProxy::CaptureFrame() { | 294 void DesktopSessionProxy::CaptureFrame() { |
230 if (!caller_task_runner_->BelongsToCurrentThread()) { | 295 if (!caller_task_runner_->BelongsToCurrentThread()) { |
231 caller_task_runner_->PostTask( | 296 caller_task_runner_->PostTask( |
232 FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this)); | 297 FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this)); |
233 return; | 298 return; |
234 } | 299 } |
235 | 300 |
236 if (desktop_channel_) { | 301 if (desktop_channel_) { |
237 ++pending_capture_frame_requests_; | 302 ++pending_capture_frame_requests_; |
238 SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame()); | 303 SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame()); |
239 } else { | 304 } else { |
240 PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>()); | 305 PostCaptureCompleted(scoped_ptr<webrtc::DesktopFrame>()); |
241 } | 306 } |
242 } | 307 } |
243 | 308 |
244 void DesktopSessionProxy::SetVideoCapturer( | 309 void DesktopSessionProxy::SetVideoCapturer( |
245 const base::WeakPtr<IpcVideoFrameCapturer> video_capturer) { | 310 const base::WeakPtr<IpcVideoFrameCapturer> video_capturer) { |
246 DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); | 311 DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); |
247 | 312 |
248 video_capturer_ = video_capturer; | 313 video_capturer_ = video_capturer; |
249 } | 314 } |
250 | 315 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 365 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
301 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 366 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
302 | 367 |
303 client_clipboard_ = client_clipboard.Pass(); | 368 client_clipboard_ = client_clipboard.Pass(); |
304 } | 369 } |
305 | 370 |
306 void DesktopSessionProxy::SetScreenResolution( | 371 void DesktopSessionProxy::SetScreenResolution( |
307 const ScreenResolution& resolution) { | 372 const ScreenResolution& resolution) { |
308 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 373 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
309 | 374 |
310 if (!resolution.IsValid()) | 375 if (!resolution.IsEmpty()) |
311 return; | 376 return; |
312 | 377 |
313 screen_resolution_ = resolution; | 378 screen_resolution_ = resolution; |
314 | 379 |
315 // Connect to the desktop session if it is not done yet. | 380 // Connect to the desktop session if it is not done yet. |
316 if (!is_desktop_session_connected_) { | 381 if (!is_desktop_session_connected_) { |
317 is_desktop_session_connected_ = true; | 382 is_desktop_session_connected_ = true; |
318 if (desktop_session_connector_) { | 383 if (desktop_session_connector_) { |
319 desktop_session_connector_->ConnectTerminal(this, screen_resolution_, | 384 desktop_session_connector_->ConnectTerminal(this, screen_resolution_, |
320 virtual_terminal_); | 385 virtual_terminal_); |
(...skipping 16 matching lines...) Expand all Loading... |
337 | 402 |
338 if (desktop_session_connector_ && is_desktop_session_connected_) | 403 if (desktop_session_connector_ && is_desktop_session_connected_) |
339 desktop_session_connector_->DisconnectTerminal(this); | 404 desktop_session_connector_->DisconnectTerminal(this); |
340 | 405 |
341 if (desktop_process_ != base::kNullProcessHandle) { | 406 if (desktop_process_ != base::kNullProcessHandle) { |
342 base::CloseProcessHandle(desktop_process_); | 407 base::CloseProcessHandle(desktop_process_); |
343 desktop_process_ = base::kNullProcessHandle; | 408 desktop_process_ = base::kNullProcessHandle; |
344 } | 409 } |
345 } | 410 } |
346 | 411 |
347 scoped_refptr<media::SharedBuffer> DesktopSessionProxy::GetSharedBuffer( | 412 scoped_refptr<DesktopSessionProxy::IpcSharedBufferCore> |
348 int id) { | 413 DesktopSessionProxy::GetSharedBufferCore(int id) { |
349 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 414 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
350 | 415 |
351 SharedBuffers::const_iterator i = shared_buffers_.find(id); | 416 SharedBuffers::const_iterator i = shared_buffers_.find(id); |
352 if (i != shared_buffers_.end()) { | 417 if (i != shared_buffers_.end()) { |
353 return i->second; | 418 return i->second; |
354 } else { | 419 } else { |
355 LOG(ERROR) << "Failed to find the shared buffer " << id; | 420 LOG(ERROR) << "Failed to find the shared buffer " << id; |
356 return scoped_refptr<media::SharedBuffer>(); | 421 return NULL; |
357 } | 422 } |
358 } | 423 } |
359 | 424 |
360 void DesktopSessionProxy::OnAudioPacket(const std::string& serialized_packet) { | 425 void DesktopSessionProxy::OnAudioPacket(const std::string& serialized_packet) { |
361 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 426 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
362 | 427 |
363 // Parse a serialized audio packet. No further validation is done since | 428 // Parse a serialized audio packet. No further validation is done since |
364 // the message was sent by more privileged process. | 429 // the message was sent by more privileged process. |
365 scoped_ptr<AudioPacket> packet(new AudioPacket()); | 430 scoped_ptr<AudioPacket> packet(new AudioPacket()); |
366 if (!packet->ParseFromString(serialized_packet)) { | 431 if (!packet->ParseFromString(serialized_packet)) { |
367 LOG(ERROR) << "Failed to parse AudioPacket."; | 432 LOG(ERROR) << "Failed to parse AudioPacket."; |
368 return; | 433 return; |
369 } | 434 } |
370 | 435 |
371 // Pass a captured audio packet to |audio_capturer_|. | 436 // Pass a captured audio packet to |audio_capturer_|. |
372 audio_capture_task_runner_->PostTask( | 437 audio_capture_task_runner_->PostTask( |
373 FROM_HERE, base::Bind(&IpcAudioCapturer::OnAudioPacket, audio_capturer_, | 438 FROM_HERE, base::Bind(&IpcAudioCapturer::OnAudioPacket, audio_capturer_, |
374 base::Passed(&packet))); | 439 base::Passed(&packet))); |
375 } | 440 } |
376 | 441 |
377 void DesktopSessionProxy::OnCreateSharedBuffer( | 442 void DesktopSessionProxy::OnCreateSharedBuffer( |
378 int id, | 443 int id, |
379 IPC::PlatformFileForTransit handle, | 444 IPC::PlatformFileForTransit handle, |
380 uint32 size) { | 445 uint32 size) { |
381 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 446 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
382 | 447 |
383 scoped_refptr<media::SharedBuffer> shared_buffer; | 448 scoped_refptr<IpcSharedBufferCore> shared_buffer = |
| 449 new IpcSharedBufferCore(id, handle, desktop_process_, size); |
384 | 450 |
385 #if defined(OS_WIN) | 451 if (shared_buffer->memory() != NULL && |
386 shared_buffer = new media::SharedBuffer(id, handle, desktop_process_, size); | |
387 #elif defined(OS_POSIX) | |
388 shared_buffer = new media::SharedBuffer(id, handle, size); | |
389 #else | |
390 #error Unsupported platform. | |
391 #endif | |
392 | |
393 // Check if the buffer has been successfully mapped. | |
394 bool mapped = shared_buffer->ptr() != NULL; | |
395 if (!mapped) { | |
396 #if defined(OS_WIN) | |
397 LOG(ERROR) << "Failed to map a shared buffer: id=" << id | |
398 << ", handle=" << handle | |
399 << ", size=" << size; | |
400 #elif defined(OS_POSIX) | |
401 LOG(ERROR) << "Failed to map a shared buffer: id=" << id | |
402 << ", handle.fd=" << handle.fd | |
403 << ", size=" << size; | |
404 #endif | |
405 } | |
406 | |
407 if (mapped && | |
408 !shared_buffers_.insert(std::make_pair(id, shared_buffer)).second) { | 452 !shared_buffers_.insert(std::make_pair(id, shared_buffer)).second) { |
409 LOG(ERROR) << "Duplicate shared buffer id " << id << " encountered"; | 453 LOG(ERROR) << "Duplicate shared buffer id " << id << " encountered"; |
410 } | 454 } |
411 | |
412 // Notify the desktop process that the buffer has been seen and can now be | |
413 // safely deleted if needed. | |
414 SendToDesktop(new ChromotingNetworkDesktopMsg_SharedBufferCreated(id)); | |
415 } | 455 } |
416 | 456 |
417 void DesktopSessionProxy::OnReleaseSharedBuffer(int id) { | 457 void DesktopSessionProxy::OnReleaseSharedBuffer(int id) { |
418 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 458 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
419 | 459 |
420 // Drop the cached reference to the buffer. | 460 // Drop the cached reference to the buffer. |
421 shared_buffers_.erase(id); | 461 shared_buffers_.erase(id); |
422 } | 462 } |
423 | 463 |
424 void DesktopSessionProxy::OnCaptureCompleted( | 464 void DesktopSessionProxy::OnCaptureCompleted( |
425 const SerializedCapturedData& serialized_data) { | 465 const SerializedDesktopFrame& serialized_frame) { |
426 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 466 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
427 | 467 |
428 // Assume that |serialized_data| is well formed because it was received from | 468 // Assume that |serialized_frame| is well-formed because it was received from |
429 // a more privileged process. | 469 // a more privileged process. |
430 scoped_refptr<media::ScreenCaptureData> capture_data; | 470 scoped_refptr<IpcSharedBufferCore> shared_buffer_core = |
431 scoped_refptr<media::SharedBuffer> shared_buffer = | 471 GetSharedBufferCore(serialized_frame.shared_buffer_id); |
432 GetSharedBuffer(serialized_data.shared_buffer_id); | 472 CHECK(shared_buffer_core); |
433 CHECK(shared_buffer); | |
434 | 473 |
435 capture_data = new media::ScreenCaptureData( | 474 scoped_ptr<webrtc::DesktopFrame> frame( |
436 reinterpret_cast<uint8*>(shared_buffer->ptr()), | 475 new webrtc::SharedMemoryDesktopFrame( |
437 serialized_data.bytes_per_row, | 476 serialized_frame.dimensions, serialized_frame.bytes_per_row, |
438 serialized_data.dimensions); | 477 new IpcSharedBuffer(shared_buffer_core))); |
439 capture_data->set_capture_time_ms(serialized_data.capture_time_ms); | 478 frame->set_capture_time_ms(serialized_frame.capture_time_ms); |
440 capture_data->set_client_sequence_number( | 479 frame->set_dpi(serialized_frame.dpi); |
441 serialized_data.client_sequence_number); | |
442 capture_data->set_dpi(serialized_data.dpi); | |
443 capture_data->set_shared_buffer(shared_buffer); | |
444 | 480 |
445 if (!serialized_data.dirty_region.empty()) { | 481 for (size_t i = 0; i < serialized_frame.dirty_region.size(); ++i) { |
446 capture_data->mutable_dirty_region().setRects( | 482 frame->mutable_updated_region()->AddRect(serialized_frame.dirty_region[i]); |
447 &serialized_data.dirty_region[0], | |
448 serialized_data.dirty_region.size()); | |
449 } | 483 } |
450 | 484 |
451 --pending_capture_frame_requests_; | 485 --pending_capture_frame_requests_; |
452 PostCaptureCompleted(capture_data); | 486 PostCaptureCompleted(frame.Pass()); |
453 } | 487 } |
454 | 488 |
455 void DesktopSessionProxy::OnCursorShapeChanged( | 489 void DesktopSessionProxy::OnCursorShapeChanged( |
456 const media::MouseCursorShape& cursor_shape) { | 490 const media::MouseCursorShape& cursor_shape) { |
457 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 491 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
458 PostCursorShape(scoped_ptr<media::MouseCursorShape>( | 492 PostCursorShape(scoped_ptr<media::MouseCursorShape>( |
459 new media::MouseCursorShape(cursor_shape))); | 493 new media::MouseCursorShape(cursor_shape))); |
460 } | 494 } |
461 | 495 |
462 void DesktopSessionProxy::OnInjectClipboardEvent( | 496 void DesktopSessionProxy::OnInjectClipboardEvent( |
463 const std::string& serialized_event) { | 497 const std::string& serialized_event) { |
464 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 498 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
465 | 499 |
466 if (client_clipboard_) { | 500 if (client_clipboard_) { |
467 protocol::ClipboardEvent event; | 501 protocol::ClipboardEvent event; |
468 if (!event.ParseFromString(serialized_event)) { | 502 if (!event.ParseFromString(serialized_event)) { |
469 LOG(ERROR) << "Failed to parse protocol::ClipboardEvent."; | 503 LOG(ERROR) << "Failed to parse protocol::ClipboardEvent."; |
470 return; | 504 return; |
471 } | 505 } |
472 | 506 |
473 client_clipboard_->InjectClipboardEvent(event); | 507 client_clipboard_->InjectClipboardEvent(event); |
474 } | 508 } |
475 } | 509 } |
476 | 510 |
477 void DesktopSessionProxy::PostCaptureCompleted( | 511 void DesktopSessionProxy::PostCaptureCompleted( |
478 scoped_refptr<media::ScreenCaptureData> capture_data) { | 512 scoped_ptr<webrtc::DesktopFrame> frame) { |
479 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 513 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
480 | 514 |
481 video_capture_task_runner_->PostTask( | 515 video_capture_task_runner_->PostTask( |
482 FROM_HERE, | 516 FROM_HERE, |
483 base::Bind(&IpcVideoFrameCapturer::OnCaptureCompleted, video_capturer_, | 517 base::Bind(&IpcVideoFrameCapturer::OnCaptureCompleted, video_capturer_, |
484 capture_data)); | 518 base::Passed(&frame))); |
485 } | 519 } |
486 | 520 |
487 void DesktopSessionProxy::PostCursorShape( | 521 void DesktopSessionProxy::PostCursorShape( |
488 scoped_ptr<media::MouseCursorShape> cursor_shape) { | 522 scoped_ptr<media::MouseCursorShape> cursor_shape) { |
489 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 523 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
490 | 524 |
491 video_capture_task_runner_->PostTask( | 525 video_capture_task_runner_->PostTask( |
492 FROM_HERE, | 526 FROM_HERE, |
493 base::Bind(&IpcVideoFrameCapturer::OnCursorShapeChanged, video_capturer_, | 527 base::Bind(&IpcVideoFrameCapturer::OnCursorShapeChanged, video_capturer_, |
494 base::Passed(&cursor_shape))); | 528 base::Passed(&cursor_shape))); |
(...skipping 10 matching lines...) Expand all Loading... |
505 } | 539 } |
506 | 540 |
507 // static | 541 // static |
508 void DesktopSessionProxyTraits::Destruct( | 542 void DesktopSessionProxyTraits::Destruct( |
509 const DesktopSessionProxy* desktop_session_proxy) { | 543 const DesktopSessionProxy* desktop_session_proxy) { |
510 desktop_session_proxy->caller_task_runner_->DeleteSoon(FROM_HERE, | 544 desktop_session_proxy->caller_task_runner_->DeleteSoon(FROM_HERE, |
511 desktop_session_proxy); | 545 desktop_session_proxy); |
512 } | 546 } |
513 | 547 |
514 } // namespace remoting | 548 } // namespace remoting |
OLD | NEW |