Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
bloba86dc6b95cbd2da8eb3df670a2aad382d931b21c
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.
5 #include "content/renderer/media/rtc_peer_connection_handler.h"
7 #include <string>
8 #include <utility>
9 #include <vector>
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/WebRTCOfferOptions.h"
38 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
39 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
40 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
41 #include "third_party/WebKit/public/platform/WebURL.h"
43 using webrtc::StatsReport;
44 using webrtc::StatsReports;
46 namespace content {
48 // Converter functions from libjingle types to WebKit types.
49 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
50 GetWebKitIceGatheringState(
51 webrtc::PeerConnectionInterface::IceGatheringState state) {
52 using blink::WebRTCPeerConnectionHandlerClient;
53 switch (state) {
54 case webrtc::PeerConnectionInterface::kIceGatheringNew:
55 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
56 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
57 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering;
58 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
59 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete;
60 default:
61 NOTREACHED();
62 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
66 static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
67 GetWebKitIceConnectionState(
68 webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
69 using blink::WebRTCPeerConnectionHandlerClient;
70 switch (ice_state) {
71 case webrtc::PeerConnectionInterface::kIceConnectionNew:
72 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
73 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
74 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking;
75 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
76 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected;
77 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
78 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted;
79 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
80 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed;
81 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
82 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected;
83 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
84 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
85 default:
86 NOTREACHED();
87 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
91 static blink::WebRTCPeerConnectionHandlerClient::SignalingState
92 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
93 using blink::WebRTCPeerConnectionHandlerClient;
94 switch (state) {
95 case webrtc::PeerConnectionInterface::kStable:
96 return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
97 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
98 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer;
99 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
100 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer;
101 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
102 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer;
103 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
104 return
105 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer;
106 case webrtc::PeerConnectionInterface::kClosed:
107 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
108 default:
109 NOTREACHED();
110 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
114 static blink::WebRTCSessionDescription
115 CreateWebKitSessionDescription(
116 const webrtc::SessionDescriptionInterface* native_desc) {
117 blink::WebRTCSessionDescription description;
118 if (!native_desc) {
119 LOG(ERROR) << "Native session description is null.";
120 return description;
123 std::string sdp;
124 if (!native_desc->ToString(&sdp)) {
125 LOG(ERROR) << "Failed to get SDP string of native session description.";
126 return description;
129 description.initialize(base::UTF8ToUTF16(native_desc->type()),
130 base::UTF8ToUTF16(sdp));
131 return description;
134 // Converter functions from WebKit types to libjingle types.
136 static void GetNativeRtcConfiguration(
137 const blink::WebRTCConfiguration& server_configuration,
138 webrtc::PeerConnectionInterface::RTCConfiguration* config) {
139 if (server_configuration.isNull() || !config)
140 return;
141 for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) {
142 webrtc::PeerConnectionInterface::IceServer server;
143 const blink::WebRTCICEServer& webkit_server =
144 server_configuration.server(i);
145 server.username = base::UTF16ToUTF8(webkit_server.username());
146 server.password = base::UTF16ToUTF8(webkit_server.credential());
147 server.uri = webkit_server.uri().spec();
148 config->servers.push_back(server);
151 switch (server_configuration.iceTransports()) {
152 case blink::WebRTCIceTransportsNone:
153 config->type = webrtc::PeerConnectionInterface::kNone;
154 break;
155 case blink::WebRTCIceTransportsRelay:
156 config->type = webrtc::PeerConnectionInterface::kRelay;
157 break;
158 case blink::WebRTCIceTransportsAll:
159 config->type = webrtc::PeerConnectionInterface::kAll;
160 break;
161 default:
162 NOTREACHED();
166 class SessionDescriptionRequestTracker {
167 public:
168 SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler,
169 PeerConnectionTracker::Action action)
170 : handler_(handler), action_(action) {}
172 void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
173 std::string value;
174 if (desc) {
175 desc->ToString(&value);
176 value = "type: " + desc->type() + ", sdp: " + value;
178 if (handler_->peer_connection_tracker())
179 handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
180 handler_, action_, "OnSuccess", value);
183 void TrackOnFailure(const std::string& error) {
184 if (handler_->peer_connection_tracker())
185 handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
186 handler_, action_, "OnFailure", error);
189 private:
190 RTCPeerConnectionHandler* handler_;
191 PeerConnectionTracker::Action action_;
194 // Class mapping responses from calls to libjingle CreateOffer/Answer and
195 // the blink::WebRTCSessionDescriptionRequest.
196 class CreateSessionDescriptionRequest
197 : public webrtc::CreateSessionDescriptionObserver {
198 public:
199 explicit CreateSessionDescriptionRequest(
200 const blink::WebRTCSessionDescriptionRequest& request,
201 RTCPeerConnectionHandler* handler,
202 PeerConnectionTracker::Action action)
203 : webkit_request_(request), tracker_(handler, action) {}
205 virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE {
206 tracker_.TrackOnSuccess(desc);
207 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
208 delete desc;
210 virtual void OnFailure(const std::string& error) OVERRIDE {
211 tracker_.TrackOnFailure(error);
212 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
215 protected:
216 virtual ~CreateSessionDescriptionRequest() {}
218 private:
219 blink::WebRTCSessionDescriptionRequest webkit_request_;
220 SessionDescriptionRequestTracker tracker_;
223 // Class mapping responses from calls to libjingle
224 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
225 class SetSessionDescriptionRequest
226 : public webrtc::SetSessionDescriptionObserver {
227 public:
228 explicit SetSessionDescriptionRequest(
229 const blink::WebRTCVoidRequest& request,
230 RTCPeerConnectionHandler* handler,
231 PeerConnectionTracker::Action action)
232 : webkit_request_(request), tracker_(handler, action) {}
234 virtual void OnSuccess() OVERRIDE {
235 tracker_.TrackOnSuccess(NULL);
236 webkit_request_.requestSucceeded();
238 virtual void OnFailure(const std::string& error) OVERRIDE {
239 tracker_.TrackOnFailure(error);
240 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
243 protected:
244 virtual ~SetSessionDescriptionRequest() {}
246 private:
247 blink::WebRTCVoidRequest webkit_request_;
248 SessionDescriptionRequestTracker tracker_;
251 // Class mapping responses from calls to libjingle
252 // GetStats into a blink::WebRTCStatsCallback.
253 class StatsResponse : public webrtc::StatsObserver {
254 public:
255 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
256 : request_(request.get()), response_(request_->createResponse().get()) {
257 // Measure the overall time it takes to satisfy a getStats request.
258 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
261 virtual void OnComplete(const StatsReports& reports) OVERRIDE {
262 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete")
263 for (StatsReports::const_iterator it = reports.begin();
264 it != reports.end(); ++it) {
265 if ((*it)->values.size() > 0) {
266 AddReport(*(*it));
270 // Record the getSync operation as done before calling into Blink so that
271 // we don't skew the perf measurements of the native code with whatever the
272 // callback might be doing.
273 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
275 request_->requestSucceeded(response_);
278 private:
279 void AddReport(const StatsReport& report) {
280 int idx = response_->addReport(blink::WebString::fromUTF8(report.id),
281 blink::WebString::fromUTF8(report.type),
282 report.timestamp);
283 for (StatsReport::Values::const_iterator value_it = report.values.begin();
284 value_it != report.values.end(); ++value_it) {
285 AddStatistic(idx, value_it->display_name(), value_it->value);
289 void AddStatistic(int idx, const char* name, const std::string& value) {
290 response_->addStatistic(idx,
291 blink::WebString::fromUTF8(name),
292 blink::WebString::fromUTF8(value));
295 rtc::scoped_refptr<LocalRTCStatsRequest> request_;
296 rtc::scoped_refptr<LocalRTCStatsResponse> response_;
299 // Implementation of LocalRTCStatsRequest.
300 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
301 : impl_(impl),
302 response_(NULL) {
305 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
306 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
308 bool LocalRTCStatsRequest::hasSelector() const {
309 return impl_.hasSelector();
312 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
313 return impl_.component();
316 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
317 DCHECK(!response_);
318 response_ = new rtc::RefCountedObject<LocalRTCStatsResponse>(
319 impl_.createResponse());
320 return response_.get();
323 void LocalRTCStatsRequest::requestSucceeded(
324 const LocalRTCStatsResponse* response) {
325 impl_.requestSucceeded(response->webKitStatsResponse());
328 // Implementation of LocalRTCStatsResponse.
329 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
330 return impl_;
333 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
334 blink::WebString id,
335 double timestamp) {
336 return impl_.addReport(type, id, timestamp);
339 void LocalRTCStatsResponse::addStatistic(size_t report,
340 blink::WebString name,
341 blink::WebString value) {
342 impl_.addStatistic(report, name, value);
345 namespace {
347 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
348 public:
349 PeerConnectionUMAObserver() {}
350 virtual ~PeerConnectionUMAObserver() {}
352 virtual void IncrementCounter(
353 webrtc::PeerConnectionUMAMetricsCounter counter) OVERRIDE {
354 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
355 counter,
356 webrtc::kBoundary);
359 virtual void AddHistogramSample(
360 webrtc::PeerConnectionUMAMetricsName type, int value) OVERRIDE {
361 switch (type) {
362 case webrtc::kTimeToConnect:
363 UMA_HISTOGRAM_MEDIUM_TIMES(
364 "WebRTC.PeerConnection.TimeToConnect",
365 base::TimeDelta::FromMilliseconds(value));
366 break;
367 case webrtc::kNetworkInterfaces_IPv4:
368 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
369 value);
370 break;
371 case webrtc::kNetworkInterfaces_IPv6:
372 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
373 value);
374 break;
375 default:
376 NOTREACHED();
381 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
382 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
384 } // namespace
386 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
387 blink::WebRTCPeerConnectionHandlerClient* client,
388 PeerConnectionDependencyFactory* dependency_factory)
389 : client_(client),
390 dependency_factory_(dependency_factory),
391 frame_(NULL),
392 peer_connection_tracker_(NULL),
393 num_data_channels_created_(0) {
394 g_peer_connection_handlers.Get().insert(this);
397 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
398 g_peer_connection_handlers.Get().erase(this);
399 if (peer_connection_tracker_)
400 peer_connection_tracker_->UnregisterPeerConnection(this);
401 STLDeleteValues(&remote_streams_);
403 UMA_HISTOGRAM_COUNTS_10000(
404 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
407 // static
408 void RTCPeerConnectionHandler::DestructAllHandlers() {
409 std::set<RTCPeerConnectionHandler*> handlers(
410 g_peer_connection_handlers.Get().begin(),
411 g_peer_connection_handlers.Get().end());
412 for (std::set<RTCPeerConnectionHandler*>::iterator handler = handlers.begin();
413 handler != handlers.end();
414 ++handler) {
415 (*handler)->client_->releasePeerConnectionHandler();
419 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
420 const blink::WebRTCOfferOptions& options,
421 RTCMediaConstraints* output) {
422 output->AddMandatory(
423 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
424 options.offerToReceiveAudio() > 0 ? "true" : "false",
425 true);
427 output->AddMandatory(
428 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
429 options.offerToReceiveVideo() > 0 ? "true" : "false",
430 true);
432 if (!options.voiceActivityDetection()) {
433 output->AddMandatory(
434 webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
435 "false",
436 true);
439 if (options.iceRestart()) {
440 output->AddMandatory(
441 webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
445 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
446 DCHECK(frame);
447 frame_ = frame;
450 bool RTCPeerConnectionHandler::initialize(
451 const blink::WebRTCConfiguration& server_configuration,
452 const blink::WebMediaConstraints& options) {
453 DCHECK(frame_);
455 peer_connection_tracker_ =
456 RenderThreadImpl::current()->peer_connection_tracker();
458 webrtc::PeerConnectionInterface::RTCConfiguration config;
459 GetNativeRtcConfiguration(server_configuration, &config);
461 RTCMediaConstraints constraints(options);
463 native_peer_connection_ =
464 dependency_factory_->CreatePeerConnection(
465 config, &constraints, frame_, this);
467 if (!native_peer_connection_.get()) {
468 LOG(ERROR) << "Failed to initialize native PeerConnection.";
469 return false;
471 if (peer_connection_tracker_)
472 peer_connection_tracker_->RegisterPeerConnection(
473 this, config, constraints, frame_);
475 uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
476 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
477 return true;
480 bool RTCPeerConnectionHandler::InitializeForTest(
481 const blink::WebRTCConfiguration& server_configuration,
482 const blink::WebMediaConstraints& options,
483 PeerConnectionTracker* peer_connection_tracker) {
484 webrtc::PeerConnectionInterface::RTCConfiguration config;
485 GetNativeRtcConfiguration(server_configuration, &config);
487 RTCMediaConstraints constraints(options);
488 native_peer_connection_ =
489 dependency_factory_->CreatePeerConnection(
490 config, &constraints, NULL, this);
491 if (!native_peer_connection_.get()) {
492 LOG(ERROR) << "Failed to initialize native PeerConnection.";
493 return false;
495 peer_connection_tracker_ = peer_connection_tracker;
496 return true;
499 void RTCPeerConnectionHandler::createOffer(
500 const blink::WebRTCSessionDescriptionRequest& request,
501 const blink::WebMediaConstraints& options) {
502 scoped_refptr<CreateSessionDescriptionRequest> description_request(
503 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
504 request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
505 RTCMediaConstraints constraints(options);
506 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
508 if (peer_connection_tracker_)
509 peer_connection_tracker_->TrackCreateOffer(this, constraints);
512 void RTCPeerConnectionHandler::createOffer(
513 const blink::WebRTCSessionDescriptionRequest& request,
514 const blink::WebRTCOfferOptions& options) {
515 scoped_refptr<CreateSessionDescriptionRequest> description_request(
516 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
517 request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
519 RTCMediaConstraints constraints;
520 ConvertOfferOptionsToConstraints(options, &constraints);
521 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
523 if (peer_connection_tracker_)
524 peer_connection_tracker_->TrackCreateOffer(this, constraints);
527 void RTCPeerConnectionHandler::createAnswer(
528 const blink::WebRTCSessionDescriptionRequest& request,
529 const blink::WebMediaConstraints& options) {
530 scoped_refptr<CreateSessionDescriptionRequest> description_request(
531 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
532 request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER));
533 RTCMediaConstraints constraints(options);
534 native_peer_connection_->CreateAnswer(description_request.get(),
535 &constraints);
537 if (peer_connection_tracker_)
538 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
541 void RTCPeerConnectionHandler::setLocalDescription(
542 const blink::WebRTCVoidRequest& request,
543 const blink::WebRTCSessionDescription& description) {
544 webrtc::SdpParseError error;
545 webrtc::SessionDescriptionInterface* native_desc =
546 CreateNativeSessionDescription(description, &error);
547 if (!native_desc) {
548 std::string reason_str = "Failed to parse SessionDescription. ";
549 reason_str.append(error.line);
550 reason_str.append(" ");
551 reason_str.append(error.description);
552 LOG(ERROR) << reason_str;
553 request.requestFailed(blink::WebString::fromUTF8(reason_str));
554 return;
556 if (peer_connection_tracker_)
557 peer_connection_tracker_->TrackSetSessionDescription(
558 this, description, PeerConnectionTracker::SOURCE_LOCAL);
560 scoped_refptr<SetSessionDescriptionRequest> set_request(
561 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
562 request, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
563 native_peer_connection_->SetLocalDescription(set_request.get(), native_desc);
566 void RTCPeerConnectionHandler::setRemoteDescription(
567 const blink::WebRTCVoidRequest& request,
568 const blink::WebRTCSessionDescription& description) {
569 webrtc::SdpParseError error;
570 webrtc::SessionDescriptionInterface* native_desc =
571 CreateNativeSessionDescription(description, &error);
572 if (!native_desc) {
573 std::string reason_str = "Failed to parse SessionDescription. ";
574 reason_str.append(error.line);
575 reason_str.append(" ");
576 reason_str.append(error.description);
577 LOG(ERROR) << reason_str;
578 request.requestFailed(blink::WebString::fromUTF8(reason_str));
579 return;
581 if (peer_connection_tracker_)
582 peer_connection_tracker_->TrackSetSessionDescription(
583 this, description, PeerConnectionTracker::SOURCE_REMOTE);
585 scoped_refptr<SetSessionDescriptionRequest> set_request(
586 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
587 request, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
588 native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc);
591 blink::WebRTCSessionDescription
592 RTCPeerConnectionHandler::localDescription() {
593 const webrtc::SessionDescriptionInterface* native_desc =
594 native_peer_connection_->local_description();
595 blink::WebRTCSessionDescription description =
596 CreateWebKitSessionDescription(native_desc);
597 return description;
600 blink::WebRTCSessionDescription
601 RTCPeerConnectionHandler::remoteDescription() {
602 const webrtc::SessionDescriptionInterface* native_desc =
603 native_peer_connection_->remote_description();
604 blink::WebRTCSessionDescription description =
605 CreateWebKitSessionDescription(native_desc);
606 return description;
609 bool RTCPeerConnectionHandler::updateICE(
610 const blink::WebRTCConfiguration& server_configuration,
611 const blink::WebMediaConstraints& options) {
612 webrtc::PeerConnectionInterface::RTCConfiguration config;
613 GetNativeRtcConfiguration(server_configuration, &config);
614 RTCMediaConstraints constraints(options);
616 if (peer_connection_tracker_)
617 peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
619 return native_peer_connection_->UpdateIce(config.servers,
620 &constraints);
623 bool RTCPeerConnectionHandler::addICECandidate(
624 const blink::WebRTCVoidRequest& request,
625 const blink::WebRTCICECandidate& candidate) {
626 // Libjingle currently does not accept callbacks for addICECandidate.
627 // For that reason we are going to call callbacks from here.
628 bool result = addICECandidate(candidate);
629 base::MessageLoop::current()->PostTask(
630 FROM_HERE,
631 base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
632 base::Unretained(this), request, result));
633 // On failure callback will be triggered.
634 return true;
637 bool RTCPeerConnectionHandler::addICECandidate(
638 const blink::WebRTCICECandidate& candidate) {
639 scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
640 dependency_factory_->CreateIceCandidate(
641 base::UTF16ToUTF8(candidate.sdpMid()),
642 candidate.sdpMLineIndex(),
643 base::UTF16ToUTF8(candidate.candidate())));
644 if (!native_candidate) {
645 LOG(ERROR) << "Could not create native ICE candidate.";
646 return false;
649 bool return_value =
650 native_peer_connection_->AddIceCandidate(native_candidate.get());
651 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
653 if (peer_connection_tracker_)
654 peer_connection_tracker_->TrackAddIceCandidate(
655 this, candidate, PeerConnectionTracker::SOURCE_REMOTE);
657 return return_value;
660 void RTCPeerConnectionHandler::OnaddICECandidateResult(
661 const blink::WebRTCVoidRequest& webkit_request, bool result) {
662 if (!result) {
663 // We don't have the actual error code from the libjingle, so for now
664 // using a generic error string.
665 return webkit_request.requestFailed(
666 base::UTF8ToUTF16("Error processing ICE candidate"));
669 return webkit_request.requestSucceeded();
672 bool RTCPeerConnectionHandler::addStream(
673 const blink::WebMediaStream& stream,
674 const blink::WebMediaConstraints& options) {
676 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
677 local_streams_.begin(); adapter_it != local_streams_.end();
678 ++adapter_it) {
679 if ((*adapter_it)->IsEqual(stream)) {
680 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
681 << "stream twice. id=" << stream.id().utf8();
682 return false;
686 if (peer_connection_tracker_)
687 peer_connection_tracker_->TrackAddStream(
688 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
690 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
692 WebRtcMediaStreamAdapter* adapter =
693 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
694 local_streams_.push_back(adapter);
696 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
697 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
698 webrtc_stream);
700 RTCMediaConstraints constraints(options);
701 return native_peer_connection_->AddStream(webrtc_stream, &constraints);
704 void RTCPeerConnectionHandler::removeStream(
705 const blink::WebMediaStream& stream) {
706 // Find the webrtc stream.
707 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
708 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
709 local_streams_.begin(); adapter_it != local_streams_.end();
710 ++adapter_it) {
711 if ((*adapter_it)->IsEqual(stream)) {
712 webrtc_stream = (*adapter_it)->webrtc_media_stream();
713 local_streams_.erase(adapter_it);
714 break;
717 DCHECK(webrtc_stream.get());
718 native_peer_connection_->RemoveStream(webrtc_stream.get());
720 if (peer_connection_tracker_)
721 peer_connection_tracker_->TrackRemoveStream(
722 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
723 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
724 track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
725 webrtc_stream.get());
728 void RTCPeerConnectionHandler::getStats(
729 const blink::WebRTCStatsRequest& request) {
730 scoped_refptr<LocalRTCStatsRequest> inner_request(
731 new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
732 getStats(inner_request.get());
735 void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
736 rtc::scoped_refptr<webrtc::StatsObserver> observer(
737 new rtc::RefCountedObject<StatsResponse>(request));
738 webrtc::MediaStreamTrackInterface* track = NULL;
739 if (request->hasSelector()) {
740 blink::WebMediaStreamSource::Type type =
741 request->component().source().type();
742 std::string track_id = request->component().id().utf8();
743 if (type == blink::WebMediaStreamSource::TypeAudio) {
744 track =
745 native_peer_connection_->local_streams()->FindAudioTrack(track_id);
746 if (!track) {
747 track =
748 native_peer_connection_->remote_streams()->FindAudioTrack(track_id);
750 } else {
751 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, type);
752 track =
753 native_peer_connection_->local_streams()->FindVideoTrack(track_id);
754 if (!track) {
755 track =
756 native_peer_connection_->remote_streams()->FindVideoTrack(track_id);
759 if (!track) {
760 DVLOG(1) << "GetStats: Track not found.";
761 // TODO(hta): Consider how to get an error back.
762 observer->OnComplete(StatsReports());
763 return;
766 GetStats(observer,
767 track,
768 webrtc::PeerConnectionInterface::kStatsOutputLevelStandard);
771 void RTCPeerConnectionHandler::GetStats(
772 webrtc::StatsObserver* observer,
773 webrtc::MediaStreamTrackInterface* track,
774 webrtc::PeerConnectionInterface::StatsOutputLevel level) {
775 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::GetStats");
776 if (!native_peer_connection_->GetStats(observer, track, level)) {
777 DVLOG(1) << "GetStats failed.";
778 // TODO(hta): Consider how to get an error back.
779 observer->OnComplete(StatsReports());
780 return;
784 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
785 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
786 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
788 webrtc::DataChannelInit config;
789 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
790 // to handle that.
791 config.reliable = false;
792 config.id = init.id;
793 config.ordered = init.ordered;
794 config.negotiated = init.negotiated;
795 config.maxRetransmits = init.maxRetransmits;
796 config.maxRetransmitTime = init.maxRetransmitTime;
797 config.protocol = base::UTF16ToUTF8(init.protocol);
799 rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
800 native_peer_connection_->CreateDataChannel(base::UTF16ToUTF8(label),
801 &config));
802 if (!webrtc_channel) {
803 DLOG(ERROR) << "Could not create native data channel.";
804 return NULL;
806 if (peer_connection_tracker_)
807 peer_connection_tracker_->TrackCreateDataChannel(
808 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
810 ++num_data_channels_created_;
812 return new RtcDataChannelHandler(webrtc_channel);
815 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
816 const blink::WebMediaStreamTrack& track) {
817 DVLOG(1) << "createDTMFSender.";
819 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
820 if (!native_track ||
821 track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
822 DLOG(ERROR) << "Could not create DTMF sender from a non-audio track.";
823 return NULL;
826 webrtc::AudioTrackInterface* audio_track = native_track->GetAudioAdapter();
827 rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
828 native_peer_connection_->CreateDtmfSender(audio_track));
829 if (!sender) {
830 DLOG(ERROR) << "Could not create native DTMF sender.";
831 return NULL;
833 if (peer_connection_tracker_)
834 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
836 return new RtcDtmfSenderHandler(sender);
839 void RTCPeerConnectionHandler::stop() {
840 DVLOG(1) << "RTCPeerConnectionHandler::stop";
842 if (peer_connection_tracker_)
843 peer_connection_tracker_->TrackStop(this);
844 native_peer_connection_->Close();
847 void RTCPeerConnectionHandler::OnError() {
848 // TODO(perkj): Implement.
849 NOTIMPLEMENTED();
852 void RTCPeerConnectionHandler::OnSignalingChange(
853 webrtc::PeerConnectionInterface::SignalingState new_state) {
854 blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
855 GetWebKitSignalingState(new_state);
856 if (peer_connection_tracker_)
857 peer_connection_tracker_->TrackSignalingStateChange(this, state);
858 client_->didChangeSignalingState(state);
861 // Called any time the IceConnectionState changes
862 void RTCPeerConnectionHandler::OnIceConnectionChange(
863 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
864 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
865 ice_connection_checking_start_ = base::TimeTicks::Now();
866 } else if (new_state ==
867 webrtc::PeerConnectionInterface::kIceConnectionConnected) {
868 // If the state becomes connected, send the time needed for PC to become
869 // connected from checking to UMA. UMA data will help to know how much
870 // time needed for PC to connect with remote peer.
871 UMA_HISTOGRAM_MEDIUM_TIMES(
872 "WebRTC.PeerConnection.TimeToConnect",
873 base::TimeTicks::Now() - ice_connection_checking_start_);
876 track_metrics_.IceConnectionChange(new_state);
877 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
878 GetWebKitIceConnectionState(new_state);
879 if (peer_connection_tracker_)
880 peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
881 client_->didChangeICEConnectionState(state);
884 // Called any time the IceGatheringState changes
885 void RTCPeerConnectionHandler::OnIceGatheringChange(
886 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
887 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
888 // If ICE gathering is completed, generate a NULL ICE candidate,
889 // to signal end of candidates.
890 blink::WebRTCICECandidate null_candidate;
891 client_->didGenerateICECandidate(null_candidate);
894 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
895 GetWebKitIceGatheringState(new_state);
896 if (peer_connection_tracker_)
897 peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
898 client_->didChangeICEGatheringState(state);
901 void RTCPeerConnectionHandler::OnAddStream(
902 webrtc::MediaStreamInterface* stream_interface) {
903 DCHECK(stream_interface);
904 DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
906 RemoteMediaStreamImpl* remote_stream =
907 new RemoteMediaStreamImpl(stream_interface);
908 remote_streams_.insert(
909 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
910 stream_interface, remote_stream));
912 if (peer_connection_tracker_)
913 peer_connection_tracker_->TrackAddStream(
914 this, remote_stream->webkit_stream(),
915 PeerConnectionTracker::SOURCE_REMOTE);
917 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
919 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
920 stream_interface);
922 client_->didAddRemoteStream(remote_stream->webkit_stream());
925 void RTCPeerConnectionHandler::OnRemoveStream(
926 webrtc::MediaStreamInterface* stream_interface) {
927 DCHECK(stream_interface);
928 RemoteStreamMap::iterator it = remote_streams_.find(stream_interface);
929 if (it == remote_streams_.end()) {
930 NOTREACHED() << "Stream not found";
931 return;
934 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
935 stream_interface);
936 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
938 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
939 const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
940 DCHECK(!webkit_stream.isNull());
941 remote_streams_.erase(it);
943 if (peer_connection_tracker_)
944 peer_connection_tracker_->TrackRemoveStream(
945 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
947 client_->didRemoveRemoteStream(webkit_stream);
950 void RTCPeerConnectionHandler::OnIceCandidate(
951 const webrtc::IceCandidateInterface* candidate) {
952 DCHECK(candidate);
953 std::string sdp;
954 if (!candidate->ToString(&sdp)) {
955 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
956 return;
958 blink::WebRTCICECandidate web_candidate;
959 web_candidate.initialize(base::UTF8ToUTF16(sdp),
960 base::UTF8ToUTF16(candidate->sdp_mid()),
961 candidate->sdp_mline_index());
962 if (peer_connection_tracker_)
963 peer_connection_tracker_->TrackAddIceCandidate(
964 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL);
966 client_->didGenerateICECandidate(web_candidate);
969 void RTCPeerConnectionHandler::OnDataChannel(
970 webrtc::DataChannelInterface* data_channel) {
971 if (peer_connection_tracker_)
972 peer_connection_tracker_->TrackCreateDataChannel(
973 this, data_channel, PeerConnectionTracker::SOURCE_REMOTE);
975 DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
976 << data_channel->label();
977 client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel));
980 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
981 if (peer_connection_tracker_)
982 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
983 client_->negotiationNeeded();
986 PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
987 return peer_connection_tracker_;
990 webrtc::SessionDescriptionInterface*
991 RTCPeerConnectionHandler::CreateNativeSessionDescription(
992 const blink::WebRTCSessionDescription& description,
993 webrtc::SdpParseError* error) {
994 std::string sdp = base::UTF16ToUTF8(description.sdp());
995 std::string type = base::UTF16ToUTF8(description.type());
996 webrtc::SessionDescriptionInterface* native_desc =
997 dependency_factory_->CreateSessionDescription(type, sdp, error);
999 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1000 << " Type: " << type << " SDP: " << sdp;
1002 return native_desc;
1005 } // namespace content