Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
blobcdd11c9afaf92445505c22b4633a2c232e2a12ea
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/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram.h"
16 #include "base/stl_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/trace_event/trace_event.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/renderer/media/media_stream_track.h"
22 #include "content/renderer/media/peer_connection_tracker.h"
23 #include "content/renderer/media/remote_media_stream_impl.h"
24 #include "content/renderer/media/rtc_data_channel_handler.h"
25 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
26 #include "content/renderer/media/rtc_media_constraints.h"
27 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
28 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
29 #include "content/renderer/media/webrtc_audio_capturer.h"
30 #include "content/renderer/media/webrtc_audio_device_impl.h"
31 #include "content/renderer/media/webrtc_uma_histograms.h"
32 #include "content/renderer/render_thread_impl.h"
33 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
34 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
35 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
36 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
37 #include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
38 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
39 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
40 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
41 #include "third_party/WebKit/public/platform/WebURL.h"
43 using webrtc::DataChannelInterface;
44 using webrtc::IceCandidateInterface;
45 using webrtc::MediaStreamInterface;
46 using webrtc::PeerConnectionInterface;
47 using webrtc::PeerConnectionObserver;
48 using webrtc::StatsReport;
49 using webrtc::StatsReports;
51 namespace content {
52 namespace {
54 // Converter functions from libjingle types to WebKit types.
55 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
56 GetWebKitIceGatheringState(
57 webrtc::PeerConnectionInterface::IceGatheringState state) {
58 using blink::WebRTCPeerConnectionHandlerClient;
59 switch (state) {
60 case webrtc::PeerConnectionInterface::kIceGatheringNew:
61 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
62 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
63 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering;
64 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
65 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete;
66 default:
67 NOTREACHED();
68 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
72 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
73 GetWebKitIceConnectionState(
74 webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
75 using blink::WebRTCPeerConnectionHandlerClient;
76 switch (ice_state) {
77 case webrtc::PeerConnectionInterface::kIceConnectionNew:
78 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
79 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
80 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking;
81 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
82 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected;
83 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
84 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted;
85 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
86 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed;
87 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
88 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected;
89 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
90 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
91 default:
92 NOTREACHED();
93 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
97 blink::WebRTCPeerConnectionHandlerClient::SignalingState
98 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
99 using blink::WebRTCPeerConnectionHandlerClient;
100 switch (state) {
101 case webrtc::PeerConnectionInterface::kStable:
102 return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
103 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
104 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer;
105 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
106 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer;
107 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
108 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer;
109 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
110 return
111 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer;
112 case webrtc::PeerConnectionInterface::kClosed:
113 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
114 default:
115 NOTREACHED();
116 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
120 blink::WebRTCSessionDescription CreateWebKitSessionDescription(
121 const std::string& sdp, const std::string& type) {
122 blink::WebRTCSessionDescription description;
123 description.initialize(base::UTF8ToUTF16(type), base::UTF8ToUTF16(sdp));
124 return description;
127 blink::WebRTCSessionDescription
128 CreateWebKitSessionDescription(
129 const webrtc::SessionDescriptionInterface* native_desc) {
130 if (!native_desc) {
131 LOG(ERROR) << "Native session description is null.";
132 return blink::WebRTCSessionDescription();
135 std::string sdp;
136 if (!native_desc->ToString(&sdp)) {
137 LOG(ERROR) << "Failed to get SDP string of native session description.";
138 return blink::WebRTCSessionDescription();
141 return CreateWebKitSessionDescription(sdp, native_desc->type());
144 void RunClosureWithTrace(const base::Closure& closure,
145 const char* trace_event_name) {
146 TRACE_EVENT0("webrtc", trace_event_name);
147 closure.Run();
150 void RunSynchronousClosure(const base::Closure& closure,
151 const char* trace_event_name,
152 base::WaitableEvent* event) {
154 TRACE_EVENT0("webrtc", trace_event_name);
155 closure.Run();
157 event->Signal();
160 void GetSdpAndTypeFromSessionDescription(
161 const base::Callback<const webrtc::SessionDescriptionInterface*()>&
162 description_callback,
163 std::string* sdp, std::string* type) {
164 const webrtc::SessionDescriptionInterface* description =
165 description_callback.Run();
166 if (description) {
167 description->ToString(sdp);
168 *type = description->type();
172 // Converter functions from WebKit types to libjingle types.
174 void GetNativeRtcConfiguration(
175 const blink::WebRTCConfiguration& server_configuration,
176 webrtc::PeerConnectionInterface::RTCConfiguration* config) {
177 if (server_configuration.isNull() || !config)
178 return;
179 for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) {
180 webrtc::PeerConnectionInterface::IceServer server;
181 const blink::WebRTCICEServer& webkit_server =
182 server_configuration.server(i);
183 server.username = base::UTF16ToUTF8(webkit_server.username());
184 server.password = base::UTF16ToUTF8(webkit_server.credential());
185 server.uri = webkit_server.uri().spec();
186 config->servers.push_back(server);
189 switch (server_configuration.iceTransports()) {
190 case blink::WebRTCIceTransportsNone:
191 config->type = webrtc::PeerConnectionInterface::kNone;
192 break;
193 case blink::WebRTCIceTransportsRelay:
194 config->type = webrtc::PeerConnectionInterface::kRelay;
195 break;
196 case blink::WebRTCIceTransportsAll:
197 config->type = webrtc::PeerConnectionInterface::kAll;
198 break;
199 default:
200 NOTREACHED();
204 class SessionDescriptionRequestTracker {
205 public:
206 SessionDescriptionRequestTracker(
207 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
208 const base::WeakPtr<PeerConnectionTracker>& tracker,
209 PeerConnectionTracker::Action action)
210 : handler_(handler), tracker_(tracker), action_(action) {}
212 void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
213 DCHECK(thread_checker_.CalledOnValidThread());
214 if (tracker_ && handler_) {
215 std::string value;
216 if (desc) {
217 desc->ToString(&value);
218 value = "type: " + desc->type() + ", sdp: " + value;
220 tracker_->TrackSessionDescriptionCallback(
221 handler_.get(), action_, "OnSuccess", value);
225 void TrackOnFailure(const std::string& error) {
226 DCHECK(thread_checker_.CalledOnValidThread());
227 if (handler_ && tracker_) {
228 tracker_->TrackSessionDescriptionCallback(
229 handler_.get(), action_, "OnFailure", error);
233 private:
234 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
235 const base::WeakPtr<PeerConnectionTracker> tracker_;
236 PeerConnectionTracker::Action action_;
237 base::ThreadChecker thread_checker_;
240 // Class mapping responses from calls to libjingle CreateOffer/Answer and
241 // the blink::WebRTCSessionDescriptionRequest.
242 class CreateSessionDescriptionRequest
243 : public webrtc::CreateSessionDescriptionObserver {
244 public:
245 explicit CreateSessionDescriptionRequest(
246 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
247 const blink::WebRTCSessionDescriptionRequest& request,
248 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
249 const base::WeakPtr<PeerConnectionTracker>& tracker,
250 PeerConnectionTracker::Action action)
251 : main_thread_(main_thread),
252 webkit_request_(request),
253 tracker_(handler, tracker, action) {
256 void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
257 if (!main_thread_->BelongsToCurrentThread()) {
258 main_thread_->PostTask(FROM_HERE,
259 base::Bind(&CreateSessionDescriptionRequest::OnSuccess, this, desc));
260 return;
263 tracker_.TrackOnSuccess(desc);
264 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
265 webkit_request_.reset();
266 delete desc;
268 void OnFailure(const std::string& error) override {
269 if (!main_thread_->BelongsToCurrentThread()) {
270 main_thread_->PostTask(FROM_HERE,
271 base::Bind(&CreateSessionDescriptionRequest::OnFailure, this, error));
272 return;
275 tracker_.TrackOnFailure(error);
276 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
277 webkit_request_.reset();
280 protected:
281 ~CreateSessionDescriptionRequest() override {
282 DCHECK(webkit_request_.isNull());
285 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
286 blink::WebRTCSessionDescriptionRequest webkit_request_;
287 SessionDescriptionRequestTracker tracker_;
290 // Class mapping responses from calls to libjingle
291 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
292 class SetSessionDescriptionRequest
293 : public webrtc::SetSessionDescriptionObserver {
294 public:
295 explicit SetSessionDescriptionRequest(
296 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
297 const blink::WebRTCVoidRequest& request,
298 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
299 const base::WeakPtr<PeerConnectionTracker>& tracker,
300 PeerConnectionTracker::Action action)
301 : main_thread_(main_thread),
302 webkit_request_(request),
303 tracker_(handler, tracker, action) {
306 void OnSuccess() override {
307 if (!main_thread_->BelongsToCurrentThread()) {
308 main_thread_->PostTask(FROM_HERE,
309 base::Bind(&SetSessionDescriptionRequest::OnSuccess, this));
310 return;
312 tracker_.TrackOnSuccess(NULL);
313 webkit_request_.requestSucceeded();
314 webkit_request_.reset();
316 void OnFailure(const std::string& error) override {
317 if (!main_thread_->BelongsToCurrentThread()) {
318 main_thread_->PostTask(FROM_HERE,
319 base::Bind(&SetSessionDescriptionRequest::OnFailure, this, error));
320 return;
322 tracker_.TrackOnFailure(error);
323 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
324 webkit_request_.reset();
327 protected:
328 ~SetSessionDescriptionRequest() override {
329 DCHECK(webkit_request_.isNull());
332 private:
333 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
334 blink::WebRTCVoidRequest webkit_request_;
335 SessionDescriptionRequestTracker tracker_;
338 // Class mapping responses from calls to libjingle
339 // GetStats into a blink::WebRTCStatsCallback.
340 class StatsResponse : public webrtc::StatsObserver {
341 public:
342 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
343 : request_(request.get()),
344 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
345 // Measure the overall time it takes to satisfy a getStats request.
346 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
347 signaling_thread_checker_.DetachFromThread();
350 void OnComplete(const StatsReports& reports) override {
351 DCHECK(signaling_thread_checker_.CalledOnValidThread());
352 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
353 // We can't use webkit objects directly since they use a single threaded
354 // heap allocator.
355 std::vector<Report*>* report_copies = new std::vector<Report*>();
356 report_copies->reserve(reports.size());
357 for (auto* r : reports)
358 report_copies->push_back(new Report(r));
360 main_thread_->PostTaskAndReply(FROM_HERE,
361 base::Bind(&StatsResponse::DeliverCallback, this,
362 base::Unretained(report_copies)),
363 base::Bind(&StatsResponse::DeleteReports,
364 base::Unretained(report_copies)));
367 private:
368 struct Report {
369 Report(const StatsReport* report)
370 : thread_checker(), id(report->id()->ToString()),
371 type(report->TypeToString()), timestamp(report->timestamp()),
372 values(report->values()) {
375 ~Report() {
376 // Since the values vector holds pointers to const objects that are bound
377 // to the signaling thread, they must be released on the same thread.
378 DCHECK(thread_checker.CalledOnValidThread());
381 const base::ThreadChecker thread_checker;
382 const std::string id, type;
383 const double timestamp;
384 const StatsReport::Values values;
387 static void DeleteReports(std::vector<Report*>* reports) {
388 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
389 for (auto* p : *reports)
390 delete p;
391 delete reports;
394 void DeliverCallback(const std::vector<Report*>* reports) {
395 DCHECK(main_thread_->BelongsToCurrentThread());
396 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
398 rtc::scoped_refptr<LocalRTCStatsResponse> response(
399 request_->createResponse().get());
400 for (const auto* report : *reports) {
401 if (report->values.size() > 0)
402 AddReport(response.get(), *report);
405 // Record the getStats operation as done before calling into Blink so that
406 // we don't skew the perf measurements of the native code with whatever the
407 // callback might be doing.
408 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
409 request_->requestSucceeded(response);
410 request_ = nullptr; // must be freed on the main thread.
413 void AddReport(LocalRTCStatsResponse* response, const Report& report) {
414 int idx = response->addReport(blink::WebString::fromUTF8(report.id),
415 blink::WebString::fromUTF8(report.type),
416 report.timestamp);
417 blink::WebString name, value_str;
418 for (const auto& value : report.values) {
419 const StatsReport::ValuePtr& v = value.second;
420 name = blink::WebString::fromUTF8(value.second->display_name());
422 if (v->type() == StatsReport::Value::kString)
423 value_str = blink::WebString::fromUTF8(v->string_val());
424 if (v->type() == StatsReport::Value::kStaticString)
425 value_str = blink::WebString::fromUTF8(v->static_string_val());
426 else
427 value_str = blink::WebString::fromUTF8(v->ToString());
429 response->addStatistic(idx, name, value_str);
433 rtc::scoped_refptr<LocalRTCStatsRequest> request_;
434 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
435 base::ThreadChecker signaling_thread_checker_;
438 void GetStatsOnSignalingThread(
439 const scoped_refptr<webrtc::PeerConnectionInterface>& pc,
440 webrtc::PeerConnectionInterface::StatsOutputLevel level,
441 const scoped_refptr<webrtc::StatsObserver>& observer,
442 const std::string track_id, blink::WebMediaStreamSource::Type track_type) {
443 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
445 scoped_refptr<webrtc::MediaStreamTrackInterface> track;
446 if (!track_id.empty()) {
447 if (track_type == blink::WebMediaStreamSource::TypeAudio) {
448 track = pc->local_streams()->FindAudioTrack(track_id);
449 if (!track.get())
450 track = pc->remote_streams()->FindAudioTrack(track_id);
451 } else {
452 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track_type);
453 track = pc->local_streams()->FindVideoTrack(track_id);
454 if (!track.get())
455 track = pc->remote_streams()->FindVideoTrack(track_id);
458 if (!track.get()) {
459 DVLOG(1) << "GetStats: Track not found.";
460 observer->OnComplete(StatsReports());
461 return;
465 if (!pc->GetStats(observer.get(), track.get(), level)) {
466 DVLOG(1) << "GetStats failed.";
467 observer->OnComplete(StatsReports());
471 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
472 public:
473 PeerConnectionUMAObserver() {}
474 ~PeerConnectionUMAObserver() override {}
476 void IncrementCounter(
477 webrtc::PeerConnectionUMAMetricsCounter counter) override {
478 // Runs on libjingle's signaling thread.
479 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
480 counter,
481 webrtc::kBoundary);
484 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,
485 int value) override {
486 // Runs on libjingle's signaling thread.
487 switch (type) {
488 case webrtc::kTimeToConnect:
489 UMA_HISTOGRAM_MEDIUM_TIMES(
490 "WebRTC.PeerConnection.TimeToConnect",
491 base::TimeDelta::FromMilliseconds(value));
492 break;
493 case webrtc::kNetworkInterfaces_IPv4:
494 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
495 value);
496 break;
497 case webrtc::kNetworkInterfaces_IPv6:
498 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
499 value);
500 break;
501 default:
502 NOTREACHED();
507 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
508 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
510 } // namespace
512 // Implementation of LocalRTCStatsRequest.
513 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
514 : impl_(impl) {
517 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
518 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
520 bool LocalRTCStatsRequest::hasSelector() const {
521 return impl_.hasSelector();
524 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
525 return impl_.component();
528 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
529 return scoped_refptr<LocalRTCStatsResponse>(
530 new rtc::RefCountedObject<LocalRTCStatsResponse>(impl_.createResponse()));
533 void LocalRTCStatsRequest::requestSucceeded(
534 const LocalRTCStatsResponse* response) {
535 impl_.requestSucceeded(response->webKitStatsResponse());
538 // Implementation of LocalRTCStatsResponse.
539 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
540 return impl_;
543 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
544 blink::WebString id,
545 double timestamp) {
546 return impl_.addReport(type, id, timestamp);
549 void LocalRTCStatsResponse::addStatistic(size_t report,
550 blink::WebString name,
551 blink::WebString value) {
552 impl_.addStatistic(report, name, value);
555 // Receives notifications from a PeerConnection object about state changes,
556 // track addition/removal etc. The callbacks we receive here come on the
557 // signaling thread, so this class takes care of delivering them to an
558 // RTCPeerConnectionHandler instance on the main thread.
559 // In order to do safe PostTask-ing, the class is reference counted and
560 // checks for the existence of the RTCPeerConnectionHandler instance before
561 // delivering callbacks on the main thread.
562 class RTCPeerConnectionHandler::Observer
563 : public base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>,
564 public PeerConnectionObserver {
565 public:
566 Observer(const base::WeakPtr<RTCPeerConnectionHandler>& handler)
567 : handler_(handler), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
569 protected:
570 friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>;
571 virtual ~Observer() {}
573 void OnSignalingChange(
574 PeerConnectionInterface::SignalingState new_state) override {
575 if (!main_thread_->BelongsToCurrentThread()) {
576 main_thread_->PostTask(FROM_HERE,
577 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange,
578 this, new_state));
579 } else if (handler_) {
580 handler_->OnSignalingChange(new_state);
584 void OnAddStream(MediaStreamInterface* stream) override {
585 DCHECK(stream);
586 scoped_ptr<RemoteMediaStreamImpl> remote_stream(
587 new RemoteMediaStreamImpl(main_thread_, stream));
589 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
590 // asynchronously and the posted task will execude after that initialization
591 // is done.
592 main_thread_->PostTask(FROM_HERE,
593 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl,
594 this, base::Passed(&remote_stream)));
597 void OnRemoveStream(MediaStreamInterface* stream) override {
598 main_thread_->PostTask(FROM_HERE,
599 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
600 this, make_scoped_refptr(stream)));
603 void OnDataChannel(DataChannelInterface* data_channel) override {
604 scoped_ptr<RtcDataChannelHandler> handler(
605 new RtcDataChannelHandler(main_thread_, data_channel));
606 main_thread_->PostTask(FROM_HERE,
607 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
608 this, base::Passed(&handler)));
611 void OnRenegotiationNeeded() override {
612 if (!main_thread_->BelongsToCurrentThread()) {
613 main_thread_->PostTask(FROM_HERE,
614 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
615 this));
616 } else if (handler_) {
617 handler_->OnRenegotiationNeeded();
621 void OnIceConnectionChange(
622 PeerConnectionInterface::IceConnectionState new_state) override {
623 if (!main_thread_->BelongsToCurrentThread()) {
624 main_thread_->PostTask(FROM_HERE,
625 base::Bind(
626 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
627 new_state));
628 } else if (handler_) {
629 handler_->OnIceConnectionChange(new_state);
633 void OnIceGatheringChange(
634 PeerConnectionInterface::IceGatheringState new_state) override {
635 if (!main_thread_->BelongsToCurrentThread()) {
636 main_thread_->PostTask(FROM_HERE,
637 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
638 this, new_state));
639 } else if (handler_) {
640 handler_->OnIceGatheringChange(new_state);
644 void OnIceCandidate(const IceCandidateInterface* candidate) override {
645 std::string sdp;
646 if (!candidate->ToString(&sdp)) {
647 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
648 return;
651 main_thread_->PostTask(FROM_HERE,
652 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
653 this, sdp, candidate->sdp_mid(), candidate->sdp_mline_index(),
654 candidate->candidate().component(),
655 candidate->candidate().address().family()));
658 void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
659 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
660 if (handler_)
661 handler_->OnAddStream(stream.Pass());
664 void OnRemoveStreamImpl(const scoped_refptr<MediaStreamInterface>& stream) {
665 if (handler_)
666 handler_->OnRemoveStream(stream);
669 void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
670 if (handler_)
671 handler_->OnDataChannel(handler.Pass());
674 void OnIceCandidateImpl(const std::string& sdp, const std::string& sdp_mid,
675 int sdp_mline_index, int component, int address_family) {
676 if (handler_) {
677 handler_->OnIceCandidate(sdp, sdp_mid, sdp_mline_index, component,
678 address_family);
682 private:
683 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
684 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
687 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
688 blink::WebRTCPeerConnectionHandlerClient* client,
689 PeerConnectionDependencyFactory* dependency_factory)
690 : client_(client),
691 dependency_factory_(dependency_factory),
692 frame_(NULL),
693 num_data_channels_created_(0),
694 num_local_candidates_ipv4_(0),
695 num_local_candidates_ipv6_(0),
696 weak_factory_(this) {
697 g_peer_connection_handlers.Get().insert(this);
700 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
701 DCHECK(thread_checker_.CalledOnValidThread());
703 stop();
705 g_peer_connection_handlers.Get().erase(this);
706 if (peer_connection_tracker_)
707 peer_connection_tracker_->UnregisterPeerConnection(this);
708 STLDeleteValues(&remote_streams_);
710 UMA_HISTOGRAM_COUNTS_10000(
711 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
714 // static
715 void RTCPeerConnectionHandler::DestructAllHandlers() {
716 std::set<RTCPeerConnectionHandler*> handlers(
717 g_peer_connection_handlers.Get().begin(),
718 g_peer_connection_handlers.Get().end());
719 for (auto handler : handlers) {
720 if (handler->client_)
721 handler->client_->releasePeerConnectionHandler();
725 // static
726 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
727 const blink::WebRTCOfferOptions& options,
728 RTCMediaConstraints* output) {
729 output->AddMandatory(
730 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
731 options.offerToReceiveAudio() > 0 ? "true" : "false",
732 true);
734 output->AddMandatory(
735 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
736 options.offerToReceiveVideo() > 0 ? "true" : "false",
737 true);
739 if (!options.voiceActivityDetection()) {
740 output->AddMandatory(
741 webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
742 "false",
743 true);
746 if (options.iceRestart()) {
747 output->AddMandatory(
748 webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
752 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
753 DCHECK(thread_checker_.CalledOnValidThread());
754 DCHECK(frame);
755 frame_ = frame;
758 bool RTCPeerConnectionHandler::initialize(
759 const blink::WebRTCConfiguration& server_configuration,
760 const blink::WebMediaConstraints& options) {
761 DCHECK(thread_checker_.CalledOnValidThread());
762 DCHECK(frame_);
764 peer_connection_tracker_ =
765 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
767 webrtc::PeerConnectionInterface::RTCConfiguration config;
768 GetNativeRtcConfiguration(server_configuration, &config);
770 RTCMediaConstraints constraints(options);
772 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
773 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
774 config, &constraints, frame_, peer_connection_observer_.get());
776 if (!native_peer_connection_.get()) {
777 LOG(ERROR) << "Failed to initialize native PeerConnection.";
778 return false;
781 if (peer_connection_tracker_) {
782 peer_connection_tracker_->RegisterPeerConnection(
783 this, config, constraints, frame_);
786 uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
787 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
788 return true;
791 bool RTCPeerConnectionHandler::InitializeForTest(
792 const blink::WebRTCConfiguration& server_configuration,
793 const blink::WebMediaConstraints& options,
794 const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
795 DCHECK(thread_checker_.CalledOnValidThread());
796 webrtc::PeerConnectionInterface::RTCConfiguration config;
797 GetNativeRtcConfiguration(server_configuration, &config);
799 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
800 RTCMediaConstraints constraints(options);
801 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
802 config, &constraints, NULL, peer_connection_observer_.get());
803 if (!native_peer_connection_.get()) {
804 LOG(ERROR) << "Failed to initialize native PeerConnection.";
805 return false;
807 peer_connection_tracker_ = peer_connection_tracker;
808 return true;
811 void RTCPeerConnectionHandler::createOffer(
812 const blink::WebRTCSessionDescriptionRequest& request,
813 const blink::WebMediaConstraints& options) {
814 DCHECK(thread_checker_.CalledOnValidThread());
815 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
817 scoped_refptr<CreateSessionDescriptionRequest> description_request(
818 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
819 base::ThreadTaskRunnerHandle::Get(), request,
820 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
821 PeerConnectionTracker::ACTION_CREATE_OFFER));
823 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
824 RTCMediaConstraints constraints(options);
825 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
827 if (peer_connection_tracker_)
828 peer_connection_tracker_->TrackCreateOffer(this, constraints);
831 void RTCPeerConnectionHandler::createOffer(
832 const blink::WebRTCSessionDescriptionRequest& request,
833 const blink::WebRTCOfferOptions& options) {
834 DCHECK(thread_checker_.CalledOnValidThread());
835 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
837 scoped_refptr<CreateSessionDescriptionRequest> description_request(
838 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
839 base::ThreadTaskRunnerHandle::Get(), request,
840 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
841 PeerConnectionTracker::ACTION_CREATE_OFFER));
843 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
844 RTCMediaConstraints constraints;
845 ConvertOfferOptionsToConstraints(options, &constraints);
846 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
848 if (peer_connection_tracker_)
849 peer_connection_tracker_->TrackCreateOffer(this, constraints);
852 void RTCPeerConnectionHandler::createAnswer(
853 const blink::WebRTCSessionDescriptionRequest& request,
854 const blink::WebMediaConstraints& options) {
855 DCHECK(thread_checker_.CalledOnValidThread());
856 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
857 scoped_refptr<CreateSessionDescriptionRequest> description_request(
858 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
859 base::ThreadTaskRunnerHandle::Get(), request,
860 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
861 PeerConnectionTracker::ACTION_CREATE_ANSWER));
862 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
863 RTCMediaConstraints constraints(options);
864 native_peer_connection_->CreateAnswer(description_request.get(),
865 &constraints);
867 if (peer_connection_tracker_)
868 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
871 void RTCPeerConnectionHandler::setLocalDescription(
872 const blink::WebRTCVoidRequest& request,
873 const blink::WebRTCSessionDescription& description) {
874 DCHECK(thread_checker_.CalledOnValidThread());
875 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
877 std::string sdp = base::UTF16ToUTF8(description.sdp());
878 std::string type = base::UTF16ToUTF8(description.type());
880 webrtc::SdpParseError error;
881 // Since CreateNativeSessionDescription uses the dependency factory, we need
882 // to make this call on the current thread to be safe.
883 webrtc::SessionDescriptionInterface* native_desc =
884 CreateNativeSessionDescription(sdp, type, &error);
885 if (!native_desc) {
886 std::string reason_str = "Failed to parse SessionDescription. ";
887 reason_str.append(error.line);
888 reason_str.append(" ");
889 reason_str.append(error.description);
890 LOG(ERROR) << reason_str;
891 request.requestFailed(blink::WebString::fromUTF8(reason_str));
892 return;
895 if (peer_connection_tracker_) {
896 peer_connection_tracker_->TrackSetSessionDescription(
897 this, sdp, type, PeerConnectionTracker::SOURCE_LOCAL);
900 scoped_refptr<SetSessionDescriptionRequest> set_request(
901 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
902 base::ThreadTaskRunnerHandle::Get(), request,
903 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
904 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
906 signaling_thread()->PostTask(FROM_HERE,
907 base::Bind(&RunClosureWithTrace,
908 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
909 native_peer_connection_, set_request,
910 base::Unretained(native_desc)),
911 "SetLocalDescription"));
914 void RTCPeerConnectionHandler::setRemoteDescription(
915 const blink::WebRTCVoidRequest& request,
916 const blink::WebRTCSessionDescription& description) {
917 DCHECK(thread_checker_.CalledOnValidThread());
918 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
919 std::string sdp = base::UTF16ToUTF8(description.sdp());
920 std::string type = base::UTF16ToUTF8(description.type());
922 webrtc::SdpParseError error;
923 // Since CreateNativeSessionDescription uses the dependency factory, we need
924 // to make this call on the current thread to be safe.
925 webrtc::SessionDescriptionInterface* native_desc =
926 CreateNativeSessionDescription(sdp, type, &error);
927 if (!native_desc) {
928 std::string reason_str = "Failed to parse SessionDescription. ";
929 reason_str.append(error.line);
930 reason_str.append(" ");
931 reason_str.append(error.description);
932 LOG(ERROR) << reason_str;
933 request.requestFailed(blink::WebString::fromUTF8(reason_str));
934 return;
937 if (peer_connection_tracker_) {
938 peer_connection_tracker_->TrackSetSessionDescription(
939 this, sdp, type, PeerConnectionTracker::SOURCE_REMOTE);
942 scoped_refptr<SetSessionDescriptionRequest> set_request(
943 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
944 base::ThreadTaskRunnerHandle::Get(), request,
945 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
946 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
947 signaling_thread()->PostTask(FROM_HERE,
948 base::Bind(&RunClosureWithTrace,
949 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
950 native_peer_connection_, set_request,
951 base::Unretained(native_desc)),
952 "SetRemoteDescription"));
955 blink::WebRTCSessionDescription
956 RTCPeerConnectionHandler::localDescription() {
957 DCHECK(thread_checker_.CalledOnValidThread());
958 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
960 // Since local_description returns a pointer to a non-reference-counted object
961 // that lives on the signaling thread, we cannot fetch a pointer to it and use
962 // it directly here. Instead, we access the object completely on the signaling
963 // thread.
964 std::string sdp, type;
965 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
966 base::Bind(&webrtc::PeerConnectionInterface::local_description,
967 native_peer_connection_);
968 RunSynchronousClosureOnSignalingThread(
969 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
970 base::Unretained(&sdp), base::Unretained(&type)),
971 "localDescription");
973 return CreateWebKitSessionDescription(sdp, type);
976 blink::WebRTCSessionDescription
977 RTCPeerConnectionHandler::remoteDescription() {
978 DCHECK(thread_checker_.CalledOnValidThread());
979 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
980 // Since local_description returns a pointer to a non-reference-counted object
981 // that lives on the signaling thread, we cannot fetch a pointer to it and use
982 // it directly here. Instead, we access the object completely on the signaling
983 // thread.
984 std::string sdp, type;
985 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
986 base::Bind(&webrtc::PeerConnectionInterface::remote_description,
987 native_peer_connection_);
988 RunSynchronousClosureOnSignalingThread(
989 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
990 base::Unretained(&sdp), base::Unretained(&type)),
991 "remoteDescription");
993 return CreateWebKitSessionDescription(sdp, type);
996 bool RTCPeerConnectionHandler::updateICE(
997 const blink::WebRTCConfiguration& server_configuration,
998 const blink::WebMediaConstraints& options) {
999 DCHECK(thread_checker_.CalledOnValidThread());
1000 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1001 webrtc::PeerConnectionInterface::RTCConfiguration config;
1002 GetNativeRtcConfiguration(server_configuration, &config);
1003 RTCMediaConstraints constraints(options);
1005 if (peer_connection_tracker_)
1006 peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
1008 return native_peer_connection_->UpdateIce(config.servers, &constraints);
1011 bool RTCPeerConnectionHandler::addICECandidate(
1012 const blink::WebRTCVoidRequest& request,
1013 const blink::WebRTCICECandidate& candidate) {
1014 DCHECK(thread_checker_.CalledOnValidThread());
1015 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1016 // Libjingle currently does not accept callbacks for addICECandidate.
1017 // For that reason we are going to call callbacks from here.
1019 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1020 // PostTaskAndReply kind of a thing.
1021 bool result = addICECandidate(candidate);
1022 base::MessageLoop::current()->PostTask(
1023 FROM_HERE,
1024 base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
1025 weak_factory_.GetWeakPtr(), request, result));
1026 // On failure callback will be triggered.
1027 return true;
1030 bool RTCPeerConnectionHandler::addICECandidate(
1031 const blink::WebRTCICECandidate& candidate) {
1032 DCHECK(thread_checker_.CalledOnValidThread());
1033 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1034 scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
1035 dependency_factory_->CreateIceCandidate(
1036 base::UTF16ToUTF8(candidate.sdpMid()),
1037 candidate.sdpMLineIndex(),
1038 base::UTF16ToUTF8(candidate.candidate())));
1039 bool return_value = false;
1041 if (native_candidate) {
1042 return_value =
1043 native_peer_connection_->AddIceCandidate(native_candidate.get());
1044 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
1045 } else {
1046 LOG(ERROR) << "Could not create native ICE candidate.";
1049 if (peer_connection_tracker_) {
1050 peer_connection_tracker_->TrackAddIceCandidate(
1051 this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
1053 return return_value;
1056 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1057 const blink::WebRTCVoidRequest& webkit_request, bool result) {
1058 DCHECK(thread_checker_.CalledOnValidThread());
1059 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1060 if (!result) {
1061 // We don't have the actual error code from the libjingle, so for now
1062 // using a generic error string.
1063 return webkit_request.requestFailed(
1064 base::UTF8ToUTF16("Error processing ICE candidate"));
1067 return webkit_request.requestSucceeded();
1070 bool RTCPeerConnectionHandler::addStream(
1071 const blink::WebMediaStream& stream,
1072 const blink::WebMediaConstraints& options) {
1073 DCHECK(thread_checker_.CalledOnValidThread());
1074 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1075 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1076 local_streams_.begin(); adapter_it != local_streams_.end();
1077 ++adapter_it) {
1078 if ((*adapter_it)->IsEqual(stream)) {
1079 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1080 << "stream twice. id=" << stream.id().utf8();
1081 return false;
1085 if (peer_connection_tracker_) {
1086 peer_connection_tracker_->TrackAddStream(
1087 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1090 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1092 WebRtcMediaStreamAdapter* adapter =
1093 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
1094 local_streams_.push_back(adapter);
1096 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
1097 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
1098 webrtc_stream);
1100 RTCMediaConstraints constraints(options);
1101 if (!constraints.GetMandatory().empty() ||
1102 !constraints.GetOptional().empty()) {
1103 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1104 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1105 // should be removed from blink as well.
1106 LOG(WARNING)
1107 << "mediaConstraints is not a supported argument to addStream.";
1110 return native_peer_connection_->AddStream(webrtc_stream);
1113 void RTCPeerConnectionHandler::removeStream(
1114 const blink::WebMediaStream& stream) {
1115 DCHECK(thread_checker_.CalledOnValidThread());
1116 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1117 // Find the webrtc stream.
1118 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
1119 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1120 local_streams_.begin(); adapter_it != local_streams_.end();
1121 ++adapter_it) {
1122 if ((*adapter_it)->IsEqual(stream)) {
1123 webrtc_stream = (*adapter_it)->webrtc_media_stream();
1124 local_streams_.erase(adapter_it);
1125 break;
1128 DCHECK(webrtc_stream.get());
1129 // TODO(tommi): Make this async (PostTaskAndReply).
1130 native_peer_connection_->RemoveStream(webrtc_stream.get());
1132 if (peer_connection_tracker_) {
1133 peer_connection_tracker_->TrackRemoveStream(
1134 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1136 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1137 track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
1138 webrtc_stream.get());
1141 void RTCPeerConnectionHandler::getStats(
1142 const blink::WebRTCStatsRequest& request) {
1143 DCHECK(thread_checker_.CalledOnValidThread());
1144 scoped_refptr<LocalRTCStatsRequest> inner_request(
1145 new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
1146 getStats(inner_request);
1149 void RTCPeerConnectionHandler::getStats(
1150 const scoped_refptr<LocalRTCStatsRequest>& request) {
1151 DCHECK(thread_checker_.CalledOnValidThread());
1152 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1155 rtc::scoped_refptr<webrtc::StatsObserver> observer(
1156 new rtc::RefCountedObject<StatsResponse>(request));
1158 std::string track_id;
1159 blink::WebMediaStreamSource::Type track_type =
1160 blink::WebMediaStreamSource::TypeAudio;
1161 if (request->hasSelector()) {
1162 track_type = request->component().source().type();
1163 track_id = request->component().id().utf8();
1166 GetStats(observer, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard,
1167 track_id, track_type);
1170 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1171 void RTCPeerConnectionHandler::GetStats(
1172 webrtc::StatsObserver* observer,
1173 webrtc::PeerConnectionInterface::StatsOutputLevel level,
1174 const std::string& track_id,
1175 blink::WebMediaStreamSource::Type track_type) {
1176 DCHECK(thread_checker_.CalledOnValidThread());
1177 signaling_thread()->PostTask(FROM_HERE,
1178 base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level,
1179 make_scoped_refptr(observer), track_id, track_type));
1182 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1183 DCHECK(thread_checker_.CalledOnValidThread());
1184 if (client_)
1185 client_->closePeerConnection();
1188 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
1189 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
1190 DCHECK(thread_checker_.CalledOnValidThread());
1191 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1192 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
1194 webrtc::DataChannelInit config;
1195 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1196 // to handle that.
1197 config.reliable = false;
1198 config.id = init.id;
1199 config.ordered = init.ordered;
1200 config.negotiated = init.negotiated;
1201 config.maxRetransmits = init.maxRetransmits;
1202 config.maxRetransmitTime = init.maxRetransmitTime;
1203 config.protocol = base::UTF16ToUTF8(init.protocol);
1205 rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
1206 native_peer_connection_->CreateDataChannel(base::UTF16ToUTF8(label),
1207 &config));
1208 if (!webrtc_channel) {
1209 DLOG(ERROR) << "Could not create native data channel.";
1210 return NULL;
1212 if (peer_connection_tracker_) {
1213 peer_connection_tracker_->TrackCreateDataChannel(
1214 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
1217 ++num_data_channels_created_;
1219 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1220 webrtc_channel);
1223 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
1224 const blink::WebMediaStreamTrack& track) {
1225 DCHECK(thread_checker_.CalledOnValidThread());
1226 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1227 DVLOG(1) << "createDTMFSender.";
1229 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
1230 if (!native_track || !native_track->is_local_track() ||
1231 track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
1232 DLOG(ERROR) << "The DTMF sender requires a local audio track.";
1233 return nullptr;
1236 scoped_refptr<webrtc::AudioTrackInterface> audio_track =
1237 native_track->GetAudioAdapter();
1238 rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
1239 native_peer_connection_->CreateDtmfSender(audio_track.get()));
1240 if (!sender) {
1241 DLOG(ERROR) << "Could not create native DTMF sender.";
1242 return nullptr;
1244 if (peer_connection_tracker_)
1245 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
1247 return new RtcDtmfSenderHandler(sender);
1250 void RTCPeerConnectionHandler::stop() {
1251 DCHECK(thread_checker_.CalledOnValidThread());
1252 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1254 if (!client_ || !native_peer_connection_.get())
1255 return; // Already stopped.
1257 if (peer_connection_tracker_)
1258 peer_connection_tracker_->TrackStop(this);
1260 native_peer_connection_->Close();
1262 // The client_ pointer is not considered valid after this point and no further
1263 // callbacks must be made.
1264 client_ = nullptr;
1267 void RTCPeerConnectionHandler::OnSignalingChange(
1268 webrtc::PeerConnectionInterface::SignalingState new_state) {
1269 DCHECK(thread_checker_.CalledOnValidThread());
1270 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1272 blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
1273 GetWebKitSignalingState(new_state);
1274 if (peer_connection_tracker_)
1275 peer_connection_tracker_->TrackSignalingStateChange(this, state);
1276 if (client_)
1277 client_->didChangeSignalingState(state);
1280 // Called any time the IceConnectionState changes
1281 void RTCPeerConnectionHandler::OnIceConnectionChange(
1282 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
1283 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1284 DCHECK(thread_checker_.CalledOnValidThread());
1285 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
1286 ice_connection_checking_start_ = base::TimeTicks::Now();
1287 } else if (new_state ==
1288 webrtc::PeerConnectionInterface::kIceConnectionConnected) {
1289 // If the state becomes connected, send the time needed for PC to become
1290 // connected from checking to UMA. UMA data will help to know how much
1291 // time needed for PC to connect with remote peer.
1292 UMA_HISTOGRAM_MEDIUM_TIMES(
1293 "WebRTC.PeerConnection.TimeToConnect",
1294 base::TimeTicks::Now() - ice_connection_checking_start_);
1297 track_metrics_.IceConnectionChange(new_state);
1298 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
1299 GetWebKitIceConnectionState(new_state);
1300 if (peer_connection_tracker_)
1301 peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
1302 if(client_)
1303 client_->didChangeICEConnectionState(state);
1306 // Called any time the IceGatheringState changes
1307 void RTCPeerConnectionHandler::OnIceGatheringChange(
1308 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
1309 DCHECK(thread_checker_.CalledOnValidThread());
1310 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1312 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
1313 // If ICE gathering is completed, generate a NULL ICE candidate,
1314 // to signal end of candidates.
1315 if (client_) {
1316 blink::WebRTCICECandidate null_candidate;
1317 client_->didGenerateICECandidate(null_candidate);
1320 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1321 num_local_candidates_ipv4_);
1323 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1324 num_local_candidates_ipv6_);
1325 } else if (new_state ==
1326 webrtc::PeerConnectionInterface::kIceGatheringGathering) {
1327 // ICE restarts will change gathering state back to "gathering",
1328 // reset the counter.
1329 num_local_candidates_ipv6_ = 0;
1330 num_local_candidates_ipv4_ = 0;
1333 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
1334 GetWebKitIceGatheringState(new_state);
1335 if (peer_connection_tracker_)
1336 peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
1337 if (client_)
1338 client_->didChangeICEGatheringState(state);
1341 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1342 DCHECK(thread_checker_.CalledOnValidThread());
1343 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1344 if (peer_connection_tracker_)
1345 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
1346 if (client_)
1347 client_->negotiationNeeded();
1350 void RTCPeerConnectionHandler::OnAddStream(
1351 scoped_ptr<RemoteMediaStreamImpl> stream) {
1352 DCHECK(thread_checker_.CalledOnValidThread());
1353 DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
1354 remote_streams_.end());
1355 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
1356 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1358 // Ownership is with remote_streams_ now.
1359 RemoteMediaStreamImpl* s = stream.release();
1360 remote_streams_.insert(
1361 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
1362 s->webrtc_stream().get(), s));
1364 if (peer_connection_tracker_) {
1365 peer_connection_tracker_->TrackAddStream(
1366 this, s->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE);
1369 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1371 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1372 s->webrtc_stream().get());
1373 if (client_)
1374 client_->didAddRemoteStream(s->webkit_stream());
1377 void RTCPeerConnectionHandler::OnRemoveStream(
1378 const scoped_refptr<webrtc::MediaStreamInterface>& stream) {
1379 DCHECK(thread_checker_.CalledOnValidThread());
1380 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1381 RemoteStreamMap::iterator it = remote_streams_.find(stream.get());
1382 if (it == remote_streams_.end()) {
1383 NOTREACHED() << "Stream not found";
1384 return;
1387 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1388 stream.get());
1389 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1391 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
1392 const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
1393 DCHECK(!webkit_stream.isNull());
1394 remote_streams_.erase(it);
1396 if (peer_connection_tracker_) {
1397 peer_connection_tracker_->TrackRemoveStream(
1398 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
1401 if (client_)
1402 client_->didRemoveRemoteStream(webkit_stream);
1405 void RTCPeerConnectionHandler::OnDataChannel(
1406 scoped_ptr<RtcDataChannelHandler> handler) {
1407 DCHECK(thread_checker_.CalledOnValidThread());
1408 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1410 if (peer_connection_tracker_) {
1411 peer_connection_tracker_->TrackCreateDataChannel(
1412 this, handler->channel().get(), PeerConnectionTracker::SOURCE_REMOTE);
1415 if (client_)
1416 client_->didAddRemoteDataChannel(handler.release());
1419 void RTCPeerConnectionHandler::OnIceCandidate(
1420 const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index,
1421 int component, int address_family) {
1422 DCHECK(thread_checker_.CalledOnValidThread());
1423 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1424 blink::WebRTCICECandidate web_candidate;
1425 web_candidate.initialize(base::UTF8ToUTF16(sdp),
1426 base::UTF8ToUTF16(sdp_mid),
1427 sdp_mline_index);
1428 if (peer_connection_tracker_) {
1429 peer_connection_tracker_->TrackAddIceCandidate(
1430 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
1433 // Only the first m line's first component is tracked to avoid
1434 // miscounting when doing BUNDLE or rtcp mux.
1435 if (sdp_mline_index == 0 && component == 1) {
1436 if (address_family == AF_INET) {
1437 ++num_local_candidates_ipv4_;
1438 } else if (address_family == AF_INET6) {
1439 ++num_local_candidates_ipv6_;
1440 } else {
1441 NOTREACHED();
1444 if (client_)
1445 client_->didGenerateICECandidate(web_candidate);
1448 webrtc::SessionDescriptionInterface*
1449 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1450 const std::string& sdp, const std::string& type,
1451 webrtc::SdpParseError* error) {
1452 webrtc::SessionDescriptionInterface* native_desc =
1453 dependency_factory_->CreateSessionDescription(type, sdp, error);
1455 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1456 << " Type: " << type << " SDP: " << sdp;
1458 return native_desc;
1461 scoped_refptr<base::SingleThreadTaskRunner>
1462 RTCPeerConnectionHandler::signaling_thread() const {
1463 DCHECK(thread_checker_.CalledOnValidThread());
1464 return dependency_factory_->GetWebRtcSignalingThread();
1467 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1468 const base::Closure& closure,
1469 const char* trace_event_name) {
1470 DCHECK(thread_checker_.CalledOnValidThread());
1471 scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
1472 if (!thread.get() || thread->BelongsToCurrentThread()) {
1473 TRACE_EVENT0("webrtc", trace_event_name);
1474 closure.Run();
1475 } else {
1476 base::WaitableEvent event(false, false);
1477 thread->PostTask(FROM_HERE,
1478 base::Bind(&RunSynchronousClosure, closure,
1479 base::Unretained(trace_event_name),
1480 base::Unretained(&event)));
1481 event.Wait();
1485 } // namespace content