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