1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/renderer/media/rtc_peer_connection_handler.h" 6 7#include <string> 8#include <utility> 9#include <vector> 10 11#include "base/command_line.h" 12#include "base/logging.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/stl_util.h" 15#include "base/strings/utf_string_conversions.h" 16#include "content/public/common/content_switches.h" 17#include "content/renderer/media/media_stream_dependency_factory.h" 18#include "content/renderer/media/peer_connection_tracker.h" 19#include "content/renderer/media/remote_media_stream_impl.h" 20#include "content/renderer/media/rtc_data_channel_handler.h" 21#include "content/renderer/media/rtc_dtmf_sender_handler.h" 22#include "content/renderer/media/rtc_media_constraints.h" 23#include "content/renderer/render_thread_impl.h" 24#include "third_party/WebKit/public/platform/WebMediaConstraints.h" 25// TODO(hta): Move the following include to WebRTCStatsRequest.h file. 26#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" 27#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" 28#include "third_party/WebKit/public/platform/WebRTCConfiguration.h" 29#include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h" 30#include "third_party/WebKit/public/platform/WebRTCICECandidate.h" 31#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h" 32#include "third_party/WebKit/public/platform/WebRTCSessionDescription.h" 33#include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h" 34#include "third_party/WebKit/public/platform/WebRTCStatsRequest.h" 35#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h" 36#include "third_party/WebKit/public/platform/WebURL.h" 37#include "third_party/WebKit/public/web/WebFrame.h" 38 39namespace content { 40 41// Converter functions from libjingle types to WebKit types. 42WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState 43GetWebKitIceGatheringState( 44 webrtc::PeerConnectionInterface::IceGatheringState state) { 45 using WebKit::WebRTCPeerConnectionHandlerClient; 46 switch (state) { 47 case webrtc::PeerConnectionInterface::kIceGatheringNew: 48 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew; 49 case webrtc::PeerConnectionInterface::kIceGatheringGathering: 50 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering; 51 case webrtc::PeerConnectionInterface::kIceGatheringComplete: 52 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete; 53 default: 54 NOTREACHED(); 55 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew; 56 } 57} 58 59static WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState 60GetWebKitIceConnectionState( 61 webrtc::PeerConnectionInterface::IceConnectionState ice_state) { 62 using WebKit::WebRTCPeerConnectionHandlerClient; 63 switch (ice_state) { 64 case webrtc::PeerConnectionInterface::kIceConnectionNew: 65 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting; 66 case webrtc::PeerConnectionInterface::kIceConnectionChecking: 67 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking; 68 case webrtc::PeerConnectionInterface::kIceConnectionConnected: 69 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected; 70 case webrtc::PeerConnectionInterface::kIceConnectionCompleted: 71 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted; 72 case webrtc::PeerConnectionInterface::kIceConnectionFailed: 73 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed; 74 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected: 75 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected; 76 case webrtc::PeerConnectionInterface::kIceConnectionClosed: 77 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed; 78 default: 79 NOTREACHED(); 80 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed; 81 } 82} 83 84static WebKit::WebRTCPeerConnectionHandlerClient::SignalingState 85GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) { 86 using WebKit::WebRTCPeerConnectionHandlerClient; 87 switch (state) { 88 case webrtc::PeerConnectionInterface::kStable: 89 return WebRTCPeerConnectionHandlerClient::SignalingStateStable; 90 case webrtc::PeerConnectionInterface::kHaveLocalOffer: 91 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer; 92 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: 93 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer; 94 case webrtc::PeerConnectionInterface::kHaveRemoteOffer: 95 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer; 96 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: 97 return 98 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer; 99 case webrtc::PeerConnectionInterface::kClosed: 100 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed; 101 default: 102 NOTREACHED(); 103 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed; 104 } 105} 106 107static WebKit::WebRTCSessionDescription 108CreateWebKitSessionDescription( 109 const webrtc::SessionDescriptionInterface* native_desc) { 110 WebKit::WebRTCSessionDescription description; 111 if (!native_desc) { 112 LOG(ERROR) << "Native session description is null."; 113 return description; 114 } 115 116 std::string sdp; 117 if (!native_desc->ToString(&sdp)) { 118 LOG(ERROR) << "Failed to get SDP string of native session description."; 119 return description; 120 } 121 122 description.initialize(UTF8ToUTF16(native_desc->type()), UTF8ToUTF16(sdp)); 123 return description; 124} 125 126// Converter functions from WebKit types to libjingle types. 127 128static void GetNativeIceServers( 129 const WebKit::WebRTCConfiguration& server_configuration, 130 webrtc::PeerConnectionInterface::IceServers* servers) { 131 if (server_configuration.isNull() || !servers) 132 return; 133 for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) { 134 webrtc::PeerConnectionInterface::IceServer server; 135 const WebKit::WebRTCICEServer& webkit_server = 136 server_configuration.server(i); 137 server.username = UTF16ToUTF8(webkit_server.username()); 138 server.password = UTF16ToUTF8(webkit_server.credential()); 139 server.uri = webkit_server.uri().spec(); 140 servers->push_back(server); 141 } 142} 143 144class SessionDescriptionRequestTracker { 145 public: 146 SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler, 147 PeerConnectionTracker::Action action) 148 : handler_(handler), action_(action) {} 149 150 void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) { 151 std::string value; 152 if (desc) { 153 desc->ToString(&value); 154 value = "type: " + desc->type() + ", sdp: " + value; 155 } 156 if (handler_->peer_connection_tracker()) 157 handler_->peer_connection_tracker()->TrackSessionDescriptionCallback( 158 handler_, action_, "OnSuccess", value); 159 } 160 161 void TrackOnFailure(const std::string& error) { 162 if (handler_->peer_connection_tracker()) 163 handler_->peer_connection_tracker()->TrackSessionDescriptionCallback( 164 handler_, action_, "OnFailure", error); 165 } 166 167 private: 168 RTCPeerConnectionHandler* handler_; 169 PeerConnectionTracker::Action action_; 170}; 171 172// Class mapping responses from calls to libjingle CreateOffer/Answer and 173// the WebKit::WebRTCSessionDescriptionRequest. 174class CreateSessionDescriptionRequest 175 : public webrtc::CreateSessionDescriptionObserver { 176 public: 177 explicit CreateSessionDescriptionRequest( 178 const WebKit::WebRTCSessionDescriptionRequest& request, 179 RTCPeerConnectionHandler* handler, 180 PeerConnectionTracker::Action action) 181 : webkit_request_(request), tracker_(handler, action) {} 182 183 virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE { 184 tracker_.TrackOnSuccess(desc); 185 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc)); 186 } 187 virtual void OnFailure(const std::string& error) OVERRIDE { 188 tracker_.TrackOnFailure(error); 189 webkit_request_.requestFailed(UTF8ToUTF16(error)); 190 } 191 192 protected: 193 virtual ~CreateSessionDescriptionRequest() {} 194 195 private: 196 WebKit::WebRTCSessionDescriptionRequest webkit_request_; 197 SessionDescriptionRequestTracker tracker_; 198}; 199 200// Class mapping responses from calls to libjingle 201// SetLocalDescription/SetRemoteDescription and a WebKit::WebRTCVoidRequest. 202class SetSessionDescriptionRequest 203 : public webrtc::SetSessionDescriptionObserver { 204 public: 205 explicit SetSessionDescriptionRequest( 206 const WebKit::WebRTCVoidRequest& request, 207 RTCPeerConnectionHandler* handler, 208 PeerConnectionTracker::Action action) 209 : webkit_request_(request), tracker_(handler, action) {} 210 211 virtual void OnSuccess() OVERRIDE { 212 tracker_.TrackOnSuccess(NULL); 213 webkit_request_.requestSucceeded(); 214 } 215 virtual void OnFailure(const std::string& error) OVERRIDE { 216 tracker_.TrackOnFailure(error); 217 webkit_request_.requestFailed(UTF8ToUTF16(error)); 218 } 219 220 protected: 221 virtual ~SetSessionDescriptionRequest() {} 222 223 private: 224 WebKit::WebRTCVoidRequest webkit_request_; 225 SessionDescriptionRequestTracker tracker_; 226}; 227 228// Class mapping responses from calls to libjingle 229// GetStats into a WebKit::WebRTCStatsCallback. 230class StatsResponse : public webrtc::StatsObserver { 231 public: 232 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request) 233 : request_(request.get()), response_(request_->createResponse().get()) {} 234 235 virtual void OnComplete( 236 const std::vector<webrtc::StatsReport>& reports) OVERRIDE { 237 for (std::vector<webrtc::StatsReport>::const_iterator it = reports.begin(); 238 it != reports.end(); ++it) { 239 if (it->values.size() > 0) { 240 AddReport(*it); 241 } 242 } 243 request_->requestSucceeded(response_); 244 } 245 246 private: 247 void AddReport(const webrtc::StatsReport& report) { 248 int idx = response_->addReport(WebKit::WebString::fromUTF8(report.id), 249 WebKit::WebString::fromUTF8(report.type), 250 report.timestamp); 251 for (webrtc::StatsReport::Values::const_iterator value_it = 252 report.values.begin(); 253 value_it != report.values.end(); ++value_it) { 254 AddStatistic(idx, value_it->name, value_it->value); 255 } 256 } 257 258 void AddStatistic(int idx, const std::string& name, 259 const std::string& value) { 260 response_->addStatistic(idx, 261 WebKit::WebString::fromUTF8(name), 262 WebKit::WebString::fromUTF8(value)); 263 } 264 265 talk_base::scoped_refptr<LocalRTCStatsRequest> request_; 266 talk_base::scoped_refptr<LocalRTCStatsResponse> response_; 267}; 268 269// Implementation of LocalRTCStatsRequest. 270LocalRTCStatsRequest::LocalRTCStatsRequest(WebKit::WebRTCStatsRequest impl) 271 : impl_(impl), 272 response_(NULL) { 273} 274 275LocalRTCStatsRequest::LocalRTCStatsRequest() {} 276LocalRTCStatsRequest::~LocalRTCStatsRequest() {} 277 278bool LocalRTCStatsRequest::hasSelector() const { 279 return impl_.hasSelector(); 280} 281 282WebKit::WebMediaStream LocalRTCStatsRequest::stream() const { 283 return impl_.stream(); 284} 285 286WebKit::WebMediaStreamTrack LocalRTCStatsRequest::component() const { 287 return impl_.component(); 288} 289 290scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() { 291 DCHECK(!response_); 292 response_ = new talk_base::RefCountedObject<LocalRTCStatsResponse>( 293 impl_.createResponse()); 294 return response_.get(); 295} 296 297void LocalRTCStatsRequest::requestSucceeded( 298 const LocalRTCStatsResponse* response) { 299 impl_.requestSucceeded(response->webKitStatsResponse()); 300} 301 302// Implementation of LocalRTCStatsResponse. 303WebKit::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const { 304 return impl_; 305} 306 307size_t LocalRTCStatsResponse::addReport(WebKit::WebString type, 308 WebKit::WebString id, 309 double timestamp) { 310 return impl_.addReport(type, id, timestamp); 311} 312 313void LocalRTCStatsResponse::addStatistic(size_t report, 314 WebKit::WebString name, 315 WebKit::WebString value) { 316 impl_.addStatistic(report, name, value); 317} 318 319RTCPeerConnectionHandler::RTCPeerConnectionHandler( 320 WebKit::WebRTCPeerConnectionHandlerClient* client, 321 MediaStreamDependencyFactory* dependency_factory) 322 : PeerConnectionHandlerBase(dependency_factory), 323 client_(client), 324 frame_(NULL), 325 peer_connection_tracker_(NULL) { 326} 327 328RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { 329 if (peer_connection_tracker_) 330 peer_connection_tracker_->UnregisterPeerConnection(this); 331 STLDeleteValues(&remote_streams_); 332} 333 334void RTCPeerConnectionHandler::associateWithFrame(WebKit::WebFrame* frame) { 335 DCHECK(frame); 336 frame_ = frame; 337} 338 339bool RTCPeerConnectionHandler::initialize( 340 const WebKit::WebRTCConfiguration& server_configuration, 341 const WebKit::WebMediaConstraints& options) { 342 DCHECK(frame_); 343 344 peer_connection_tracker_ = 345 RenderThreadImpl::current()->peer_connection_tracker(); 346 347 webrtc::PeerConnectionInterface::IceServers servers; 348 GetNativeIceServers(server_configuration, &servers); 349 350 RTCMediaConstraints constraints(options); 351 352 if (CommandLine::ForCurrentProcess()->HasSwitch( 353 switches::kEnableSCTPDataChannels)) { 354 // TODO(jiayl): replace the hard coded string with 355 // webrtc::MediaConstraintsInterface::kEnableSctpDataChannels when 356 // the Libjingle change is rolled. 357 constraints.AddOptional("internalSctpDataChannels", "true"); 358 } 359 360 native_peer_connection_ = 361 dependency_factory_->CreatePeerConnection( 362 servers, &constraints, frame_, this); 363 if (!native_peer_connection_.get()) { 364 LOG(ERROR) << "Failed to initialize native PeerConnection."; 365 return false; 366 } 367 if (peer_connection_tracker_) 368 peer_connection_tracker_->RegisterPeerConnection( 369 this, servers, constraints, frame_); 370 371 return true; 372} 373 374bool RTCPeerConnectionHandler::InitializeForTest( 375 const WebKit::WebRTCConfiguration& server_configuration, 376 const WebKit::WebMediaConstraints& options, 377 PeerConnectionTracker* peer_connection_tracker) { 378 webrtc::PeerConnectionInterface::IceServers servers; 379 GetNativeIceServers(server_configuration, &servers); 380 381 RTCMediaConstraints constraints(options); 382 native_peer_connection_ = 383 dependency_factory_->CreatePeerConnection( 384 servers, &constraints, NULL, this); 385 if (!native_peer_connection_.get()) { 386 LOG(ERROR) << "Failed to initialize native PeerConnection."; 387 return false; 388 } 389 peer_connection_tracker_ = peer_connection_tracker; 390 return true; 391} 392 393void RTCPeerConnectionHandler::createOffer( 394 const WebKit::WebRTCSessionDescriptionRequest& request, 395 const WebKit::WebMediaConstraints& options) { 396 scoped_refptr<CreateSessionDescriptionRequest> description_request( 397 new talk_base::RefCountedObject<CreateSessionDescriptionRequest>( 398 request, this, PeerConnectionTracker::ACTION_CREATE_OFFER)); 399 RTCMediaConstraints constraints(options); 400 native_peer_connection_->CreateOffer(description_request.get(), &constraints); 401 402 if (peer_connection_tracker_) 403 peer_connection_tracker_->TrackCreateOffer(this, constraints); 404} 405 406void RTCPeerConnectionHandler::createAnswer( 407 const WebKit::WebRTCSessionDescriptionRequest& request, 408 const WebKit::WebMediaConstraints& options) { 409 scoped_refptr<CreateSessionDescriptionRequest> description_request( 410 new talk_base::RefCountedObject<CreateSessionDescriptionRequest>( 411 request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER)); 412 RTCMediaConstraints constraints(options); 413 native_peer_connection_->CreateAnswer(description_request.get(), 414 &constraints); 415 416 if (peer_connection_tracker_) 417 peer_connection_tracker_->TrackCreateAnswer(this, constraints); 418} 419 420void RTCPeerConnectionHandler::setLocalDescription( 421 const WebKit::WebRTCVoidRequest& request, 422 const WebKit::WebRTCSessionDescription& description) { 423 webrtc::SdpParseError error; 424 webrtc::SessionDescriptionInterface* native_desc = 425 CreateNativeSessionDescription(description, &error); 426 if (!native_desc) { 427 std::string reason_str = "Failed to parse SessionDescription. "; 428 reason_str.append(error.line); 429 reason_str.append(" "); 430 reason_str.append(error.description); 431 LOG(ERROR) << reason_str; 432 request.requestFailed(WebKit::WebString::fromUTF8(reason_str)); 433 return; 434 } 435 if (peer_connection_tracker_) 436 peer_connection_tracker_->TrackSetSessionDescription( 437 this, description, PeerConnectionTracker::SOURCE_LOCAL); 438 439 scoped_refptr<SetSessionDescriptionRequest> set_request( 440 new talk_base::RefCountedObject<SetSessionDescriptionRequest>( 441 request, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION)); 442 native_peer_connection_->SetLocalDescription(set_request.get(), native_desc); 443} 444 445void RTCPeerConnectionHandler::setRemoteDescription( 446 const WebKit::WebRTCVoidRequest& request, 447 const WebKit::WebRTCSessionDescription& description) { 448 webrtc::SdpParseError error; 449 webrtc::SessionDescriptionInterface* native_desc = 450 CreateNativeSessionDescription(description, &error); 451 if (!native_desc) { 452 std::string reason_str = "Failed to parse SessionDescription. "; 453 reason_str.append(error.line); 454 reason_str.append(" "); 455 reason_str.append(error.description); 456 LOG(ERROR) << reason_str; 457 request.requestFailed(WebKit::WebString::fromUTF8(reason_str)); 458 return; 459 } 460 if (peer_connection_tracker_) 461 peer_connection_tracker_->TrackSetSessionDescription( 462 this, description, PeerConnectionTracker::SOURCE_REMOTE); 463 464 scoped_refptr<SetSessionDescriptionRequest> set_request( 465 new talk_base::RefCountedObject<SetSessionDescriptionRequest>( 466 request, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION)); 467 native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc); 468} 469 470WebKit::WebRTCSessionDescription 471RTCPeerConnectionHandler::localDescription() { 472 const webrtc::SessionDescriptionInterface* native_desc = 473 native_peer_connection_->local_description(); 474 WebKit::WebRTCSessionDescription description = 475 CreateWebKitSessionDescription(native_desc); 476 return description; 477} 478 479WebKit::WebRTCSessionDescription 480RTCPeerConnectionHandler::remoteDescription() { 481 const webrtc::SessionDescriptionInterface* native_desc = 482 native_peer_connection_->remote_description(); 483 WebKit::WebRTCSessionDescription description = 484 CreateWebKitSessionDescription(native_desc); 485 return description; 486} 487 488bool RTCPeerConnectionHandler::updateICE( 489 const WebKit::WebRTCConfiguration& server_configuration, 490 const WebKit::WebMediaConstraints& options) { 491 webrtc::PeerConnectionInterface::IceServers servers; 492 GetNativeIceServers(server_configuration, &servers); 493 RTCMediaConstraints constraints(options); 494 495 if (peer_connection_tracker_) 496 peer_connection_tracker_->TrackUpdateIce(this, servers, constraints); 497 498 return native_peer_connection_->UpdateIce(servers, 499 &constraints); 500} 501 502bool RTCPeerConnectionHandler::addICECandidate( 503 const WebKit::WebRTCICECandidate& candidate) { 504 scoped_ptr<webrtc::IceCandidateInterface> native_candidate( 505 dependency_factory_->CreateIceCandidate( 506 UTF16ToUTF8(candidate.sdpMid()), 507 candidate.sdpMLineIndex(), 508 UTF16ToUTF8(candidate.candidate()))); 509 if (!native_candidate) { 510 LOG(ERROR) << "Could not create native ICE candidate."; 511 return false; 512 } 513 514 bool return_value = 515 native_peer_connection_->AddIceCandidate(native_candidate.get()); 516 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate."; 517 518 if (peer_connection_tracker_) 519 peer_connection_tracker_->TrackAddIceCandidate( 520 this, candidate, PeerConnectionTracker::SOURCE_REMOTE); 521 522 return return_value; 523} 524 525bool RTCPeerConnectionHandler::addStream( 526 const WebKit::WebMediaStream& stream, 527 const WebKit::WebMediaConstraints& options) { 528 RTCMediaConstraints constraints(options); 529 530 if (peer_connection_tracker_) 531 peer_connection_tracker_->TrackAddStream( 532 this, stream, PeerConnectionTracker::SOURCE_LOCAL); 533 return AddStream(stream, &constraints); 534} 535 536void RTCPeerConnectionHandler::removeStream( 537 const WebKit::WebMediaStream& stream) { 538 RemoveStream(stream); 539 if (peer_connection_tracker_) 540 peer_connection_tracker_->TrackRemoveStream( 541 this, stream, PeerConnectionTracker::SOURCE_LOCAL); 542} 543 544void RTCPeerConnectionHandler::getStats( 545 const WebKit::WebRTCStatsRequest& request) { 546 scoped_refptr<LocalRTCStatsRequest> inner_request( 547 new talk_base::RefCountedObject<LocalRTCStatsRequest>(request)); 548 getStats(inner_request.get()); 549} 550 551void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) { 552 talk_base::scoped_refptr<webrtc::StatsObserver> observer( 553 new talk_base::RefCountedObject<StatsResponse>(request)); 554 webrtc::MediaStreamTrackInterface* track = NULL; 555 if (request->hasSelector()) { 556 track = GetNativeMediaStreamTrack(request->stream(), 557 request->component()); 558 if (!track) { 559 DVLOG(1) << "GetStats: Track not found."; 560 // TODO(hta): Consider how to get an error back. 561 std::vector<webrtc::StatsReport> no_reports; 562 observer->OnComplete(no_reports); 563 return; 564 } 565 } 566 GetStats(observer, track); 567} 568 569void RTCPeerConnectionHandler::GetStats( 570 webrtc::StatsObserver* observer, 571 webrtc::MediaStreamTrackInterface* track) { 572 if (!native_peer_connection_->GetStats(observer, track)) { 573 DVLOG(1) << "GetStats failed."; 574 // TODO(hta): Consider how to get an error back. 575 std::vector<webrtc::StatsReport> no_reports; 576 observer->OnComplete(no_reports); 577 return; 578 } 579} 580 581WebKit::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel( 582 const WebKit::WebString& label, const WebKit::WebRTCDataChannelInit& init) { 583 DVLOG(1) << "createDataChannel label " << UTF16ToUTF8(label); 584 585 webrtc::DataChannelInit config; 586 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated 587 // to handle that. 588 config.reliable = false; 589 config.id = init.id; 590 config.ordered = init.ordered; 591 config.negotiated = init.negotiated; 592 config.maxRetransmits = init.maxRetransmits; 593 config.maxRetransmitTime = init.maxRetransmitTime; 594 config.protocol = UTF16ToUTF8(init.protocol); 595 596 talk_base::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel( 597 native_peer_connection_->CreateDataChannel(UTF16ToUTF8(label), &config)); 598 if (!webrtc_channel) { 599 DLOG(ERROR) << "Could not create native data channel."; 600 return NULL; 601 } 602 if (peer_connection_tracker_) 603 peer_connection_tracker_->TrackCreateDataChannel( 604 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL); 605 606 return new RtcDataChannelHandler(webrtc_channel); 607} 608 609WebKit::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender( 610 const WebKit::WebMediaStreamTrack& track) { 611 DVLOG(1) << "createDTMFSender."; 612 613 if (track.source().type() != WebKit::WebMediaStreamSource::TypeAudio) { 614 DLOG(ERROR) << "Could not create DTMF sender from a non-audio track."; 615 return NULL; 616 } 617 618 webrtc::AudioTrackInterface* audio_track = 619 static_cast<webrtc::AudioTrackInterface*>( 620 GetNativeMediaStreamTrack(track.stream(), track)); 621 622 talk_base::scoped_refptr<webrtc::DtmfSenderInterface> sender( 623 native_peer_connection_->CreateDtmfSender(audio_track)); 624 if (!sender) { 625 DLOG(ERROR) << "Could not create native DTMF sender."; 626 return NULL; 627 } 628 if (peer_connection_tracker_) 629 peer_connection_tracker_->TrackCreateDTMFSender(this, track); 630 631 return new RtcDtmfSenderHandler(sender); 632} 633 634void RTCPeerConnectionHandler::stop() { 635 DVLOG(1) << "RTCPeerConnectionHandler::stop"; 636 637 if (peer_connection_tracker_) 638 peer_connection_tracker_->TrackStop(this); 639 native_peer_connection_->Close(); 640} 641 642void RTCPeerConnectionHandler::OnError() { 643 // TODO(perkj): Implement. 644 NOTIMPLEMENTED(); 645} 646 647void RTCPeerConnectionHandler::OnSignalingChange( 648 webrtc::PeerConnectionInterface::SignalingState new_state) { 649 WebKit::WebRTCPeerConnectionHandlerClient::SignalingState state = 650 GetWebKitSignalingState(new_state); 651 if (peer_connection_tracker_) 652 peer_connection_tracker_->TrackSignalingStateChange(this, state); 653 client_->didChangeSignalingState(state); 654} 655 656// Called any time the IceConnectionState changes 657void RTCPeerConnectionHandler::OnIceConnectionChange( 658 webrtc::PeerConnectionInterface::IceConnectionState new_state) { 659 WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState state = 660 GetWebKitIceConnectionState(new_state); 661 if (peer_connection_tracker_) 662 peer_connection_tracker_->TrackIceConnectionStateChange(this, state); 663 client_->didChangeICEConnectionState(state); 664} 665 666// Called any time the IceGatheringState changes 667void RTCPeerConnectionHandler::OnIceGatheringChange( 668 webrtc::PeerConnectionInterface::IceGatheringState new_state) { 669 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) { 670 // If ICE gathering is completed, generate a NULL ICE candidate, 671 // to signal end of candidates. 672 WebKit::WebRTCICECandidate null_candidate; 673 client_->didGenerateICECandidate(null_candidate); 674 } 675 676 WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState state = 677 GetWebKitIceGatheringState(new_state); 678 if (peer_connection_tracker_) 679 peer_connection_tracker_->TrackIceGatheringStateChange(this, state); 680 client_->didChangeICEGatheringState(state); 681} 682 683void RTCPeerConnectionHandler::OnAddStream( 684 webrtc::MediaStreamInterface* stream_interface) { 685 DCHECK(stream_interface); 686 DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end()); 687 688 RemoteMediaStreamImpl* remote_stream = 689 new RemoteMediaStreamImpl(stream_interface); 690 remote_streams_.insert( 691 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> ( 692 stream_interface, remote_stream)); 693 694 if (peer_connection_tracker_) 695 peer_connection_tracker_->TrackAddStream( 696 this, remote_stream->webkit_stream(), 697 PeerConnectionTracker::SOURCE_REMOTE); 698 699 client_->didAddRemoteStream(remote_stream->webkit_stream()); 700} 701 702void RTCPeerConnectionHandler::OnRemoveStream( 703 webrtc::MediaStreamInterface* stream_interface) { 704 DCHECK(stream_interface); 705 RemoteStreamMap::iterator it = remote_streams_.find(stream_interface); 706 if (it == remote_streams_.end()) { 707 NOTREACHED() << "Stream not found"; 708 return; 709 } 710 711 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second); 712 const WebKit::WebMediaStream& webkit_stream = remote_stream->webkit_stream(); 713 DCHECK(!webkit_stream.isNull()); 714 remote_streams_.erase(it); 715 716 if (peer_connection_tracker_) 717 peer_connection_tracker_->TrackRemoveStream( 718 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE); 719 720 client_->didRemoveRemoteStream(webkit_stream); 721} 722 723void RTCPeerConnectionHandler::OnIceCandidate( 724 const webrtc::IceCandidateInterface* candidate) { 725 DCHECK(candidate); 726 std::string sdp; 727 if (!candidate->ToString(&sdp)) { 728 NOTREACHED() << "OnIceCandidate: Could not get SDP string."; 729 return; 730 } 731 WebKit::WebRTCICECandidate web_candidate; 732 web_candidate.initialize(UTF8ToUTF16(sdp), 733 UTF8ToUTF16(candidate->sdp_mid()), 734 candidate->sdp_mline_index()); 735 if (peer_connection_tracker_) 736 peer_connection_tracker_->TrackAddIceCandidate( 737 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL); 738 739 client_->didGenerateICECandidate(web_candidate); 740} 741 742void RTCPeerConnectionHandler::OnDataChannel( 743 webrtc::DataChannelInterface* data_channel) { 744 if (peer_connection_tracker_) 745 peer_connection_tracker_->TrackCreateDataChannel( 746 this, data_channel, PeerConnectionTracker::SOURCE_REMOTE); 747 748 DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel " 749 << data_channel->label(); 750 client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel)); 751} 752 753void RTCPeerConnectionHandler::OnRenegotiationNeeded() { 754 if (peer_connection_tracker_) 755 peer_connection_tracker_->TrackOnRenegotiationNeeded(this); 756 client_->negotiationNeeded(); 757} 758 759PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() { 760 return peer_connection_tracker_; 761} 762 763webrtc::SessionDescriptionInterface* 764RTCPeerConnectionHandler::CreateNativeSessionDescription( 765 const WebKit::WebRTCSessionDescription& description, 766 webrtc::SdpParseError* error) { 767 std::string sdp = UTF16ToUTF8(description.sdp()); 768 std::string type = UTF16ToUTF8(description.type()); 769 webrtc::SessionDescriptionInterface* native_desc = 770 dependency_factory_->CreateSessionDescription(type, sdp, error); 771 772 LOG_IF(ERROR, !native_desc) << "Failed to create native session description." 773 << " Type: " << type << " SDP: " << sdp; 774 775 return native_desc; 776} 777 778} // namespace content 779