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