103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file. 403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "remoting/host/cast_extension_session.h" 603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/bind.h" 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/json/json_reader.h" 903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/json/json_writer.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/logging.h" 1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "remoting/host/cast_video_capturer_adapter.h" 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "remoting/host/chromium_port_allocator_factory.h" 1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "remoting/host/client_session.h" 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "remoting/proto/control.pb.h" 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "remoting/protocol/client_stub.h" 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "third_party/libjingle/source/talk/app/webrtc/test/fakeconstraints.h" 2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h" 2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace remoting { 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Used as the type attribute of all Cast protocol::ExtensionMessages. 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kExtensionMessageType[] = "cast_message"; 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Top-level keys used in all extension messages between host and client. 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Must keep synced with webapp. 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kTopLevelData[] = "chromoting_data"; 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kTopLevelSubject[] = "subject"; 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Keys used to describe the subject of a cast extension message. WebRTC-related 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// message subjects are prepended with "webrtc_". 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Must keep synced with webapp. 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kSubjectReady[] = "ready"; 3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kSubjectTest[] = "test"; 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kSubjectNewCandidate[] = "webrtc_candidate"; 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kSubjectOffer[] = "webrtc_offer"; 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kSubjectAnswer[] = "webrtc_answer"; 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// WebRTC headers used inside messages with subject = "webrtc_*". 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kWebRtcCandidate[] = "candidate"; 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kWebRtcSessionDescType[] = "type"; 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kWebRtcSessionDescSDP[] = "sdp"; 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kWebRtcSDPMid[] = "sdpMid"; 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kWebRtcSDPMLineIndex[] = "sdpMLineIndex"; 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Media labels used over the PeerConnection. 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kVideoLabel[] = "cast_video_label"; 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kStreamLabel[] = "stream_label"; 5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Default STUN server used to construct 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// webrtc::PeerConnectionInterface::RTCConfiguration for the PeerConnection. 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kDefaultStunURI[] = "stun:stun.l.google.com:19302"; 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kWorkerThreadName[] = "CastExtensionSessionWorkerThread"; 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Interval between each call to PollPeerConnectionStats(). 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const int kStatsLogIntervalSec = 10; 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Minimum frame rate for video streaming over the PeerConnection in frames per 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// second, added as a media constraint when constructing the video source for 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// the Peer Connection. 6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const int kMinFramesPerSecond = 5; 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// A webrtc::SetSessionDescriptionObserver implementation used to receive the 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// results of setting local and remote descriptions of the PeerConnection. 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CastSetSessionDescriptionObserver 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : public webrtc::SetSessionDescriptionObserver { 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public: 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static CastSetSessionDescriptionObserver* Create() { 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return new rtc::RefCountedObject<CastSetSessionDescriptionObserver>(); 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void OnSuccess() OVERRIDE { 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Setting session description succeeded."; 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void OnFailure(const std::string& error) OVERRIDE { 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Setting session description failed: " << error; 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protected: 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastSetSessionDescriptionObserver() {} 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual ~CastSetSessionDescriptionObserver() {} 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CastSetSessionDescriptionObserver); 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}; 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// A webrtc::CreateSessionDescriptionObserver implementation used to receive the 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// results of creating descriptions for this end of the PeerConnection. 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CastCreateSessionDescriptionObserver 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : public webrtc::CreateSessionDescriptionObserver { 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public: 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static CastCreateSessionDescriptionObserver* Create( 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastExtensionSession* session) { 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return new rtc::RefCountedObject<CastCreateSessionDescriptionObserver>( 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) session); 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE { 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (cast_extension_session_ == NULL) { 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << "No CastExtensionSession. Creating session description succeeded."; 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_extension_session_->OnCreateSessionDescription(desc); 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void OnFailure(const std::string& error) OVERRIDE { 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (cast_extension_session_ == NULL) { 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << "No CastExtensionSession. Creating session description failed."; 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_extension_session_->OnCreateSessionDescriptionFailure(error); 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void SetCastExtensionSession(CastExtensionSession* cast_extension_session) { 11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_extension_session_ = cast_extension_session; 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protected: 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) explicit CastCreateSessionDescriptionObserver(CastExtensionSession* session) 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : cast_extension_session_(session) {} 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual ~CastCreateSessionDescriptionObserver() {} 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private: 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastExtensionSession* cast_extension_session_; 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CastCreateSessionDescriptionObserver); 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}; 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// A webrtc::StatsObserver implementation used to receive statistics about the 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// current PeerConnection. 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CastStatsObserver : public webrtc::StatsObserver { 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public: 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static CastStatsObserver* Create() { 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return new rtc::RefCountedObject<CastStatsObserver>(); 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void OnComplete( 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::vector<webrtc::StatsReport>& reports) OVERRIDE { 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) typedef webrtc::StatsReport::Values::iterator ValuesIterator; 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Received " << reports.size() << " new StatsReports."; 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int index; 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::vector<webrtc::StatsReport>::const_iterator it; 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (it = reports.begin(), index = 0; it != reports.end(); ++it, ++index) { 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::StatsReport::Values v = it->values; 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Report " << index << ":"; 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (ValuesIterator vIt = v.begin(); vIt != v.end(); ++vIt) { 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Stat: " << vIt->name << "=" << vIt->value << "."; 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protected: 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastStatsObserver() {} 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual ~CastStatsObserver() {} 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CastStatsObserver); 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}; 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// TODO(aiguha): Fix PeerConnnection-related tear down crash caused by premature 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// destruction of cricket::CaptureManager (which occurs on releasing 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// |peer_conn_factory_|). See crbug.com/403840. 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)CastExtensionSession::~CastExtensionSession() { 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Explicitly clear |create_session_desc_observer_|'s pointer to |this|, 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // since the CastExtensionSession is destructing. Otherwise, 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // |create_session_desc_observer_| would be left with a dangling pointer. 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) create_session_desc_observer_->SetCastExtensionSession(NULL); 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CleanupPeerConnection(); 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)scoped_ptr<CastExtensionSession> CastExtensionSession::Create( 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const protocol::NetworkSettings& network_settings, 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ClientSessionControl* client_session_control, 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protocol::ClientStub* client_stub) { 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<CastExtensionSession> cast_extension_session( 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new CastExtensionSession(caller_task_runner, 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) url_request_context_getter, 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_settings, 18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_session_control, 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_stub)); 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!cast_extension_session->WrapTasksAndSave()) { 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return scoped_ptr<CastExtensionSession>(); 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!cast_extension_session->InitializePeerConnection()) { 19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return scoped_ptr<CastExtensionSession>(); 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return cast_extension_session.Pass(); 19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnCreateSessionDescription( 19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::SessionDescriptionInterface* desc) { 19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!caller_task_runner_->BelongsToCurrentThread()) { 20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) caller_task_runner_->PostTask( 20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&CastExtensionSession::OnCreateSessionDescription, 20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Unretained(this), 20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) desc)); 20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 20603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_->SetLocalDescription( 20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastSetSessionDescriptionObserver::Create(), desc); 21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::DictionaryValue> json(new base::DictionaryValue()); 21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json->SetString(kWebRtcSessionDescType, desc->type()); 21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string subject = 21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (desc->type() == "offer") ? kSubjectOffer : kSubjectAnswer; 21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string desc_str; 21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) desc->ToString(&desc_str); 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json->SetString(kWebRtcSessionDescSDP, desc_str); 21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string json_str; 21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!base::JSONWriter::Write(json.get(), &json_str)) { 22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Failed to serialize sdp message."; 22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SendMessageToClient(subject.c_str(), json_str); 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnCreateSessionDescriptionFailure( 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::string& error) { 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Creating Session Description failed: " << error; 23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// TODO(aiguha): Support the case(s) where we've grabbed the capturer already, 23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// but another extension reset the video pipeline. We should remove the 23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// stream from the peer connection here, and then attempt to re-setup the 23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// peer connection in the OnRenegotiationNeeded() callback. 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// See crbug.com/403843. 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CastExtensionSession::OnCreateVideoCapturer( 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<webrtc::DesktopCapturer>* capturer) { 23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (has_grabbed_capturer_) { 24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "The video pipeline was reset unexpectedly."; 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_grabbed_capturer_ = false; 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_->RemoveStream(stream_.release()); 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (received_offer_) { 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_grabbed_capturer_ = true; 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (SetupVideoStream(capturer->Pass())) { 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_->CreateAnswer(create_session_desc_observer_, NULL); 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_grabbed_capturer_ = false; 25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Ignore the received offer, since we failed to setup a video stream. 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) received_offer_ = false; 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::ModifiesVideoPipeline() const { 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Returns true if the |message| is a Cast ExtensionMessage, even if 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// it was badly formed or a resulting action failed. This is done so that 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// the host does not continue to attempt to pass |message| to other 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// HostExtensionSessions. 26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::OnExtensionMessage( 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ClientSessionControl* client_session_control, 26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protocol::ClientStub* client_stub, 27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const protocol::ExtensionMessage& message) { 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (message.type() != kExtensionMessageType) { 27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(message.data())); 27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* client_message; 27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!(value && value->GetAsDictionary(&client_message))) { 27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Could not read cast extension message."; 27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string subject; 28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!client_message->GetString(kTopLevelSubject, &subject)) { 28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Invalid Cast Extension Message (missing subject header)."; 28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 28803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (subject == kSubjectOffer && !received_offer_) { 28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Reset the video pipeline so we can grab the screen capturer and setup 29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // a video stream. 29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (ParseAndSetRemoteDescription(client_message)) { 29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) received_offer_ = true; 29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(INFO) << "About to ResetVideoPipeline."; 29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_session_control_->ResetVideoPipeline(); 29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (subject == kSubjectAnswer) { 29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ParseAndSetRemoteDescription(client_message); 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (subject == kSubjectNewCandidate) { 30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ParseAndAddICECandidate(client_message); 30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Unexpected CastExtension Message: " << message.data(); 30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Private methods ------------------------------------------------------------ 30803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)CastExtensionSession::CastExtensionSession( 31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, 31203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const protocol::NetworkSettings& network_settings, 31303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ClientSessionControl* client_session_control, 31403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protocol::ClientStub* client_stub) 31503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : caller_task_runner_(caller_task_runner), 31603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) url_request_context_getter_(url_request_context_getter), 31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_settings_(network_settings), 31803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_session_control_(client_session_control), 31903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_stub_(client_stub), 32003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) stats_observer_(CastStatsObserver::Create()), 32103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) received_offer_(false), 32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_grabbed_capturer_(false), 32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) signaling_thread_wrapper_(NULL), 32403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_thread_wrapper_(NULL), 32503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_thread_(kWorkerThreadName) { 32603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(url_request_context_getter_.get()); 32803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(client_session_control_); 32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(client_stub_); 33003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 33103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The worker thread is created with base::MessageLoop::TYPE_IO because 33203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the PeerConnection performs some port allocation operations on this thread 33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // that require it. See crbug.com/404013. 33403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); 33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_thread_.StartWithOptions(options); 33603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_task_runner_ = worker_thread_.task_runner(); 33703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::ParseAndSetRemoteDescription( 34003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* message) { 34103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(peer_connection_.get() != NULL); 34203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* message_data; 34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!message->GetDictionary(kTopLevelData, &message_data)) { 34503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Invalid Cast Extension Message (missing data)."; 34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 34803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 34903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string webrtc_type; 35003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!message_data->GetString(kWebRtcSessionDescType, &webrtc_type)) { 35103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) 35203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << "Invalid Cast Extension Message (missing webrtc type header)."; 35303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 35503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 35603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string sdp; 35703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!message_data->GetString(kWebRtcSessionDescSDP, &sdp)) { 35803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Invalid Cast Extension Message (missing webrtc sdp header)."; 35903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 36003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 36103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 36203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::SdpParseError error; 36303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::SessionDescriptionInterface* session_description( 36403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::CreateSessionDescription(webrtc_type, sdp, &error)); 36503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 36603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!session_description) { 36703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Invalid Cast Extension Message (could not parse sdp)."; 36803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "SdpParseError was: " << error.description; 36903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_->SetRemoteDescription( 37303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastSetSessionDescriptionObserver::Create(), session_description); 37403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 37503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 37603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 37703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::ParseAndAddICECandidate( 37803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* message) { 37903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(peer_connection_.get() != NULL); 38003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 38103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* message_data; 38203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!message->GetDictionary(kTopLevelData, &message_data)) { 38303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Invalid Cast Extension Message (missing data)."; 38403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 38503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 38603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 38703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string candidate_str; 38803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string sdp_mid; 38903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int sdp_mlineindex = 0; 39003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!message_data->GetString(kWebRtcSDPMid, &sdp_mid) || 39103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !message_data->GetInteger(kWebRtcSDPMLineIndex, &sdp_mlineindex) || 39203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !message_data->GetString(kWebRtcCandidate, &candidate_str)) { 39303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Invalid Cast Extension Message (could not parse)."; 39403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 39503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 39603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 39703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) rtc::scoped_ptr<webrtc::IceCandidateInterface> candidate( 39803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, candidate_str)); 39903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!candidate.get()) { 40003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) 40103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << "Invalid Cast Extension Message (could not create candidate)."; 40203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 40303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 40403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 40503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!peer_connection_->AddIceCandidate(candidate.get())) { 40603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Failed to apply received ICE Candidate to PeerConnection."; 40703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 40803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 40903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Received and Added ICE Candidate: " << candidate_str; 41103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 41303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 41403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::SendMessageToClient(const std::string& subject, 41603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::string& data) { 41703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 41803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (client_stub_ == NULL) { 42003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "No Client Stub. Cannot send message to client."; 42103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 42203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 42303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 42403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue message_dict; 42503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) message_dict.SetString(kTopLevelSubject, subject); 42603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) message_dict.SetString(kTopLevelData, data); 42703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string message_json; 42803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 42903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!base::JSONWriter::Write(&message_dict, &message_json)) { 43003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Failed to serialize JSON message."; 43103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 43203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 43303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 43403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) protocol::ExtensionMessage message; 43503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) message.set_type(kExtensionMessageType); 43603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) message.set_data(message_json); 43703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_stub_->DeliverHostMessage(message); 43803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 43903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 44003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 44103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::EnsureTaskAndSetSend(rtc::Thread** ptr, 44203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::WaitableEvent* event) { 44303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); 44403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true); 44503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *ptr = jingle_glue::JingleThreadWrapper::current(); 44603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 44703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (event != NULL) { 44803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event->Signal(); 44903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 45003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 45103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 45203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::WrapTasksAndSave() { 45303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 45403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 45503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EnsureTaskAndSetSend(&signaling_thread_wrapper_); 45603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (signaling_thread_wrapper_ == NULL) 45703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 45803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 45903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::WaitableEvent wrap_worker_thread_event(true, false); 46003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_task_runner_->PostTask( 46103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 46203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&CastExtensionSession::EnsureTaskAndSetSend, 46303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Unretained(this), 46403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &worker_thread_wrapper_, 46503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &wrap_worker_thread_event)); 46603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) wrap_worker_thread_event.Wait(); 46703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 46803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return (worker_thread_wrapper_ != NULL); 46903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 47003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 47103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::InitializePeerConnection() { 47203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 47303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(!peer_conn_factory_); 47403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(!peer_connection_); 47503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(worker_thread_wrapper_ != NULL); 47603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(signaling_thread_wrapper_ != NULL); 47703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 47803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_conn_factory_ = webrtc::CreatePeerConnectionFactory( 47903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_thread_wrapper_, signaling_thread_wrapper_, NULL, NULL, NULL); 48003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 48103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!peer_conn_factory_.get()) { 48203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CleanupPeerConnection(); 48303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 48403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 48503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 48603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Created PeerConnectionFactory successfully."; 48703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 48803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::IceServers servers; 48903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::IceServer server; 49003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) server.uri = kDefaultStunURI; 49103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) servers.push_back(server); 49203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::RTCConfiguration rtc_config; 49303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) rtc_config.servers = servers; 49403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 49503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // DTLS-SRTP is the preferred encryption method. If set to kValueFalse, the 49603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // peer connection uses SDES. Disabling SDES as well will cause the peer 49703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // connection to fail to connect. 49803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Note: For protection and unprotection of SRTP packets, the libjingle 49903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // ENABLE_EXTERNAL_AUTH flag must not be set. 50003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::FakeConstraints constraints; 50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, 50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::MediaConstraintsInterface::kValueTrue); 50303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 50403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface> 50503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) port_allocator_factory = ChromiumPortAllocatorFactory::Create( 50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_settings_, url_request_context_getter_); 50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_ = peer_conn_factory_->CreatePeerConnection( 50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) rtc_config, &constraints, port_allocator_factory, NULL, this); 51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 51103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!peer_connection_.get()) { 51203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CleanupPeerConnection(); 51303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 51403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 51503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 51603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Created PeerConnection successfully."; 51703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 51803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) create_session_desc_observer_ = 51903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CastCreateSessionDescriptionObserver::Create(this); 52003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 52103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Send a test message to the client. Then, notify the client to start 52203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // webrtc offer/answer negotiation. 52303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!SendMessageToClient(kSubjectTest, "Hello, client.") || 52403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !SendMessageToClient(kSubjectReady, "Host ready to receive offers.")) { 52503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Failed to send messages to client."; 52603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 52703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 52803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 52903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 53003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 53103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 53203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::SetupVideoStream( 53303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<webrtc::DesktopCapturer> desktop_capturer) { 53403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 53503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(desktop_capturer); 53603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 53703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (stream_) { 53803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Already added MediaStream. Aborting Setup."; 53903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 54003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 54103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 54203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<CastVideoCapturerAdapter> cast_video_capturer_adapter( 54303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new CastVideoCapturerAdapter(desktop_capturer.Pass())); 54403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 54503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Set video stream constraints. 54603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::FakeConstraints video_constraints; 54703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) video_constraints.AddMandatory( 54803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::MediaConstraintsInterface::kMinFrameRate, kMinFramesPerSecond); 54903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 55003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track = 55103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_conn_factory_->CreateVideoTrack( 55203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) kVideoLabel, 55303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_conn_factory_->CreateVideoSource( 55403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_video_capturer_adapter.release(), &video_constraints)); 55503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 55603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) stream_ = peer_conn_factory_->CreateLocalMediaStream(kStreamLabel); 55703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 55803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!stream_->AddTrack(video_track) || 55903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !peer_connection_->AddStream(stream_, NULL)) { 56003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 56103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 56203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 56303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Setup video stream successfully."; 56403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 56503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 56603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 56703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 56803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::PollPeerConnectionStats() { 56903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!connection_active()) { 57003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Cannot poll stats while PeerConnection is inactive."; 57103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 57203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> video_track = 57303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) stream_->FindVideoTrack(kVideoLabel); 57403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_->GetStats( 57503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) stats_observer_, 57603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) video_track.release(), 57703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::kStatsOutputLevelStandard); 57803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 57903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 58003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::CleanupPeerConnection() { 58103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_->Close(); 58203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_connection_ = NULL; 58303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) stream_ = NULL; 58403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) peer_conn_factory_ = NULL; 58503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) worker_thread_.Stop(); 58603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 58703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 58803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool CastExtensionSession::connection_active() const { 58903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return peer_connection_.get() != NULL; 59003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 59103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 59203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// webrtc::PeerConnectionObserver implementation ------------------------------- 59303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 59403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnError() { 59503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: an error occurred."; 59603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 59703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 59803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnSignalingChange( 59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::SignalingState new_state) { 60003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: SignalingState changed to:" << new_state; 60103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 60203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 60303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnStateChange( 60403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionObserver::StateType state_changed) { 60503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: StateType changed to: " << state_changed; 60603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 60703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 60803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnAddStream(webrtc::MediaStreamInterface* stream) { 60903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: stream added: " << stream->label(); 61003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 61103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 61203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnRemoveStream( 61303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::MediaStreamInterface* stream) { 61403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: stream removed: " << stream->label(); 61503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 61603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 61703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnDataChannel( 61803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::DataChannelInterface* data_channel) { 61903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: data channel: " << data_channel->label(); 62003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 62103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 62203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnRenegotiationNeeded() { 62303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: renegotiation needed."; 62403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 62503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 62603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnIceConnectionChange( 62703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::IceConnectionState new_state) { 62803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: IceConnectionState changed to: " 62903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << new_state; 63003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 63103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // TODO(aiguha): Maybe start timer only if enabled by command-line flag or 63203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // at a particular verbosity level. 63303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!stats_polling_timer_.IsRunning() && 63403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_state == webrtc::PeerConnectionInterface::kIceConnectionConnected) { 63503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) stats_polling_timer_.Start( 63603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 63703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::TimeDelta::FromSeconds(kStatsLogIntervalSec), 63803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this, 63903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &CastExtensionSession::PollPeerConnectionStats); 64003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 64103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 64203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 64303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnIceGatheringChange( 64403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) webrtc::PeerConnectionInterface::IceGatheringState new_state) { 64503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: IceGatheringState changed to: " 64603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << new_state; 64703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 64803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 64903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnIceComplete() { 65003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "PeerConnectionObserver: all ICE candidates found."; 65103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 65203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 65303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CastExtensionSession::OnIceCandidate( 65403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const webrtc::IceCandidateInterface* candidate) { 65503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string candidate_str; 65603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!candidate->ToString(&candidate_str)) { 65703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "PeerConnectionObserver: failed to serialize candidate."; 65803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 65903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 66003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::DictionaryValue> json(new base::DictionaryValue()); 66103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json->SetString(kWebRtcSDPMid, candidate->sdp_mid()); 66203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json->SetInteger(kWebRtcSDPMLineIndex, candidate->sdp_mline_index()); 66303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json->SetString(kWebRtcCandidate, candidate_str); 66403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string json_str; 66503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!base::JSONWriter::Write(json.get(), &json_str)) { 66603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "Failed to serialize candidate message."; 66703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 66803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 66903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SendMessageToClient(kSubjectNewCandidate, json_str); 67003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 67103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 67203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace remoting 673