Chromium Code Reviews| Index: remoting/host/desktop_session_proxy.cc |
| diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc |
| index 9e52f8d6dbcf35299b2ded382a83c176bb100462..3787adc6b244f1a696a21f2a5ce7af2a81f14158 100644 |
| --- a/remoting/host/desktop_session_proxy.cc |
| +++ b/remoting/host/desktop_session_proxy.cc |
| @@ -19,6 +19,7 @@ |
| #include "remoting/host/desktop_session_connector.h" |
| #include "remoting/host/ipc_audio_capturer.h" |
| #include "remoting/host/ipc_input_injector.h" |
| +#include "remoting/host/ipc_mouse_cursor_monitor.h" |
| #include "remoting/host/ipc_screen_controls.h" |
| #include "remoting/host/ipc_video_frame_capturer.h" |
| #include "remoting/proto/audio.pb.h" |
| @@ -26,6 +27,7 @@ |
| #include "remoting/proto/event.pb.h" |
| #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" |
| +#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h" |
| #include "third_party/webrtc/modules/desktop_capture/shared_memory.h" |
| #if defined(OS_WIN) |
| @@ -144,6 +146,12 @@ scoped_ptr<webrtc::ScreenCapturer> DesktopSessionProxy::CreateVideoCapturer() { |
| return scoped_ptr<webrtc::ScreenCapturer>(new IpcVideoFrameCapturer(this)); |
| } |
| +scoped_ptr<webrtc::MouseCursorMonitor> |
| + DesktopSessionProxy::CreateMouseCursorMonitor() { |
| + return scoped_ptr<webrtc::MouseCursorMonitor>( |
| + new IpcMouseCursorMonitor(this)); |
| +} |
| + |
| std::string DesktopSessionProxy::GetCapabilities() const { |
| std::string result = kRateLimitResizeRequests; |
| // Ask the client to send its resolution unconditionally. |
| @@ -183,8 +191,8 @@ bool DesktopSessionProxy::OnMessageReceived(const IPC::Message& message) { |
| OnAudioPacket) |
| IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CaptureCompleted, |
| OnCaptureCompleted) |
| - IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CursorShapeChanged, |
| - OnCursorShapeChanged) |
| + IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_MouseCursor, |
| + OnMouseCursor) |
| IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CreateSharedBuffer, |
| OnCreateSharedBuffer) |
| IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_ReleaseSharedBuffer, |
| @@ -317,6 +325,13 @@ void DesktopSessionProxy::SetVideoCapturer( |
| video_capturer_ = video_capturer; |
| } |
| +void DesktopSessionProxy::SetMouseCursorMonitor( |
| + const base::WeakPtr<IpcMouseCursorMonitor>& mouse_cursor_monitor) { |
| + DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); |
| + |
| + mouse_cursor_monitor_ = mouse_cursor_monitor; |
| +} |
| + |
| void DesktopSessionProxy::DisconnectSession() { |
| DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| @@ -490,11 +505,41 @@ void DesktopSessionProxy::OnCaptureCompleted( |
| PostCaptureCompleted(frame.Pass()); |
| } |
| -void DesktopSessionProxy::OnCursorShapeChanged( |
| - const webrtc::MouseCursorShape& cursor_shape) { |
| +void DesktopSessionProxy::OnMouseCursor( |
| + const SerializedMouseCursor& mouse_cursor) { |
| DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| - PostCursorShape(scoped_ptr<webrtc::MouseCursorShape>( |
| - new webrtc::MouseCursorShape(cursor_shape))); |
| + |
| + // Sanitize IPC message. Check for overflow, and that enough data was sent. |
| + int cursor_width = mouse_cursor.size.width(); |
| + int cursor_height = mouse_cursor.size.height(); |
| + uint32 expected_total_bytes = cursor_width * cursor_height * |
| + webrtc::DesktopFrame::kBytesPerPixel; |
| + if (cursor_width <= 0 || cursor_width > (SHRT_MAX / 2) || |
| + cursor_height <= 0 || cursor_height > (SHRT_MAX / 2) || |
| + mouse_cursor.data.size() < expected_total_bytes) { |
| + LOG(ERROR) << "Invalid SerializedMouseCursor:" |
| + << " w=" << cursor_width << " h=" << cursor_height |
| + << " data_size=" << mouse_cursor.data.size(); |
| + return; |
|
Sergey Ulanov
2013/12/03 21:47:28
bogus IPC message indicates that something went ve
dcaiafa
2013/12/10 01:32:03
Done.
|
| + } |
| + |
| + // Rebuild a |webrtc::DesktopFrame| from the IPC message. |
| + webrtc::BasicDesktopFrame* frame = |
| + new webrtc::BasicDesktopFrame(mouse_cursor.size); |
| + const char* source = mouse_cursor.data.data(); |
| + uint8_t* target = frame->data(); |
| + for (int y = 0; y < frame->size().height(); y++) { |
| + int bytes_to_copy = mouse_cursor.size.width() * |
| + webrtc::DesktopFrame::kBytesPerPixel; |
| + memcpy(target, source, bytes_to_copy); |
| + source += bytes_to_copy; |
| + // N.B. |stride()| is in bytes already. |
| + target += frame->stride(); |
| + } |
| + |
| + scoped_ptr<webrtc::MouseCursor> cursor(new webrtc::MouseCursor( |
| + frame, mouse_cursor.hotspot)); |
| + PostMouseCursor(cursor.Pass()); |
| } |
| void DesktopSessionProxy::OnInjectClipboardEvent( |
| @@ -522,14 +567,14 @@ void DesktopSessionProxy::PostCaptureCompleted( |
| base::Passed(&frame))); |
| } |
| -void DesktopSessionProxy::PostCursorShape( |
| - scoped_ptr<webrtc::MouseCursorShape> cursor_shape) { |
| +void DesktopSessionProxy::PostMouseCursor( |
| + scoped_ptr<webrtc::MouseCursor> mouse_cursor) { |
| DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| video_capture_task_runner_->PostTask( |
| FROM_HERE, |
| - base::Bind(&IpcVideoFrameCapturer::OnCursorShapeChanged, video_capturer_, |
| - base::Passed(&cursor_shape))); |
| + base::Bind(&IpcMouseCursorMonitor::OnMouseCursor, mouse_cursor_monitor_, |
| + base::Passed(&mouse_cursor))); |
| } |
| void DesktopSessionProxy::SendToDesktop(IPC::Message* message) { |