chrome.bluetoothSocket: clean-up Listen functions
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
blobb8c39be0ce6fb35674e2b2de20d0cd6a4c1acd8b
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/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"
42 namespace content {
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;
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;
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;
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;
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;
125 description.initialize(base::UTF8ToUTF16(native_desc->type()),
126 base::UTF8ToUTF16(sdp));
127 return description;
130 // Converter functions from WebKit types to libjingle types.
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);
148 class SessionDescriptionRequestTracker {
149 public:
150 SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler,
151 PeerConnectionTracker::Action action)
152 : handler_(handler), action_(action) {}
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;
160 if (handler_->peer_connection_tracker())
161 handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
162 handler_, action_, "OnSuccess", value);
165 void TrackOnFailure(const std::string& error) {
166 if (handler_->peer_connection_tracker())
167 handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
168 handler_, action_, "OnFailure", error);
171 private:
172 RTCPeerConnectionHandler* handler_;
173 PeerConnectionTracker::Action action_;
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) {}
187 virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE {
188 tracker_.TrackOnSuccess(desc);
189 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
190 delete desc;
192 virtual void OnFailure(const std::string& error) OVERRIDE {
193 tracker_.TrackOnFailure(error);
194 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
197 protected:
198 virtual ~CreateSessionDescriptionRequest() {}
200 private:
201 blink::WebRTCSessionDescriptionRequest webkit_request_;
202 SessionDescriptionRequestTracker tracker_;
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) {}
216 virtual void OnSuccess() OVERRIDE {
217 tracker_.TrackOnSuccess(NULL);
218 webkit_request_.requestSucceeded();
220 virtual void OnFailure(const std::string& error) OVERRIDE {
221 tracker_.TrackOnFailure(error);
222 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
225 protected:
226 virtual ~SetSessionDescriptionRequest() {}
228 private:
229 blink::WebRTCVoidRequest webkit_request_;
230 SessionDescriptionRequestTracker tracker_;
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);
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);
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);
258 request_->requestSucceeded(response_);
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);
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));
280 talk_base::scoped_refptr<LocalRTCStatsRequest> request_;
281 talk_base::scoped_refptr<LocalRTCStatsResponse> response_;
284 // Implementation of LocalRTCStatsRequest.
285 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
286 : impl_(impl),
287 response_(NULL) {
290 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
291 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
293 bool LocalRTCStatsRequest::hasSelector() const {
294 return impl_.hasSelector();
297 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
298 return impl_.component();
301 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
302 DCHECK(!response_);
303 response_ = new talk_base::RefCountedObject<LocalRTCStatsResponse>(
304 impl_.createResponse());
305 return response_.get();
308 void LocalRTCStatsRequest::requestSucceeded(
309 const LocalRTCStatsResponse* response) {
310 impl_.requestSucceeded(response->webKitStatsResponse());
313 // Implementation of LocalRTCStatsResponse.
314 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
315 return impl_;
318 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
319 blink::WebString id,
320 double timestamp) {
321 return impl_.addReport(type, id, timestamp);
324 void LocalRTCStatsResponse::addStatistic(size_t report,
325 blink::WebString name,
326 blink::WebString value) {
327 impl_.addStatistic(report, name, value);
330 namespace {
332 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
333 public:
334 PeerConnectionUMAObserver() {}
335 virtual ~PeerConnectionUMAObserver() {}
337 virtual void IncrementCounter(
338 webrtc::PeerConnectionUMAMetricsCounter counter) OVERRIDE {
339 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
340 counter,
341 webrtc::kBoundary);
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();
366 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
367 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
369 } // namespace
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);
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_);
388 UMA_HISTOGRAM_COUNTS_10000(
389 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
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();
404 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
405 DCHECK(frame);
406 frame_ = frame;
409 bool RTCPeerConnectionHandler::initialize(
410 const blink::WebRTCConfiguration& server_configuration,
411 const blink::WebMediaConstraints& options) {
412 DCHECK(frame_);
414 peer_connection_tracker_ =
415 RenderThreadImpl::current()->peer_connection_tracker();
417 webrtc::PeerConnectionInterface::IceServers servers;
418 GetNativeIceServers(server_configuration, &servers);
420 RTCMediaConstraints constraints(options);
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;
429 if (peer_connection_tracker_)
430 peer_connection_tracker_->RegisterPeerConnection(
431 this, servers, constraints, frame_);
433 uma_observer_ = new talk_base::RefCountedObject<PeerConnectionUMAObserver>();
434 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
435 return true;
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);
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;
453 peer_connection_tracker_ = peer_connection_tracker;
454 return true;
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);
466 if (peer_connection_tracker_)
467 peer_connection_tracker_->TrackCreateOffer(this, constraints);
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);
480 if (peer_connection_tracker_)
481 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
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;
499 if (peer_connection_tracker_)
500 peer_connection_tracker_->TrackSetSessionDescription(
501 this, description, PeerConnectionTracker::SOURCE_LOCAL);
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);
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;
524 if (peer_connection_tracker_)
525 peer_connection_tracker_->TrackSetSessionDescription(
526 this, description, PeerConnectionTracker::SOURCE_REMOTE);
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);
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;
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;
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);
559 if (peer_connection_tracker_)
560 peer_connection_tracker_->TrackUpdateIce(this, servers, constraints);
562 return native_peer_connection_->UpdateIce(servers,
563 &constraints);
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;
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;
592 bool return_value =
593 native_peer_connection_->AddIceCandidate(native_candidate.get());
594 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
596 if (peer_connection_tracker_)
597 peer_connection_tracker_->TrackAddIceCandidate(
598 this, candidate, PeerConnectionTracker::SOURCE_REMOTE);
600 return return_value;
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"));
612 return webkit_request.requestSucceeded();
615 bool RTCPeerConnectionHandler::addStream(
616 const blink::WebMediaStream& stream,
617 const blink::WebMediaConstraints& options) {
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;
629 if (peer_connection_tracker_)
630 peer_connection_tracker_->TrackAddStream(
631 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
633 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
635 WebRtcMediaStreamAdapter* adapter =
636 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
637 local_streams_.push_back(adapter);
639 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
640 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
641 webrtc_stream);
643 RTCMediaConstraints constraints(options);
644 return native_peer_connection_->AddStream(webrtc_stream, &constraints);
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;
660 DCHECK(webrtc_stream);
661 native_peer_connection_->RemoveStream(webrtc_stream);
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);
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());
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);
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);
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;
710 GetStats(observer,
711 track,
712 webrtc::PeerConnectionInterface::kStatsOutputLevelStandard);
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;
729 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
730 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
731 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
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);
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;
751 if (peer_connection_tracker_)
752 peer_connection_tracker_->TrackCreateDataChannel(
753 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
755 ++num_data_channels_created_;
757 return new RtcDataChannelHandler(webrtc_channel);
760 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
761 const blink::WebMediaStreamTrack& track) {
762 DVLOG(1) << "createDTMFSender.";
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;
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;
778 if (peer_connection_tracker_)
779 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
781 return new RtcDtmfSenderHandler(sender);
784 void RTCPeerConnectionHandler::stop() {
785 DVLOG(1) << "RTCPeerConnectionHandler::stop";
787 if (peer_connection_tracker_)
788 peer_connection_tracker_->TrackStop(this);
789 native_peer_connection_->Close();
792 void RTCPeerConnectionHandler::OnError() {
793 // TODO(perkj): Implement.
794 NOTIMPLEMENTED();
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);
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);
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);
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);
834 void RTCPeerConnectionHandler::OnAddStream(
835 webrtc::MediaStreamInterface* stream_interface) {
836 DCHECK(stream_interface);
837 DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
839 RemoteMediaStreamImpl* remote_stream =
840 new RemoteMediaStreamImpl(stream_interface);
841 remote_streams_.insert(
842 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
843 stream_interface, remote_stream));
845 if (peer_connection_tracker_)
846 peer_connection_tracker_->TrackAddStream(
847 this, remote_stream->webkit_stream(),
848 PeerConnectionTracker::SOURCE_REMOTE);
850 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
852 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
853 stream_interface);
855 client_->didAddRemoteStream(remote_stream->webkit_stream());
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;
867 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
868 stream_interface);
869 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
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);
876 if (peer_connection_tracker_)
877 peer_connection_tracker_->TrackRemoveStream(
878 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
880 client_->didRemoveRemoteStream(webkit_stream);
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;
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);
899 client_->didGenerateICECandidate(web_candidate);
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);
908 DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
909 << data_channel->label();
910 client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel));
913 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
914 if (peer_connection_tracker_)
915 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
916 client_->negotiationNeeded();
919 PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
920 return peer_connection_tracker_;
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);
932 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
933 << " Type: " << type << " SDP: " << sdp;
935 return native_desc;
938 } // namespace content