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