15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/desktop_session_agent.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/shared_memory.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_proxy.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/auto_thread_task_runner.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/base/constants.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/audio_capturer.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/chromoting_messages.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/desktop_environment.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/input_injector.h" 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "remoting/host/ipc_util.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/remote_input_filter.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_controls.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_resolution.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/proto/audio.pb.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/proto/control.pb.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/proto/event.pb.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/protocol/clipboard_stub.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/protocol/input_event_tracker.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/shared_memory.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Routes local clipboard events though the IPC channel to the network process. 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DesktopSesssionClipboardStub : public protocol::ClipboardStub { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit DesktopSesssionClipboardStub( 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<DesktopSessionAgent> desktop_session_agent); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~DesktopSesssionClipboardStub(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // protocol::ClipboardStub implementation. 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void InjectClipboardEvent( 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const protocol::ClipboardEvent& event) OVERRIDE; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<DesktopSessionAgent> desktop_session_agent_; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DesktopSesssionClipboardStub); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DesktopSesssionClipboardStub::DesktopSesssionClipboardStub( 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<DesktopSessionAgent> desktop_session_agent) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : desktop_session_agent_(desktop_session_agent) { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DesktopSesssionClipboardStub::~DesktopSesssionClipboardStub() { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSesssionClipboardStub::InjectClipboardEvent( 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const protocol::ClipboardEvent& event) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_session_agent_->InjectClipboardEvent(event); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// webrtc::SharedMemory implementation that notifies creating 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// DesktopSessionAgent when it's deleted. 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class DesktopSessionAgent::SharedBuffer : public webrtc::SharedMemory { 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static scoped_ptr<SharedBuffer> Create(DesktopSessionAgent* agent, 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t size, 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int id) { 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<base::SharedMemory> memory(new base::SharedMemory()); 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!memory->CreateAndMapAnonymous(size)) 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return scoped_ptr<SharedBuffer>(); 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return scoped_ptr<SharedBuffer>( 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) new SharedBuffer(agent, memory.Pass(), size, id)); 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~SharedBuffer() { 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) agent_->OnSharedBufferDeleted(id()); 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SharedBuffer(DesktopSessionAgent* agent, 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<base::SharedMemory> memory, 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t size, 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int id) 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : SharedMemory(memory->memory(), size, 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN) 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) memory->handle(), 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) memory->handle().fd, 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) id), 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) agent_(agent), 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shared_memory_(memory.Pass()) { 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DesktopSessionAgent* agent_; 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<base::SharedMemory> shared_memory_; 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SharedBuffer); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DesktopSessionAgent::Delegate::~Delegate() { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)DesktopSessionAgent::DesktopSessionAgent( 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> audio_capture_task_runner, 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> caller_task_runner, 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> input_task_runner, 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> io_task_runner, 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner) 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : audio_capture_task_runner_(audio_capture_task_runner), 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) caller_task_runner_(caller_task_runner), 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) input_task_runner_(input_task_runner), 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) io_task_runner_(io_task_runner), 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) video_capture_task_runner_(video_capture_task_runner), 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) next_shared_buffer_id_(1), 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shared_buffers_(0), 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci started_(false), 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_(this) { 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DesktopSessionAgent::OnMessageReceived(const IPC::Message& message) { 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool handled = true; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (started_) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(DesktopSessionAgent, message) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_CaptureFrame, 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnCaptureFrame) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectClipboardEvent, 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnInjectClipboardEvent) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectKeyEvent, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnInjectKeyEvent) 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectTextEvent, 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnInjectTextEvent) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectMouseEvent, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnInjectMouseEvent) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_SetScreenResolution, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetScreenResolution) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_END_MESSAGE_MAP() 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(DesktopSessionAgent, message) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_StartSessionAgent, 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnStartSessionAgent) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_END_MESSAGE_MAP() 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(handled) << "Received unexpected IPC type: " << message.type(); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return handled; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopSessionAgent::OnChannelConnected(int32 peer_pid) { 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "IPC: desktop <- network (" << peer_pid << ")"; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) desktop_pipe_.Close(); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopSessionAgent::OnChannelError() { 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the channel is closed. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_channel_.reset(); 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) desktop_pipe_.Close(); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notify the caller that the channel has been disconnected. 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delegate_.get()) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->OnNetworkProcessDisconnected(); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)webrtc::SharedMemory* DesktopSessionAgent::CreateSharedMemory(size_t size) { 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SharedBuffer> buffer = 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SharedBuffer::Create(this, size, next_shared_buffer_id_); 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (buffer) { 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shared_buffers_++; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |next_shared_buffer_id_| starts from 1 and incrementing it by 2 makes 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sure it is always odd and therefore zero is never used as a valid buffer 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ID. 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is very unlikely (though theoretically possible) to allocate the same 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ID for two different buffers due to integer overflow. It should take 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // about a year of allocating 100 new buffers every second. Practically 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // speaking it never happens. 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_shared_buffer_id_ += 2; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) IPC::PlatformFileForTransit handle; 20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN) 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) handle = buffer->handle(); 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) handle = base::FileDescriptor(buffer->handle(), false); 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendToNetwork(new ChromotingDesktopNetworkMsg_CreateSharedBuffer( 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) buffer->id(), handle, buffer->size())); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return buffer.release(); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)DesktopSessionAgent::~DesktopSessionAgent() { 21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!audio_capturer_); 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!desktop_environment_); 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!network_channel_); 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!screen_controls_); 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!video_capturer_); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string& DesktopSessionAgent::client_jid() const { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return client_jid_; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::DisconnectSession() { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendToNetwork(new ChromotingDesktopNetworkMsg_DisconnectSession()); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DesktopSessionAgent::OnLocalMouseMoved( 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::DesktopVector& new_pos) { 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_->LocalMouseMoved(new_pos); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::SetDisableInputs(bool disable_inputs) { 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not expect this method to be called because it is only used by It2Me. 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DesktopSessionAgent::ResetVideoPipeline() { 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This method is only used by HostExtensionSessions in the network process. 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED(); 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::OnStartSessionAgent( 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& authenticated_jid, 252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const ScreenResolution& resolution, 253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool virtual_terminal) { 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!started_); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!audio_capturer_); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!desktop_environment_); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!input_injector_); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!screen_controls_); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!video_capturer_); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) started_ = true; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_jid_ = authenticated_jid; 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Enable the curtain mode. 266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) delegate_->desktop_environment_factory().SetEnableCurtaining( 267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) virtual_terminal); 268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a desktop environment for the new session. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_ = delegate_->desktop_environment_factory().Create( 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.GetWeakPtr()); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the session controller and set the initial screen resolution. 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_controls_ = desktop_environment_->CreateScreenControls(); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetScreenResolution(resolution); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the input injector. 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_injector_ = desktop_environment_->CreateInputInjector(); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Hook up the input filter. 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_tracker_.reset(new protocol::InputEventTracker(input_injector_.get())); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_.reset(new RemoteInputFilter(input_tracker_.get())); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // LocalInputMonitorWin filters out an echo of the injected input before it 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // reaches |remote_input_filter_|. 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_->SetExpectLocalEcho(false); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(OS_WIN) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start the input injector. 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<protocol::ClipboardStub> clipboard_stub( 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new DesktopSesssionClipboardStub(this)); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_injector_->Start(clipboard_stub.Pass()); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start the audio capturer. 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delegate_->desktop_environment_factory().SupportsAudioCapture()) { 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_capturer_ = desktop_environment_->CreateAudioCapturer(); 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) audio_capture_task_runner_->PostTask( 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, base::Bind(&DesktopSessionAgent::StartAudioCapturer, this)); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Start the video capturer and mouse cursor monitor. 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_capturer_ = desktop_environment_->CreateVideoCapturer(); 3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mouse_cursor_monitor_ = desktop_environment_->CreateMouseCursorMonitor(); 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) video_capture_task_runner_->PostTask( 3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, base::Bind( 3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &DesktopSessionAgent::StartVideoCapturerAndMouseMonitor, this)); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DesktopSessionAgent::OnCaptureCompleted(webrtc::DesktopFrame* frame) { 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) last_frame_.reset(frame); 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) current_size_ = frame->size(); 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Serialize webrtc::DesktopFrame. 31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SerializedDesktopFrame serialized_frame; 31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_frame.shared_buffer_id = frame->shared_memory()->id(); 32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_frame.bytes_per_row = frame->stride(); 32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_frame.dimensions = frame->size(); 32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_frame.capture_time_ms = frame->capture_time_ms(); 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_frame.dpi = frame->dpi(); 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_frame.dirty_region.push_back(i.rect()); 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendToNetwork( 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) new ChromotingDesktopNetworkMsg_CaptureCompleted(serialized_frame)); 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DesktopSessionAgent::OnMouseCursor(webrtc::MouseCursor* cursor) { 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<webrtc::MouseCursor> owned_cursor(cursor); 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SendToNetwork( 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new ChromotingDesktopNetworkMsg_MouseCursor(*owned_cursor)); 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DesktopSessionAgent::OnMouseCursorPosition( 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) webrtc::MouseCursorMonitor::CursorState state, 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const webrtc::DesktopVector& position) { 3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // We're not subscribing to mouse position changes. 3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::InjectClipboardEvent( 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const protocol::ClipboardEvent& event) { 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string serialized_event; 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event.SerializeToString(&serialized_event)) { 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to serialize protocol::ClipboardEvent."; 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendToNetwork( 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new ChromotingDesktopNetworkMsg_InjectClipboardEvent(serialized_event)); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::ProcessAudioPacket(scoped_ptr<AudioPacket> packet) { 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string serialized_packet; 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!packet->SerializeToString(&serialized_packet)) { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to serialize AudioPacket."; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendToNetwork(new ChromotingDesktopNetworkMsg_AudioPacket(serialized_packet)); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DesktopSessionAgent::Start(const base::WeakPtr<Delegate>& delegate, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::PlatformFileForTransit* desktop_pipe_out) { 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(delegate_.get() == NULL); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_ = delegate; 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create an IPC channel to communicate with the network process. 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool result = CreateConnectedIpcChannel(io_task_runner_, 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) this, 38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &desktop_pipe_, 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &network_channel_); 38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::PlatformFile raw_desktop_pipe = desktop_pipe_.GetPlatformFile(); 38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(OS_WIN) 38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *desktop_pipe_out = IPC::PlatformFileForTransit(raw_desktop_pipe); 39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#elif defined(OS_POSIX) 39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *desktop_pipe_out = IPC::PlatformFileForTransit(raw_desktop_pipe, false); 39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#else 39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#error Unsupported platform. 39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::Stop() { 39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_.reset(); 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure the channel is closed. 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) network_channel_.reset(); 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (started_) { 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) started_ = false; 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ignore any further callbacks. 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.InvalidateWeakPtrs(); 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_jid_.clear(); 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_.reset(); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ensure that any pressed keys or buttons are released. 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_tracker_->ReleaseAll(); 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_tracker_.reset(); 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_.reset(); 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_injector_.reset(); 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_controls_.reset(); 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stop the audio capturer. 42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) audio_capture_task_runner_->PostTask( 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, base::Bind(&DesktopSessionAgent::StopAudioCapturer, this)); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stop the video capturer. 42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) video_capture_task_runner_->PostTask( 4296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, base::Bind( 4306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &DesktopSessionAgent::StopVideoCapturerAndMouseMonitor, this)); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::OnCaptureFrame() { 43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!video_capture_task_runner_->BelongsToCurrentThread()) { 43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) video_capture_task_runner_->PostTask( 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DesktopSessionAgent::OnCaptureFrame, this)); 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mouse_cursor_monitor_->Capture(); 4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // webrtc::DesktopCapturer supports a very few (currently 2) outstanding 445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // capture requests. The requests are serialized on 446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |video_capture_task_runner()| task runner. If the client issues more 447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // requests, pixel data in captured frames will likely be corrupted but 4486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // stability of webrtc::DesktopCapturer will not be affected. 44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) video_capturer_->Capture(webrtc::DesktopRegion()); 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::OnInjectClipboardEvent( 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& serialized_event) { 45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protocol::ClipboardEvent event; 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event.ParseFromString(serialized_event)) { 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to parse protocol::ClipboardEvent."; 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // InputStub implementations must verify events themselves, so we don't need 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // verification here. This matches HostEventDispatcher. 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_injector_->InjectClipboardEvent(event); 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::OnInjectKeyEvent( 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& serialized_event) { 46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protocol::KeyEvent event; 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event.ParseFromString(serialized_event)) { 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to parse protocol::KeyEvent."; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // InputStub implementations must verify events themselves, so we need only 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // basic verification here. This matches HostEventDispatcher. 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event.has_usb_keycode() || !event.has_pressed()) { 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Received invalid key event."; 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_->InjectKeyEvent(event); 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 487effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DesktopSessionAgent::OnInjectTextEvent( 488effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& serialized_event) { 489effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(caller_task_runner_->BelongsToCurrentThread()); 490effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 491effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch protocol::TextEvent event; 492effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!event.ParseFromString(serialized_event)) { 493effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Failed to parse protocol::TextEvent."; 494effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 495effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 496effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 497effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // InputStub implementations must verify events themselves, so we need only 498effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // basic verification here. This matches HostEventDispatcher. 499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!event.has_text()) { 500effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Received invalid TextEvent."; 501effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 502effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 503effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 504effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch remote_input_filter_->InjectTextEvent(event); 505effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 506effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::OnInjectMouseEvent( 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& serialized_event) { 50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protocol::MouseEvent event; 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event.ParseFromString(serialized_event)) { 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to parse protocol::MouseEvent."; 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // InputStub implementations must verify events themselves, so we don't need 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // verification here. This matches HostEventDispatcher. 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_->InjectMouseEvent(event); 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::SetScreenResolution( 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ScreenResolution& resolution) { 52490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (screen_controls_ && resolution.IsEmpty()) 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_controls_->SetScreenResolution(resolution); 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::SendToNetwork(IPC::Message* message) { 53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!caller_task_runner_->BelongsToCurrentThread()) { 53290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) caller_task_runner_->PostTask( 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DesktopSessionAgent::SendToNetwork, this, message)); 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (network_channel_) { 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) network_channel_->Send(message); 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete message; 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::StartAudioCapturer() { 54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (audio_capturer_) { 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_capturer_->Start(base::Bind(&DesktopSessionAgent::ProcessAudioPacket, 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this)); 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopSessionAgent::StopAudioCapturer() { 55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(audio_capture_task_runner_->BelongsToCurrentThread()); 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_capturer_.reset(); 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DesktopSessionAgent::StartVideoCapturerAndMouseMonitor() { 56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (video_capturer_) { 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_capturer_->Start(this); 56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 5666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (mouse_cursor_monitor_) { 5686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mouse_cursor_monitor_->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY); 5696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DesktopSessionAgent::StopVideoCapturerAndMouseMonitor() { 57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video_capturer_.reset(); 57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) last_frame_.reset(); 5776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mouse_cursor_monitor_.reset(); 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 57990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Video capturer must delete all buffers. 58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(shared_buffers_, 0); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DesktopSessionAgent::OnSharedBufferDeleted(int id) { 58490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); 58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(id != 0); 58690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 58790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shared_buffers_--; 58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(shared_buffers_, 0); 58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SendToNetwork(new ChromotingDesktopNetworkMsg_ReleaseSharedBuffer(id)); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 593