[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / content / renderer / media / rtc_peer_connection_handler.cc
blobda93384f6a889aea18abf7a71153f7c2f97882ab
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 delete desc;
267 void OnFailure(const std::string& error) override {
268 if (!main_thread_->BelongsToCurrentThread()) {
269 main_thread_->PostTask(FROM_HERE,
270 base::Bind(&CreateSessionDescriptionRequest::OnFailure, this, error));
271 return;
274 tracker_.TrackOnFailure(error);
275 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
278 protected:
279 ~CreateSessionDescriptionRequest() override {}
281 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
282 blink::WebRTCSessionDescriptionRequest webkit_request_;
283 SessionDescriptionRequestTracker tracker_;
286 // Class mapping responses from calls to libjingle
287 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
288 class SetSessionDescriptionRequest
289 : public webrtc::SetSessionDescriptionObserver {
290 public:
291 explicit SetSessionDescriptionRequest(
292 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
293 const blink::WebRTCVoidRequest& request,
294 const base::WeakPtr<RTCPeerConnectionHandler>& handler,
295 const base::WeakPtr<PeerConnectionTracker>& tracker,
296 PeerConnectionTracker::Action action)
297 : main_thread_(main_thread),
298 webkit_request_(request),
299 tracker_(handler, tracker, action) {
302 void OnSuccess() override {
303 if (!main_thread_->BelongsToCurrentThread()) {
304 main_thread_->PostTask(FROM_HERE,
305 base::Bind(&SetSessionDescriptionRequest::OnSuccess, this));
306 return;
308 tracker_.TrackOnSuccess(NULL);
309 webkit_request_.requestSucceeded();
311 void OnFailure(const std::string& error) override {
312 if (!main_thread_->BelongsToCurrentThread()) {
313 main_thread_->PostTask(FROM_HERE,
314 base::Bind(&SetSessionDescriptionRequest::OnFailure, this, error));
315 return;
317 tracker_.TrackOnFailure(error);
318 webkit_request_.requestFailed(base::UTF8ToUTF16(error));
321 protected:
322 ~SetSessionDescriptionRequest() override {}
324 private:
325 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
326 blink::WebRTCVoidRequest webkit_request_;
327 SessionDescriptionRequestTracker tracker_;
330 // Class mapping responses from calls to libjingle
331 // GetStats into a blink::WebRTCStatsCallback.
332 class StatsResponse : public webrtc::StatsObserver {
333 public:
334 explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
335 : request_(request.get()),
336 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
337 // Measure the overall time it takes to satisfy a getStats request.
338 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
339 signaling_thread_checker_.DetachFromThread();
342 void OnComplete(const StatsReports& reports) override {
343 DCHECK(signaling_thread_checker_.CalledOnValidThread());
344 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
345 // We can't use webkit objects directly since they use a single threaded
346 // heap allocator.
347 std::vector<Report*>* report_copies = new std::vector<Report*>();
348 report_copies->reserve(reports.size());
349 for (auto* r : reports)
350 report_copies->push_back(new Report(r));
352 main_thread_->PostTaskAndReply(FROM_HERE,
353 base::Bind(&StatsResponse::DeliverCallback, this,
354 base::Unretained(report_copies)),
355 base::Bind(&StatsResponse::DeleteReports,
356 base::Unretained(report_copies)));
359 private:
360 struct Report {
361 Report(const StatsReport* report)
362 : thread_checker(), id(report->id().ToString()),
363 type(report->TypeToString()), timestamp(report->timestamp()),
364 values(report->values()) {
367 ~Report() {
368 // Since the values vector holds pointers to const objects that are bound
369 // to the signaling thread, they must be released on the same thread.
370 DCHECK(thread_checker.CalledOnValidThread());
373 const base::ThreadChecker thread_checker;
374 const std::string id, type;
375 const double timestamp;
376 const StatsReport::Values values;
379 static void DeleteReports(std::vector<Report*>* reports) {
380 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
381 for (auto* p : *reports)
382 delete p;
383 delete reports;
386 void DeliverCallback(const std::vector<Report*>* reports) {
387 DCHECK(main_thread_->BelongsToCurrentThread());
388 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
390 rtc::scoped_refptr<LocalRTCStatsResponse> response(
391 request_->createResponse().get());
392 for (const auto* report : *reports) {
393 if (report->values.size() > 0)
394 AddReport(response.get(), *report);
397 // Record the getStats operation as done before calling into Blink so that
398 // we don't skew the perf measurements of the native code with whatever the
399 // callback might be doing.
400 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
401 request_->requestSucceeded(response);
402 request_ = nullptr; // must be freed on the main thread.
405 void AddReport(LocalRTCStatsResponse* response, const Report& report) {
406 int idx = response->addReport(blink::WebString::fromUTF8(report.id),
407 blink::WebString::fromUTF8(report.type),
408 report.timestamp);
409 for (const auto& value : report.values) {
410 response->addStatistic(idx,
411 blink::WebString::fromUTF8(value->display_name()),
412 blink::WebString::fromUTF8(value->value));
416 rtc::scoped_refptr<LocalRTCStatsRequest> request_;
417 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
418 base::ThreadChecker signaling_thread_checker_;
421 void GetStatsOnSignalingThread(
422 const scoped_refptr<webrtc::PeerConnectionInterface>& pc,
423 webrtc::PeerConnectionInterface::StatsOutputLevel level,
424 const scoped_refptr<webrtc::StatsObserver>& observer,
425 const std::string track_id, blink::WebMediaStreamSource::Type track_type) {
426 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
428 scoped_refptr<webrtc::MediaStreamTrackInterface> track;
429 if (!track_id.empty()) {
430 if (track_type == blink::WebMediaStreamSource::TypeAudio) {
431 track = pc->local_streams()->FindAudioTrack(track_id);
432 if (!track.get())
433 track = pc->remote_streams()->FindAudioTrack(track_id);
434 } else {
435 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track_type);
436 track = pc->local_streams()->FindVideoTrack(track_id);
437 if (!track.get())
438 track = pc->remote_streams()->FindVideoTrack(track_id);
441 if (!track.get()) {
442 DVLOG(1) << "GetStats: Track not found.";
443 observer->OnComplete(StatsReports());
444 return;
448 if (!pc->GetStats(observer.get(), track.get(), level)) {
449 DVLOG(1) << "GetStats failed.";
450 observer->OnComplete(StatsReports());
454 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
455 public:
456 PeerConnectionUMAObserver() {}
457 ~PeerConnectionUMAObserver() override {}
459 void IncrementCounter(
460 webrtc::PeerConnectionUMAMetricsCounter counter) override {
461 // Runs on libjingle's signaling thread.
462 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
463 counter,
464 webrtc::kBoundary);
467 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,
468 int value) override {
469 // Runs on libjingle's signaling thread.
470 switch (type) {
471 case webrtc::kTimeToConnect:
472 UMA_HISTOGRAM_MEDIUM_TIMES(
473 "WebRTC.PeerConnection.TimeToConnect",
474 base::TimeDelta::FromMilliseconds(value));
475 break;
476 case webrtc::kNetworkInterfaces_IPv4:
477 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
478 value);
479 break;
480 case webrtc::kNetworkInterfaces_IPv6:
481 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
482 value);
483 break;
484 default:
485 NOTREACHED();
490 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
491 g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
493 } // namespace
495 // Implementation of LocalRTCStatsRequest.
496 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
497 : impl_(impl) {
500 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
501 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
503 bool LocalRTCStatsRequest::hasSelector() const {
504 return impl_.hasSelector();
507 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
508 return impl_.component();
511 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
512 return scoped_refptr<LocalRTCStatsResponse>(
513 new rtc::RefCountedObject<LocalRTCStatsResponse>(impl_.createResponse()));
516 void LocalRTCStatsRequest::requestSucceeded(
517 const LocalRTCStatsResponse* response) {
518 impl_.requestSucceeded(response->webKitStatsResponse());
521 // Implementation of LocalRTCStatsResponse.
522 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
523 return impl_;
526 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
527 blink::WebString id,
528 double timestamp) {
529 return impl_.addReport(type, id, timestamp);
532 void LocalRTCStatsResponse::addStatistic(size_t report,
533 blink::WebString name,
534 blink::WebString value) {
535 impl_.addStatistic(report, name, value);
538 // Receives notifications from a PeerConnection object about state changes,
539 // track addition/removal etc. The callbacks we receive here come on the
540 // signaling thread, so this class takes care of delivering them to an
541 // RTCPeerConnectionHandler instance on the main thread.
542 // In order to do safe PostTask-ing, the class is reference counted and
543 // checks for the existence of the RTCPeerConnectionHandler instance before
544 // delivering callbacks on the main thread.
545 class RTCPeerConnectionHandler::Observer
546 : public base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>,
547 public PeerConnectionObserver {
548 public:
549 Observer(const base::WeakPtr<RTCPeerConnectionHandler>& handler)
550 : handler_(handler), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
552 protected:
553 friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>;
554 virtual ~Observer() {}
556 void OnSignalingChange(
557 PeerConnectionInterface::SignalingState new_state) override {
558 if (!main_thread_->BelongsToCurrentThread()) {
559 main_thread_->PostTask(FROM_HERE,
560 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange,
561 this, new_state));
562 } else if (handler_) {
563 handler_->OnSignalingChange(new_state);
567 void OnAddStream(MediaStreamInterface* stream) override {
568 DCHECK(stream);
569 scoped_ptr<RemoteMediaStreamImpl> remote_stream(
570 new RemoteMediaStreamImpl(main_thread_, stream));
572 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
573 // asynchronously and the posted task will execude after that initialization
574 // is done.
575 main_thread_->PostTask(FROM_HERE,
576 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl,
577 this, base::Passed(&remote_stream)));
580 void OnRemoveStream(MediaStreamInterface* stream) override {
581 main_thread_->PostTask(FROM_HERE,
582 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
583 this, make_scoped_refptr(stream)));
586 void OnDataChannel(DataChannelInterface* data_channel) override {
587 scoped_ptr<RtcDataChannelHandler> handler(
588 new RtcDataChannelHandler(main_thread_, data_channel));
589 main_thread_->PostTask(FROM_HERE,
590 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
591 this, base::Passed(&handler)));
594 void OnRenegotiationNeeded() override {
595 if (!main_thread_->BelongsToCurrentThread()) {
596 main_thread_->PostTask(FROM_HERE,
597 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
598 this));
599 } else if (handler_) {
600 handler_->OnRenegotiationNeeded();
604 void OnIceConnectionChange(
605 PeerConnectionInterface::IceConnectionState new_state) override {
606 if (!main_thread_->BelongsToCurrentThread()) {
607 main_thread_->PostTask(FROM_HERE,
608 base::Bind(
609 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
610 new_state));
611 } else if (handler_) {
612 handler_->OnIceConnectionChange(new_state);
616 void OnIceGatheringChange(
617 PeerConnectionInterface::IceGatheringState new_state) override {
618 if (!main_thread_->BelongsToCurrentThread()) {
619 main_thread_->PostTask(FROM_HERE,
620 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
621 this, new_state));
622 } else if (handler_) {
623 handler_->OnIceGatheringChange(new_state);
627 void OnIceCandidate(const IceCandidateInterface* candidate) override {
628 std::string sdp;
629 if (!candidate->ToString(&sdp)) {
630 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
631 return;
634 main_thread_->PostTask(FROM_HERE,
635 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
636 this, sdp, candidate->sdp_mid(), candidate->sdp_mline_index(),
637 candidate->candidate().component(),
638 candidate->candidate().address().family()));
641 void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
642 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
643 if (handler_)
644 handler_->OnAddStream(stream.Pass());
647 void OnRemoveStreamImpl(const scoped_refptr<MediaStreamInterface>& stream) {
648 if (handler_)
649 handler_->OnRemoveStream(stream);
652 void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
653 if (handler_)
654 handler_->OnDataChannel(handler.Pass());
657 void OnIceCandidateImpl(const std::string& sdp, const std::string& sdp_mid,
658 int sdp_mline_index, int component, int address_family) {
659 if (handler_) {
660 handler_->OnIceCandidate(sdp, sdp_mid, sdp_mline_index, component,
661 address_family);
665 private:
666 const base::WeakPtr<RTCPeerConnectionHandler> handler_;
667 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
670 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
671 blink::WebRTCPeerConnectionHandlerClient* client,
672 PeerConnectionDependencyFactory* dependency_factory)
673 : client_(client),
674 dependency_factory_(dependency_factory),
675 frame_(NULL),
676 num_data_channels_created_(0),
677 num_local_candidates_ipv4_(0),
678 num_local_candidates_ipv6_(0),
679 weak_factory_(this) {
680 g_peer_connection_handlers.Get().insert(this);
683 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
684 DCHECK(thread_checker_.CalledOnValidThread());
686 stop();
688 g_peer_connection_handlers.Get().erase(this);
689 if (peer_connection_tracker_)
690 peer_connection_tracker_->UnregisterPeerConnection(this);
691 STLDeleteValues(&remote_streams_);
693 UMA_HISTOGRAM_COUNTS_10000(
694 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
697 // static
698 void RTCPeerConnectionHandler::DestructAllHandlers() {
699 std::set<RTCPeerConnectionHandler*> handlers(
700 g_peer_connection_handlers.Get().begin(),
701 g_peer_connection_handlers.Get().end());
702 for (auto handler : handlers) {
703 if (handler->client_)
704 handler->client_->releasePeerConnectionHandler();
708 // static
709 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
710 const blink::WebRTCOfferOptions& options,
711 RTCMediaConstraints* output) {
712 output->AddMandatory(
713 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
714 options.offerToReceiveAudio() > 0 ? "true" : "false",
715 true);
717 output->AddMandatory(
718 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
719 options.offerToReceiveVideo() > 0 ? "true" : "false",
720 true);
722 if (!options.voiceActivityDetection()) {
723 output->AddMandatory(
724 webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
725 "false",
726 true);
729 if (options.iceRestart()) {
730 output->AddMandatory(
731 webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
735 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
736 DCHECK(thread_checker_.CalledOnValidThread());
737 DCHECK(frame);
738 frame_ = frame;
741 bool RTCPeerConnectionHandler::initialize(
742 const blink::WebRTCConfiguration& server_configuration,
743 const blink::WebMediaConstraints& options) {
744 DCHECK(thread_checker_.CalledOnValidThread());
745 DCHECK(frame_);
747 peer_connection_tracker_ =
748 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
750 webrtc::PeerConnectionInterface::RTCConfiguration config;
751 GetNativeRtcConfiguration(server_configuration, &config);
753 RTCMediaConstraints constraints(options);
755 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
756 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
757 config, &constraints, frame_, peer_connection_observer_.get());
759 if (!native_peer_connection_.get()) {
760 LOG(ERROR) << "Failed to initialize native PeerConnection.";
761 return false;
764 if (peer_connection_tracker_) {
765 peer_connection_tracker_->RegisterPeerConnection(
766 this, config, constraints, frame_);
769 uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
770 native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
771 return true;
774 bool RTCPeerConnectionHandler::InitializeForTest(
775 const blink::WebRTCConfiguration& server_configuration,
776 const blink::WebMediaConstraints& options,
777 const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
778 DCHECK(thread_checker_.CalledOnValidThread());
779 webrtc::PeerConnectionInterface::RTCConfiguration config;
780 GetNativeRtcConfiguration(server_configuration, &config);
782 peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
783 RTCMediaConstraints constraints(options);
784 native_peer_connection_ = dependency_factory_->CreatePeerConnection(
785 config, &constraints, NULL, peer_connection_observer_.get());
786 if (!native_peer_connection_.get()) {
787 LOG(ERROR) << "Failed to initialize native PeerConnection.";
788 return false;
790 peer_connection_tracker_ = peer_connection_tracker;
791 return true;
794 void RTCPeerConnectionHandler::createOffer(
795 const blink::WebRTCSessionDescriptionRequest& request,
796 const blink::WebMediaConstraints& options) {
797 DCHECK(thread_checker_.CalledOnValidThread());
798 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
800 scoped_refptr<CreateSessionDescriptionRequest> description_request(
801 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
802 base::ThreadTaskRunnerHandle::Get(), request,
803 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
804 PeerConnectionTracker::ACTION_CREATE_OFFER));
806 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
807 RTCMediaConstraints constraints(options);
808 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
810 if (peer_connection_tracker_)
811 peer_connection_tracker_->TrackCreateOffer(this, constraints);
814 void RTCPeerConnectionHandler::createOffer(
815 const blink::WebRTCSessionDescriptionRequest& request,
816 const blink::WebRTCOfferOptions& options) {
817 DCHECK(thread_checker_.CalledOnValidThread());
818 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
820 scoped_refptr<CreateSessionDescriptionRequest> description_request(
821 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
822 base::ThreadTaskRunnerHandle::Get(), request,
823 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
824 PeerConnectionTracker::ACTION_CREATE_OFFER));
826 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
827 RTCMediaConstraints constraints;
828 ConvertOfferOptionsToConstraints(options, &constraints);
829 native_peer_connection_->CreateOffer(description_request.get(), &constraints);
831 if (peer_connection_tracker_)
832 peer_connection_tracker_->TrackCreateOffer(this, constraints);
835 void RTCPeerConnectionHandler::createAnswer(
836 const blink::WebRTCSessionDescriptionRequest& request,
837 const blink::WebMediaConstraints& options) {
838 DCHECK(thread_checker_.CalledOnValidThread());
839 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
840 scoped_refptr<CreateSessionDescriptionRequest> description_request(
841 new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
842 base::ThreadTaskRunnerHandle::Get(), request,
843 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
844 PeerConnectionTracker::ACTION_CREATE_ANSWER));
845 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
846 RTCMediaConstraints constraints(options);
847 native_peer_connection_->CreateAnswer(description_request.get(),
848 &constraints);
850 if (peer_connection_tracker_)
851 peer_connection_tracker_->TrackCreateAnswer(this, constraints);
854 void RTCPeerConnectionHandler::setLocalDescription(
855 const blink::WebRTCVoidRequest& request,
856 const blink::WebRTCSessionDescription& description) {
857 DCHECK(thread_checker_.CalledOnValidThread());
858 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
860 std::string sdp = base::UTF16ToUTF8(description.sdp());
861 std::string type = base::UTF16ToUTF8(description.type());
863 webrtc::SdpParseError error;
864 // Since CreateNativeSessionDescription uses the dependency factory, we need
865 // to make this call on the current thread to be safe.
866 webrtc::SessionDescriptionInterface* native_desc =
867 CreateNativeSessionDescription(sdp, type, &error);
868 if (!native_desc) {
869 std::string reason_str = "Failed to parse SessionDescription. ";
870 reason_str.append(error.line);
871 reason_str.append(" ");
872 reason_str.append(error.description);
873 LOG(ERROR) << reason_str;
874 request.requestFailed(blink::WebString::fromUTF8(reason_str));
875 return;
878 if (peer_connection_tracker_) {
879 peer_connection_tracker_->TrackSetSessionDescription(
880 this, sdp, type, PeerConnectionTracker::SOURCE_LOCAL);
883 scoped_refptr<SetSessionDescriptionRequest> set_request(
884 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
885 base::ThreadTaskRunnerHandle::Get(), request,
886 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
887 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
889 signaling_thread()->PostTask(FROM_HERE,
890 base::Bind(&RunClosureWithTrace,
891 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
892 native_peer_connection_, set_request,
893 base::Unretained(native_desc)),
894 "SetLocalDescription"));
897 void RTCPeerConnectionHandler::setRemoteDescription(
898 const blink::WebRTCVoidRequest& request,
899 const blink::WebRTCSessionDescription& description) {
900 DCHECK(thread_checker_.CalledOnValidThread());
901 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
902 std::string sdp = base::UTF16ToUTF8(description.sdp());
903 std::string type = base::UTF16ToUTF8(description.type());
905 webrtc::SdpParseError error;
906 // Since CreateNativeSessionDescription uses the dependency factory, we need
907 // to make this call on the current thread to be safe.
908 webrtc::SessionDescriptionInterface* native_desc =
909 CreateNativeSessionDescription(sdp, type, &error);
910 if (!native_desc) {
911 std::string reason_str = "Failed to parse SessionDescription. ";
912 reason_str.append(error.line);
913 reason_str.append(" ");
914 reason_str.append(error.description);
915 LOG(ERROR) << reason_str;
916 request.requestFailed(blink::WebString::fromUTF8(reason_str));
917 return;
920 if (peer_connection_tracker_) {
921 peer_connection_tracker_->TrackSetSessionDescription(
922 this, sdp, type, PeerConnectionTracker::SOURCE_REMOTE);
925 scoped_refptr<SetSessionDescriptionRequest> set_request(
926 new rtc::RefCountedObject<SetSessionDescriptionRequest>(
927 base::ThreadTaskRunnerHandle::Get(), request,
928 weak_factory_.GetWeakPtr(), peer_connection_tracker_,
929 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
930 signaling_thread()->PostTask(FROM_HERE,
931 base::Bind(&RunClosureWithTrace,
932 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
933 native_peer_connection_, set_request,
934 base::Unretained(native_desc)),
935 "SetRemoteDescription"));
938 blink::WebRTCSessionDescription
939 RTCPeerConnectionHandler::localDescription() {
940 DCHECK(thread_checker_.CalledOnValidThread());
941 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
943 // Since local_description returns a pointer to a non-reference-counted object
944 // that lives on the signaling thread, we cannot fetch a pointer to it and use
945 // it directly here. Instead, we access the object completely on the signaling
946 // thread.
947 std::string sdp, type;
948 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
949 base::Bind(&webrtc::PeerConnectionInterface::local_description,
950 native_peer_connection_);
951 RunSynchronousClosureOnSignalingThread(
952 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
953 base::Unretained(&sdp), base::Unretained(&type)),
954 "localDescription");
956 return CreateWebKitSessionDescription(sdp, type);
959 blink::WebRTCSessionDescription
960 RTCPeerConnectionHandler::remoteDescription() {
961 DCHECK(thread_checker_.CalledOnValidThread());
962 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
963 // Since local_description returns a pointer to a non-reference-counted object
964 // that lives on the signaling thread, we cannot fetch a pointer to it and use
965 // it directly here. Instead, we access the object completely on the signaling
966 // thread.
967 std::string sdp, type;
968 base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
969 base::Bind(&webrtc::PeerConnectionInterface::remote_description,
970 native_peer_connection_);
971 RunSynchronousClosureOnSignalingThread(
972 base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
973 base::Unretained(&sdp), base::Unretained(&type)),
974 "remoteDescription");
976 return CreateWebKitSessionDescription(sdp, type);
979 bool RTCPeerConnectionHandler::updateICE(
980 const blink::WebRTCConfiguration& server_configuration,
981 const blink::WebMediaConstraints& options) {
982 DCHECK(thread_checker_.CalledOnValidThread());
983 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
984 webrtc::PeerConnectionInterface::RTCConfiguration config;
985 GetNativeRtcConfiguration(server_configuration, &config);
986 RTCMediaConstraints constraints(options);
988 if (peer_connection_tracker_)
989 peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
991 return native_peer_connection_->UpdateIce(config.servers, &constraints);
994 bool RTCPeerConnectionHandler::addICECandidate(
995 const blink::WebRTCVoidRequest& request,
996 const blink::WebRTCICECandidate& candidate) {
997 DCHECK(thread_checker_.CalledOnValidThread());
998 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
999 // Libjingle currently does not accept callbacks for addICECandidate.
1000 // For that reason we are going to call callbacks from here.
1002 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1003 // PostTaskAndReply kind of a thing.
1004 bool result = addICECandidate(candidate);
1005 base::MessageLoop::current()->PostTask(
1006 FROM_HERE,
1007 base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
1008 weak_factory_.GetWeakPtr(), request, result));
1009 // On failure callback will be triggered.
1010 return true;
1013 bool RTCPeerConnectionHandler::addICECandidate(
1014 const blink::WebRTCICECandidate& candidate) {
1015 DCHECK(thread_checker_.CalledOnValidThread());
1016 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1017 scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
1018 dependency_factory_->CreateIceCandidate(
1019 base::UTF16ToUTF8(candidate.sdpMid()),
1020 candidate.sdpMLineIndex(),
1021 base::UTF16ToUTF8(candidate.candidate())));
1022 bool return_value = false;
1024 if (native_candidate) {
1025 return_value =
1026 native_peer_connection_->AddIceCandidate(native_candidate.get());
1027 LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
1028 } else {
1029 LOG(ERROR) << "Could not create native ICE candidate.";
1032 if (peer_connection_tracker_) {
1033 peer_connection_tracker_->TrackAddIceCandidate(
1034 this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
1036 return return_value;
1039 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1040 const blink::WebRTCVoidRequest& webkit_request, bool result) {
1041 DCHECK(thread_checker_.CalledOnValidThread());
1042 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1043 if (!result) {
1044 // We don't have the actual error code from the libjingle, so for now
1045 // using a generic error string.
1046 return webkit_request.requestFailed(
1047 base::UTF8ToUTF16("Error processing ICE candidate"));
1050 return webkit_request.requestSucceeded();
1053 bool RTCPeerConnectionHandler::addStream(
1054 const blink::WebMediaStream& stream,
1055 const blink::WebMediaConstraints& options) {
1056 DCHECK(thread_checker_.CalledOnValidThread());
1057 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1058 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1059 local_streams_.begin(); adapter_it != local_streams_.end();
1060 ++adapter_it) {
1061 if ((*adapter_it)->IsEqual(stream)) {
1062 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1063 << "stream twice. id=" << stream.id().utf8();
1064 return false;
1068 if (peer_connection_tracker_) {
1069 peer_connection_tracker_->TrackAddStream(
1070 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1073 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1075 WebRtcMediaStreamAdapter* adapter =
1076 new WebRtcMediaStreamAdapter(stream, dependency_factory_);
1077 local_streams_.push_back(adapter);
1079 webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
1080 track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
1081 webrtc_stream);
1083 RTCMediaConstraints constraints(options);
1084 if (!constraints.GetMandatory().empty() ||
1085 !constraints.GetOptional().empty()) {
1086 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1087 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1088 // should be removed from blink as well.
1089 LOG(WARNING)
1090 << "mediaConstraints is not a supported argument to addStream.";
1093 return native_peer_connection_->AddStream(webrtc_stream);
1096 void RTCPeerConnectionHandler::removeStream(
1097 const blink::WebMediaStream& stream) {
1098 DCHECK(thread_checker_.CalledOnValidThread());
1099 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1100 // Find the webrtc stream.
1101 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
1102 for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
1103 local_streams_.begin(); adapter_it != local_streams_.end();
1104 ++adapter_it) {
1105 if ((*adapter_it)->IsEqual(stream)) {
1106 webrtc_stream = (*adapter_it)->webrtc_media_stream();
1107 local_streams_.erase(adapter_it);
1108 break;
1111 DCHECK(webrtc_stream.get());
1112 // TODO(tommi): Make this async (PostTaskAndReply).
1113 native_peer_connection_->RemoveStream(webrtc_stream.get());
1115 if (peer_connection_tracker_) {
1116 peer_connection_tracker_->TrackRemoveStream(
1117 this, stream, PeerConnectionTracker::SOURCE_LOCAL);
1119 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1120 track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
1121 webrtc_stream.get());
1124 void RTCPeerConnectionHandler::getStats(
1125 const blink::WebRTCStatsRequest& request) {
1126 DCHECK(thread_checker_.CalledOnValidThread());
1127 scoped_refptr<LocalRTCStatsRequest> inner_request(
1128 new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
1129 getStats(inner_request);
1132 void RTCPeerConnectionHandler::getStats(
1133 const scoped_refptr<LocalRTCStatsRequest>& request) {
1134 DCHECK(thread_checker_.CalledOnValidThread());
1135 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1138 rtc::scoped_refptr<webrtc::StatsObserver> observer(
1139 new rtc::RefCountedObject<StatsResponse>(request));
1141 std::string track_id;
1142 blink::WebMediaStreamSource::Type track_type =
1143 blink::WebMediaStreamSource::TypeAudio;
1144 if (request->hasSelector()) {
1145 track_type = request->component().source().type();
1146 track_id = request->component().id().utf8();
1149 GetStats(observer, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard,
1150 track_id, track_type);
1153 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1154 void RTCPeerConnectionHandler::GetStats(
1155 webrtc::StatsObserver* observer,
1156 webrtc::PeerConnectionInterface::StatsOutputLevel level,
1157 const std::string& track_id,
1158 blink::WebMediaStreamSource::Type track_type) {
1159 DCHECK(thread_checker_.CalledOnValidThread());
1160 signaling_thread()->PostTask(FROM_HERE,
1161 base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level,
1162 make_scoped_refptr(observer), track_id, track_type));
1165 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1166 DCHECK(thread_checker_.CalledOnValidThread());
1167 if (client_)
1168 client_->closePeerConnection();
1171 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
1172 const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
1173 DCHECK(thread_checker_.CalledOnValidThread());
1174 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1175 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
1177 webrtc::DataChannelInit config;
1178 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1179 // to handle that.
1180 config.reliable = false;
1181 config.id = init.id;
1182 config.ordered = init.ordered;
1183 config.negotiated = init.negotiated;
1184 config.maxRetransmits = init.maxRetransmits;
1185 config.maxRetransmitTime = init.maxRetransmitTime;
1186 config.protocol = base::UTF16ToUTF8(init.protocol);
1188 rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
1189 native_peer_connection_->CreateDataChannel(base::UTF16ToUTF8(label),
1190 &config));
1191 if (!webrtc_channel) {
1192 DLOG(ERROR) << "Could not create native data channel.";
1193 return NULL;
1195 if (peer_connection_tracker_) {
1196 peer_connection_tracker_->TrackCreateDataChannel(
1197 this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
1200 ++num_data_channels_created_;
1202 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1203 webrtc_channel);
1206 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
1207 const blink::WebMediaStreamTrack& track) {
1208 DCHECK(thread_checker_.CalledOnValidThread());
1209 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1210 DVLOG(1) << "createDTMFSender.";
1212 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
1213 if (!native_track || !native_track->is_local_track() ||
1214 track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
1215 DLOG(ERROR) << "The DTMF sender requires a local audio track.";
1216 return nullptr;
1219 scoped_refptr<webrtc::AudioTrackInterface> audio_track =
1220 native_track->GetAudioAdapter();
1221 rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
1222 native_peer_connection_->CreateDtmfSender(audio_track.get()));
1223 if (!sender) {
1224 DLOG(ERROR) << "Could not create native DTMF sender.";
1225 return nullptr;
1227 if (peer_connection_tracker_)
1228 peer_connection_tracker_->TrackCreateDTMFSender(this, track);
1230 return new RtcDtmfSenderHandler(sender);
1233 void RTCPeerConnectionHandler::stop() {
1234 DCHECK(thread_checker_.CalledOnValidThread());
1235 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1237 if (!client_ || !native_peer_connection_.get())
1238 return; // Already stopped.
1240 if (peer_connection_tracker_)
1241 peer_connection_tracker_->TrackStop(this);
1243 native_peer_connection_->Close();
1245 // The client_ pointer is not considered valid after this point and no further
1246 // callbacks must be made.
1247 client_ = nullptr;
1250 void RTCPeerConnectionHandler::OnSignalingChange(
1251 webrtc::PeerConnectionInterface::SignalingState new_state) {
1252 DCHECK(thread_checker_.CalledOnValidThread());
1253 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1255 blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
1256 GetWebKitSignalingState(new_state);
1257 if (peer_connection_tracker_)
1258 peer_connection_tracker_->TrackSignalingStateChange(this, state);
1259 if (client_)
1260 client_->didChangeSignalingState(state);
1263 // Called any time the IceConnectionState changes
1264 void RTCPeerConnectionHandler::OnIceConnectionChange(
1265 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
1266 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1267 DCHECK(thread_checker_.CalledOnValidThread());
1268 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
1269 ice_connection_checking_start_ = base::TimeTicks::Now();
1270 } else if (new_state ==
1271 webrtc::PeerConnectionInterface::kIceConnectionConnected) {
1272 // If the state becomes connected, send the time needed for PC to become
1273 // connected from checking to UMA. UMA data will help to know how much
1274 // time needed for PC to connect with remote peer.
1275 UMA_HISTOGRAM_MEDIUM_TIMES(
1276 "WebRTC.PeerConnection.TimeToConnect",
1277 base::TimeTicks::Now() - ice_connection_checking_start_);
1280 track_metrics_.IceConnectionChange(new_state);
1281 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
1282 GetWebKitIceConnectionState(new_state);
1283 if (peer_connection_tracker_)
1284 peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
1285 if(client_)
1286 client_->didChangeICEConnectionState(state);
1289 // Called any time the IceGatheringState changes
1290 void RTCPeerConnectionHandler::OnIceGatheringChange(
1291 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
1292 DCHECK(thread_checker_.CalledOnValidThread());
1293 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1295 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
1296 // If ICE gathering is completed, generate a NULL ICE candidate,
1297 // to signal end of candidates.
1298 if (client_) {
1299 blink::WebRTCICECandidate null_candidate;
1300 client_->didGenerateICECandidate(null_candidate);
1303 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1304 num_local_candidates_ipv4_);
1306 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1307 num_local_candidates_ipv6_);
1308 } else if (new_state ==
1309 webrtc::PeerConnectionInterface::kIceGatheringGathering) {
1310 // ICE restarts will change gathering state back to "gathering",
1311 // reset the counter.
1312 num_local_candidates_ipv6_ = 0;
1313 num_local_candidates_ipv4_ = 0;
1316 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
1317 GetWebKitIceGatheringState(new_state);
1318 if (peer_connection_tracker_)
1319 peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
1320 if (client_)
1321 client_->didChangeICEGatheringState(state);
1324 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1325 DCHECK(thread_checker_.CalledOnValidThread());
1326 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1327 if (peer_connection_tracker_)
1328 peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
1329 if (client_)
1330 client_->negotiationNeeded();
1333 void RTCPeerConnectionHandler::OnAddStream(
1334 scoped_ptr<RemoteMediaStreamImpl> stream) {
1335 DCHECK(thread_checker_.CalledOnValidThread());
1336 DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
1337 remote_streams_.end());
1338 DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
1339 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1341 // Ownership is with remote_streams_ now.
1342 RemoteMediaStreamImpl* s = stream.release();
1343 remote_streams_.insert(
1344 std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
1345 s->webrtc_stream().get(), s));
1347 if (peer_connection_tracker_) {
1348 peer_connection_tracker_->TrackAddStream(
1349 this, s->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE);
1352 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1354 track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1355 s->webrtc_stream().get());
1356 if (client_)
1357 client_->didAddRemoteStream(s->webkit_stream());
1360 void RTCPeerConnectionHandler::OnRemoveStream(
1361 const scoped_refptr<webrtc::MediaStreamInterface>& stream) {
1362 DCHECK(thread_checker_.CalledOnValidThread());
1363 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1364 RemoteStreamMap::iterator it = remote_streams_.find(stream.get());
1365 if (it == remote_streams_.end()) {
1366 NOTREACHED() << "Stream not found";
1367 return;
1370 track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
1371 stream.get());
1372 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1374 scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
1375 const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
1376 DCHECK(!webkit_stream.isNull());
1377 remote_streams_.erase(it);
1379 if (peer_connection_tracker_) {
1380 peer_connection_tracker_->TrackRemoveStream(
1381 this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
1384 if (client_)
1385 client_->didRemoveRemoteStream(webkit_stream);
1388 void RTCPeerConnectionHandler::OnDataChannel(
1389 scoped_ptr<RtcDataChannelHandler> handler) {
1390 DCHECK(thread_checker_.CalledOnValidThread());
1391 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1393 if (peer_connection_tracker_) {
1394 peer_connection_tracker_->TrackCreateDataChannel(
1395 this, handler->channel().get(), PeerConnectionTracker::SOURCE_REMOTE);
1398 if (client_)
1399 client_->didAddRemoteDataChannel(handler.release());
1402 void RTCPeerConnectionHandler::OnIceCandidate(
1403 const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index,
1404 int component, int address_family) {
1405 DCHECK(thread_checker_.CalledOnValidThread());
1406 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1407 blink::WebRTCICECandidate web_candidate;
1408 web_candidate.initialize(base::UTF8ToUTF16(sdp),
1409 base::UTF8ToUTF16(sdp_mid),
1410 sdp_mline_index);
1411 if (peer_connection_tracker_) {
1412 peer_connection_tracker_->TrackAddIceCandidate(
1413 this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
1416 // Only the first m line's first component is tracked to avoid
1417 // miscounting when doing BUNDLE or rtcp mux.
1418 if (sdp_mline_index == 0 && component == 1) {
1419 if (address_family == AF_INET) {
1420 ++num_local_candidates_ipv4_;
1421 } else if (address_family == AF_INET6) {
1422 ++num_local_candidates_ipv6_;
1423 } else {
1424 NOTREACHED();
1427 if (client_)
1428 client_->didGenerateICECandidate(web_candidate);
1431 webrtc::SessionDescriptionInterface*
1432 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1433 const std::string& sdp, const std::string& type,
1434 webrtc::SdpParseError* error) {
1435 webrtc::SessionDescriptionInterface* native_desc =
1436 dependency_factory_->CreateSessionDescription(type, sdp, error);
1438 LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1439 << " Type: " << type << " SDP: " << sdp;
1441 return native_desc;
1444 scoped_refptr<base::SingleThreadTaskRunner>
1445 RTCPeerConnectionHandler::signaling_thread() const {
1446 DCHECK(thread_checker_.CalledOnValidThread());
1447 return dependency_factory_->GetWebRtcSignalingThread();
1450 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1451 const base::Closure& closure,
1452 const char* trace_event_name) {
1453 DCHECK(thread_checker_.CalledOnValidThread());
1454 scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
1455 if (!thread.get() || thread->BelongsToCurrentThread()) {
1456 TRACE_EVENT0("webrtc", trace_event_name);
1457 closure.Run();
1458 } else {
1459 base::WaitableEvent event(false, false);
1460 thread->PostTask(FROM_HERE,
1461 base::Bind(&RunSynchronousClosure, closure,
1462 base::Unretained(trace_event_name),
1463 base::Unretained(&event)));
1464 event.Wait();
1468 } // namespace content