client_session.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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/client_session.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/capabilities.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "remoting/base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder_opus.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder_verbatim.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_encoder.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_encoder_verbatim.h"
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "remoting/codec/video_encoder_vpx.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/audio_capturer.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/audio_scheduler.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/desktop_environment.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/input_injector.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_controls.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_resolution.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/video_scheduler.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/control.pb.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/client_stub.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/clipboard_thread_proxy.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "remoting/protocol/pairing_registry.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default DPI to assume for old clients that use notifyClientDimensions.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDefaultDPI = 96;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClientSession::ClientSession(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventHandler* event_handler,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<protocol::ConnectionToClient> connection,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DesktopEnvironmentFactory* desktop_environment_factory,
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::TimeDelta& max_duration,
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<protocol::PairingRegistry> pairing_registry)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : event_handler_(event_handler),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_(connection.Pass()),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_jid_(connection_->session()->jid()),
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      control_factory_(this),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      desktop_environment_factory_(desktop_environment_factory),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_tracker_(&host_input_filter_),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remote_input_filter_(&input_tracker_),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mouse_clamping_filter_(&remote_input_filter_),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      disable_input_filter_(mouse_clamping_filter_.input_filter()),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      auth_input_filter_(&disable_input_filter_),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      auth_clipboard_filter_(&disable_clipboard_filter_),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_duration_(max_duration),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_task_runner_(audio_task_runner),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_task_runner_(input_task_runner),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_capture_task_runner_(video_capture_task_runner),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_encode_task_runner_(video_encode_task_runner),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_task_runner_(network_task_runner),
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ui_task_runner_(ui_task_runner),
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pairing_registry_(pairing_registry) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->SetEventHandler(this);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sergeyu): Currently ConnectionToClient expects stubs to be
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set before channels are connected. Make it possible to set stubs
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // later and set them only when connection is authenticated.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->set_clipboard_stub(&auth_clipboard_filter_);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->set_host_stub(this);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->set_input_stub(&auth_input_filter_);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |auth_*_filter_|'s states reflect whether the session is authenticated.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_input_filter_.set_enabled(false);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_clipboard_filter_.set_enabled(false);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // LocalInputMonitorWin filters out an echo of the injected input before it
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // reaches |remote_input_filter_|.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_input_filter_.SetExpectLocalEcho(false);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(OS_WIN)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ClientSession::~ClientSession() {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!audio_scheduler_.get());
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!desktop_environment_);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!input_injector_);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!screen_controls_);
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!video_scheduler_.get());
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connection_.reset();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClientSession::NotifyClientResolution(
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const protocol::ClientResolution& resolution) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(sergeyu): Move these checks to protocol layer.
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!resolution.has_dips_width() || !resolution.has_dips_height() ||
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      resolution.dips_width() < 0 || resolution.dips_height() < 0 ||
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      resolution.width() <= 0 || resolution.height() <= 0) {
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "Received invalid ClientResolution message.";
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Received ClientResolution (dips_width="
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << resolution.dips_width() << ", dips_height="
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << resolution.dips_height() << ")";
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!screen_controls_)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScreenResolution client_resolution(
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      webrtc::DesktopSize(resolution.dips_width(), resolution.dips_height()),
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Try to match the client's resolution.
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  screen_controls_->SetScreenResolution(client_resolution);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (video_control.has_enable()) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received VideoControl (enable="
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << video_control.enable() << ")";
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    video_scheduler_->Pause(!video_control.enable());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) {
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (audio_control.has_enable()) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received AudioControl (enable="
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << audio_control.enable() << ")";
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (audio_scheduler_.get())
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      audio_scheduler_->Pause(!audio_control.enable());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ClientSession::SetCapabilities(
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const protocol::Capabilities& capabilities) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The client should not send protocol::Capabilities if it is not supported by
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the config channel.
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!connection_->session()->config().SupportsCapabilities()) {
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unexpected protocol::Capabilities has been received.";
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Ignore all the messages but the 1st one.
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (client_capabilities_) {
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "protocol::Capabilities has been received already.";
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  client_capabilities_ = make_scoped_ptr(new std::string());
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (capabilities.has_capabilities())
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *client_capabilities_ = capabilities.capabilities();
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "Client capabilities: " << *client_capabilities_;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Calculate the set of capabilities enabled by both client and host and
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // pass it to the desktop environment if it is available.
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  desktop_environment_->SetCapabilities(
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IntersectCapabilities(*client_capabilities_, host_capabilities_));
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ClientSession::RequestPairing(
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const protocol::PairingRequest& pairing_request) {
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pairing_registry_ && pairing_request.has_client_name()) {
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    protocol::PairingRegistry::Pairing pairing =
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pairing_registry_->CreatePairing(pairing_request.client_name());
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    protocol::PairingResponse pairing_response;
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pairing_response.set_client_id(pairing.client_id());
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pairing_response.set_shared_secret(pairing.shared_secret());
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    connection_->client_stub()->SetPairingResponse(pairing_response);
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
190c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid ClientSession::DeliverClientMessage(
191c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    const protocol::ExtensionMessage& message) {
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (message.has_type()) {
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (message.type() == "test-echo") {
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      protocol::ExtensionMessage reply;
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      reply.set_type("test-echo-reply");
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (message.has_data())
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        reply.set_data(message.data().substr(0, 16));
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      connection_->client_stub()->DeliverHostMessage(reply);
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else if (message.type() == "gnubby-auth") {
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (gnubby_auth_handler_) {
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        gnubby_auth_handler_->DeliverClientMessage(message.data());
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      } else {
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        HOST_LOG << "gnubby auth is not enabled";
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HOST_LOG << "Unexpected message received: "
210c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            << message.type() << ": " << message.data();
211c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}
212c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnConnectionAuthenticated(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol::ConnectionToClient* connection) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(connection_.get(), connection);
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!audio_scheduler_.get());
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!desktop_environment_);
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!input_injector_);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!screen_controls_);
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!video_scheduler_.get());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_input_filter_.set_enabled(true);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_clipboard_filter_.set_enabled(true);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_echo_filter_.set_client_stub(connection_->client_stub());
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mouse_clamping_filter_.set_video_stub(connection_->video_stub());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (max_duration_ > base::TimeDelta()) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(simonmorris): Let Disconnect() tell the client that the
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // disconnection was caused by the session exceeding its maximum duration.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_duration_timer_.Start(FROM_HERE, max_duration_,
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              this, &ClientSession::DisconnectSession);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Disconnect the session if the connection was rejected by the host.
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!event_handler_->OnSessionAuthenticated(this)) {
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DisconnectSession();
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Create the desktop environment. Drop the connection if it could not be
243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // created for any reason (for instance the curtain could not initialize).
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  desktop_environment_ =
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      desktop_environment_factory_->Create(control_factory_.GetWeakPtr());
246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!desktop_environment_) {
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DisconnectSession();
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  host_capabilities_ = desktop_environment_->GetCapabilities();
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Ignore protocol::Capabilities messages from the client if it does not
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // support any capabilities.
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!connection_->session()->config().SupportsCapabilities()) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "The client does not support any capabilities.";
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_capabilities_ = make_scoped_ptr(new std::string());
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    desktop_environment_->SetCapabilities(*client_capabilities_);
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create the object that controls the screen resolution.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  screen_controls_ = desktop_environment_->CreateScreenControls();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create the event executor.
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  input_injector_ = desktop_environment_->CreateInputInjector();
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Connect the host clipboard and input stubs.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  host_input_filter_.set_input_stub(input_injector_.get());
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  clipboard_echo_filter_.set_host_stub(input_injector_.get());
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a VideoEncoder based on the session's video channel configuration.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<VideoEncoder> video_encoder =
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateVideoEncoder(connection_->session()->config());
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a VideoScheduler to pump frames from the capturer to the client.
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  video_scheduler_ = new VideoScheduler(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_capture_task_runner_,
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_encode_task_runner_,
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      network_task_runner_,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      desktop_environment_->CreateVideoCapturer(),
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_encoder.Pass(),
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connection_->client_stub(),
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &mouse_clamping_filter_);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an AudioScheduler if audio is enabled, to pump audio samples.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connection_->session()->config().is_audio_enabled()) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioEncoder> audio_encoder =
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateAudioEncoder(connection_->session()->config());
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_scheduler_ = new AudioScheduler(
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_task_runner_,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        network_task_runner_,
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        desktop_environment_->CreateAudioCapturer(),
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_encoder.Pass(),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        connection_->audio_stub());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Create a GnubbyAuthHandler to proxy gnubbyd messages.
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gnubby_auth_handler_ = desktop_environment_->CreateGnubbyAuthHandler(
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection_->client_stub());
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ClientSession::OnConnectionChannelsConnected(
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    protocol::ConnectionToClient* connection) {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(connection_.get(), connection);
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Negotiate capabilities with the client.
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (connection_->session()->config().SupportsCapabilities()) {
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Host capabilities: " << host_capabilities_;
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    protocol::Capabilities capabilities;
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capabilities.set_capabilities(host_capabilities_);
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    connection_->client_stub()->SetCapabilities(capabilities);
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Start the event executor.
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  input_injector_->Start(CreateClipboardProxy());
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetDisableInputs(false);
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Start capturing the screen.
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  video_scheduler_->Start();
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Start recording audio.
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (connection_->session()->config().is_audio_enabled())
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_scheduler_->Start();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify the event handler that all our channels are now connected.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_handler_->OnSessionChannelsConnected(this);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnConnectionClosed(
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol::ConnectionToClient* connection,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol::ErrorCode error) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(connection_.get(), connection);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ignore any further callbacks.
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  control_factory_.InvalidateWeakPtrs();
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the client never authenticated then the session failed.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_input_filter_.enabled())
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_handler_->OnSessionAuthenticationFailed(this);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Block any further input events from the client.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(wez): Fix ChromotingHost::OnSessionClosed not to check our
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is_authenticated(), so that we can disable |auth_*_filter_| here.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disable_input_filter_.set_enabled(false);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disable_clipboard_filter_.set_enabled(false);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that any pressed keys or buttons are released.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  input_tracker_.ReleaseAll();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Stop components access the client, audio or video stubs, which are no
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // longer valid once ConnectionToClient calls OnConnectionClosed().
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (audio_scheduler_.get()) {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_scheduler_->Stop();
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_scheduler_ = NULL;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (video_scheduler_.get()) {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    video_scheduler_->Stop();
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    video_scheduler_ = NULL;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_clipboard_factory_.InvalidateWeakPtrs();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  input_injector_.reset();
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  screen_controls_.reset();
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  desktop_environment_.reset();
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify the ChromotingHost that this client is disconnected.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sergeyu): Log failure reason?
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_handler_->OnSessionClosed(this);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnSequenceNumberUpdated(
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol::ConnectionToClient* connection, int64 sequence_number) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(connection_.get(), connection);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (video_scheduler_.get())
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    video_scheduler_->UpdateSequenceNumber(sequence_number);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_handler_->OnSessionSequenceNumber(this, sequence_number);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnRouteChange(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol::ConnectionToClient* connection,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& channel_name,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const protocol::TransportRoute& route) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(connection_.get(), connection);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_handler_->OnSessionRouteChange(this, channel_name, route);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string& ClientSession::client_jid() const {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_jid_;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClientSession::DisconnectSession() {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_.get());
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  max_duration_timer_.Stop();
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This triggers OnConnectionClosed(), and the session may be destroyed
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as the result, so this call must be the last in this method.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->Disconnect();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_input_filter_.LocalMouseMoved(position);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::SetDisableInputs(bool disable_inputs) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disable_inputs)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_tracker_.ReleaseAll();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disable_input_filter_.set_enabled(!disable_inputs);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disable_clipboard_filter_.set_enabled(!disable_inputs);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ClientSession::SetGnubbyAuthHandlerForTesting(
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    GnubbyAuthHandler* gnubby_auth_handler) {
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gnubby_auth_handler_.reset(gnubby_auth_handler);
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_ptr<protocol::ClipboardStub>(
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new protocol::ClipboardThreadProxy(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          client_clipboard_factory_.GetWeakPtr(),
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::MessageLoopProxy::current()));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(sergeyu): Move this to SessionManager?
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<VideoEncoder> ClientSession::CreateVideoEncoder(
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const protocol::SessionConfig& config) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const protocol::ChannelConfig& video_config = config.video_config();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
4468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return remoting::VideoEncoderVpx::CreateForVP8().PassAs<VideoEncoder>();
447e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP9) {
448e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return remoting::VideoEncoderVpx::CreateForVP9().PassAs<VideoEncoder>();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NOTREACHED();
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return scoped_ptr<VideoEncoder>();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<AudioEncoder> ClientSession::CreateAudioEncoder(
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const protocol::SessionConfig& config) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const protocol::ChannelConfig& audio_config = config.audio_config();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim());
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (audio_config.codec == protocol::ChannelConfig::CODEC_OPUS) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_ptr<AudioEncoder>(new AudioEncoderOpus());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NOTREACHED();
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return scoped_ptr<AudioEncoder>();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
471