Roll src/third_party/WebKit d10c917:a1123a1 (svn 198729:198730)
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
blob6bbbbfb589f53b25ae8d4a27769e2baa60a8ea12
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"
44 using webrtc::DataChannelInterface;
45 using webrtc::IceCandidateInterface;
46 using webrtc::MediaStreamInterface;
47 using webrtc::PeerConnectionInterface;
48 using webrtc::PeerConnectionObserver;
49 using webrtc::StatsReport;
50 using webrtc::StatsReports;
52 namespace content {
53 namespace {
55 // Converter functions from libjingle types to WebKit types.
56 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
57 GetWebKitIceGatheringState(
58 webrtc::PeerConnectionInterface::IceGatheringState state) {
59 using blink::WebRTCPeerConnectionHandlerClient;
60 switch (state) {
61 case webrtc::PeerConnectionInterface::kIceGatheringNew:
62 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
63 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
64 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering;
65 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
66 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete;
67 default:
68 NOTREACHED();
69 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
73 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
74 GetWebKitIceConnectionState(
75 webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
76 using blink::WebRTCPeerConnectionHandlerClient;
77 switch (ice_state) {
78 case webrtc::PeerConnectionInterface::kIceConnectionNew:
79 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
80 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
81 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking;
82 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
83 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected;
84 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
85 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted;
86 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
87 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed;
88 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
89 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected;
90 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
91 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
92 default:
93 NOTREACHED();
94 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
98 blink::WebRTCPeerConnectionHandlerClient::SignalingState
99 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
100 using blink::WebRTCPeerConnectionHandlerClient;
101 switch (state) {
102 case webrtc::PeerConnectionInterface::kStable:
103 return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
104 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
105 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer;
106 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
107 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer;
108 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
109 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer;
110 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
111 return
112 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer;
113 case webrtc::PeerConnectionInterface::kClosed:
114 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
115 default:
116 NOTREACHED();
117 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
121 blink::WebRTCSessionDescription CreateWebKitSessionDescription(
122 const std::string& sdp, const std::string& type) {
123 blink::WebRTCSessionDescription description;
124 description.initialize(base::UTF8ToUTF16(type), base::UTF8ToUTF16(sdp));
125 return description;
128 blink::WebRTCSessionDescription
129 CreateWebKitSessionDescription(
130 const webrtc::SessionDescriptionInterface* native_desc) {
131 if (!native_desc) {
132 LOG(ERROR) << "Native session description is null.";
133 return blink::WebRTCSessionDescription();
136 std::string sdp;
137 if (!native_desc->ToString(&sdp)) {
138 LOG(ERROR) << "Failed to get SDP string of native session description.";
139 return blink::WebRTCSessionDescription();
142 return CreateWebKitSessionDescription(sdp, native_desc->type());
145 void RunClosureWithTrace(const base::Closure& closure,
146 const char* trace_event_name) {
147 TRACE_EVENT0("webrtc", trace_event_name);
148 closure.Run();
151 void RunSynchronousClosure(const base::Closure& closure,
152 const char* trace_event_name,
153 base::WaitableEvent* event) {
155 TRACE_EVENT0("webrtc", trace_event_name);
156 closure.Run();
158 event->Signal();
161 void GetSdpAndTypeFromSessionDescription(
162 const base::Callback<const webrtc::SessionDescriptionInterface*()>&
163 description_callback,
164 std::string* sdp, std::string* type) {
165 const webrtc::SessionDescriptionInterface* description =
166 description_callback.Run();
167 if (description) {
168 description->ToString(sdp);
169 *type = description->type();
173 // Converter functions from WebKit types to WebRTC types.
175 void GetNativeRtcConfiguration(
176 const blink::WebRTCConfiguration& blink_config,
177 webrtc::PeerConnectionInterface::RTCConfiguration* webrtc_config) {
178 if (blink_config.isNull() || !webrtc_config)
179 return;
180 for (size_t i = 0; i < blink_config.numberOfServers(); ++i) {
181 webrtc::PeerConnectionInterface::IceServer server;
182 const blink::WebRTCICEServer& webkit_server =
183 blink_config.server(i);
184 server.username = base::UTF16ToUTF8(webkit_server.username());
185 server.password = base::UTF16ToUTF8(webkit_server.credential());
186 server.uri = webkit_server.uri().spec();
187 webrtc_config->servers.push_back(server);
190 switch (blink_config.iceTransports()) {
191 case blink::WebRTCIceTransportsNone:
192 webrtc_config->type = webrtc::PeerConnectionInterface::kNone;
193 break;
194 case blink::WebRTCIceTransportsRelay:
195 webrtc_config->type = webrtc::PeerConnectionInterface::kRelay;
196 break;
197 case blink::WebRTCIceTransportsAll:
198 webrtc_config->type = webrtc::PeerConnectionInterface::kAll;
199 break;
200 default:
201 NOTREACHED();
204 switch (blink_config.bundlePolicy()) {
205 case blink::WebRTCBundlePolicyBalanced:
206 webrtc_config->bundle_policy =
207 webrtc::PeerConnectionInterface::kBundlePolicyBalanced;
208 break;
209 case blink::WebRTCBundlePolicyMaxBundle:
210 webrtc_config->bundle_policy =
211 webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle;
212 break;
213 case blink::WebRTCBundlePolicyMaxCompat:
214 webrtc_config->bundle_policy =
215 webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
216 break;
217 default:
218 NOTREACHED();
221 switch (blink_config.rtcpMuxPolicy()) {
222 case blink::WebRTCRtcpMuxPolicyNegotiate:
223 webrtc_config->rtcp_mux_policy =
224 webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
225 break;
226 case blink::WebRTCRtcpMuxPolicyRequire:
227 webrtc_config->rtcp_mux_policy =
228 webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire;
229 break;
230 default:
231 NOTREACHED();
235 class SessionDescriptionRequestTracker {
236 public:
237 SessionDescriptionRequestTracker(
238 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
239 const base::WeakPtr<PeerConnectionTracker>& tracker,
240 PeerConnectionTracker::Action action)
241 : handler_(handler), tracker_(tracker), action_(action) {}
243 void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
244 DCHECK(thread_checker_.CalledOnValidThread());
245 if (tracker_ && handler_) {
246 std::string value;
247 if (desc) {
248 desc->ToString(&value);
249 value = "type: " + desc->type() + ", sdp: " + value;
251 tracker_->TrackSessionDescriptionCallback(
252 handler_.get(), action_, "OnSuccess", value);
256 void TrackOnFailure(const std::string& error) {
257 DCHECK(thread_checker_.CalledOnValidThread());
258 if (handler_ && tracker_) {
259 tracker_->TrackSessionDescriptionCallback(
260 handler_.get(), action_, "OnFailure", error);
264 private:
265 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
266 const base::WeakPtr<PeerConnectionTracker> tracker_;
267 PeerConnectionTracker::Action action_;
268 base::ThreadChecker thread_checker_;
271 // Class mapping responses from calls to libjingle CreateOffer/Answer and
272 // the blink::WebRTCSessionDescriptionRequest.
273 class CreateSessionDescriptionRequest
274 : public webrtc::CreateSessionDescriptionObserver {
275 public:
276 explicit CreateSessionDescriptionRequest(
277 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
278 const blink::WebRTCSessionDescriptionRequest& request,
279 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
280 const base::WeakPtr<PeerConnectionTracker>& tracker,
281 PeerConnectionTracker::Action action)
282 : main_thread_(main_thread),
283 webkit_request_(request),
284 tracker_(handler, tracker, action) {
287 void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
288 if (!main_thread_->BelongsToCurrentThread()) {
289 main_thread_->PostTask(FROM_HERE,
290 base::Bind(&CreateSessionDescriptionRequest::OnSuccess, this, desc));
291 return;
294 tracker_.TrackOnSuccess(desc);
295 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
296 webkit_request_.reset();
297 delete desc;
299 void OnFailure(const std::string& error) override {
300 if (!main_thread_->BelongsToCurrentThread()) {
301 main_thread_->PostTask(FROM_HERE,
302 base::Bind(&CreateSessionDescriptionRequest::OnFailure, this, error));
303 return;
306 tracker_.TrackOnFailure(error);
307 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
308 webkit_request_.reset();
311 protected:
312 ~CreateSessionDescriptionRequest() override {
313 CHECK(webkit_request_.isNull());
316 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
317 blink::WebRTCSessionDescriptionRequest webkit_request_;
318 SessionDescriptionRequestTracker tracker_;
321 // Class mapping responses from calls to libjingle
322 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
323 class SetSessionDescriptionRequest
324 : public webrtc::SetSessionDescriptionObserver {
325 public:
326 explicit SetSessionDescriptionRequest(
327 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
328 const blink::WebRTCVoidRequest& request,
329 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
330 const base::WeakPtr<PeerConnectionTracker>& tracker,
331 PeerConnectionTracker::Action action)
332 : main_thread_(main_thread),
333 webkit_request_(request),
334 tracker_(handler, tracker, action) {
337 void OnSuccess() override {
338 if (!main_thread_->BelongsToCurrentThread()) {
339 main_thread_->PostTask(FROM_HERE,
340 base::Bind(&SetSessionDescriptionRequest::OnSuccess, this));
341 return;
343 tracker_.TrackOnSuccess(NULL);
344 webkit_request_.requestSucceeded();
345 webkit_request_.reset();
347 void OnFailure(const std::string& error) override {
348 if (!main_thread_->BelongsToCurrentThread()) {
349 main_thread_->PostTask(FROM_HERE,
350 base::Bind(&SetSessionDescriptionRequest::OnFailure, this, error));
351 return;
353 tracker_.TrackOnFailure(error);
354 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
355 webkit_request_.reset();
358 protected:
359 ~SetSessionDescriptionRequest() override {
360 DCHECK(webkit_request_.isNull());
363 private:
364 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
365 blink::WebRTCVoidRequest webkit_request_;
366 SessionDescriptionRequestTracker tracker_;
369 // Class mapping responses from calls to libjingle
370 // GetStats into a blink::WebRTCStatsCallback.
371 class StatsResponse : public webrtc::StatsObserver {
372 public:
373 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
374 : request_(request.get()),
375 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
376 // Measure the overall time it takes to satisfy a getStats request.
377 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
378 signaling_thread_checker_.DetachFromThread();
381 void OnComplete(const StatsReports& reports) override {
382 DCHECK(signaling_thread_checker_.CalledOnValidThread());
383 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
384 // We can't use webkit objects directly since they use a single threaded
385 // heap allocator.
386 std::vector<Report*>* report_copies = new std::vector<Report*>();
387 report_copies->reserve(reports.size());
388 for (auto* r : reports)
389 report_copies->push_back(new Report(r));
391 main_thread_->PostTaskAndReply(FROM_HERE,
392 base::Bind(&StatsResponse::DeliverCallback, this,
393 base::Unretained(report_copies)),
394 base::Bind(&StatsResponse::DeleteReports,
395 base::Unretained(report_copies)));
398 private:
399 struct Report {
400 Report(const StatsReport* report)
401 : thread_checker(), id(report->id()->ToString()),
402 type(report->TypeToString()), timestamp(report->timestamp()),
403 values(report->values()) {
406 ~Report() {
407 // Since the values vector holds pointers to const objects that are bound
408 // to the signaling thread, they must be released on the same thread.
409 DCHECK(thread_checker.CalledOnValidThread());
412 const base::ThreadChecker thread_checker;
413 const std::string id, type;
414 const double timestamp;
415 const StatsReport::Values values;
418 static void DeleteReports(std::vector<Report*>* reports) {
419 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
420 for (auto* p : *reports)
421 delete p;
422 delete reports;
425 void DeliverCallback(const std::vector<Report*>* reports) {
426 DCHECK(main_thread_->BelongsToCurrentThread());
427 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
429 rtc::scoped_refptr<LocalRTCStatsResponse> response(
430 request_->createResponse().get());
431 for (const auto* report : *reports) {
432 if (report->values.size() > 0)
433 AddReport(response.get(), *report);
436 // Record the getStats operation as done before calling into Blink so that
437 // we don't skew the perf measurements of the native code with whatever the
438 // callback might be doing.
439 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
440 request_->requestSucceeded(response);
441 request_ = nullptr; // must be freed on the main thread.
444 void AddReport(LocalRTCStatsResponse* response, const Report& report) {
445 int idx = response->addReport(blink::WebString::fromUTF8(report.id),
446 blink::WebString::fromUTF8(report.type),
447 report.timestamp);
448 blink::WebString name, value_str;
449 for (const auto& value : report.values) {
450 const StatsReport::ValuePtr& v = value.second;
451 name = blink::WebString::fromUTF8(value.second->display_name());
453 if (v->type() == StatsReport::Value::kString)
454 value_str = blink::WebString::fromUTF8(v->string_val());
455 if (v->type() == StatsReport::Value::kStaticString)
456 value_str = blink::WebString::fromUTF8(v->static_string_val());
457 else
458 value_str = blink::WebString::fromUTF8(v->ToString());
460 response->addStatistic(idx, name, value_str);
464 rtc::scoped_refptr<LocalRTCStatsRequest> request_;
465 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
466 base::ThreadChecker signaling_thread_checker_;
469 void GetStatsOnSignalingThread(
470 const scoped_refptr<webrtc::PeerConnectionInterface>& pc,
471 webrtc::PeerConnectionInterface::StatsOutputLevel level,
472 const scoped_refptr<webrtc::StatsObserver>& observer,
473 const std::string track_id, blink::WebMediaStreamSource::Type track_type) {
474 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
476 scoped_refptr<webrtc::MediaStreamTrackInterface> track;
477 if (!track_id.empty()) {
478 if (track_type == blink::WebMediaStreamSource::TypeAudio) {
479 track = pc->local_streams()->FindAudioTrack(track_id);
480 if (!track.get())
481 track = pc->remote_streams()->FindAudioTrack(track_id);
482 } else {
483 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track_type);
484 track = pc->local_streams()->FindVideoTrack(track_id);
485 if (!track.get())
486 track = pc->remote_streams()->FindVideoTrack(track_id);
489 if (!track.get()) {
490 DVLOG(1) << "GetStats: Track not found.";
491 observer->OnComplete(StatsReports());
492 return;
496 if (!pc->GetStats(observer.get(), track.get(), level)) {
497 DVLOG(1) << "GetStats failed.";
498 observer->OnComplete(StatsReports());
502 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
503 public:
504 PeerConnectionUMAObserver() {}
505 ~PeerConnectionUMAObserver() override {}
507 void IncrementCounter(
508 webrtc::PeerConnectionUMAMetricsCounter counter) override {
509 // Runs on libjingle's signaling thread.
510 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
511 counter,
512 webrtc::kBoundary);
515 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,
516 int value) override {
517 // Runs on libjingle's signaling thread.
518 switch (type) {
519 case webrtc::kTimeToConnect:
520 UMA_HISTOGRAM_MEDIUM_TIMES(
521 "WebRTC.PeerConnection.TimeToConnect",
522 base::TimeDelta::FromMilliseconds(value));
523 break;
524 case webrtc::kNetworkInterfaces_IPv4:
525 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
526 value);
527 break;
528 case webrtc::kNetworkInterfaces_IPv6:
529 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
530 value);
531 break;
532 default:
533 NOTREACHED();
538 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
539 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
541 } // namespace
543 // Implementation of LocalRTCStatsRequest.
544 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
545 : impl_(impl) {
548 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
549 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
551 bool LocalRTCStatsRequest::hasSelector() const {
552 return impl_.hasSelector();
555 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
556 return impl_.component();
559 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
560 return scoped_refptr<LocalRTCStatsResponse>(
561 new rtc::RefCountedObject<LocalRTCStatsResponse>(impl_.createResponse()));
564 void LocalRTCStatsRequest::requestSucceeded(
565 const LocalRTCStatsResponse* response) {
566 impl_.requestSucceeded(response->webKitStatsResponse());
569 // Implementation of LocalRTCStatsResponse.
570 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
571 return impl_;
574 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
575 blink::WebString id,
576 double timestamp) {
577 return impl_.addReport(type, id, timestamp);
580 void LocalRTCStatsResponse::addStatistic(size_t report,
581 blink::WebString name,
582 blink::WebString value) {
583 impl_.addStatistic(report, name, value);
586 // Receives notifications from a PeerConnection object about state changes,
587 // track addition/removal etc. The callbacks we receive here come on the
588 // signaling thread, so this class takes care of delivering them to an
589 // RTCPeerConnectionHandler instance on the main thread.
590 // In order to do safe PostTask-ing, the class is reference counted and
591 // checks for the existence of the RTCPeerConnectionHandler instance before
592 // delivering callbacks on the main thread.
593 class RTCPeerConnectionHandler::Observer
594 : public base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>,
595 public PeerConnectionObserver {
596 public:
597 Observer(const base::WeakPtr<RTCPeerConnectionHandler>& handler)
598 : handler_(handler), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
600 protected:
601 friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>;
602 virtual ~Observer() {}
604 void OnSignalingChange(
605 PeerConnectionInterface::SignalingState new_state) override {
606 if (!main_thread_->BelongsToCurrentThread()) {
607 main_thread_->PostTask(FROM_HERE,
608 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange,
609 this, new_state));
610 } else if (handler_) {
611 handler_->OnSignalingChange(new_state);
615 void OnAddStream(MediaStreamInterface* stream) override {
616 DCHECK(stream);
617 scoped_ptr<RemoteMediaStreamImpl> remote_stream(
618 new RemoteMediaStreamImpl(main_thread_, stream));
620 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
621 // asynchronously and the posted task will execude after that initialization
622 // is done.
623 main_thread_->PostTask(FROM_HERE,
624 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl,
625 this, base::Passed(&remote_stream)));
628 void OnRemoveStream(MediaStreamInterface* stream) override {
629 main_thread_->PostTask(FROM_HERE,
630 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
631 this, make_scoped_refptr(stream)));
634 void OnDataChannel(DataChannelInterface* data_channel) override {
635 scoped_ptr<RtcDataChannelHandler> handler(
636 new RtcDataChannelHandler(main_thread_, data_channel));
637 main_thread_->PostTask(FROM_HERE,
638 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
639 this, base::Passed(&handler)));
642 void OnRenegotiationNeeded() override {
643 if (!main_thread_->BelongsToCurrentThread()) {
644 main_thread_->PostTask(FROM_HERE,
645 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
646 this));
647 } else if (handler_) {
648 handler_->OnRenegotiationNeeded();
652 void OnIceConnectionChange(
653 PeerConnectionInterface::IceConnectionState new_state) override {
654 if (!main_thread_->BelongsToCurrentThread()) {
655 main_thread_->PostTask(FROM_HERE,
656 base::Bind(
657 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
658 new_state));
659 } else if (handler_) {
660 handler_->OnIceConnectionChange(new_state);
664 void OnIceGatheringChange(
665 PeerConnectionInterface::IceGatheringState new_state) override {
666 if (!main_thread_->BelongsToCurrentThread()) {
667 main_thread_->PostTask(FROM_HERE,
668 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
669 this, new_state));
670 } else if (handler_) {
671 handler_->OnIceGatheringChange(new_state);
675 void OnIceCandidate(const IceCandidateInterface* candidate) override {
676 std::string sdp;
677 if (!candidate->ToString(&sdp)) {
678 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
679 return;
682 main_thread_->PostTask(FROM_HERE,
683 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
684 this, sdp, candidate->sdp_mid(), candidate->sdp_mline_index(),
685 candidate->candidate().component(),
686 candidate->candidate().address().family()));
689 void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
690 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
691 if (handler_)
692 handler_->OnAddStream(stream.Pass());
695 void OnRemoveStreamImpl(const scoped_refptr<MediaStreamInterface>& stream) {
696 if (handler_)
697 handler_->OnRemoveStream(stream);
700 void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
701 if (handler_)
702 handler_->OnDataChannel(handler.Pass());
705 void OnIceCandidateImpl(const std::string& sdp, const std::string& sdp_mid,
706 int sdp_mline_index, int component, int address_family) {
707 if (handler_) {
708 handler_->OnIceCandidate(sdp, sdp_mid, sdp_mline_index, component,
709 address_family);
713 private:
714 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
715 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
718 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
719 blink::WebRTCPeerConnectionHandlerClient* client,
720 PeerConnectionDependencyFactory* dependency_factory)
721 : client_(client),
722 dependency_factory_(dependency_factory),
723 frame_(NULL),
724 num_data_channels_created_(0),
725 num_local_candidates_ipv4_(0),
726 num_local_candidates_ipv6_(0),
727 weak_factory_(this) {
728 g_peer_connection_handlers.Get().insert(this);
731 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
732 DCHECK(thread_checker_.CalledOnValidThread());
734 stop();
736 g_peer_connection_handlers.Get().erase(this);
737 if (peer_connection_tracker_)
738 peer_connection_tracker_->UnregisterPeerConnection(this);
739 STLDeleteValues(&remote_streams_);
741 UMA_HISTOGRAM_COUNTS_10000(
742 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
745 // static
746 void RTCPeerConnectionHandler::DestructAllHandlers() {
747 std::set<RTCPeerConnectionHandler*> handlers(
748 g_peer_connection_handlers.Get().begin(),
749 g_peer_connection_handlers.Get().end());
750 for (auto handler : handlers) {
751 if (handler->client_)
752 handler->client_->releasePeerConnectionHandler();
756 // static
757 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
758 const blink::WebRTCOfferOptions& options,
759 RTCMediaConstraints* output) {
760 output->AddMandatory(
761 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
762 options.offerToReceiveAudio() > 0 ? "true" : "false",
763 true);
765 output->AddMandatory(
766 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
767 options.offerToReceiveVideo() > 0 ? "true" : "false",
768 true);
770 if (!options.voiceActivityDetection()) {
771 output->AddMandatory(
772 webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
773 "false",
774 true);
777 if (options.iceRestart()) {
778 output->AddMandatory(
779 webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
783 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
784 DCHECK(thread_checker_.CalledOnValidThread());
785 DCHECK(frame);
786 frame_ = frame;
789 bool RTCPeerConnectionHandler::initialize(
790 const blink::WebRTCConfiguration& server_configuration,
791 const blink::WebMediaConstraints& options) {
792 DCHECK(thread_checker_.CalledOnValidThread());
793 DCHECK(frame_);
795 peer_connection_tracker_ =
796 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
798 webrtc::PeerConnectionInterface::RTCConfiguration config;
799 GetNativeRtcConfiguration(server_configuration, &config);
801 RTCMediaConstraints constraints(options);
803 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
804 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
805 config, &constraints, frame_, peer_connection_observer_.get());
807 if (!native_peer_connection_.get()) {
808 LOG(ERROR) << "Failed to initialize native PeerConnection.";
809 return false;
812 if (peer_connection_tracker_) {
813 peer_connection_tracker_->RegisterPeerConnection(
814 this, config, constraints, frame_);
817 uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
818 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
819 return true;
822 bool RTCPeerConnectionHandler::InitializeForTest(
823 const blink::WebRTCConfiguration& server_configuration,
824 const blink::WebMediaConstraints& options,
825 const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
826 DCHECK(thread_checker_.CalledOnValidThread());
827 webrtc::PeerConnectionInterface::RTCConfiguration config;
828 GetNativeRtcConfiguration(server_configuration, &config);
830 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
831 RTCMediaConstraints constraints(options);
832 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
833 config, &constraints, NULL, peer_connection_observer_.get());
834 if (!native_peer_connection_.get()) {
835 LOG(ERROR) << "Failed to initialize native PeerConnection.";
836 return false;
838 peer_connection_tracker_ = peer_connection_tracker;
839 return true;
842 void RTCPeerConnectionHandler::createOffer(
843 const blink::WebRTCSessionDescriptionRequest& request,
844 const blink::WebMediaConstraints& options) {
845 DCHECK(thread_checker_.CalledOnValidThread());
846 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
848 scoped_refptr<CreateSessionDescriptionRequest> description_request(
849 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
850 base::ThreadTaskRunnerHandle::Get(), request,
851 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
852 PeerConnectionTracker::ACTION_CREATE_OFFER));
854 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
855 RTCMediaConstraints constraints(options);
856 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
858 if (peer_connection_tracker_)
859 peer_connection_tracker_->TrackCreateOffer(this, constraints);
862 void RTCPeerConnectionHandler::createOffer(
863 const blink::WebRTCSessionDescriptionRequest& request,
864 const blink::WebRTCOfferOptions& options) {
865 DCHECK(thread_checker_.CalledOnValidThread());
866 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
868 scoped_refptr<CreateSessionDescriptionRequest> description_request(
869 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
870 base::ThreadTaskRunnerHandle::Get(), request,
871 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
872 PeerConnectionTracker::ACTION_CREATE_OFFER));
874 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
875 RTCMediaConstraints constraints;
876 ConvertOfferOptionsToConstraints(options, &constraints);
877 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
879 if (peer_connection_tracker_)
880 peer_connection_tracker_->TrackCreateOffer(this, constraints);
883 void RTCPeerConnectionHandler::createAnswer(
884 const blink::WebRTCSessionDescriptionRequest& request,
885 const blink::WebMediaConstraints& options) {
886 DCHECK(thread_checker_.CalledOnValidThread());
887 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
888 scoped_refptr<CreateSessionDescriptionRequest> description_request(
889 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
890 base::ThreadTaskRunnerHandle::Get(), request,
891 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
892 PeerConnectionTracker::ACTION_CREATE_ANSWER));
893 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
894 RTCMediaConstraints constraints(options);
895 native_peer_connection_->CreateAnswer(description_request.get(),
896 &constraints);
898 if (peer_connection_tracker_)
899 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
902 void RTCPeerConnectionHandler::setLocalDescription(
903 const blink::WebRTCVoidRequest& request,
904 const blink::WebRTCSessionDescription& description) {
905 DCHECK(thread_checker_.CalledOnValidThread());
906 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
908 std::string sdp = base::UTF16ToUTF8(description.sdp());
909 std::string type = base::UTF16ToUTF8(description.type());
911 webrtc::SdpParseError error;
912 // Since CreateNativeSessionDescription uses the dependency factory, we need
913 // to make this call on the current thread to be safe.
914 webrtc::SessionDescriptionInterface* native_desc =
915 CreateNativeSessionDescription(sdp, type, &error);
916 if (!native_desc) {
917 std::string reason_str = "Failed to parse SessionDescription. ";
918 reason_str.append(error.line);
919 reason_str.append(" ");
920 reason_str.append(error.description);
921 LOG(ERROR) << reason_str;
922 request.requestFailed(blink::WebString::fromUTF8(reason_str));
923 return;
926 if (peer_connection_tracker_) {
927 peer_connection_tracker_->TrackSetSessionDescription(
928 this, sdp, type, PeerConnectionTracker::SOURCE_LOCAL);
931 scoped_refptr<SetSessionDescriptionRequest> set_request(
932 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
933 base::ThreadTaskRunnerHandle::Get(), request,
934 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
935 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
937 signaling_thread()->PostTask(FROM_HERE,
938 base::Bind(&RunClosureWithTrace,
939 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
940 native_peer_connection_, set_request,
941 base::Unretained(native_desc)),
942 "SetLocalDescription"));
945 void RTCPeerConnectionHandler::setRemoteDescription(
946 const blink::WebRTCVoidRequest& request,
947 const blink::WebRTCSessionDescription& description) {
948 DCHECK(thread_checker_.CalledOnValidThread());
949 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
950 std::string sdp = base::UTF16ToUTF8(description.sdp());
951 std::string type = base::UTF16ToUTF8(description.type());
953 webrtc::SdpParseError error;
954 // Since CreateNativeSessionDescription uses the dependency factory, we need
955 // to make this call on the current thread to be safe.
956 webrtc::SessionDescriptionInterface* native_desc =
957 CreateNativeSessionDescription(sdp, type, &error);
958 if (!native_desc) {
959 std::string reason_str = "Failed to parse SessionDescription. ";
960 reason_str.append(error.line);
961 reason_str.append(" ");
962 reason_str.append(error.description);
963 LOG(ERROR) << reason_str;
964 request.requestFailed(blink::WebString::fromUTF8(reason_str));
965 return;
968 if (peer_connection_tracker_) {
969 peer_connection_tracker_->TrackSetSessionDescription(
970 this, sdp, type, PeerConnectionTracker::SOURCE_REMOTE);
973 scoped_refptr<SetSessionDescriptionRequest> set_request(
974 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
975 base::ThreadTaskRunnerHandle::Get(), request,
976 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
977 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
978 signaling_thread()->PostTask(FROM_HERE,
979 base::Bind(&RunClosureWithTrace,
980 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
981 native_peer_connection_, set_request,
982 base::Unretained(native_desc)),
983 "SetRemoteDescription"));
986 blink::WebRTCSessionDescription
987 RTCPeerConnectionHandler::localDescription() {
988 DCHECK(thread_checker_.CalledOnValidThread());
989 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
991 // Since local_description returns a pointer to a non-reference-counted object
992 // that lives on the signaling thread, we cannot fetch a pointer to it and use
993 // it directly here. Instead, we access the object completely on the signaling
994 // thread.
995 std::string sdp, type;
996 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
997 base::Bind(&webrtc::PeerConnectionInterface::local_description,
998 native_peer_connection_);
999 RunSynchronousClosureOnSignalingThread(
1000 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
1001 base::Unretained(&sdp), base::Unretained(&type)),
1002 "localDescription");
1004 return CreateWebKitSessionDescription(sdp, type);
1007 blink::WebRTCSessionDescription
1008 RTCPeerConnectionHandler::remoteDescription() {
1009 DCHECK(thread_checker_.CalledOnValidThread());
1010 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
1011 // Since local_description returns a pointer to a non-reference-counted object
1012 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1013 // it directly here. Instead, we access the object completely on the signaling
1014 // thread.
1015 std::string sdp, type;
1016 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
1017 base::Bind(&webrtc::PeerConnectionInterface::remote_description,
1018 native_peer_connection_);
1019 RunSynchronousClosureOnSignalingThread(
1020 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
1021 base::Unretained(&sdp), base::Unretained(&type)),
1022 "remoteDescription");
1024 return CreateWebKitSessionDescription(sdp, type);
1027 bool RTCPeerConnectionHandler::updateICE(
1028 const blink::WebRTCConfiguration& server_configuration,
1029 const blink::WebMediaConstraints& options) {
1030 DCHECK(thread_checker_.CalledOnValidThread());
1031 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1032 webrtc::PeerConnectionInterface::RTCConfiguration config;
1033 GetNativeRtcConfiguration(server_configuration, &config);
1034 RTCMediaConstraints constraints(options);
1036 if (peer_connection_tracker_)
1037 peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
1039 return native_peer_connection_->UpdateIce(config.servers, &constraints);
1042 bool RTCPeerConnectionHandler::addICECandidate(
1043 const blink::WebRTCVoidRequest& request,
1044 const blink::WebRTCICECandidate& candidate) {
1045 DCHECK(thread_checker_.CalledOnValidThread());
1046 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1047 // Libjingle currently does not accept callbacks for addICECandidate.
1048 // For that reason we are going to call callbacks from here.
1050 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1051 // PostTaskAndReply kind of a thing.
1052 bool result = addICECandidate(candidate);
1053 base::ThreadTaskRunnerHandle::Get()->PostTask(
1054 FROM_HERE, base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
1055 weak_factory_.GetWeakPtr(), request, result));
1056 // On failure callback will be triggered.
1057 return true;
1060 bool RTCPeerConnectionHandler::addICECandidate(
1061 const blink::WebRTCICECandidate& candidate) {
1062 DCHECK(thread_checker_.CalledOnValidThread());
1063 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1064 scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
1065 dependency_factory_->CreateIceCandidate(
1066 base::UTF16ToUTF8(candidate.sdpMid()),
1067 candidate.sdpMLineIndex(),
1068 base::UTF16ToUTF8(candidate.candidate())));
1069 bool return_value = false;
1071 if (native_candidate) {
1072 return_value =
1073 native_peer_connection_->AddIceCandidate(native_candidate.get());
1074 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
1075 } else {
1076 LOG(ERROR) << "Could not create native ICE candidate.";
1079 if (peer_connection_tracker_) {
1080 peer_connection_tracker_->TrackAddIceCandidate(
1081 this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
1083 return return_value;
1086 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1087 const blink::WebRTCVoidRequest& webkit_request, bool result) {
1088 DCHECK(thread_checker_.CalledOnValidThread());
1089 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1090 if (!result) {
1091 // We don't have the actual error code from the libjingle, so for now
1092 // using a generic error string.
1093 return webkit_request.requestFailed(
1094 base::UTF8ToUTF16("Error processing ICE candidate"));
1097 return webkit_request.requestSucceeded();
1100 bool RTCPeerConnectionHandler::addStream(
1101 const blink::WebMediaStream& stream,
1102 const blink::WebMediaConstraints& options) {
1103 DCHECK(thread_checker_.CalledOnValidThread());
1104 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1105 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1106 local_streams_.begin(); adapter_it != local_streams_.end();
1107 ++adapter_it) {
1108 if ((*adapter_it)->IsEqual(stream)) {
1109 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1110 << "stream twice. id=" << stream.id().utf8();
1111 return false;
1115 if (peer_connection_tracker_) {
1116 peer_connection_tracker_->TrackAddStream(
1117 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1120 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1122 WebRtcMediaStreamAdapter* adapter =
1123 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
1124 local_streams_.push_back(adapter);
1126 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
1127 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
1128 webrtc_stream);
1130 RTCMediaConstraints constraints(options);
1131 if (!constraints.GetMandatory().empty() ||
1132 !constraints.GetOptional().empty()) {
1133 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1134 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1135 // should be removed from blink as well.
1136 LOG(WARNING)
1137 << "mediaConstraints is not a supported argument to addStream.";
1140 return native_peer_connection_->AddStream(webrtc_stream);
1143 void RTCPeerConnectionHandler::removeStream(
1144 const blink::WebMediaStream& stream) {
1145 DCHECK(thread_checker_.CalledOnValidThread());
1146 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1147 // Find the webrtc stream.
1148 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
1149 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1150 local_streams_.begin(); adapter_it != local_streams_.end();
1151 ++adapter_it) {
1152 if ((*adapter_it)->IsEqual(stream)) {
1153 webrtc_stream = (*adapter_it)->webrtc_media_stream();
1154 local_streams_.erase(adapter_it);
1155 break;
1158 DCHECK(webrtc_stream.get());
1159 // TODO(tommi): Make this async (PostTaskAndReply).
1160 native_peer_connection_->RemoveStream(webrtc_stream.get());
1162 if (peer_connection_tracker_) {
1163 peer_connection_tracker_->TrackRemoveStream(
1164 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1166 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1167 track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
1168 webrtc_stream.get());
1171 void RTCPeerConnectionHandler::getStats(
1172 const blink::WebRTCStatsRequest& request) {
1173 DCHECK(thread_checker_.CalledOnValidThread());
1174 scoped_refptr<LocalRTCStatsRequest> inner_request(
1175 new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
1176 getStats(inner_request);
1179 void RTCPeerConnectionHandler::getStats(
1180 const scoped_refptr<LocalRTCStatsRequest>& request) {
1181 DCHECK(thread_checker_.CalledOnValidThread());
1182 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1185 rtc::scoped_refptr<webrtc::StatsObserver> observer(
1186 new rtc::RefCountedObject<StatsResponse>(request));
1188 std::string track_id;
1189 blink::WebMediaStreamSource::Type track_type =
1190 blink::WebMediaStreamSource::TypeAudio;
1191 if (request->hasSelector()) {
1192 track_type = request->component().source().type();
1193 track_id = request->component().id().utf8();
1196 GetStats(observer, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard,
1197 track_id, track_type);
1200 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1201 void RTCPeerConnectionHandler::GetStats(
1202 webrtc::StatsObserver* observer,
1203 webrtc::PeerConnectionInterface::StatsOutputLevel level,
1204 const std::string& track_id,
1205 blink::WebMediaStreamSource::Type track_type) {
1206 DCHECK(thread_checker_.CalledOnValidThread());
1207 signaling_thread()->PostTask(FROM_HERE,
1208 base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level,
1209 make_scoped_refptr(observer), track_id, track_type));
1212 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1213 DCHECK(thread_checker_.CalledOnValidThread());
1214 if (client_)
1215 client_->closePeerConnection();
1218 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
1219 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
1220 DCHECK(thread_checker_.CalledOnValidThread());
1221 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1222 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
1224 webrtc::DataChannelInit config;
1225 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1226 // to handle that.
1227 config.reliable = false;
1228 config.id = init.id;
1229 config.ordered = init.ordered;
1230 config.negotiated = init.negotiated;
1231 config.maxRetransmits = init.maxRetransmits;
1232 config.maxRetransmitTime = init.maxRetransmitTime;
1233 config.protocol = base::UTF16ToUTF8(init.protocol);
1235 rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
1236 native_peer_connection_->CreateDataChannel(base::UTF16ToUTF8(label),
1237 &config));
1238 if (!webrtc_channel) {
1239 DLOG(ERROR) << "Could not create native data channel.";
1240 return NULL;
1242 if (peer_connection_tracker_) {
1243 peer_connection_tracker_->TrackCreateDataChannel(
1244 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
1247 ++num_data_channels_created_;
1249 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1250 webrtc_channel);
1253 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
1254 const blink::WebMediaStreamTrack& track) {
1255 DCHECK(thread_checker_.CalledOnValidThread());
1256 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1257 DVLOG(1) << "createDTMFSender.";
1259 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
1260 if (!native_track || !native_track->is_local_track() ||
1261 track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
1262 DLOG(ERROR) << "The DTMF sender requires a local audio track.";
1263 return nullptr;
1266 scoped_refptr<webrtc::AudioTrackInterface> audio_track =
1267 native_track->GetAudioAdapter();
1268 rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
1269 native_peer_connection_->CreateDtmfSender(audio_track.get()));
1270 if (!sender) {
1271 DLOG(ERROR) << "Could not create native DTMF sender.";
1272 return nullptr;
1274 if (peer_connection_tracker_)
1275 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
1277 return new RtcDtmfSenderHandler(sender);
1280 void RTCPeerConnectionHandler::stop() {
1281 DCHECK(thread_checker_.CalledOnValidThread());
1282 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1284 if (!client_ || !native_peer_connection_.get())
1285 return; // Already stopped.
1287 if (peer_connection_tracker_)
1288 peer_connection_tracker_->TrackStop(this);
1290 native_peer_connection_->Close();
1292 // The client_ pointer is not considered valid after this point and no further
1293 // callbacks must be made.
1294 client_ = nullptr;
1297 void RTCPeerConnectionHandler::OnSignalingChange(
1298 webrtc::PeerConnectionInterface::SignalingState new_state) {
1299 DCHECK(thread_checker_.CalledOnValidThread());
1300 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1302 blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
1303 GetWebKitSignalingState(new_state);
1304 if (peer_connection_tracker_)
1305 peer_connection_tracker_->TrackSignalingStateChange(this, state);
1306 if (client_)
1307 client_->didChangeSignalingState(state);
1310 // Called any time the IceConnectionState changes
1311 void RTCPeerConnectionHandler::OnIceConnectionChange(
1312 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
1313 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1314 DCHECK(thread_checker_.CalledOnValidThread());
1315 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
1316 ice_connection_checking_start_ = base::TimeTicks::Now();
1317 } else if (new_state ==
1318 webrtc::PeerConnectionInterface::kIceConnectionConnected) {
1319 // If the state becomes connected, send the time needed for PC to become
1320 // connected from checking to UMA. UMA data will help to know how much
1321 // time needed for PC to connect with remote peer.
1322 if (ice_connection_checking_start_.is_null()) {
1323 // From UMA, we have observed a large number of calls falling into the
1324 // overflow buckets. One possibility is that the Checking is not signaled
1325 // before Connected. This is to guard against that situation to make the
1326 // metric more robust.
1327 UMA_HISTOGRAM_MEDIUM_TIMES("WebRTC.PeerConnection.TimeToConnect",
1328 base::TimeDelta());
1329 } else {
1330 UMA_HISTOGRAM_MEDIUM_TIMES(
1331 "WebRTC.PeerConnection.TimeToConnect",
1332 base::TimeTicks::Now() - ice_connection_checking_start_);
1336 track_metrics_.IceConnectionChange(new_state);
1337 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
1338 GetWebKitIceConnectionState(new_state);
1339 if (peer_connection_tracker_)
1340 peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
1341 if(client_)
1342 client_->didChangeICEConnectionState(state);
1345 // Called any time the IceGatheringState changes
1346 void RTCPeerConnectionHandler::OnIceGatheringChange(
1347 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
1348 DCHECK(thread_checker_.CalledOnValidThread());
1349 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1351 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
1352 // If ICE gathering is completed, generate a NULL ICE candidate,
1353 // to signal end of candidates.
1354 if (client_) {
1355 blink::WebRTCICECandidate null_candidate;
1356 client_->didGenerateICECandidate(null_candidate);
1359 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1360 num_local_candidates_ipv4_);
1362 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1363 num_local_candidates_ipv6_);
1364 } else if (new_state ==
1365 webrtc::PeerConnectionInterface::kIceGatheringGathering) {
1366 // ICE restarts will change gathering state back to "gathering",
1367 // reset the counter.
1368 num_local_candidates_ipv6_ = 0;
1369 num_local_candidates_ipv4_ = 0;
1372 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
1373 GetWebKitIceGatheringState(new_state);
1374 if (peer_connection_tracker_)
1375 peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
1376 if (client_)
1377 client_->didChangeICEGatheringState(state);
1380 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1381 DCHECK(thread_checker_.CalledOnValidThread());
1382 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1383 if (peer_connection_tracker_)
1384 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
1385 if (client_)
1386 client_->negotiationNeeded();
1389 void RTCPeerConnectionHandler::OnAddStream(
1390 scoped_ptr<RemoteMediaStreamImpl> stream) {
1391 DCHECK(thread_checker_.CalledOnValidThread());
1392 DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
1393 remote_streams_.end());
1394 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
1395 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1397 // Ownership is with remote_streams_ now.
1398 RemoteMediaStreamImpl* s = stream.release();
1399 remote_streams_.insert(
1400 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
1401 s->webrtc_stream().get(), s));
1403 if (peer_connection_tracker_) {
1404 peer_connection_tracker_->TrackAddStream(
1405 this, s->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE);
1408 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1410 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1411 s->webrtc_stream().get());
1412 if (client_)
1413 client_->didAddRemoteStream(s->webkit_stream());
1416 void RTCPeerConnectionHandler::OnRemoveStream(
1417 const scoped_refptr<webrtc::MediaStreamInterface>& stream) {
1418 DCHECK(thread_checker_.CalledOnValidThread());
1419 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1420 RemoteStreamMap::iterator it = remote_streams_.find(stream.get());
1421 if (it == remote_streams_.end()) {
1422 NOTREACHED() << "Stream not found";
1423 return;
1426 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1427 stream.get());
1428 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1430 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
1431 const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
1432 DCHECK(!webkit_stream.isNull());
1433 remote_streams_.erase(it);
1435 if (peer_connection_tracker_) {
1436 peer_connection_tracker_->TrackRemoveStream(
1437 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
1440 if (client_)
1441 client_->didRemoveRemoteStream(webkit_stream);
1444 void RTCPeerConnectionHandler::OnDataChannel(
1445 scoped_ptr<RtcDataChannelHandler> handler) {
1446 DCHECK(thread_checker_.CalledOnValidThread());
1447 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1449 if (peer_connection_tracker_) {
1450 peer_connection_tracker_->TrackCreateDataChannel(
1451 this, handler->channel().get(), PeerConnectionTracker::SOURCE_REMOTE);
1454 if (client_)
1455 client_->didAddRemoteDataChannel(handler.release());
1458 void RTCPeerConnectionHandler::OnIceCandidate(
1459 const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index,
1460 int component, int address_family) {
1461 DCHECK(thread_checker_.CalledOnValidThread());
1462 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1463 blink::WebRTCICECandidate web_candidate;
1464 web_candidate.initialize(base::UTF8ToUTF16(sdp),
1465 base::UTF8ToUTF16(sdp_mid),
1466 sdp_mline_index);
1467 if (peer_connection_tracker_) {
1468 peer_connection_tracker_->TrackAddIceCandidate(
1469 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
1472 // Only the first m line's first component is tracked to avoid
1473 // miscounting when doing BUNDLE or rtcp mux.
1474 if (sdp_mline_index == 0 && component == 1) {
1475 if (address_family == AF_INET) {
1476 ++num_local_candidates_ipv4_;
1477 } else if (address_family == AF_INET6) {
1478 ++num_local_candidates_ipv6_;
1479 } else {
1480 NOTREACHED();
1483 if (client_)
1484 client_->didGenerateICECandidate(web_candidate);
1487 webrtc::SessionDescriptionInterface*
1488 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1489 const std::string& sdp, const std::string& type,
1490 webrtc::SdpParseError* error) {
1491 webrtc::SessionDescriptionInterface* native_desc =
1492 dependency_factory_->CreateSessionDescription(type, sdp, error);
1494 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1495 << " Type: " << type << " SDP: " << sdp;
1497 return native_desc;
1500 scoped_refptr<base::SingleThreadTaskRunner>
1501 RTCPeerConnectionHandler::signaling_thread() const {
1502 DCHECK(thread_checker_.CalledOnValidThread());
1503 return dependency_factory_->GetWebRtcSignalingThread();
1506 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1507 const base::Closure& closure,
1508 const char* trace_event_name) {
1509 DCHECK(thread_checker_.CalledOnValidThread());
1510 scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
1511 if (!thread.get() || thread->BelongsToCurrentThread()) {
1512 TRACE_EVENT0("webrtc", trace_event_name);
1513 closure.Run();
1514 } else {
1515 base::WaitableEvent event(false, false);
1516 thread->PostTask(FROM_HERE,
1517 base::Bind(&RunSynchronousClosure, closure,
1518 base::Unretained(trace_event_name),
1519 base::Unretained(&event)));
1520 event.Wait();
1524 } // namespace content