Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
blob2de508789f2b1050a5f9e62ffef495cf89cd1de8
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 =
185 base::UTF16ToUTF8(base::StringPiece16(webkit_server.username()));
186 server.password =
187 base::UTF16ToUTF8(base::StringPiece16(webkit_server.credential()));
188 server.uri = webkit_server.uri().spec();
189 webrtc_config->servers.push_back(server);
192 switch (blink_config.iceTransports()) {
193 case blink::WebRTCIceTransportsNone:
194 webrtc_config->type = webrtc::PeerConnectionInterface::kNone;
195 break;
196 case blink::WebRTCIceTransportsRelay:
197 webrtc_config->type = webrtc::PeerConnectionInterface::kRelay;
198 break;
199 case blink::WebRTCIceTransportsAll:
200 webrtc_config->type = webrtc::PeerConnectionInterface::kAll;
201 break;
202 default:
203 NOTREACHED();
206 switch (blink_config.bundlePolicy()) {
207 case blink::WebRTCBundlePolicyBalanced:
208 webrtc_config->bundle_policy =
209 webrtc::PeerConnectionInterface::kBundlePolicyBalanced;
210 break;
211 case blink::WebRTCBundlePolicyMaxBundle:
212 webrtc_config->bundle_policy =
213 webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle;
214 break;
215 case blink::WebRTCBundlePolicyMaxCompat:
216 webrtc_config->bundle_policy =
217 webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
218 break;
219 default:
220 NOTREACHED();
223 switch (blink_config.rtcpMuxPolicy()) {
224 case blink::WebRTCRtcpMuxPolicyNegotiate:
225 webrtc_config->rtcp_mux_policy =
226 webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
227 break;
228 case blink::WebRTCRtcpMuxPolicyRequire:
229 webrtc_config->rtcp_mux_policy =
230 webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire;
231 break;
232 default:
233 NOTREACHED();
237 class SessionDescriptionRequestTracker {
238 public:
239 SessionDescriptionRequestTracker(
240 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
241 const base::WeakPtr<PeerConnectionTracker>& tracker,
242 PeerConnectionTracker::Action action)
243 : handler_(handler), tracker_(tracker), action_(action) {}
245 void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
246 DCHECK(thread_checker_.CalledOnValidThread());
247 if (tracker_ && handler_) {
248 std::string value;
249 if (desc) {
250 desc->ToString(&value);
251 value = "type: " + desc->type() + ", sdp: " + value;
253 tracker_->TrackSessionDescriptionCallback(
254 handler_.get(), action_, "OnSuccess", value);
258 void TrackOnFailure(const std::string& error) {
259 DCHECK(thread_checker_.CalledOnValidThread());
260 if (handler_ && tracker_) {
261 tracker_->TrackSessionDescriptionCallback(
262 handler_.get(), action_, "OnFailure", error);
266 private:
267 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
268 const base::WeakPtr<PeerConnectionTracker> tracker_;
269 PeerConnectionTracker::Action action_;
270 base::ThreadChecker thread_checker_;
273 // Class mapping responses from calls to libjingle CreateOffer/Answer and
274 // the blink::WebRTCSessionDescriptionRequest.
275 class CreateSessionDescriptionRequest
276 : public webrtc::CreateSessionDescriptionObserver {
277 public:
278 explicit CreateSessionDescriptionRequest(
279 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
280 const blink::WebRTCSessionDescriptionRequest& request,
281 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
282 const base::WeakPtr<PeerConnectionTracker>& tracker,
283 PeerConnectionTracker::Action action)
284 : main_thread_(main_thread),
285 webkit_request_(request),
286 tracker_(handler, tracker, action) {
289 void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
290 if (!main_thread_->BelongsToCurrentThread()) {
291 main_thread_->PostTask(FROM_HERE,
292 base::Bind(&CreateSessionDescriptionRequest::OnSuccess, this, desc));
293 return;
296 tracker_.TrackOnSuccess(desc);
297 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
298 webkit_request_.reset();
299 delete desc;
301 void OnFailure(const std::string& error) override {
302 if (!main_thread_->BelongsToCurrentThread()) {
303 main_thread_->PostTask(FROM_HERE,
304 base::Bind(&CreateSessionDescriptionRequest::OnFailure, this, error));
305 return;
308 tracker_.TrackOnFailure(error);
309 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
310 webkit_request_.reset();
313 protected:
314 ~CreateSessionDescriptionRequest() override {
315 CHECK(webkit_request_.isNull());
318 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
319 blink::WebRTCSessionDescriptionRequest webkit_request_;
320 SessionDescriptionRequestTracker tracker_;
323 // Class mapping responses from calls to libjingle
324 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
325 class SetSessionDescriptionRequest
326 : public webrtc::SetSessionDescriptionObserver {
327 public:
328 explicit SetSessionDescriptionRequest(
329 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
330 const blink::WebRTCVoidRequest& request,
331 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
332 const base::WeakPtr<PeerConnectionTracker>& tracker,
333 PeerConnectionTracker::Action action)
334 : main_thread_(main_thread),
335 webkit_request_(request),
336 tracker_(handler, tracker, action) {
339 void OnSuccess() override {
340 if (!main_thread_->BelongsToCurrentThread()) {
341 main_thread_->PostTask(FROM_HERE,
342 base::Bind(&SetSessionDescriptionRequest::OnSuccess, this));
343 return;
345 tracker_.TrackOnSuccess(NULL);
346 webkit_request_.requestSucceeded();
347 webkit_request_.reset();
349 void OnFailure(const std::string& error) override {
350 if (!main_thread_->BelongsToCurrentThread()) {
351 main_thread_->PostTask(FROM_HERE,
352 base::Bind(&SetSessionDescriptionRequest::OnFailure, this, error));
353 return;
355 tracker_.TrackOnFailure(error);
356 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
357 webkit_request_.reset();
360 protected:
361 ~SetSessionDescriptionRequest() override {
362 DCHECK(webkit_request_.isNull());
365 private:
366 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
367 blink::WebRTCVoidRequest webkit_request_;
368 SessionDescriptionRequestTracker tracker_;
371 // Class mapping responses from calls to libjingle
372 // GetStats into a blink::WebRTCStatsCallback.
373 class StatsResponse : public webrtc::StatsObserver {
374 public:
375 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
376 : request_(request.get()),
377 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
378 // Measure the overall time it takes to satisfy a getStats request.
379 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
380 signaling_thread_checker_.DetachFromThread();
383 void OnComplete(const StatsReports& reports) override {
384 DCHECK(signaling_thread_checker_.CalledOnValidThread());
385 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
386 // We can't use webkit objects directly since they use a single threaded
387 // heap allocator.
388 std::vector<Report*>* report_copies = new std::vector<Report*>();
389 report_copies->reserve(reports.size());
390 for (auto* r : reports)
391 report_copies->push_back(new Report(r));
393 main_thread_->PostTaskAndReply(FROM_HERE,
394 base::Bind(&StatsResponse::DeliverCallback, this,
395 base::Unretained(report_copies)),
396 base::Bind(&StatsResponse::DeleteReports,
397 base::Unretained(report_copies)));
400 private:
401 struct Report {
402 Report(const StatsReport* report)
403 : thread_checker(), id(report->id()->ToString()),
404 type(report->TypeToString()), timestamp(report->timestamp()),
405 values(report->values()) {
408 ~Report() {
409 // Since the values vector holds pointers to const objects that are bound
410 // to the signaling thread, they must be released on the same thread.
411 DCHECK(thread_checker.CalledOnValidThread());
414 const base::ThreadChecker thread_checker;
415 const std::string id, type;
416 const double timestamp;
417 const StatsReport::Values values;
420 static void DeleteReports(std::vector<Report*>* reports) {
421 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
422 for (auto* p : *reports)
423 delete p;
424 delete reports;
427 void DeliverCallback(const std::vector<Report*>* reports) {
428 DCHECK(main_thread_->BelongsToCurrentThread());
429 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
431 rtc::scoped_refptr<LocalRTCStatsResponse> response(
432 request_->createResponse().get());
433 for (const auto* report : *reports) {
434 if (report->values.size() > 0)
435 AddReport(response.get(), *report);
438 // Record the getStats operation as done before calling into Blink so that
439 // we don't skew the perf measurements of the native code with whatever the
440 // callback might be doing.
441 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
442 request_->requestSucceeded(response);
443 request_ = nullptr; // must be freed on the main thread.
446 void AddReport(LocalRTCStatsResponse* response, const Report& report) {
447 int idx = response->addReport(blink::WebString::fromUTF8(report.id),
448 blink::WebString::fromUTF8(report.type),
449 report.timestamp);
450 blink::WebString name, value_str;
451 for (const auto& value : report.values) {
452 const StatsReport::ValuePtr& v = value.second;
453 name = blink::WebString::fromUTF8(value.second->display_name());
455 if (v->type() == StatsReport::Value::kString)
456 value_str = blink::WebString::fromUTF8(v->string_val());
457 if (v->type() == StatsReport::Value::kStaticString)
458 value_str = blink::WebString::fromUTF8(v->static_string_val());
459 else
460 value_str = blink::WebString::fromUTF8(v->ToString());
462 response->addStatistic(idx, name, value_str);
466 rtc::scoped_refptr<LocalRTCStatsRequest> request_;
467 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
468 base::ThreadChecker signaling_thread_checker_;
471 void GetStatsOnSignalingThread(
472 const scoped_refptr<webrtc::PeerConnectionInterface>& pc,
473 webrtc::PeerConnectionInterface::StatsOutputLevel level,
474 const scoped_refptr<webrtc::StatsObserver>& observer,
475 const std::string track_id, blink::WebMediaStreamSource::Type track_type) {
476 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
478 scoped_refptr<webrtc::MediaStreamTrackInterface> track;
479 if (!track_id.empty()) {
480 if (track_type == blink::WebMediaStreamSource::TypeAudio) {
481 track = pc->local_streams()->FindAudioTrack(track_id);
482 if (!track.get())
483 track = pc->remote_streams()->FindAudioTrack(track_id);
484 } else {
485 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track_type);
486 track = pc->local_streams()->FindVideoTrack(track_id);
487 if (!track.get())
488 track = pc->remote_streams()->FindVideoTrack(track_id);
491 if (!track.get()) {
492 DVLOG(1) << "GetStats: Track not found.";
493 observer->OnComplete(StatsReports());
494 return;
498 if (!pc->GetStats(observer.get(), track.get(), level)) {
499 DVLOG(1) << "GetStats failed.";
500 observer->OnComplete(StatsReports());
504 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
505 public:
506 PeerConnectionUMAObserver() {}
507 ~PeerConnectionUMAObserver() override {}
509 void IncrementCounter(
510 webrtc::PeerConnectionUMAMetricsCounter counter) override {
511 // Runs on libjingle's signaling thread.
512 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
513 counter,
514 webrtc::kBoundary);
517 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,
518 int value) override {
519 // Runs on libjingle's signaling thread.
520 switch (type) {
521 case webrtc::kTimeToConnect:
522 UMA_HISTOGRAM_MEDIUM_TIMES(
523 "WebRTC.PeerConnection.TimeToConnect",
524 base::TimeDelta::FromMilliseconds(value));
525 break;
526 case webrtc::kNetworkInterfaces_IPv4:
527 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
528 value);
529 break;
530 case webrtc::kNetworkInterfaces_IPv6:
531 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
532 value);
533 break;
534 default:
535 NOTREACHED();
540 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
541 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
543 } // namespace
545 // Implementation of LocalRTCStatsRequest.
546 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
547 : impl_(impl) {
550 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
551 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
553 bool LocalRTCStatsRequest::hasSelector() const {
554 return impl_.hasSelector();
557 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
558 return impl_.component();
561 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
562 return scoped_refptr<LocalRTCStatsResponse>(
563 new rtc::RefCountedObject<LocalRTCStatsResponse>(impl_.createResponse()));
566 void LocalRTCStatsRequest::requestSucceeded(
567 const LocalRTCStatsResponse* response) {
568 impl_.requestSucceeded(response->webKitStatsResponse());
571 // Implementation of LocalRTCStatsResponse.
572 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
573 return impl_;
576 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
577 blink::WebString id,
578 double timestamp) {
579 return impl_.addReport(type, id, timestamp);
582 void LocalRTCStatsResponse::addStatistic(size_t report,
583 blink::WebString name,
584 blink::WebString value) {
585 impl_.addStatistic(report, name, value);
588 // Receives notifications from a PeerConnection object about state changes,
589 // track addition/removal etc. The callbacks we receive here come on the
590 // signaling thread, so this class takes care of delivering them to an
591 // RTCPeerConnectionHandler instance on the main thread.
592 // In order to do safe PostTask-ing, the class is reference counted and
593 // checks for the existence of the RTCPeerConnectionHandler instance before
594 // delivering callbacks on the main thread.
595 class RTCPeerConnectionHandler::Observer
596 : public base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>,
597 public PeerConnectionObserver {
598 public:
599 Observer(const base::WeakPtr<RTCPeerConnectionHandler>& handler)
600 : handler_(handler), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
602 protected:
603 friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>;
604 virtual ~Observer() {}
606 void OnSignalingChange(
607 PeerConnectionInterface::SignalingState new_state) override {
608 if (!main_thread_->BelongsToCurrentThread()) {
609 main_thread_->PostTask(FROM_HERE,
610 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange,
611 this, new_state));
612 } else if (handler_) {
613 handler_->OnSignalingChange(new_state);
617 void OnAddStream(MediaStreamInterface* stream) override {
618 DCHECK(stream);
619 scoped_ptr<RemoteMediaStreamImpl> remote_stream(
620 new RemoteMediaStreamImpl(main_thread_, stream));
622 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
623 // asynchronously and the posted task will execude after that initialization
624 // is done.
625 main_thread_->PostTask(FROM_HERE,
626 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl,
627 this, base::Passed(&remote_stream)));
630 void OnRemoveStream(MediaStreamInterface* stream) override {
631 main_thread_->PostTask(FROM_HERE,
632 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
633 this, make_scoped_refptr(stream)));
636 void OnDataChannel(DataChannelInterface* data_channel) override {
637 scoped_ptr<RtcDataChannelHandler> handler(
638 new RtcDataChannelHandler(main_thread_, data_channel));
639 main_thread_->PostTask(FROM_HERE,
640 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
641 this, base::Passed(&handler)));
644 void OnRenegotiationNeeded() override {
645 if (!main_thread_->BelongsToCurrentThread()) {
646 main_thread_->PostTask(FROM_HERE,
647 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
648 this));
649 } else if (handler_) {
650 handler_->OnRenegotiationNeeded();
654 void OnIceConnectionChange(
655 PeerConnectionInterface::IceConnectionState new_state) override {
656 if (!main_thread_->BelongsToCurrentThread()) {
657 main_thread_->PostTask(FROM_HERE,
658 base::Bind(
659 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
660 new_state));
661 } else if (handler_) {
662 handler_->OnIceConnectionChange(new_state);
666 void OnIceGatheringChange(
667 PeerConnectionInterface::IceGatheringState new_state) override {
668 if (!main_thread_->BelongsToCurrentThread()) {
669 main_thread_->PostTask(FROM_HERE,
670 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
671 this, new_state));
672 } else if (handler_) {
673 handler_->OnIceGatheringChange(new_state);
677 void OnIceCandidate(const IceCandidateInterface* candidate) override {
678 std::string sdp;
679 if (!candidate->ToString(&sdp)) {
680 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
681 return;
684 main_thread_->PostTask(FROM_HERE,
685 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
686 this, sdp, candidate->sdp_mid(), candidate->sdp_mline_index(),
687 candidate->candidate().component(),
688 candidate->candidate().address().family()));
691 void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
692 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
693 if (handler_)
694 handler_->OnAddStream(stream.Pass());
697 void OnRemoveStreamImpl(const scoped_refptr<MediaStreamInterface>& stream) {
698 if (handler_)
699 handler_->OnRemoveStream(stream);
702 void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
703 if (handler_)
704 handler_->OnDataChannel(handler.Pass());
707 void OnIceCandidateImpl(const std::string& sdp, const std::string& sdp_mid,
708 int sdp_mline_index, int component, int address_family) {
709 if (handler_) {
710 handler_->OnIceCandidate(sdp, sdp_mid, sdp_mline_index, component,
711 address_family);
715 private:
716 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
717 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
720 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
721 blink::WebRTCPeerConnectionHandlerClient* client,
722 PeerConnectionDependencyFactory* dependency_factory)
723 : client_(client),
724 dependency_factory_(dependency_factory),
725 frame_(NULL),
726 num_data_channels_created_(0),
727 num_local_candidates_ipv4_(0),
728 num_local_candidates_ipv6_(0),
729 weak_factory_(this) {
730 g_peer_connection_handlers.Get().insert(this);
733 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
734 DCHECK(thread_checker_.CalledOnValidThread());
736 stop();
738 g_peer_connection_handlers.Get().erase(this);
739 if (peer_connection_tracker_)
740 peer_connection_tracker_->UnregisterPeerConnection(this);
741 STLDeleteValues(&remote_streams_);
743 UMA_HISTOGRAM_COUNTS_10000(
744 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
747 // static
748 void RTCPeerConnectionHandler::DestructAllHandlers() {
749 std::set<RTCPeerConnectionHandler*> handlers(
750 g_peer_connection_handlers.Get().begin(),
751 g_peer_connection_handlers.Get().end());
752 for (auto handler : handlers) {
753 if (handler->client_)
754 handler->client_->releasePeerConnectionHandler();
758 // static
759 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
760 const blink::WebRTCOfferOptions& options,
761 RTCMediaConstraints* output) {
762 output->AddMandatory(
763 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
764 options.offerToReceiveAudio() > 0 ? "true" : "false",
765 true);
767 output->AddMandatory(
768 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
769 options.offerToReceiveVideo() > 0 ? "true" : "false",
770 true);
772 if (!options.voiceActivityDetection()) {
773 output->AddMandatory(
774 webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
775 "false",
776 true);
779 if (options.iceRestart()) {
780 output->AddMandatory(
781 webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
785 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
786 DCHECK(thread_checker_.CalledOnValidThread());
787 DCHECK(frame);
788 frame_ = frame;
791 bool RTCPeerConnectionHandler::initialize(
792 const blink::WebRTCConfiguration& server_configuration,
793 const blink::WebMediaConstraints& options) {
794 DCHECK(thread_checker_.CalledOnValidThread());
795 DCHECK(frame_);
797 peer_connection_tracker_ =
798 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
800 webrtc::PeerConnectionInterface::RTCConfiguration config;
801 GetNativeRtcConfiguration(server_configuration, &config);
803 RTCMediaConstraints constraints(options);
805 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
806 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
807 config, &constraints, frame_, peer_connection_observer_.get());
809 if (!native_peer_connection_.get()) {
810 LOG(ERROR) << "Failed to initialize native PeerConnection.";
811 return false;
814 if (peer_connection_tracker_) {
815 peer_connection_tracker_->RegisterPeerConnection(
816 this, config, constraints, frame_);
819 uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
820 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
821 return true;
824 bool RTCPeerConnectionHandler::InitializeForTest(
825 const blink::WebRTCConfiguration& server_configuration,
826 const blink::WebMediaConstraints& options,
827 const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
828 DCHECK(thread_checker_.CalledOnValidThread());
829 webrtc::PeerConnectionInterface::RTCConfiguration config;
830 GetNativeRtcConfiguration(server_configuration, &config);
832 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
833 RTCMediaConstraints constraints(options);
834 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
835 config, &constraints, NULL, peer_connection_observer_.get());
836 if (!native_peer_connection_.get()) {
837 LOG(ERROR) << "Failed to initialize native PeerConnection.";
838 return false;
840 peer_connection_tracker_ = peer_connection_tracker;
841 return true;
844 void RTCPeerConnectionHandler::createOffer(
845 const blink::WebRTCSessionDescriptionRequest& request,
846 const blink::WebMediaConstraints& options) {
847 DCHECK(thread_checker_.CalledOnValidThread());
848 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
850 scoped_refptr<CreateSessionDescriptionRequest> description_request(
851 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
852 base::ThreadTaskRunnerHandle::Get(), request,
853 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
854 PeerConnectionTracker::ACTION_CREATE_OFFER));
856 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
857 RTCMediaConstraints constraints(options);
858 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
860 if (peer_connection_tracker_)
861 peer_connection_tracker_->TrackCreateOffer(this, constraints);
864 void RTCPeerConnectionHandler::createOffer(
865 const blink::WebRTCSessionDescriptionRequest& request,
866 const blink::WebRTCOfferOptions& options) {
867 DCHECK(thread_checker_.CalledOnValidThread());
868 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
870 scoped_refptr<CreateSessionDescriptionRequest> description_request(
871 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
872 base::ThreadTaskRunnerHandle::Get(), request,
873 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
874 PeerConnectionTracker::ACTION_CREATE_OFFER));
876 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
877 RTCMediaConstraints constraints;
878 ConvertOfferOptionsToConstraints(options, &constraints);
879 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
881 if (peer_connection_tracker_)
882 peer_connection_tracker_->TrackCreateOffer(this, constraints);
885 void RTCPeerConnectionHandler::createAnswer(
886 const blink::WebRTCSessionDescriptionRequest& request,
887 const blink::WebMediaConstraints& options) {
888 DCHECK(thread_checker_.CalledOnValidThread());
889 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
890 scoped_refptr<CreateSessionDescriptionRequest> description_request(
891 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
892 base::ThreadTaskRunnerHandle::Get(), request,
893 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
894 PeerConnectionTracker::ACTION_CREATE_ANSWER));
895 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
896 RTCMediaConstraints constraints(options);
897 native_peer_connection_->CreateAnswer(description_request.get(),
898 &constraints);
900 if (peer_connection_tracker_)
901 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
904 void RTCPeerConnectionHandler::setLocalDescription(
905 const blink::WebRTCVoidRequest& request,
906 const blink::WebRTCSessionDescription& description) {
907 DCHECK(thread_checker_.CalledOnValidThread());
908 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
910 std::string sdp = base::UTF16ToUTF8(base::StringPiece16(description.sdp()));
911 std::string type =
912 base::UTF16ToUTF8(base::StringPiece16(description.type()));
914 webrtc::SdpParseError error;
915 // Since CreateNativeSessionDescription uses the dependency factory, we need
916 // to make this call on the current thread to be safe.
917 webrtc::SessionDescriptionInterface* native_desc =
918 CreateNativeSessionDescription(sdp, type, &error);
919 if (!native_desc) {
920 std::string reason_str = "Failed to parse SessionDescription. ";
921 reason_str.append(error.line);
922 reason_str.append(" ");
923 reason_str.append(error.description);
924 LOG(ERROR) << reason_str;
925 request.requestFailed(blink::WebString::fromUTF8(reason_str));
926 return;
929 if (peer_connection_tracker_) {
930 peer_connection_tracker_->TrackSetSessionDescription(
931 this, sdp, type, PeerConnectionTracker::SOURCE_LOCAL);
934 scoped_refptr<SetSessionDescriptionRequest> set_request(
935 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
936 base::ThreadTaskRunnerHandle::Get(), request,
937 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
938 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
940 signaling_thread()->PostTask(FROM_HERE,
941 base::Bind(&RunClosureWithTrace,
942 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
943 native_peer_connection_, set_request,
944 base::Unretained(native_desc)),
945 "SetLocalDescription"));
948 void RTCPeerConnectionHandler::setRemoteDescription(
949 const blink::WebRTCVoidRequest& request,
950 const blink::WebRTCSessionDescription& description) {
951 DCHECK(thread_checker_.CalledOnValidThread());
952 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
953 std::string sdp = base::UTF16ToUTF8(base::StringPiece16(description.sdp()));
954 std::string type =
955 base::UTF16ToUTF8(base::StringPiece16(description.type()));
957 webrtc::SdpParseError error;
958 // Since CreateNativeSessionDescription uses the dependency factory, we need
959 // to make this call on the current thread to be safe.
960 webrtc::SessionDescriptionInterface* native_desc =
961 CreateNativeSessionDescription(sdp, type, &error);
962 if (!native_desc) {
963 std::string reason_str = "Failed to parse SessionDescription. ";
964 reason_str.append(error.line);
965 reason_str.append(" ");
966 reason_str.append(error.description);
967 LOG(ERROR) << reason_str;
968 request.requestFailed(blink::WebString::fromUTF8(reason_str));
969 return;
972 if (peer_connection_tracker_) {
973 peer_connection_tracker_->TrackSetSessionDescription(
974 this, sdp, type, PeerConnectionTracker::SOURCE_REMOTE);
977 scoped_refptr<SetSessionDescriptionRequest> set_request(
978 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
979 base::ThreadTaskRunnerHandle::Get(), request,
980 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
981 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
982 signaling_thread()->PostTask(FROM_HERE,
983 base::Bind(&RunClosureWithTrace,
984 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
985 native_peer_connection_, set_request,
986 base::Unretained(native_desc)),
987 "SetRemoteDescription"));
990 blink::WebRTCSessionDescription
991 RTCPeerConnectionHandler::localDescription() {
992 DCHECK(thread_checker_.CalledOnValidThread());
993 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
995 // Since local_description returns a pointer to a non-reference-counted object
996 // that lives on the signaling thread, we cannot fetch a pointer to it and use
997 // it directly here. Instead, we access the object completely on the signaling
998 // thread.
999 std::string sdp, type;
1000 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
1001 base::Bind(&webrtc::PeerConnectionInterface::local_description,
1002 native_peer_connection_);
1003 RunSynchronousClosureOnSignalingThread(
1004 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
1005 base::Unretained(&sdp), base::Unretained(&type)),
1006 "localDescription");
1008 return CreateWebKitSessionDescription(sdp, type);
1011 blink::WebRTCSessionDescription
1012 RTCPeerConnectionHandler::remoteDescription() {
1013 DCHECK(thread_checker_.CalledOnValidThread());
1014 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
1015 // Since local_description returns a pointer to a non-reference-counted object
1016 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1017 // it directly here. Instead, we access the object completely on the signaling
1018 // thread.
1019 std::string sdp, type;
1020 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
1021 base::Bind(&webrtc::PeerConnectionInterface::remote_description,
1022 native_peer_connection_);
1023 RunSynchronousClosureOnSignalingThread(
1024 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
1025 base::Unretained(&sdp), base::Unretained(&type)),
1026 "remoteDescription");
1028 return CreateWebKitSessionDescription(sdp, type);
1031 bool RTCPeerConnectionHandler::updateICE(
1032 const blink::WebRTCConfiguration& server_configuration,
1033 const blink::WebMediaConstraints& options) {
1034 DCHECK(thread_checker_.CalledOnValidThread());
1035 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1036 webrtc::PeerConnectionInterface::RTCConfiguration config;
1037 GetNativeRtcConfiguration(server_configuration, &config);
1038 RTCMediaConstraints constraints(options);
1040 if (peer_connection_tracker_)
1041 peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
1043 return native_peer_connection_->UpdateIce(config.servers, &constraints);
1046 bool RTCPeerConnectionHandler::addICECandidate(
1047 const blink::WebRTCVoidRequest& request,
1048 const blink::WebRTCICECandidate& candidate) {
1049 DCHECK(thread_checker_.CalledOnValidThread());
1050 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1051 // Libjingle currently does not accept callbacks for addICECandidate.
1052 // For that reason we are going to call callbacks from here.
1054 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1055 // PostTaskAndReply kind of a thing.
1056 bool result = addICECandidate(candidate);
1057 base::ThreadTaskRunnerHandle::Get()->PostTask(
1058 FROM_HERE, base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
1059 weak_factory_.GetWeakPtr(), request, result));
1060 // On failure callback will be triggered.
1061 return true;
1064 bool RTCPeerConnectionHandler::addICECandidate(
1065 const blink::WebRTCICECandidate& candidate) {
1066 DCHECK(thread_checker_.CalledOnValidThread());
1067 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1068 scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
1069 dependency_factory_->CreateIceCandidate(
1070 base::UTF16ToUTF8(base::StringPiece16(candidate.sdpMid())),
1071 candidate.sdpMLineIndex(),
1072 base::UTF16ToUTF8(base::StringPiece16(candidate.candidate()))));
1073 bool return_value = false;
1075 if (native_candidate) {
1076 return_value =
1077 native_peer_connection_->AddIceCandidate(native_candidate.get());
1078 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
1079 } else {
1080 LOG(ERROR) << "Could not create native ICE candidate.";
1083 if (peer_connection_tracker_) {
1084 peer_connection_tracker_->TrackAddIceCandidate(
1085 this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
1087 return return_value;
1090 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1091 const blink::WebRTCVoidRequest& webkit_request, bool result) {
1092 DCHECK(thread_checker_.CalledOnValidThread());
1093 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1094 if (!result) {
1095 // We don't have the actual error code from the libjingle, so for now
1096 // using a generic error string.
1097 return webkit_request.requestFailed(
1098 base::UTF8ToUTF16("Error processing ICE candidate"));
1101 return webkit_request.requestSucceeded();
1104 bool RTCPeerConnectionHandler::addStream(
1105 const blink::WebMediaStream& stream,
1106 const blink::WebMediaConstraints& options) {
1107 DCHECK(thread_checker_.CalledOnValidThread());
1108 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1109 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1110 local_streams_.begin(); adapter_it != local_streams_.end();
1111 ++adapter_it) {
1112 if ((*adapter_it)->IsEqual(stream)) {
1113 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1114 << "stream twice. id=" << stream.id().utf8();
1115 return false;
1119 if (peer_connection_tracker_) {
1120 peer_connection_tracker_->TrackAddStream(
1121 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1124 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1126 WebRtcMediaStreamAdapter* adapter =
1127 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
1128 local_streams_.push_back(adapter);
1130 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
1131 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
1132 webrtc_stream);
1134 RTCMediaConstraints constraints(options);
1135 if (!constraints.GetMandatory().empty() ||
1136 !constraints.GetOptional().empty()) {
1137 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1138 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1139 // should be removed from blink as well.
1140 LOG(WARNING)
1141 << "mediaConstraints is not a supported argument to addStream.";
1144 return native_peer_connection_->AddStream(webrtc_stream);
1147 void RTCPeerConnectionHandler::removeStream(
1148 const blink::WebMediaStream& stream) {
1149 DCHECK(thread_checker_.CalledOnValidThread());
1150 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1151 // Find the webrtc stream.
1152 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
1153 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1154 local_streams_.begin(); adapter_it != local_streams_.end();
1155 ++adapter_it) {
1156 if ((*adapter_it)->IsEqual(stream)) {
1157 webrtc_stream = (*adapter_it)->webrtc_media_stream();
1158 local_streams_.erase(adapter_it);
1159 break;
1162 DCHECK(webrtc_stream.get());
1163 // TODO(tommi): Make this async (PostTaskAndReply).
1164 native_peer_connection_->RemoveStream(webrtc_stream.get());
1166 if (peer_connection_tracker_) {
1167 peer_connection_tracker_->TrackRemoveStream(
1168 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1170 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1171 track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
1172 webrtc_stream.get());
1175 void RTCPeerConnectionHandler::getStats(
1176 const blink::WebRTCStatsRequest& request) {
1177 DCHECK(thread_checker_.CalledOnValidThread());
1178 scoped_refptr<LocalRTCStatsRequest> inner_request(
1179 new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
1180 getStats(inner_request);
1183 void RTCPeerConnectionHandler::getStats(
1184 const scoped_refptr<LocalRTCStatsRequest>& request) {
1185 DCHECK(thread_checker_.CalledOnValidThread());
1186 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1189 rtc::scoped_refptr<webrtc::StatsObserver> observer(
1190 new rtc::RefCountedObject<StatsResponse>(request));
1192 std::string track_id;
1193 blink::WebMediaStreamSource::Type track_type =
1194 blink::WebMediaStreamSource::TypeAudio;
1195 if (request->hasSelector()) {
1196 track_type = request->component().source().type();
1197 track_id = request->component().id().utf8();
1200 GetStats(observer, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard,
1201 track_id, track_type);
1204 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1205 void RTCPeerConnectionHandler::GetStats(
1206 webrtc::StatsObserver* observer,
1207 webrtc::PeerConnectionInterface::StatsOutputLevel level,
1208 const std::string& track_id,
1209 blink::WebMediaStreamSource::Type track_type) {
1210 DCHECK(thread_checker_.CalledOnValidThread());
1211 signaling_thread()->PostTask(FROM_HERE,
1212 base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level,
1213 make_scoped_refptr(observer), track_id, track_type));
1216 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1217 DCHECK(thread_checker_.CalledOnValidThread());
1218 if (client_)
1219 client_->closePeerConnection();
1222 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
1223 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
1224 DCHECK(thread_checker_.CalledOnValidThread());
1225 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1226 DVLOG(1) << "createDataChannel label "
1227 << base::UTF16ToUTF8(base::StringPiece16(label));
1229 webrtc::DataChannelInit config;
1230 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1231 // to handle that.
1232 config.reliable = false;
1233 config.id = init.id;
1234 config.ordered = init.ordered;
1235 config.negotiated = init.negotiated;
1236 config.maxRetransmits = init.maxRetransmits;
1237 config.maxRetransmitTime = init.maxRetransmitTime;
1238 config.protocol = base::UTF16ToUTF8(base::StringPiece16(init.protocol));
1240 rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
1241 native_peer_connection_->CreateDataChannel(
1242 base::UTF16ToUTF8(base::StringPiece16(label)), &config));
1243 if (!webrtc_channel) {
1244 DLOG(ERROR) << "Could not create native data channel.";
1245 return NULL;
1247 if (peer_connection_tracker_) {
1248 peer_connection_tracker_->TrackCreateDataChannel(
1249 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
1252 ++num_data_channels_created_;
1254 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1255 webrtc_channel);
1258 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
1259 const blink::WebMediaStreamTrack& track) {
1260 DCHECK(thread_checker_.CalledOnValidThread());
1261 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1262 DVLOG(1) << "createDTMFSender.";
1264 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
1265 if (!native_track || !native_track->is_local_track() ||
1266 track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
1267 DLOG(ERROR) << "The DTMF sender requires a local audio track.";
1268 return nullptr;
1271 scoped_refptr<webrtc::AudioTrackInterface> audio_track =
1272 native_track->GetAudioAdapter();
1273 rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
1274 native_peer_connection_->CreateDtmfSender(audio_track.get()));
1275 if (!sender) {
1276 DLOG(ERROR) << "Could not create native DTMF sender.";
1277 return nullptr;
1279 if (peer_connection_tracker_)
1280 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
1282 return new RtcDtmfSenderHandler(sender);
1285 void RTCPeerConnectionHandler::stop() {
1286 DCHECK(thread_checker_.CalledOnValidThread());
1287 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1289 if (!client_ || !native_peer_connection_.get())
1290 return; // Already stopped.
1292 if (peer_connection_tracker_)
1293 peer_connection_tracker_->TrackStop(this);
1295 native_peer_connection_->Close();
1297 // The client_ pointer is not considered valid after this point and no further
1298 // callbacks must be made.
1299 client_ = nullptr;
1302 void RTCPeerConnectionHandler::OnSignalingChange(
1303 webrtc::PeerConnectionInterface::SignalingState new_state) {
1304 DCHECK(thread_checker_.CalledOnValidThread());
1305 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1307 blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
1308 GetWebKitSignalingState(new_state);
1309 if (peer_connection_tracker_)
1310 peer_connection_tracker_->TrackSignalingStateChange(this, state);
1311 if (client_)
1312 client_->didChangeSignalingState(state);
1315 // Called any time the IceConnectionState changes
1316 void RTCPeerConnectionHandler::OnIceConnectionChange(
1317 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
1318 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1319 DCHECK(thread_checker_.CalledOnValidThread());
1320 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
1321 ice_connection_checking_start_ = base::TimeTicks::Now();
1322 } else if (new_state ==
1323 webrtc::PeerConnectionInterface::kIceConnectionConnected) {
1324 // If the state becomes connected, send the time needed for PC to become
1325 // connected from checking to UMA. UMA data will help to know how much
1326 // time needed for PC to connect with remote peer.
1327 if (ice_connection_checking_start_.is_null()) {
1328 // From UMA, we have observed a large number of calls falling into the
1329 // overflow buckets. One possibility is that the Checking is not signaled
1330 // before Connected. This is to guard against that situation to make the
1331 // metric more robust.
1332 UMA_HISTOGRAM_MEDIUM_TIMES("WebRTC.PeerConnection.TimeToConnect",
1333 base::TimeDelta());
1334 } else {
1335 UMA_HISTOGRAM_MEDIUM_TIMES(
1336 "WebRTC.PeerConnection.TimeToConnect",
1337 base::TimeTicks::Now() - ice_connection_checking_start_);
1341 track_metrics_.IceConnectionChange(new_state);
1342 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
1343 GetWebKitIceConnectionState(new_state);
1344 if (peer_connection_tracker_)
1345 peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
1346 if(client_)
1347 client_->didChangeICEConnectionState(state);
1350 // Called any time the IceGatheringState changes
1351 void RTCPeerConnectionHandler::OnIceGatheringChange(
1352 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
1353 DCHECK(thread_checker_.CalledOnValidThread());
1354 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1356 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
1357 // If ICE gathering is completed, generate a NULL ICE candidate,
1358 // to signal end of candidates.
1359 if (client_) {
1360 blink::WebRTCICECandidate null_candidate;
1361 client_->didGenerateICECandidate(null_candidate);
1364 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1365 num_local_candidates_ipv4_);
1367 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1368 num_local_candidates_ipv6_);
1369 } else if (new_state ==
1370 webrtc::PeerConnectionInterface::kIceGatheringGathering) {
1371 // ICE restarts will change gathering state back to "gathering",
1372 // reset the counter.
1373 num_local_candidates_ipv6_ = 0;
1374 num_local_candidates_ipv4_ = 0;
1377 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
1378 GetWebKitIceGatheringState(new_state);
1379 if (peer_connection_tracker_)
1380 peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
1381 if (client_)
1382 client_->didChangeICEGatheringState(state);
1385 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1386 DCHECK(thread_checker_.CalledOnValidThread());
1387 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1388 if (peer_connection_tracker_)
1389 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
1390 if (client_)
1391 client_->negotiationNeeded();
1394 void RTCPeerConnectionHandler::OnAddStream(
1395 scoped_ptr<RemoteMediaStreamImpl> stream) {
1396 DCHECK(thread_checker_.CalledOnValidThread());
1397 DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
1398 remote_streams_.end());
1399 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
1400 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1402 // Ownership is with remote_streams_ now.
1403 RemoteMediaStreamImpl* s = stream.release();
1404 remote_streams_.insert(
1405 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
1406 s->webrtc_stream().get(), s));
1408 if (peer_connection_tracker_) {
1409 peer_connection_tracker_->TrackAddStream(
1410 this, s->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE);
1413 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1415 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1416 s->webrtc_stream().get());
1417 if (client_)
1418 client_->didAddRemoteStream(s->webkit_stream());
1421 void RTCPeerConnectionHandler::OnRemoveStream(
1422 const scoped_refptr<webrtc::MediaStreamInterface>& stream) {
1423 DCHECK(thread_checker_.CalledOnValidThread());
1424 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1425 RemoteStreamMap::iterator it = remote_streams_.find(stream.get());
1426 if (it == remote_streams_.end()) {
1427 NOTREACHED() << "Stream not found";
1428 return;
1431 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1432 stream.get());
1433 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1435 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
1436 const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
1437 DCHECK(!webkit_stream.isNull());
1438 remote_streams_.erase(it);
1440 if (peer_connection_tracker_) {
1441 peer_connection_tracker_->TrackRemoveStream(
1442 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
1445 if (client_)
1446 client_->didRemoveRemoteStream(webkit_stream);
1449 void RTCPeerConnectionHandler::OnDataChannel(
1450 scoped_ptr<RtcDataChannelHandler> handler) {
1451 DCHECK(thread_checker_.CalledOnValidThread());
1452 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1454 if (peer_connection_tracker_) {
1455 peer_connection_tracker_->TrackCreateDataChannel(
1456 this, handler->channel().get(), PeerConnectionTracker::SOURCE_REMOTE);
1459 if (client_)
1460 client_->didAddRemoteDataChannel(handler.release());
1463 void RTCPeerConnectionHandler::OnIceCandidate(
1464 const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index,
1465 int component, int address_family) {
1466 DCHECK(thread_checker_.CalledOnValidThread());
1467 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1468 blink::WebRTCICECandidate web_candidate;
1469 web_candidate.initialize(base::UTF8ToUTF16(sdp),
1470 base::UTF8ToUTF16(sdp_mid),
1471 sdp_mline_index);
1472 if (peer_connection_tracker_) {
1473 peer_connection_tracker_->TrackAddIceCandidate(
1474 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
1477 // Only the first m line's first component is tracked to avoid
1478 // miscounting when doing BUNDLE or rtcp mux.
1479 if (sdp_mline_index == 0 && component == 1) {
1480 if (address_family == AF_INET) {
1481 ++num_local_candidates_ipv4_;
1482 } else if (address_family == AF_INET6) {
1483 ++num_local_candidates_ipv6_;
1484 } else {
1485 NOTREACHED();
1488 if (client_)
1489 client_->didGenerateICECandidate(web_candidate);
1492 webrtc::SessionDescriptionInterface*
1493 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1494 const std::string& sdp, const std::string& type,
1495 webrtc::SdpParseError* error) {
1496 webrtc::SessionDescriptionInterface* native_desc =
1497 dependency_factory_->CreateSessionDescription(type, sdp, error);
1499 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1500 << " Type: " << type << " SDP: " << sdp;
1502 return native_desc;
1505 scoped_refptr<base::SingleThreadTaskRunner>
1506 RTCPeerConnectionHandler::signaling_thread() const {
1507 DCHECK(thread_checker_.CalledOnValidThread());
1508 return dependency_factory_->GetWebRtcSignalingThread();
1511 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1512 const base::Closure& closure,
1513 const char* trace_event_name) {
1514 DCHECK(thread_checker_.CalledOnValidThread());
1515 scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
1516 if (!thread.get() || thread->BelongsToCurrentThread()) {
1517 TRACE_EVENT0("webrtc", trace_event_name);
1518 closure.Run();
1519 } else {
1520 base::WaitableEvent event(false, false);
1521 thread->PostTask(FROM_HERE,
1522 base::Bind(&RunSynchronousClosure, closure,
1523 base::Unretained(trace_event_name),
1524 base::Unretained(&event)));
1525 event.Wait();
1529 } // namespace content