Roll src/third_party/WebKit a452221:9ff6d11 (svn 202117:202119)
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
blob626e5c91eb70f8eac21a3230002662126aa386f1
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/lazy_instance.h"
13 #include "base/location.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 "base/thread_task_runner_handle.h"
20 #include "base/trace_event/trace_event.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/renderer/media/media_stream_track.h"
23 #include "content/renderer/media/peer_connection_tracker.h"
24 #include "content/renderer/media/remote_media_stream_impl.h"
25 #include "content/renderer/media/rtc_data_channel_handler.h"
26 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
27 #include "content/renderer/media/rtc_media_constraints.h"
28 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
29 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
30 #include "content/renderer/media/webrtc_audio_capturer.h"
31 #include "content/renderer/media/webrtc_audio_device_impl.h"
32 #include "content/renderer/media/webrtc_uma_histograms.h"
33 #include "content/renderer/render_thread_impl.h"
34 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
35 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
36 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
37 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
38 #include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
39 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
40 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
41 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
42 #include "third_party/WebKit/public/platform/WebURL.h"
43 #include "third_party/libjingle/source/talk/session/media/mediasession.h"
45 using webrtc::DataChannelInterface;
46 using webrtc::IceCandidateInterface;
47 using webrtc::MediaStreamInterface;
48 using webrtc::PeerConnectionInterface;
49 using webrtc::PeerConnectionObserver;
50 using webrtc::StatsReport;
51 using webrtc::StatsReports;
53 namespace content {
54 namespace {
56 // Used to back histogram value of "WebRTC.PeerConnection.RtcpMux",
57 // so treat as append-only.
58 enum RtcpMux {
59 RTCP_MUX_DISABLED,
60 RTCP_MUX_ENABLED,
61 RTCP_MUX_NO_MEDIA,
62 RTCP_MUX_MAX
65 // Converter functions from libjingle types to WebKit types.
66 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
67 GetWebKitIceGatheringState(
68 webrtc::PeerConnectionInterface::IceGatheringState state) {
69 using blink::WebRTCPeerConnectionHandlerClient;
70 switch (state) {
71 case webrtc::PeerConnectionInterface::kIceGatheringNew:
72 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
73 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
74 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering;
75 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
76 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete;
77 default:
78 NOTREACHED();
79 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
83 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
84 GetWebKitIceConnectionState(
85 webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
86 using blink::WebRTCPeerConnectionHandlerClient;
87 switch (ice_state) {
88 case webrtc::PeerConnectionInterface::kIceConnectionNew:
89 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
90 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
91 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking;
92 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
93 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected;
94 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
95 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted;
96 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
97 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed;
98 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
99 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected;
100 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
101 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
102 default:
103 NOTREACHED();
104 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
108 blink::WebRTCPeerConnectionHandlerClient::SignalingState
109 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
110 using blink::WebRTCPeerConnectionHandlerClient;
111 switch (state) {
112 case webrtc::PeerConnectionInterface::kStable:
113 return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
114 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
115 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer;
116 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
117 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer;
118 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
119 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer;
120 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
121 return
122 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer;
123 case webrtc::PeerConnectionInterface::kClosed:
124 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
125 default:
126 NOTREACHED();
127 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
131 blink::WebRTCSessionDescription CreateWebKitSessionDescription(
132 const std::string& sdp, const std::string& type) {
133 blink::WebRTCSessionDescription description;
134 description.initialize(base::UTF8ToUTF16(type), base::UTF8ToUTF16(sdp));
135 return description;
138 blink::WebRTCSessionDescription
139 CreateWebKitSessionDescription(
140 const webrtc::SessionDescriptionInterface* native_desc) {
141 if (!native_desc) {
142 LOG(ERROR) << "Native session description is null.";
143 return blink::WebRTCSessionDescription();
146 std::string sdp;
147 if (!native_desc->ToString(&sdp)) {
148 LOG(ERROR) << "Failed to get SDP string of native session description.";
149 return blink::WebRTCSessionDescription();
152 return CreateWebKitSessionDescription(sdp, native_desc->type());
155 void RunClosureWithTrace(const base::Closure& closure,
156 const char* trace_event_name) {
157 TRACE_EVENT0("webrtc", trace_event_name);
158 closure.Run();
161 void RunSynchronousClosure(const base::Closure& closure,
162 const char* trace_event_name,
163 base::WaitableEvent* event) {
165 TRACE_EVENT0("webrtc", trace_event_name);
166 closure.Run();
168 event->Signal();
171 void GetSdpAndTypeFromSessionDescription(
172 const base::Callback<const webrtc::SessionDescriptionInterface*()>&
173 description_callback,
174 std::string* sdp, std::string* type) {
175 const webrtc::SessionDescriptionInterface* description =
176 description_callback.Run();
177 if (description) {
178 description->ToString(sdp);
179 *type = description->type();
183 // Converter functions from WebKit types to WebRTC types.
185 void GetNativeRtcConfiguration(
186 const blink::WebRTCConfiguration& blink_config,
187 webrtc::PeerConnectionInterface::RTCConfiguration* webrtc_config) {
188 if (blink_config.isNull() || !webrtc_config)
189 return;
190 for (size_t i = 0; i < blink_config.numberOfServers(); ++i) {
191 webrtc::PeerConnectionInterface::IceServer server;
192 const blink::WebRTCICEServer& webkit_server =
193 blink_config.server(i);
194 server.username =
195 base::UTF16ToUTF8(base::StringPiece16(webkit_server.username()));
196 server.password =
197 base::UTF16ToUTF8(base::StringPiece16(webkit_server.credential()));
198 server.uri = webkit_server.uri().spec();
199 webrtc_config->servers.push_back(server);
202 switch (blink_config.iceTransports()) {
203 case blink::WebRTCIceTransportsNone:
204 webrtc_config->type = webrtc::PeerConnectionInterface::kNone;
205 break;
206 case blink::WebRTCIceTransportsRelay:
207 webrtc_config->type = webrtc::PeerConnectionInterface::kRelay;
208 break;
209 case blink::WebRTCIceTransportsAll:
210 webrtc_config->type = webrtc::PeerConnectionInterface::kAll;
211 break;
212 default:
213 NOTREACHED();
216 switch (blink_config.bundlePolicy()) {
217 case blink::WebRTCBundlePolicyBalanced:
218 webrtc_config->bundle_policy =
219 webrtc::PeerConnectionInterface::kBundlePolicyBalanced;
220 break;
221 case blink::WebRTCBundlePolicyMaxBundle:
222 webrtc_config->bundle_policy =
223 webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle;
224 break;
225 case blink::WebRTCBundlePolicyMaxCompat:
226 webrtc_config->bundle_policy =
227 webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
228 break;
229 default:
230 NOTREACHED();
233 switch (blink_config.rtcpMuxPolicy()) {
234 case blink::WebRTCRtcpMuxPolicyNegotiate:
235 webrtc_config->rtcp_mux_policy =
236 webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
237 break;
238 case blink::WebRTCRtcpMuxPolicyRequire:
239 webrtc_config->rtcp_mux_policy =
240 webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire;
241 break;
242 default:
243 NOTREACHED();
247 class SessionDescriptionRequestTracker {
248 public:
249 SessionDescriptionRequestTracker(
250 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
251 const base::WeakPtr<PeerConnectionTracker>& tracker,
252 PeerConnectionTracker::Action action)
253 : handler_(handler), tracker_(tracker), action_(action) {}
255 void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
256 DCHECK(thread_checker_.CalledOnValidThread());
257 if (tracker_ && handler_) {
258 std::string value;
259 if (desc) {
260 desc->ToString(&value);
261 value = "type: " + desc->type() + ", sdp: " + value;
263 tracker_->TrackSessionDescriptionCallback(
264 handler_.get(), action_, "OnSuccess", value);
268 void TrackOnFailure(const std::string& error) {
269 DCHECK(thread_checker_.CalledOnValidThread());
270 if (handler_ && tracker_) {
271 tracker_->TrackSessionDescriptionCallback(
272 handler_.get(), action_, "OnFailure", error);
276 private:
277 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
278 const base::WeakPtr<PeerConnectionTracker> tracker_;
279 PeerConnectionTracker::Action action_;
280 base::ThreadChecker thread_checker_;
283 // Class mapping responses from calls to libjingle CreateOffer/Answer and
284 // the blink::WebRTCSessionDescriptionRequest.
285 class CreateSessionDescriptionRequest
286 : public webrtc::CreateSessionDescriptionObserver {
287 public:
288 explicit CreateSessionDescriptionRequest(
289 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
290 const blink::WebRTCSessionDescriptionRequest& request,
291 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
292 const base::WeakPtr<PeerConnectionTracker>& tracker,
293 PeerConnectionTracker::Action action)
294 : main_thread_(main_thread),
295 webkit_request_(request),
296 tracker_(handler, tracker, action) {
299 void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
300 if (!main_thread_->BelongsToCurrentThread()) {
301 main_thread_->PostTask(FROM_HERE,
302 base::Bind(&CreateSessionDescriptionRequest::OnSuccess, this, desc));
303 return;
306 tracker_.TrackOnSuccess(desc);
307 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
308 webkit_request_.reset();
309 delete desc;
311 void OnFailure(const std::string& error) override {
312 if (!main_thread_->BelongsToCurrentThread()) {
313 main_thread_->PostTask(FROM_HERE,
314 base::Bind(&CreateSessionDescriptionRequest::OnFailure, this, error));
315 return;
318 tracker_.TrackOnFailure(error);
319 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
320 webkit_request_.reset();
323 protected:
324 ~CreateSessionDescriptionRequest() override {
325 CHECK(webkit_request_.isNull());
328 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
329 blink::WebRTCSessionDescriptionRequest webkit_request_;
330 SessionDescriptionRequestTracker tracker_;
333 // Class mapping responses from calls to libjingle
334 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
335 class SetSessionDescriptionRequest
336 : public webrtc::SetSessionDescriptionObserver {
337 public:
338 explicit SetSessionDescriptionRequest(
339 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
340 const blink::WebRTCVoidRequest& request,
341 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
342 const base::WeakPtr<PeerConnectionTracker>& tracker,
343 PeerConnectionTracker::Action action)
344 : main_thread_(main_thread),
345 webkit_request_(request),
346 tracker_(handler, tracker, action) {
349 void OnSuccess() override {
350 if (!main_thread_->BelongsToCurrentThread()) {
351 main_thread_->PostTask(FROM_HERE,
352 base::Bind(&SetSessionDescriptionRequest::OnSuccess, this));
353 return;
355 tracker_.TrackOnSuccess(NULL);
356 webkit_request_.requestSucceeded();
357 webkit_request_.reset();
359 void OnFailure(const std::string& error) override {
360 if (!main_thread_->BelongsToCurrentThread()) {
361 main_thread_->PostTask(FROM_HERE,
362 base::Bind(&SetSessionDescriptionRequest::OnFailure, this, error));
363 return;
365 tracker_.TrackOnFailure(error);
366 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
367 webkit_request_.reset();
370 protected:
371 ~SetSessionDescriptionRequest() override {
372 DCHECK(webkit_request_.isNull());
375 private:
376 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
377 blink::WebRTCVoidRequest webkit_request_;
378 SessionDescriptionRequestTracker tracker_;
381 // Class mapping responses from calls to libjingle
382 // GetStats into a blink::WebRTCStatsCallback.
383 class StatsResponse : public webrtc::StatsObserver {
384 public:
385 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
386 : request_(request.get()),
387 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
388 // Measure the overall time it takes to satisfy a getStats request.
389 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
390 signaling_thread_checker_.DetachFromThread();
393 void OnComplete(const StatsReports& reports) override {
394 DCHECK(signaling_thread_checker_.CalledOnValidThread());
395 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
396 // We can't use webkit objects directly since they use a single threaded
397 // heap allocator.
398 std::vector<Report*>* report_copies = new std::vector<Report*>();
399 report_copies->reserve(reports.size());
400 for (auto* r : reports)
401 report_copies->push_back(new Report(r));
403 main_thread_->PostTaskAndReply(FROM_HERE,
404 base::Bind(&StatsResponse::DeliverCallback, this,
405 base::Unretained(report_copies)),
406 base::Bind(&StatsResponse::DeleteReports,
407 base::Unretained(report_copies)));
410 private:
411 struct Report {
412 Report(const StatsReport* report)
413 : thread_checker(), id(report->id()->ToString()),
414 type(report->TypeToString()), timestamp(report->timestamp()),
415 values(report->values()) {
418 ~Report() {
419 // Since the values vector holds pointers to const objects that are bound
420 // to the signaling thread, they must be released on the same thread.
421 DCHECK(thread_checker.CalledOnValidThread());
424 const base::ThreadChecker thread_checker;
425 const std::string id, type;
426 const double timestamp;
427 const StatsReport::Values values;
430 static void DeleteReports(std::vector<Report*>* reports) {
431 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
432 for (auto* p : *reports)
433 delete p;
434 delete reports;
437 void DeliverCallback(const std::vector<Report*>* reports) {
438 DCHECK(main_thread_->BelongsToCurrentThread());
439 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
441 rtc::scoped_refptr<LocalRTCStatsResponse> response(
442 request_->createResponse().get());
443 for (const auto* report : *reports) {
444 if (report->values.size() > 0)
445 AddReport(response.get(), *report);
448 // Record the getStats operation as done before calling into Blink so that
449 // we don't skew the perf measurements of the native code with whatever the
450 // callback might be doing.
451 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
452 request_->requestSucceeded(response);
453 request_ = nullptr; // must be freed on the main thread.
456 void AddReport(LocalRTCStatsResponse* response, const Report& report) {
457 int idx = response->addReport(blink::WebString::fromUTF8(report.id),
458 blink::WebString::fromUTF8(report.type),
459 report.timestamp);
460 blink::WebString name, value_str;
461 for (const auto& value : report.values) {
462 const StatsReport::ValuePtr& v = value.second;
463 name = blink::WebString::fromUTF8(value.second->display_name());
465 if (v->type() == StatsReport::Value::kString)
466 value_str = blink::WebString::fromUTF8(v->string_val());
467 if (v->type() == StatsReport::Value::kStaticString)
468 value_str = blink::WebString::fromUTF8(v->static_string_val());
469 else
470 value_str = blink::WebString::fromUTF8(v->ToString());
472 response->addStatistic(idx, name, value_str);
476 rtc::scoped_refptr<LocalRTCStatsRequest> request_;
477 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
478 base::ThreadChecker signaling_thread_checker_;
481 void GetStatsOnSignalingThread(
482 const scoped_refptr<webrtc::PeerConnectionInterface>& pc,
483 webrtc::PeerConnectionInterface::StatsOutputLevel level,
484 const scoped_refptr<webrtc::StatsObserver>& observer,
485 const std::string track_id, blink::WebMediaStreamSource::Type track_type) {
486 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
488 scoped_refptr<webrtc::MediaStreamTrackInterface> track;
489 if (!track_id.empty()) {
490 if (track_type == blink::WebMediaStreamSource::TypeAudio) {
491 track = pc->local_streams()->FindAudioTrack(track_id);
492 if (!track.get())
493 track = pc->remote_streams()->FindAudioTrack(track_id);
494 } else {
495 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track_type);
496 track = pc->local_streams()->FindVideoTrack(track_id);
497 if (!track.get())
498 track = pc->remote_streams()->FindVideoTrack(track_id);
501 if (!track.get()) {
502 DVLOG(1) << "GetStats: Track not found.";
503 observer->OnComplete(StatsReports());
504 return;
508 if (!pc->GetStats(observer.get(), track.get(), level)) {
509 DVLOG(1) << "GetStats failed.";
510 observer->OnComplete(StatsReports());
514 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
515 public:
516 PeerConnectionUMAObserver() {}
517 ~PeerConnectionUMAObserver() override {}
518 void IncrementEnumCounter(webrtc::PeerConnectionEnumCounterType counter_type,
519 int counter,
520 int counter_max) override {
521 switch (counter_type) {
522 case webrtc::kEnumCounterAddressFamily:
523 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics", counter,
524 counter_max);
525 break;
526 case webrtc::kEnumCounterIceCandidatePairTypeUdp:
527 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_UDP",
528 counter, counter_max);
529 break;
530 case webrtc::kEnumCounterIceCandidatePairTypeTcp:
531 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_TCP",
532 counter, counter_max);
533 break;
534 case webrtc::kPeerConnectionEnumCounterMax:
535 NOTREACHED();
536 break;
540 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,
541 int value) override {
542 // Runs on libjingle's signaling thread.
543 switch (type) {
544 case webrtc::kTimeToConnect:
545 UMA_HISTOGRAM_MEDIUM_TIMES(
546 "WebRTC.PeerConnection.TimeToConnect",
547 base::TimeDelta::FromMilliseconds(value));
548 break;
549 case webrtc::kNetworkInterfaces_IPv4:
550 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
551 value);
552 break;
553 case webrtc::kNetworkInterfaces_IPv6:
554 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
555 value);
556 break;
557 default:
558 NOTREACHED();
563 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
564 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
566 } // namespace
568 // Implementation of LocalRTCStatsRequest.
569 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
570 : impl_(impl) {
573 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
574 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
576 bool LocalRTCStatsRequest::hasSelector() const {
577 return impl_.hasSelector();
580 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
581 return impl_.component();
584 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
585 return scoped_refptr<LocalRTCStatsResponse>(
586 new rtc::RefCountedObject<LocalRTCStatsResponse>(impl_.createResponse()));
589 void LocalRTCStatsRequest::requestSucceeded(
590 const LocalRTCStatsResponse* response) {
591 impl_.requestSucceeded(response->webKitStatsResponse());
594 // Implementation of LocalRTCStatsResponse.
595 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
596 return impl_;
599 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
600 blink::WebString id,
601 double timestamp) {
602 return impl_.addReport(type, id, timestamp);
605 void LocalRTCStatsResponse::addStatistic(size_t report,
606 blink::WebString name,
607 blink::WebString value) {
608 impl_.addStatistic(report, name, value);
611 // Receives notifications from a PeerConnection object about state changes,
612 // track addition/removal etc. The callbacks we receive here come on the
613 // signaling thread, so this class takes care of delivering them to an
614 // RTCPeerConnectionHandler instance on the main thread.
615 // In order to do safe PostTask-ing, the class is reference counted and
616 // checks for the existence of the RTCPeerConnectionHandler instance before
617 // delivering callbacks on the main thread.
618 class RTCPeerConnectionHandler::Observer
619 : public base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>,
620 public PeerConnectionObserver {
621 public:
622 Observer(const base::WeakPtr<RTCPeerConnectionHandler>& handler)
623 : handler_(handler), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
625 protected:
626 friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>;
627 virtual ~Observer() {}
629 void OnSignalingChange(
630 PeerConnectionInterface::SignalingState new_state) override {
631 if (!main_thread_->BelongsToCurrentThread()) {
632 main_thread_->PostTask(FROM_HERE,
633 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange,
634 this, new_state));
635 } else if (handler_) {
636 handler_->OnSignalingChange(new_state);
640 void OnAddStream(MediaStreamInterface* stream) override {
641 DCHECK(stream);
642 scoped_ptr<RemoteMediaStreamImpl> remote_stream(
643 new RemoteMediaStreamImpl(main_thread_, stream));
645 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
646 // asynchronously and the posted task will execude after that initialization
647 // is done.
648 main_thread_->PostTask(FROM_HERE,
649 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl,
650 this, base::Passed(&remote_stream)));
653 void OnRemoveStream(MediaStreamInterface* stream) override {
654 main_thread_->PostTask(FROM_HERE,
655 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
656 this, make_scoped_refptr(stream)));
659 void OnDataChannel(DataChannelInterface* data_channel) override {
660 scoped_ptr<RtcDataChannelHandler> handler(
661 new RtcDataChannelHandler(main_thread_, data_channel));
662 main_thread_->PostTask(FROM_HERE,
663 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
664 this, base::Passed(&handler)));
667 void OnRenegotiationNeeded() override {
668 if (!main_thread_->BelongsToCurrentThread()) {
669 main_thread_->PostTask(FROM_HERE,
670 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
671 this));
672 } else if (handler_) {
673 handler_->OnRenegotiationNeeded();
677 void OnIceConnectionChange(
678 PeerConnectionInterface::IceConnectionState new_state) override {
679 if (!main_thread_->BelongsToCurrentThread()) {
680 main_thread_->PostTask(FROM_HERE,
681 base::Bind(
682 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
683 new_state));
684 } else if (handler_) {
685 handler_->OnIceConnectionChange(new_state);
689 void OnIceGatheringChange(
690 PeerConnectionInterface::IceGatheringState new_state) override {
691 if (!main_thread_->BelongsToCurrentThread()) {
692 main_thread_->PostTask(FROM_HERE,
693 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
694 this, new_state));
695 } else if (handler_) {
696 handler_->OnIceGatheringChange(new_state);
700 void OnIceCandidate(const IceCandidateInterface* candidate) override {
701 std::string sdp;
702 if (!candidate->ToString(&sdp)) {
703 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
704 return;
707 main_thread_->PostTask(FROM_HERE,
708 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
709 this, sdp, candidate->sdp_mid(), candidate->sdp_mline_index(),
710 candidate->candidate().component(),
711 candidate->candidate().address().family()));
714 void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
715 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
716 if (handler_)
717 handler_->OnAddStream(stream.Pass());
720 void OnRemoveStreamImpl(const scoped_refptr<MediaStreamInterface>& stream) {
721 if (handler_)
722 handler_->OnRemoveStream(stream);
725 void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
726 if (handler_)
727 handler_->OnDataChannel(handler.Pass());
730 void OnIceCandidateImpl(const std::string& sdp, const std::string& sdp_mid,
731 int sdp_mline_index, int component, int address_family) {
732 if (handler_) {
733 handler_->OnIceCandidate(sdp, sdp_mid, sdp_mline_index, component,
734 address_family);
738 private:
739 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
740 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
743 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
744 blink::WebRTCPeerConnectionHandlerClient* client,
745 PeerConnectionDependencyFactory* dependency_factory)
746 : client_(client),
747 dependency_factory_(dependency_factory),
748 weak_factory_(this) {
749 g_peer_connection_handlers.Get().insert(this);
752 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
753 DCHECK(thread_checker_.CalledOnValidThread());
755 stop();
757 g_peer_connection_handlers.Get().erase(this);
758 if (peer_connection_tracker_)
759 peer_connection_tracker_->UnregisterPeerConnection(this);
760 STLDeleteValues(&remote_streams_);
762 UMA_HISTOGRAM_COUNTS_10000(
763 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
766 // static
767 void RTCPeerConnectionHandler::DestructAllHandlers() {
768 std::set<RTCPeerConnectionHandler*> handlers(
769 g_peer_connection_handlers.Get().begin(),
770 g_peer_connection_handlers.Get().end());
771 for (auto handler : handlers) {
772 if (handler->client_)
773 handler->client_->releasePeerConnectionHandler();
777 // static
778 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
779 const blink::WebRTCOfferOptions& options,
780 RTCMediaConstraints* output) {
781 output->AddMandatory(
782 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
783 options.offerToReceiveAudio() > 0 ? "true" : "false",
784 true);
786 output->AddMandatory(
787 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
788 options.offerToReceiveVideo() > 0 ? "true" : "false",
789 true);
791 if (!options.voiceActivityDetection()) {
792 output->AddMandatory(
793 webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
794 "false",
795 true);
798 if (options.iceRestart()) {
799 output->AddMandatory(
800 webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
804 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
805 DCHECK(thread_checker_.CalledOnValidThread());
806 DCHECK(frame);
807 frame_ = frame;
810 bool RTCPeerConnectionHandler::initialize(
811 const blink::WebRTCConfiguration& server_configuration,
812 const blink::WebMediaConstraints& options) {
813 DCHECK(thread_checker_.CalledOnValidThread());
814 DCHECK(frame_);
816 peer_connection_tracker_ =
817 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
819 webrtc::PeerConnectionInterface::RTCConfiguration config;
820 GetNativeRtcConfiguration(server_configuration, &config);
822 RTCMediaConstraints constraints(options);
824 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
825 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
826 config, &constraints, frame_, peer_connection_observer_.get());
828 if (!native_peer_connection_.get()) {
829 LOG(ERROR) << "Failed to initialize native PeerConnection.";
830 return false;
833 if (peer_connection_tracker_) {
834 peer_connection_tracker_->RegisterPeerConnection(
835 this, config, constraints, frame_);
838 uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
839 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
840 return true;
843 bool RTCPeerConnectionHandler::InitializeForTest(
844 const blink::WebRTCConfiguration& server_configuration,
845 const blink::WebMediaConstraints& options,
846 const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
847 DCHECK(thread_checker_.CalledOnValidThread());
848 webrtc::PeerConnectionInterface::RTCConfiguration config;
849 GetNativeRtcConfiguration(server_configuration, &config);
851 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
852 RTCMediaConstraints constraints(options);
853 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
854 config, &constraints, NULL, peer_connection_observer_.get());
855 if (!native_peer_connection_.get()) {
856 LOG(ERROR) << "Failed to initialize native PeerConnection.";
857 return false;
859 peer_connection_tracker_ = peer_connection_tracker;
860 return true;
863 void RTCPeerConnectionHandler::createOffer(
864 const blink::WebRTCSessionDescriptionRequest& request,
865 const blink::WebMediaConstraints& options) {
866 DCHECK(thread_checker_.CalledOnValidThread());
867 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
869 scoped_refptr<CreateSessionDescriptionRequest> description_request(
870 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
871 base::ThreadTaskRunnerHandle::Get(), request,
872 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
873 PeerConnectionTracker::ACTION_CREATE_OFFER));
875 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
876 RTCMediaConstraints constraints(options);
877 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
879 if (peer_connection_tracker_)
880 peer_connection_tracker_->TrackCreateOffer(this, constraints);
883 void RTCPeerConnectionHandler::createOffer(
884 const blink::WebRTCSessionDescriptionRequest& request,
885 const blink::WebRTCOfferOptions& options) {
886 DCHECK(thread_checker_.CalledOnValidThread());
887 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
889 scoped_refptr<CreateSessionDescriptionRequest> description_request(
890 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
891 base::ThreadTaskRunnerHandle::Get(), request,
892 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
893 PeerConnectionTracker::ACTION_CREATE_OFFER));
895 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
896 RTCMediaConstraints constraints;
897 ConvertOfferOptionsToConstraints(options, &constraints);
898 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
900 if (peer_connection_tracker_)
901 peer_connection_tracker_->TrackCreateOffer(this, constraints);
904 void RTCPeerConnectionHandler::createAnswer(
905 const blink::WebRTCSessionDescriptionRequest& request,
906 const blink::WebMediaConstraints& options) {
907 DCHECK(thread_checker_.CalledOnValidThread());
908 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
909 scoped_refptr<CreateSessionDescriptionRequest> description_request(
910 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
911 base::ThreadTaskRunnerHandle::Get(), request,
912 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
913 PeerConnectionTracker::ACTION_CREATE_ANSWER));
914 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
915 RTCMediaConstraints constraints(options);
916 native_peer_connection_->CreateAnswer(description_request.get(),
917 &constraints);
919 if (peer_connection_tracker_)
920 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
923 bool IsOfferOrAnswer(const webrtc::SessionDescriptionInterface* native_desc) {
924 DCHECK(native_desc);
925 return native_desc->type() == "offer" || native_desc->type() == "answer";
928 void RTCPeerConnectionHandler::setLocalDescription(
929 const blink::WebRTCVoidRequest& request,
930 const blink::WebRTCSessionDescription& description) {
931 DCHECK(thread_checker_.CalledOnValidThread());
932 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
934 std::string sdp = base::UTF16ToUTF8(base::StringPiece16(description.sdp()));
935 std::string type =
936 base::UTF16ToUTF8(base::StringPiece16(description.type()));
938 webrtc::SdpParseError error;
939 // Since CreateNativeSessionDescription uses the dependency factory, we need
940 // to make this call on the current thread to be safe.
941 webrtc::SessionDescriptionInterface* native_desc =
942 CreateNativeSessionDescription(sdp, type, &error);
943 if (!native_desc) {
944 std::string reason_str = "Failed to parse SessionDescription. ";
945 reason_str.append(error.line);
946 reason_str.append(" ");
947 reason_str.append(error.description);
948 LOG(ERROR) << reason_str;
949 request.requestFailed(blink::WebString::fromUTF8(reason_str));
950 return;
953 if (peer_connection_tracker_) {
954 peer_connection_tracker_->TrackSetSessionDescription(
955 this, sdp, type, PeerConnectionTracker::SOURCE_LOCAL);
958 if (!first_local_description_ && IsOfferOrAnswer(native_desc)) {
959 first_local_description_.reset(new FirstSessionDescription(native_desc));
960 if (first_remote_description_) {
961 ReportFirstSessionDescriptions(
962 *first_local_description_,
963 *first_remote_description_);
967 scoped_refptr<SetSessionDescriptionRequest> set_request(
968 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
969 base::ThreadTaskRunnerHandle::Get(), request,
970 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
971 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
973 signaling_thread()->PostTask(FROM_HERE,
974 base::Bind(&RunClosureWithTrace,
975 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
976 native_peer_connection_, set_request,
977 base::Unretained(native_desc)),
978 "SetLocalDescription"));
981 void RTCPeerConnectionHandler::setRemoteDescription(
982 const blink::WebRTCVoidRequest& request,
983 const blink::WebRTCSessionDescription& description) {
984 DCHECK(thread_checker_.CalledOnValidThread());
985 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
986 std::string sdp = base::UTF16ToUTF8(base::StringPiece16(description.sdp()));
987 std::string type =
988 base::UTF16ToUTF8(base::StringPiece16(description.type()));
990 webrtc::SdpParseError error;
991 // Since CreateNativeSessionDescription uses the dependency factory, we need
992 // to make this call on the current thread to be safe.
993 webrtc::SessionDescriptionInterface* native_desc =
994 CreateNativeSessionDescription(sdp, type, &error);
995 if (!native_desc) {
996 std::string reason_str = "Failed to parse SessionDescription. ";
997 reason_str.append(error.line);
998 reason_str.append(" ");
999 reason_str.append(error.description);
1000 LOG(ERROR) << reason_str;
1001 request.requestFailed(blink::WebString::fromUTF8(reason_str));
1002 return;
1005 if (peer_connection_tracker_) {
1006 peer_connection_tracker_->TrackSetSessionDescription(
1007 this, sdp, type, PeerConnectionTracker::SOURCE_REMOTE);
1010 if (!first_remote_description_ && IsOfferOrAnswer(native_desc)) {
1011 first_remote_description_.reset(new FirstSessionDescription(native_desc));
1012 if (first_local_description_) {
1013 ReportFirstSessionDescriptions(
1014 *first_local_description_,
1015 *first_remote_description_);
1019 scoped_refptr<SetSessionDescriptionRequest> set_request(
1020 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
1021 base::ThreadTaskRunnerHandle::Get(), request,
1022 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
1023 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
1024 signaling_thread()->PostTask(FROM_HERE,
1025 base::Bind(&RunClosureWithTrace,
1026 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
1027 native_peer_connection_, set_request,
1028 base::Unretained(native_desc)),
1029 "SetRemoteDescription"));
1032 blink::WebRTCSessionDescription
1033 RTCPeerConnectionHandler::localDescription() {
1034 DCHECK(thread_checker_.CalledOnValidThread());
1035 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
1037 // Since local_description returns a pointer to a non-reference-counted object
1038 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1039 // it directly here. Instead, we access the object completely on the signaling
1040 // thread.
1041 std::string sdp, type;
1042 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
1043 base::Bind(&webrtc::PeerConnectionInterface::local_description,
1044 native_peer_connection_);
1045 RunSynchronousClosureOnSignalingThread(
1046 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
1047 base::Unretained(&sdp), base::Unretained(&type)),
1048 "localDescription");
1050 return CreateWebKitSessionDescription(sdp, type);
1053 blink::WebRTCSessionDescription
1054 RTCPeerConnectionHandler::remoteDescription() {
1055 DCHECK(thread_checker_.CalledOnValidThread());
1056 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
1057 // Since local_description returns a pointer to a non-reference-counted object
1058 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1059 // it directly here. Instead, we access the object completely on the signaling
1060 // thread.
1061 std::string sdp, type;
1062 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
1063 base::Bind(&webrtc::PeerConnectionInterface::remote_description,
1064 native_peer_connection_);
1065 RunSynchronousClosureOnSignalingThread(
1066 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
1067 base::Unretained(&sdp), base::Unretained(&type)),
1068 "remoteDescription");
1070 return CreateWebKitSessionDescription(sdp, type);
1073 bool RTCPeerConnectionHandler::updateICE(
1074 const blink::WebRTCConfiguration& server_configuration,
1075 const blink::WebMediaConstraints& options) {
1076 DCHECK(thread_checker_.CalledOnValidThread());
1077 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1078 webrtc::PeerConnectionInterface::RTCConfiguration config;
1079 GetNativeRtcConfiguration(server_configuration, &config);
1080 RTCMediaConstraints constraints(options);
1082 if (peer_connection_tracker_)
1083 peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
1085 return native_peer_connection_->UpdateIce(config.servers, &constraints);
1088 bool RTCPeerConnectionHandler::addICECandidate(
1089 const blink::WebRTCVoidRequest& request,
1090 const blink::WebRTCICECandidate& candidate) {
1091 DCHECK(thread_checker_.CalledOnValidThread());
1092 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1093 // Libjingle currently does not accept callbacks for addICECandidate.
1094 // For that reason we are going to call callbacks from here.
1096 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1097 // PostTaskAndReply kind of a thing.
1098 bool result = addICECandidate(candidate);
1099 base::ThreadTaskRunnerHandle::Get()->PostTask(
1100 FROM_HERE, base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
1101 weak_factory_.GetWeakPtr(), request, result));
1102 // On failure callback will be triggered.
1103 return true;
1106 bool RTCPeerConnectionHandler::addICECandidate(
1107 const blink::WebRTCICECandidate& candidate) {
1108 DCHECK(thread_checker_.CalledOnValidThread());
1109 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1110 scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
1111 dependency_factory_->CreateIceCandidate(
1112 base::UTF16ToUTF8(base::StringPiece16(candidate.sdpMid())),
1113 candidate.sdpMLineIndex(),
1114 base::UTF16ToUTF8(base::StringPiece16(candidate.candidate()))));
1115 bool return_value = false;
1117 if (native_candidate) {
1118 return_value =
1119 native_peer_connection_->AddIceCandidate(native_candidate.get());
1120 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
1121 } else {
1122 LOG(ERROR) << "Could not create native ICE candidate.";
1125 if (peer_connection_tracker_) {
1126 peer_connection_tracker_->TrackAddIceCandidate(
1127 this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
1129 return return_value;
1132 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1133 const blink::WebRTCVoidRequest& webkit_request, bool result) {
1134 DCHECK(thread_checker_.CalledOnValidThread());
1135 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1136 if (!result) {
1137 // We don't have the actual error code from the libjingle, so for now
1138 // using a generic error string.
1139 return webkit_request.requestFailed(
1140 base::UTF8ToUTF16("Error processing ICE candidate"));
1143 return webkit_request.requestSucceeded();
1146 bool RTCPeerConnectionHandler::addStream(
1147 const blink::WebMediaStream& stream,
1148 const blink::WebMediaConstraints& options) {
1149 DCHECK(thread_checker_.CalledOnValidThread());
1150 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1151 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1152 local_streams_.begin(); adapter_it != local_streams_.end();
1153 ++adapter_it) {
1154 if ((*adapter_it)->IsEqual(stream)) {
1155 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1156 << "stream twice. id=" << stream.id().utf8();
1157 return false;
1161 if (peer_connection_tracker_) {
1162 peer_connection_tracker_->TrackAddStream(
1163 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1166 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1168 WebRtcMediaStreamAdapter* adapter =
1169 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
1170 local_streams_.push_back(adapter);
1172 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
1173 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
1174 webrtc_stream);
1176 RTCMediaConstraints constraints(options);
1177 if (!constraints.GetMandatory().empty() ||
1178 !constraints.GetOptional().empty()) {
1179 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1180 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1181 // should be removed from blink as well.
1182 LOG(WARNING)
1183 << "mediaConstraints is not a supported argument to addStream.";
1186 return native_peer_connection_->AddStream(webrtc_stream);
1189 void RTCPeerConnectionHandler::removeStream(
1190 const blink::WebMediaStream& stream) {
1191 DCHECK(thread_checker_.CalledOnValidThread());
1192 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1193 // Find the webrtc stream.
1194 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
1195 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1196 local_streams_.begin(); adapter_it != local_streams_.end();
1197 ++adapter_it) {
1198 if ((*adapter_it)->IsEqual(stream)) {
1199 webrtc_stream = (*adapter_it)->webrtc_media_stream();
1200 local_streams_.erase(adapter_it);
1201 break;
1204 DCHECK(webrtc_stream.get());
1205 // TODO(tommi): Make this async (PostTaskAndReply).
1206 native_peer_connection_->RemoveStream(webrtc_stream.get());
1208 if (peer_connection_tracker_) {
1209 peer_connection_tracker_->TrackRemoveStream(
1210 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1212 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1213 track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
1214 webrtc_stream.get());
1217 void RTCPeerConnectionHandler::getStats(
1218 const blink::WebRTCStatsRequest& request) {
1219 DCHECK(thread_checker_.CalledOnValidThread());
1220 scoped_refptr<LocalRTCStatsRequest> inner_request(
1221 new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
1222 getStats(inner_request);
1225 void RTCPeerConnectionHandler::getStats(
1226 const scoped_refptr<LocalRTCStatsRequest>& request) {
1227 DCHECK(thread_checker_.CalledOnValidThread());
1228 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1231 rtc::scoped_refptr<webrtc::StatsObserver> observer(
1232 new rtc::RefCountedObject<StatsResponse>(request));
1234 std::string track_id;
1235 blink::WebMediaStreamSource::Type track_type =
1236 blink::WebMediaStreamSource::TypeAudio;
1237 if (request->hasSelector()) {
1238 track_type = request->component().source().type();
1239 track_id = request->component().id().utf8();
1242 GetStats(observer, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard,
1243 track_id, track_type);
1246 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1247 void RTCPeerConnectionHandler::GetStats(
1248 webrtc::StatsObserver* observer,
1249 webrtc::PeerConnectionInterface::StatsOutputLevel level,
1250 const std::string& track_id,
1251 blink::WebMediaStreamSource::Type track_type) {
1252 DCHECK(thread_checker_.CalledOnValidThread());
1253 signaling_thread()->PostTask(FROM_HERE,
1254 base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level,
1255 make_scoped_refptr(observer), track_id, track_type));
1258 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1259 DCHECK(thread_checker_.CalledOnValidThread());
1260 if (client_)
1261 client_->closePeerConnection();
1264 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
1265 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
1266 DCHECK(thread_checker_.CalledOnValidThread());
1267 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1268 DVLOG(1) << "createDataChannel label "
1269 << base::UTF16ToUTF8(base::StringPiece16(label));
1271 webrtc::DataChannelInit config;
1272 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1273 // to handle that.
1274 config.reliable = false;
1275 config.id = init.id;
1276 config.ordered = init.ordered;
1277 config.negotiated = init.negotiated;
1278 config.maxRetransmits = init.maxRetransmits;
1279 config.maxRetransmitTime = init.maxRetransmitTime;
1280 config.protocol = base::UTF16ToUTF8(base::StringPiece16(init.protocol));
1282 rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
1283 native_peer_connection_->CreateDataChannel(
1284 base::UTF16ToUTF8(base::StringPiece16(label)), &config));
1285 if (!webrtc_channel) {
1286 DLOG(ERROR) << "Could not create native data channel.";
1287 return NULL;
1289 if (peer_connection_tracker_) {
1290 peer_connection_tracker_->TrackCreateDataChannel(
1291 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
1294 ++num_data_channels_created_;
1296 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1297 webrtc_channel);
1300 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
1301 const blink::WebMediaStreamTrack& track) {
1302 DCHECK(thread_checker_.CalledOnValidThread());
1303 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1304 DVLOG(1) << "createDTMFSender.";
1306 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
1307 if (!native_track || !native_track->is_local_track() ||
1308 track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
1309 DLOG(ERROR) << "The DTMF sender requires a local audio track.";
1310 return nullptr;
1313 scoped_refptr<webrtc::AudioTrackInterface> audio_track =
1314 native_track->GetAudioAdapter();
1315 rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
1316 native_peer_connection_->CreateDtmfSender(audio_track.get()));
1317 if (!sender) {
1318 DLOG(ERROR) << "Could not create native DTMF sender.";
1319 return nullptr;
1321 if (peer_connection_tracker_)
1322 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
1324 return new RtcDtmfSenderHandler(sender);
1327 void RTCPeerConnectionHandler::stop() {
1328 DCHECK(thread_checker_.CalledOnValidThread());
1329 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1331 if (!client_ || !native_peer_connection_.get())
1332 return; // Already stopped.
1334 if (peer_connection_tracker_)
1335 peer_connection_tracker_->TrackStop(this);
1337 native_peer_connection_->Close();
1339 // The client_ pointer is not considered valid after this point and no further
1340 // callbacks must be made.
1341 client_ = nullptr;
1344 void RTCPeerConnectionHandler::OnSignalingChange(
1345 webrtc::PeerConnectionInterface::SignalingState new_state) {
1346 DCHECK(thread_checker_.CalledOnValidThread());
1347 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1349 blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
1350 GetWebKitSignalingState(new_state);
1351 if (peer_connection_tracker_)
1352 peer_connection_tracker_->TrackSignalingStateChange(this, state);
1353 if (client_)
1354 client_->didChangeSignalingState(state);
1357 // Called any time the IceConnectionState changes
1358 void RTCPeerConnectionHandler::OnIceConnectionChange(
1359 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
1360 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1361 DCHECK(thread_checker_.CalledOnValidThread());
1362 ReportICEState(new_state);
1363 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
1364 ice_connection_checking_start_ = base::TimeTicks::Now();
1365 } else if (new_state ==
1366 webrtc::PeerConnectionInterface::kIceConnectionConnected) {
1367 // If the state becomes connected, send the time needed for PC to become
1368 // connected from checking to UMA. UMA data will help to know how much
1369 // time needed for PC to connect with remote peer.
1370 if (ice_connection_checking_start_.is_null()) {
1371 // From UMA, we have observed a large number of calls falling into the
1372 // overflow buckets. One possibility is that the Checking is not signaled
1373 // before Connected. This is to guard against that situation to make the
1374 // metric more robust.
1375 UMA_HISTOGRAM_MEDIUM_TIMES("WebRTC.PeerConnection.TimeToConnect",
1376 base::TimeDelta());
1377 } else {
1378 UMA_HISTOGRAM_MEDIUM_TIMES(
1379 "WebRTC.PeerConnection.TimeToConnect",
1380 base::TimeTicks::Now() - ice_connection_checking_start_);
1384 track_metrics_.IceConnectionChange(new_state);
1385 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
1386 GetWebKitIceConnectionState(new_state);
1387 if (peer_connection_tracker_)
1388 peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
1389 if(client_)
1390 client_->didChangeICEConnectionState(state);
1393 // Called any time the IceGatheringState changes
1394 void RTCPeerConnectionHandler::OnIceGatheringChange(
1395 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
1396 DCHECK(thread_checker_.CalledOnValidThread());
1397 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1399 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
1400 // If ICE gathering is completed, generate a NULL ICE candidate,
1401 // to signal end of candidates.
1402 if (client_) {
1403 blink::WebRTCICECandidate null_candidate;
1404 client_->didGenerateICECandidate(null_candidate);
1407 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1408 num_local_candidates_ipv4_);
1410 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1411 num_local_candidates_ipv6_);
1412 } else if (new_state ==
1413 webrtc::PeerConnectionInterface::kIceGatheringGathering) {
1414 // ICE restarts will change gathering state back to "gathering",
1415 // reset the counter.
1416 ResetUMAStats();
1419 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
1420 GetWebKitIceGatheringState(new_state);
1421 if (peer_connection_tracker_)
1422 peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
1423 if (client_)
1424 client_->didChangeICEGatheringState(state);
1427 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1428 DCHECK(thread_checker_.CalledOnValidThread());
1429 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1430 if (peer_connection_tracker_)
1431 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
1432 if (client_)
1433 client_->negotiationNeeded();
1436 void RTCPeerConnectionHandler::OnAddStream(
1437 scoped_ptr<RemoteMediaStreamImpl> stream) {
1438 DCHECK(thread_checker_.CalledOnValidThread());
1439 DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
1440 remote_streams_.end());
1441 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
1442 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1444 // Ownership is with remote_streams_ now.
1445 RemoteMediaStreamImpl* s = stream.release();
1446 remote_streams_.insert(
1447 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
1448 s->webrtc_stream().get(), s));
1450 if (peer_connection_tracker_) {
1451 peer_connection_tracker_->TrackAddStream(
1452 this, s->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE);
1455 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1457 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1458 s->webrtc_stream().get());
1459 if (client_)
1460 client_->didAddRemoteStream(s->webkit_stream());
1463 void RTCPeerConnectionHandler::OnRemoveStream(
1464 const scoped_refptr<webrtc::MediaStreamInterface>& stream) {
1465 DCHECK(thread_checker_.CalledOnValidThread());
1466 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1467 RemoteStreamMap::iterator it = remote_streams_.find(stream.get());
1468 if (it == remote_streams_.end()) {
1469 NOTREACHED() << "Stream not found";
1470 return;
1473 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1474 stream.get());
1475 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1477 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
1478 const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
1479 DCHECK(!webkit_stream.isNull());
1480 remote_streams_.erase(it);
1482 if (peer_connection_tracker_) {
1483 peer_connection_tracker_->TrackRemoveStream(
1484 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
1487 if (client_)
1488 client_->didRemoveRemoteStream(webkit_stream);
1491 void RTCPeerConnectionHandler::OnDataChannel(
1492 scoped_ptr<RtcDataChannelHandler> handler) {
1493 DCHECK(thread_checker_.CalledOnValidThread());
1494 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1496 if (peer_connection_tracker_) {
1497 peer_connection_tracker_->TrackCreateDataChannel(
1498 this, handler->channel().get(), PeerConnectionTracker::SOURCE_REMOTE);
1501 if (client_)
1502 client_->didAddRemoteDataChannel(handler.release());
1505 void RTCPeerConnectionHandler::OnIceCandidate(
1506 const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index,
1507 int component, int address_family) {
1508 DCHECK(thread_checker_.CalledOnValidThread());
1509 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1510 blink::WebRTCICECandidate web_candidate;
1511 web_candidate.initialize(base::UTF8ToUTF16(sdp),
1512 base::UTF8ToUTF16(sdp_mid),
1513 sdp_mline_index);
1514 if (peer_connection_tracker_) {
1515 peer_connection_tracker_->TrackAddIceCandidate(
1516 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
1519 // Only the first m line's first component is tracked to avoid
1520 // miscounting when doing BUNDLE or rtcp mux.
1521 if (sdp_mline_index == 0 && component == 1) {
1522 if (address_family == AF_INET) {
1523 ++num_local_candidates_ipv4_;
1524 } else if (address_family == AF_INET6) {
1525 ++num_local_candidates_ipv6_;
1526 } else {
1527 NOTREACHED();
1530 if (client_)
1531 client_->didGenerateICECandidate(web_candidate);
1534 webrtc::SessionDescriptionInterface*
1535 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1536 const std::string& sdp, const std::string& type,
1537 webrtc::SdpParseError* error) {
1538 webrtc::SessionDescriptionInterface* native_desc =
1539 dependency_factory_->CreateSessionDescription(type, sdp, error);
1541 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1542 << " Type: " << type << " SDP: " << sdp;
1544 return native_desc;
1547 RTCPeerConnectionHandler::FirstSessionDescription::FirstSessionDescription(
1548 const webrtc::SessionDescriptionInterface* sdesc) {
1549 DCHECK(sdesc);
1551 for (const auto& content : sdesc->description()->contents()) {
1552 if (content.type == cricket::NS_JINGLE_RTP) {
1553 const auto* mdesc =
1554 static_cast<cricket::MediaContentDescription*>(content.description);
1555 audio = audio || (mdesc->type() == cricket::MEDIA_TYPE_AUDIO);
1556 video = video || (mdesc->type() == cricket::MEDIA_TYPE_VIDEO);
1557 rtcp_mux = rtcp_mux || mdesc->rtcp_mux();
1562 void RTCPeerConnectionHandler::ReportFirstSessionDescriptions(
1563 const FirstSessionDescription& local,
1564 const FirstSessionDescription& remote) {
1565 RtcpMux rtcp_mux = RTCP_MUX_ENABLED;
1566 if ((!local.audio && !local.video) || (!remote.audio && !remote.video)) {
1567 rtcp_mux = RTCP_MUX_NO_MEDIA;
1568 } else if (!local.rtcp_mux || !remote.rtcp_mux) {
1569 rtcp_mux = RTCP_MUX_DISABLED;
1572 UMA_HISTOGRAM_ENUMERATION(
1573 "WebRTC.PeerConnection.RtcpMux", rtcp_mux, RTCP_MUX_MAX);
1575 // TODO(pthatcher): Reports stats about whether we have audio and
1576 // video or not.
1579 scoped_refptr<base::SingleThreadTaskRunner>
1580 RTCPeerConnectionHandler::signaling_thread() const {
1581 DCHECK(thread_checker_.CalledOnValidThread());
1582 return dependency_factory_->GetWebRtcSignalingThread();
1585 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1586 const base::Closure& closure,
1587 const char* trace_event_name) {
1588 DCHECK(thread_checker_.CalledOnValidThread());
1589 scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
1590 if (!thread.get() || thread->BelongsToCurrentThread()) {
1591 TRACE_EVENT0("webrtc", trace_event_name);
1592 closure.Run();
1593 } else {
1594 base::WaitableEvent event(false, false);
1595 thread->PostTask(FROM_HERE,
1596 base::Bind(&RunSynchronousClosure, closure,
1597 base::Unretained(trace_event_name),
1598 base::Unretained(&event)));
1599 event.Wait();
1603 void RTCPeerConnectionHandler::ReportICEState(
1604 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
1605 DCHECK(thread_checker_.CalledOnValidThread());
1606 if (ice_state_seen_[new_state])
1607 return;
1608 ice_state_seen_[new_state] = true;
1609 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.ConnectionState", new_state,
1610 webrtc::PeerConnectionInterface::kIceConnectionMax);
1613 void RTCPeerConnectionHandler::ResetUMAStats() {
1614 DCHECK(thread_checker_.CalledOnValidThread());
1615 num_local_candidates_ipv6_ = 0;
1616 num_local_candidates_ipv4_ = 0;
1617 ice_connection_checking_start_ = base::TimeTicks();
1618 memset(ice_state_seen_, 0, sizeof(ice_state_seen_));
1620 } // namespace content