• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/renderer/media/rtc_peer_connection_handler.h"
6 
7 #include <string>
8 #include <utility>
9 #include <vector>
10 
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/lazy_instance.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 "content/public/common/content_switches.h"
20 #include "content/renderer/media/media_stream_track.h"
21 #include "content/renderer/media/peer_connection_tracker.h"
22 #include "content/renderer/media/remote_media_stream_impl.h"
23 #include "content/renderer/media/rtc_data_channel_handler.h"
24 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
25 #include "content/renderer/media/rtc_media_constraints.h"
26 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
27 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
28 #include "content/renderer/media/webrtc_audio_capturer.h"
29 #include "content/renderer/media/webrtc_audio_device_impl.h"
30 #include "content/renderer/media/webrtc_uma_histograms.h"
31 #include "content/renderer/render_thread_impl.h"
32 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
33 #include "third_party/WebKit/public/platform/WebMediaStreamSource.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"
42 
43 using webrtc::StatsReport;
44 using webrtc::StatsReports;
45 
46 namespace content {
47 
48 // Converter functions from libjingle types to WebKit types.
49 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
GetWebKitIceGatheringState(webrtc::PeerConnectionInterface::IceGatheringState state)50 GetWebKitIceGatheringState(
51     webrtc::PeerConnectionInterface::IceGatheringState state) {
52   using blink::WebRTCPeerConnectionHandlerClient;
53   switch (state) {
54     case webrtc::PeerConnectionInterface::kIceGatheringNew:
55       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
56     case webrtc::PeerConnectionInterface::kIceGatheringGathering:
57       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering;
58     case webrtc::PeerConnectionInterface::kIceGatheringComplete:
59       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete;
60     default:
61       NOTREACHED();
62       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
63   }
64 }
65 
66 static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
GetWebKitIceConnectionState(webrtc::PeerConnectionInterface::IceConnectionState ice_state)67 GetWebKitIceConnectionState(
68     webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
69   using blink::WebRTCPeerConnectionHandlerClient;
70   switch (ice_state) {
71     case webrtc::PeerConnectionInterface::kIceConnectionNew:
72       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
73     case webrtc::PeerConnectionInterface::kIceConnectionChecking:
74       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking;
75     case webrtc::PeerConnectionInterface::kIceConnectionConnected:
76       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected;
77     case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
78       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted;
79     case webrtc::PeerConnectionInterface::kIceConnectionFailed:
80       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed;
81     case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
82       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected;
83     case webrtc::PeerConnectionInterface::kIceConnectionClosed:
84       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
85     default:
86       NOTREACHED();
87       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
88   }
89 }
90 
91 static blink::WebRTCPeerConnectionHandlerClient::SignalingState
GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state)92 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
93   using blink::WebRTCPeerConnectionHandlerClient;
94   switch (state) {
95     case webrtc::PeerConnectionInterface::kStable:
96       return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
97     case webrtc::PeerConnectionInterface::kHaveLocalOffer:
98       return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer;
99     case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
100       return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer;
101     case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
102       return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer;
103     case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
104       return
105           WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer;
106     case webrtc::PeerConnectionInterface::kClosed:
107       return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
108     default:
109       NOTREACHED();
110       return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
111   }
112 }
113 
114 static blink::WebRTCSessionDescription
CreateWebKitSessionDescription(const webrtc::SessionDescriptionInterface * native_desc)115 CreateWebKitSessionDescription(
116     const webrtc::SessionDescriptionInterface* native_desc) {
117   blink::WebRTCSessionDescription description;
118   if (!native_desc) {
119     LOG(ERROR) << "Native session description is null.";
120     return description;
121   }
122 
123   std::string sdp;
124   if (!native_desc->ToString(&sdp)) {
125     LOG(ERROR) << "Failed to get SDP string of native session description.";
126     return description;
127   }
128 
129   description.initialize(base::UTF8ToUTF16(native_desc->type()),
130                          base::UTF8ToUTF16(sdp));
131   return description;
132 }
133 
134 // Converter functions from WebKit types to libjingle types.
135 
GetNativeRtcConfiguration(const blink::WebRTCConfiguration & server_configuration,webrtc::PeerConnectionInterface::RTCConfiguration * config)136 static void GetNativeRtcConfiguration(
137     const blink::WebRTCConfiguration& server_configuration,
138     webrtc::PeerConnectionInterface::RTCConfiguration* config) {
139   if (server_configuration.isNull() || !config)
140     return;
141   for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) {
142     webrtc::PeerConnectionInterface::IceServer server;
143     const blink::WebRTCICEServer& webkit_server =
144         server_configuration.server(i);
145     server.username = base::UTF16ToUTF8(webkit_server.username());
146     server.password = base::UTF16ToUTF8(webkit_server.credential());
147     server.uri = webkit_server.uri().spec();
148     config->servers.push_back(server);
149   }
150 
151   switch (server_configuration.iceTransports()) {
152   case blink::WebRTCIceTransportsNone:
153     config->type = webrtc::PeerConnectionInterface::kNone;
154     break;
155   case blink::WebRTCIceTransportsRelay:
156     config->type = webrtc::PeerConnectionInterface::kRelay;
157     break;
158   case blink::WebRTCIceTransportsAll:
159     config->type = webrtc::PeerConnectionInterface::kAll;
160     break;
161   default:
162     NOTREACHED();
163   }
164 }
165 
166 class SessionDescriptionRequestTracker {
167  public:
SessionDescriptionRequestTracker(RTCPeerConnectionHandler * handler,PeerConnectionTracker::Action action)168   SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler,
169                                    PeerConnectionTracker::Action action)
170       : handler_(handler), action_(action) {}
171 
TrackOnSuccess(const webrtc::SessionDescriptionInterface * desc)172   void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
173     std::string value;
174     if (desc) {
175       desc->ToString(&value);
176       value = "type: " + desc->type() + ", sdp: " + value;
177     }
178     if (handler_->peer_connection_tracker())
179       handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
180           handler_, action_, "OnSuccess", value);
181   }
182 
TrackOnFailure(const std::string & error)183   void TrackOnFailure(const std::string& error) {
184     if (handler_->peer_connection_tracker())
185       handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
186           handler_, action_, "OnFailure", error);
187   }
188 
189  private:
190   RTCPeerConnectionHandler* handler_;
191   PeerConnectionTracker::Action action_;
192 };
193 
194 // Class mapping responses from calls to libjingle CreateOffer/Answer and
195 // the blink::WebRTCSessionDescriptionRequest.
196 class CreateSessionDescriptionRequest
197     : public webrtc::CreateSessionDescriptionObserver {
198  public:
CreateSessionDescriptionRequest(const blink::WebRTCSessionDescriptionRequest & request,RTCPeerConnectionHandler * handler,PeerConnectionTracker::Action action)199   explicit CreateSessionDescriptionRequest(
200       const blink::WebRTCSessionDescriptionRequest& request,
201       RTCPeerConnectionHandler* handler,
202       PeerConnectionTracker::Action action)
203       : webkit_request_(request), tracker_(handler, action) {}
204 
OnSuccess(webrtc::SessionDescriptionInterface * desc)205   virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE {
206     tracker_.TrackOnSuccess(desc);
207     webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
208     delete desc;
209   }
OnFailure(const std::string & error)210   virtual void OnFailure(const std::string& error) OVERRIDE {
211     tracker_.TrackOnFailure(error);
212     webkit_request_.requestFailed(base::UTF8ToUTF16(error));
213   }
214 
215  protected:
~CreateSessionDescriptionRequest()216   virtual ~CreateSessionDescriptionRequest() {}
217 
218  private:
219   blink::WebRTCSessionDescriptionRequest webkit_request_;
220   SessionDescriptionRequestTracker tracker_;
221 };
222 
223 // Class mapping responses from calls to libjingle
224 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
225 class SetSessionDescriptionRequest
226     : public webrtc::SetSessionDescriptionObserver {
227  public:
SetSessionDescriptionRequest(const blink::WebRTCVoidRequest & request,RTCPeerConnectionHandler * handler,PeerConnectionTracker::Action action)228   explicit SetSessionDescriptionRequest(
229       const blink::WebRTCVoidRequest& request,
230       RTCPeerConnectionHandler* handler,
231       PeerConnectionTracker::Action action)
232       : webkit_request_(request), tracker_(handler, action) {}
233 
OnSuccess()234   virtual void OnSuccess() OVERRIDE {
235     tracker_.TrackOnSuccess(NULL);
236     webkit_request_.requestSucceeded();
237   }
OnFailure(const std::string & error)238   virtual void OnFailure(const std::string& error) OVERRIDE {
239     tracker_.TrackOnFailure(error);
240     webkit_request_.requestFailed(base::UTF8ToUTF16(error));
241   }
242 
243  protected:
~SetSessionDescriptionRequest()244   virtual ~SetSessionDescriptionRequest() {}
245 
246  private:
247   blink::WebRTCVoidRequest webkit_request_;
248   SessionDescriptionRequestTracker tracker_;
249 };
250 
251 // Class mapping responses from calls to libjingle
252 // GetStats into a blink::WebRTCStatsCallback.
253 class StatsResponse : public webrtc::StatsObserver {
254  public:
StatsResponse(const scoped_refptr<LocalRTCStatsRequest> & request)255   explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
256       : request_(request.get()), response_(request_->createResponse().get()) {
257     // Measure the overall time it takes to satisfy a getStats request.
258     TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
259   }
260 
OnComplete(const StatsReports & reports)261   virtual void OnComplete(const StatsReports& reports) OVERRIDE {
262     TRACE_EVENT0("webrtc", "StatsResponse::OnComplete")
263     for (StatsReports::const_iterator it = reports.begin();
264          it != reports.end(); ++it) {
265       if ((*it)->values.size() > 0) {
266         AddReport(*(*it));
267       }
268     }
269 
270     // Record the getSync operation as done before calling into Blink so that
271     // we don't skew the perf measurements of the native code with whatever the
272     // callback might be doing.
273     TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
274 
275     request_->requestSucceeded(response_);
276   }
277 
278  private:
AddReport(const StatsReport & report)279   void AddReport(const StatsReport& report) {
280     int idx = response_->addReport(blink::WebString::fromUTF8(report.id),
281                                    blink::WebString::fromUTF8(report.type),
282                                    report.timestamp);
283     for (StatsReport::Values::const_iterator value_it = report.values.begin();
284          value_it != report.values.end(); ++value_it) {
285       AddStatistic(idx, value_it->display_name(), value_it->value);
286     }
287   }
288 
AddStatistic(int idx,const char * name,const std::string & value)289   void AddStatistic(int idx, const char* name, const std::string& value) {
290     response_->addStatistic(idx,
291                             blink::WebString::fromUTF8(name),
292                             blink::WebString::fromUTF8(value));
293   }
294 
295   rtc::scoped_refptr<LocalRTCStatsRequest> request_;
296   rtc::scoped_refptr<LocalRTCStatsResponse> response_;
297 };
298 
299 // Implementation of LocalRTCStatsRequest.
LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)300 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
301     : impl_(impl),
302       response_(NULL) {
303 }
304 
LocalRTCStatsRequest()305 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
~LocalRTCStatsRequest()306 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
307 
hasSelector() const308 bool LocalRTCStatsRequest::hasSelector() const {
309   return impl_.hasSelector();
310 }
311 
component() const312 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
313   return impl_.component();
314 }
315 
createResponse()316 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
317   DCHECK(!response_);
318   response_ = new rtc::RefCountedObject<LocalRTCStatsResponse>(
319       impl_.createResponse());
320   return response_.get();
321 }
322 
requestSucceeded(const LocalRTCStatsResponse * response)323 void LocalRTCStatsRequest::requestSucceeded(
324     const LocalRTCStatsResponse* response) {
325   impl_.requestSucceeded(response->webKitStatsResponse());
326 }
327 
328 // Implementation of LocalRTCStatsResponse.
webKitStatsResponse() const329 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
330   return impl_;
331 }
332 
addReport(blink::WebString type,blink::WebString id,double timestamp)333 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
334                                         blink::WebString id,
335                                         double timestamp) {
336   return impl_.addReport(type, id, timestamp);
337 }
338 
addStatistic(size_t report,blink::WebString name,blink::WebString value)339 void LocalRTCStatsResponse::addStatistic(size_t report,
340                                          blink::WebString name,
341                                          blink::WebString value) {
342   impl_.addStatistic(report, name, value);
343 }
344 
345 namespace {
346 
347 class PeerConnectionUMAObserver : public webrtc::UMAObserver {
348  public:
PeerConnectionUMAObserver()349   PeerConnectionUMAObserver() {}
~PeerConnectionUMAObserver()350   virtual ~PeerConnectionUMAObserver() {}
351 
IncrementCounter(webrtc::PeerConnectionUMAMetricsCounter counter)352   virtual void IncrementCounter(
353       webrtc::PeerConnectionUMAMetricsCounter counter) OVERRIDE {
354     UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
355                               counter,
356                               webrtc::kBoundary);
357   }
358 
AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,int value)359   virtual void AddHistogramSample(
360       webrtc::PeerConnectionUMAMetricsName type, int value) OVERRIDE {
361     switch (type) {
362       case webrtc::kTimeToConnect:
363         UMA_HISTOGRAM_MEDIUM_TIMES(
364             "WebRTC.PeerConnection.TimeToConnect",
365             base::TimeDelta::FromMilliseconds(value));
366         break;
367       case webrtc::kNetworkInterfaces_IPv4:
368         UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
369                                  value);
370         break;
371       case webrtc::kNetworkInterfaces_IPv6:
372         UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
373                                  value);
374         break;
375       default:
376         NOTREACHED();
377     }
378   }
379 };
380 
381 base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
382     g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
383 
384 }  // namespace
385 
RTCPeerConnectionHandler(blink::WebRTCPeerConnectionHandlerClient * client,PeerConnectionDependencyFactory * dependency_factory)386 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
387     blink::WebRTCPeerConnectionHandlerClient* client,
388     PeerConnectionDependencyFactory* dependency_factory)
389     : client_(client),
390       dependency_factory_(dependency_factory),
391       frame_(NULL),
392       peer_connection_tracker_(NULL),
393       num_data_channels_created_(0),
394       num_local_candidates_ipv4_(0),
395       num_local_candidates_ipv6_(0) {
396   g_peer_connection_handlers.Get().insert(this);
397 }
398 
~RTCPeerConnectionHandler()399 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
400   g_peer_connection_handlers.Get().erase(this);
401   if (peer_connection_tracker_)
402     peer_connection_tracker_->UnregisterPeerConnection(this);
403   STLDeleteValues(&remote_streams_);
404 
405   UMA_HISTOGRAM_COUNTS_10000(
406       "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_);
407 }
408 
409 // static
DestructAllHandlers()410 void RTCPeerConnectionHandler::DestructAllHandlers() {
411   std::set<RTCPeerConnectionHandler*> handlers(
412       g_peer_connection_handlers.Get().begin(),
413       g_peer_connection_handlers.Get().end());
414   for (std::set<RTCPeerConnectionHandler*>::iterator handler = handlers.begin();
415        handler != handlers.end();
416        ++handler) {
417     (*handler)->client_->releasePeerConnectionHandler();
418   }
419 }
420 
ConvertOfferOptionsToConstraints(const blink::WebRTCOfferOptions & options,RTCMediaConstraints * output)421 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
422     const blink::WebRTCOfferOptions& options,
423     RTCMediaConstraints* output) {
424   output->AddMandatory(
425       webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
426       options.offerToReceiveAudio() > 0 ? "true" : "false",
427       true);
428 
429   output->AddMandatory(
430       webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
431       options.offerToReceiveVideo() > 0 ? "true" : "false",
432       true);
433 
434   if (!options.voiceActivityDetection()) {
435     output->AddMandatory(
436         webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
437         "false",
438         true);
439   }
440 
441   if (options.iceRestart()) {
442     output->AddMandatory(
443         webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
444   }
445 }
446 
associateWithFrame(blink::WebFrame * frame)447 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
448   DCHECK(frame);
449   frame_ = frame;
450 }
451 
initialize(const blink::WebRTCConfiguration & server_configuration,const blink::WebMediaConstraints & options)452 bool RTCPeerConnectionHandler::initialize(
453     const blink::WebRTCConfiguration& server_configuration,
454     const blink::WebMediaConstraints& options) {
455   DCHECK(frame_);
456 
457   peer_connection_tracker_ =
458       RenderThreadImpl::current()->peer_connection_tracker();
459 
460   webrtc::PeerConnectionInterface::RTCConfiguration config;
461   GetNativeRtcConfiguration(server_configuration, &config);
462 
463   RTCMediaConstraints constraints(options);
464 
465   native_peer_connection_ =
466       dependency_factory_->CreatePeerConnection(
467           config, &constraints, frame_, this);
468 
469   if (!native_peer_connection_.get()) {
470     LOG(ERROR) << "Failed to initialize native PeerConnection.";
471     return false;
472   }
473   if (peer_connection_tracker_)
474     peer_connection_tracker_->RegisterPeerConnection(
475         this, config, constraints, frame_);
476 
477   uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
478   native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
479   return true;
480 }
481 
InitializeForTest(const blink::WebRTCConfiguration & server_configuration,const blink::WebMediaConstraints & options,PeerConnectionTracker * peer_connection_tracker)482 bool RTCPeerConnectionHandler::InitializeForTest(
483     const blink::WebRTCConfiguration& server_configuration,
484     const blink::WebMediaConstraints& options,
485     PeerConnectionTracker* peer_connection_tracker) {
486   webrtc::PeerConnectionInterface::RTCConfiguration config;
487   GetNativeRtcConfiguration(server_configuration, &config);
488 
489   RTCMediaConstraints constraints(options);
490   native_peer_connection_ =
491       dependency_factory_->CreatePeerConnection(
492           config, &constraints, NULL, this);
493   if (!native_peer_connection_.get()) {
494     LOG(ERROR) << "Failed to initialize native PeerConnection.";
495     return false;
496   }
497   peer_connection_tracker_ = peer_connection_tracker;
498   return true;
499 }
500 
createOffer(const blink::WebRTCSessionDescriptionRequest & request,const blink::WebMediaConstraints & options)501 void RTCPeerConnectionHandler::createOffer(
502     const blink::WebRTCSessionDescriptionRequest& request,
503     const blink::WebMediaConstraints& options) {
504   scoped_refptr<CreateSessionDescriptionRequest> description_request(
505       new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
506           request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
507   RTCMediaConstraints constraints(options);
508   native_peer_connection_->CreateOffer(description_request.get(), &constraints);
509 
510   if (peer_connection_tracker_)
511     peer_connection_tracker_->TrackCreateOffer(this, constraints);
512 }
513 
createOffer(const blink::WebRTCSessionDescriptionRequest & request,const blink::WebRTCOfferOptions & options)514 void RTCPeerConnectionHandler::createOffer(
515     const blink::WebRTCSessionDescriptionRequest& request,
516     const blink::WebRTCOfferOptions& options) {
517   scoped_refptr<CreateSessionDescriptionRequest> description_request(
518       new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
519           request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
520 
521   RTCMediaConstraints constraints;
522   ConvertOfferOptionsToConstraints(options, &constraints);
523   native_peer_connection_->CreateOffer(description_request.get(), &constraints);
524 
525   if (peer_connection_tracker_)
526     peer_connection_tracker_->TrackCreateOffer(this, constraints);
527 }
528 
createAnswer(const blink::WebRTCSessionDescriptionRequest & request,const blink::WebMediaConstraints & options)529 void RTCPeerConnectionHandler::createAnswer(
530     const blink::WebRTCSessionDescriptionRequest& request,
531     const blink::WebMediaConstraints& options) {
532   scoped_refptr<CreateSessionDescriptionRequest> description_request(
533       new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
534           request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER));
535   RTCMediaConstraints constraints(options);
536   native_peer_connection_->CreateAnswer(description_request.get(),
537                                         &constraints);
538 
539   if (peer_connection_tracker_)
540     peer_connection_tracker_->TrackCreateAnswer(this, constraints);
541 }
542 
setLocalDescription(const blink::WebRTCVoidRequest & request,const blink::WebRTCSessionDescription & description)543 void RTCPeerConnectionHandler::setLocalDescription(
544     const blink::WebRTCVoidRequest& request,
545     const blink::WebRTCSessionDescription& description) {
546   webrtc::SdpParseError error;
547   webrtc::SessionDescriptionInterface* native_desc =
548       CreateNativeSessionDescription(description, &error);
549   if (!native_desc) {
550     std::string reason_str = "Failed to parse SessionDescription. ";
551     reason_str.append(error.line);
552     reason_str.append(" ");
553     reason_str.append(error.description);
554     LOG(ERROR) << reason_str;
555     request.requestFailed(blink::WebString::fromUTF8(reason_str));
556     return;
557   }
558   if (peer_connection_tracker_)
559     peer_connection_tracker_->TrackSetSessionDescription(
560         this, description, PeerConnectionTracker::SOURCE_LOCAL);
561 
562   scoped_refptr<SetSessionDescriptionRequest> set_request(
563       new rtc::RefCountedObject<SetSessionDescriptionRequest>(
564           request, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
565   native_peer_connection_->SetLocalDescription(set_request.get(), native_desc);
566 }
567 
setRemoteDescription(const blink::WebRTCVoidRequest & request,const blink::WebRTCSessionDescription & description)568 void RTCPeerConnectionHandler::setRemoteDescription(
569     const blink::WebRTCVoidRequest& request,
570     const blink::WebRTCSessionDescription& description) {
571   webrtc::SdpParseError error;
572   webrtc::SessionDescriptionInterface* native_desc =
573       CreateNativeSessionDescription(description, &error);
574   if (!native_desc) {
575     std::string reason_str = "Failed to parse SessionDescription. ";
576     reason_str.append(error.line);
577     reason_str.append(" ");
578     reason_str.append(error.description);
579     LOG(ERROR) << reason_str;
580     request.requestFailed(blink::WebString::fromUTF8(reason_str));
581     return;
582   }
583   if (peer_connection_tracker_)
584     peer_connection_tracker_->TrackSetSessionDescription(
585         this, description, PeerConnectionTracker::SOURCE_REMOTE);
586 
587   scoped_refptr<SetSessionDescriptionRequest> set_request(
588       new rtc::RefCountedObject<SetSessionDescriptionRequest>(
589           request, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
590   native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc);
591 }
592 
593 blink::WebRTCSessionDescription
localDescription()594 RTCPeerConnectionHandler::localDescription() {
595   const webrtc::SessionDescriptionInterface* native_desc =
596       native_peer_connection_->local_description();
597   blink::WebRTCSessionDescription description =
598       CreateWebKitSessionDescription(native_desc);
599   return description;
600 }
601 
602 blink::WebRTCSessionDescription
remoteDescription()603 RTCPeerConnectionHandler::remoteDescription() {
604   const webrtc::SessionDescriptionInterface* native_desc =
605       native_peer_connection_->remote_description();
606   blink::WebRTCSessionDescription description =
607       CreateWebKitSessionDescription(native_desc);
608   return description;
609 }
610 
updateICE(const blink::WebRTCConfiguration & server_configuration,const blink::WebMediaConstraints & options)611 bool RTCPeerConnectionHandler::updateICE(
612     const blink::WebRTCConfiguration& server_configuration,
613     const blink::WebMediaConstraints& options) {
614   webrtc::PeerConnectionInterface::RTCConfiguration config;
615   GetNativeRtcConfiguration(server_configuration, &config);
616   RTCMediaConstraints constraints(options);
617 
618   if (peer_connection_tracker_)
619     peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
620 
621   return native_peer_connection_->UpdateIce(config.servers,
622                                             &constraints);
623 }
624 
addICECandidate(const blink::WebRTCVoidRequest & request,const blink::WebRTCICECandidate & candidate)625 bool RTCPeerConnectionHandler::addICECandidate(
626   const blink::WebRTCVoidRequest& request,
627   const blink::WebRTCICECandidate& candidate) {
628   // Libjingle currently does not accept callbacks for addICECandidate.
629   // For that reason we are going to call callbacks from here.
630   bool result = addICECandidate(candidate);
631   base::MessageLoop::current()->PostTask(
632       FROM_HERE,
633       base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
634                  base::Unretained(this), request, result));
635   // On failure callback will be triggered.
636   return true;
637 }
638 
addICECandidate(const blink::WebRTCICECandidate & candidate)639 bool RTCPeerConnectionHandler::addICECandidate(
640     const blink::WebRTCICECandidate& candidate) {
641   scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
642       dependency_factory_->CreateIceCandidate(
643           base::UTF16ToUTF8(candidate.sdpMid()),
644           candidate.sdpMLineIndex(),
645           base::UTF16ToUTF8(candidate.candidate())));
646   bool return_value = false;
647 
648   if (native_candidate) {
649     return_value =
650         native_peer_connection_->AddIceCandidate(native_candidate.get());
651     LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
652   } else {
653     LOG(ERROR) << "Could not create native ICE candidate.";
654   }
655 
656   if (peer_connection_tracker_) {
657     peer_connection_tracker_->TrackAddIceCandidate(
658         this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
659   }
660   return return_value;
661 }
662 
OnaddICECandidateResult(const blink::WebRTCVoidRequest & webkit_request,bool result)663 void RTCPeerConnectionHandler::OnaddICECandidateResult(
664     const blink::WebRTCVoidRequest& webkit_request, bool result) {
665   if (!result) {
666     // We don't have the actual error code from the libjingle, so for now
667     // using a generic error string.
668     return webkit_request.requestFailed(
669         base::UTF8ToUTF16("Error processing ICE candidate"));
670   }
671 
672   return webkit_request.requestSucceeded();
673 }
674 
addStream(const blink::WebMediaStream & stream,const blink::WebMediaConstraints & options)675 bool RTCPeerConnectionHandler::addStream(
676     const blink::WebMediaStream& stream,
677     const blink::WebMediaConstraints& options) {
678 
679   for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
680       local_streams_.begin(); adapter_it != local_streams_.end();
681       ++adapter_it) {
682     if ((*adapter_it)->IsEqual(stream)) {
683       DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
684                << "stream twice. id=" << stream.id().utf8();
685       return false;
686     }
687   }
688 
689   if (peer_connection_tracker_)
690     peer_connection_tracker_->TrackAddStream(
691         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
692 
693   PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
694 
695   WebRtcMediaStreamAdapter* adapter =
696       new WebRtcMediaStreamAdapter(stream, dependency_factory_);
697   local_streams_.push_back(adapter);
698 
699   webrtc::MediaStreamInterface* webrtc_stream = adapter->webrtc_media_stream();
700   track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
701                            webrtc_stream);
702 
703   RTCMediaConstraints constraints(options);
704   return native_peer_connection_->AddStream(webrtc_stream, &constraints);
705 }
706 
removeStream(const blink::WebMediaStream & stream)707 void RTCPeerConnectionHandler::removeStream(
708     const blink::WebMediaStream& stream) {
709   // Find the webrtc stream.
710   scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
711   for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
712            local_streams_.begin(); adapter_it != local_streams_.end();
713        ++adapter_it) {
714     if ((*adapter_it)->IsEqual(stream)) {
715       webrtc_stream = (*adapter_it)->webrtc_media_stream();
716       local_streams_.erase(adapter_it);
717       break;
718     }
719   }
720   DCHECK(webrtc_stream.get());
721   native_peer_connection_->RemoveStream(webrtc_stream.get());
722 
723   if (peer_connection_tracker_)
724     peer_connection_tracker_->TrackRemoveStream(
725         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
726   PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
727   track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
728                               webrtc_stream.get());
729 }
730 
getStats(const blink::WebRTCStatsRequest & request)731 void RTCPeerConnectionHandler::getStats(
732     const blink::WebRTCStatsRequest& request) {
733   scoped_refptr<LocalRTCStatsRequest> inner_request(
734       new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
735   getStats(inner_request.get());
736 }
737 
getStats(LocalRTCStatsRequest * request)738 void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
739   rtc::scoped_refptr<webrtc::StatsObserver> observer(
740       new rtc::RefCountedObject<StatsResponse>(request));
741   webrtc::MediaStreamTrackInterface* track = NULL;
742   if (request->hasSelector()) {
743     blink::WebMediaStreamSource::Type type =
744         request->component().source().type();
745     std::string track_id = request->component().id().utf8();
746     if (type == blink::WebMediaStreamSource::TypeAudio) {
747       track =
748           native_peer_connection_->local_streams()->FindAudioTrack(track_id);
749       if (!track) {
750         track =
751             native_peer_connection_->remote_streams()->FindAudioTrack(track_id);
752       }
753     } else {
754       DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, type);
755       track =
756           native_peer_connection_->local_streams()->FindVideoTrack(track_id);
757       if (!track) {
758         track =
759             native_peer_connection_->remote_streams()->FindVideoTrack(track_id);
760       }
761     }
762     if (!track) {
763       DVLOG(1) << "GetStats: Track not found.";
764       // TODO(hta): Consider how to get an error back.
765       observer->OnComplete(StatsReports());
766       return;
767     }
768   }
769   GetStats(observer,
770            track,
771            webrtc::PeerConnectionInterface::kStatsOutputLevelStandard);
772 }
773 
GetStats(webrtc::StatsObserver * observer,webrtc::MediaStreamTrackInterface * track,webrtc::PeerConnectionInterface::StatsOutputLevel level)774 void RTCPeerConnectionHandler::GetStats(
775     webrtc::StatsObserver* observer,
776     webrtc::MediaStreamTrackInterface* track,
777     webrtc::PeerConnectionInterface::StatsOutputLevel level) {
778   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::GetStats");
779   if (!native_peer_connection_->GetStats(observer, track, level)) {
780     DVLOG(1) << "GetStats failed.";
781     // TODO(hta): Consider how to get an error back.
782     observer->OnComplete(StatsReports());
783     return;
784   }
785 }
786 
CloseClientPeerConnection()787 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
788   client_->closePeerConnection();
789 }
790 
createDataChannel(const blink::WebString & label,const blink::WebRTCDataChannelInit & init)791 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
792     const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
793   DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
794 
795   webrtc::DataChannelInit config;
796   // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
797   // to handle that.
798   config.reliable = false;
799   config.id = init.id;
800   config.ordered = init.ordered;
801   config.negotiated = init.negotiated;
802   config.maxRetransmits = init.maxRetransmits;
803   config.maxRetransmitTime = init.maxRetransmitTime;
804   config.protocol = base::UTF16ToUTF8(init.protocol);
805 
806   rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
807       native_peer_connection_->CreateDataChannel(base::UTF16ToUTF8(label),
808                                                  &config));
809   if (!webrtc_channel) {
810     DLOG(ERROR) << "Could not create native data channel.";
811     return NULL;
812   }
813   if (peer_connection_tracker_)
814     peer_connection_tracker_->TrackCreateDataChannel(
815         this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
816 
817   ++num_data_channels_created_;
818 
819   return new RtcDataChannelHandler(webrtc_channel);
820 }
821 
createDTMFSender(const blink::WebMediaStreamTrack & track)822 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
823     const blink::WebMediaStreamTrack& track) {
824   DVLOG(1) << "createDTMFSender.";
825 
826   MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
827   if (!native_track ||
828       track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
829     DLOG(ERROR) << "Could not create DTMF sender from a non-audio track.";
830     return NULL;
831   }
832 
833   webrtc::AudioTrackInterface* audio_track = native_track->GetAudioAdapter();
834   rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
835       native_peer_connection_->CreateDtmfSender(audio_track));
836   if (!sender) {
837     DLOG(ERROR) << "Could not create native DTMF sender.";
838     return NULL;
839   }
840   if (peer_connection_tracker_)
841     peer_connection_tracker_->TrackCreateDTMFSender(this, track);
842 
843   return new RtcDtmfSenderHandler(sender);
844 }
845 
stop()846 void RTCPeerConnectionHandler::stop() {
847   DVLOG(1) << "RTCPeerConnectionHandler::stop";
848 
849   if (peer_connection_tracker_)
850     peer_connection_tracker_->TrackStop(this);
851   native_peer_connection_->Close();
852 }
853 
OnError()854 void RTCPeerConnectionHandler::OnError() {
855   // TODO(perkj): Implement.
856   NOTIMPLEMENTED();
857 }
858 
OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state)859 void RTCPeerConnectionHandler::OnSignalingChange(
860     webrtc::PeerConnectionInterface::SignalingState new_state) {
861   blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
862       GetWebKitSignalingState(new_state);
863   if (peer_connection_tracker_)
864     peer_connection_tracker_->TrackSignalingStateChange(this, state);
865   client_->didChangeSignalingState(state);
866 }
867 
868 // Called any time the IceConnectionState changes
OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state)869 void RTCPeerConnectionHandler::OnIceConnectionChange(
870     webrtc::PeerConnectionInterface::IceConnectionState new_state) {
871   if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
872     ice_connection_checking_start_ = base::TimeTicks::Now();
873   } else if (new_state ==
874       webrtc::PeerConnectionInterface::kIceConnectionConnected) {
875     // If the state becomes connected, send the time needed for PC to become
876     // connected from checking to UMA. UMA data will help to know how much
877     // time needed for PC to connect with remote peer.
878     UMA_HISTOGRAM_MEDIUM_TIMES(
879         "WebRTC.PeerConnection.TimeToConnect",
880         base::TimeTicks::Now() - ice_connection_checking_start_);
881   }
882 
883   track_metrics_.IceConnectionChange(new_state);
884   blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
885       GetWebKitIceConnectionState(new_state);
886   if (peer_connection_tracker_)
887     peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
888   client_->didChangeICEConnectionState(state);
889 }
890 
891 // Called any time the IceGatheringState changes
OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state)892 void RTCPeerConnectionHandler::OnIceGatheringChange(
893     webrtc::PeerConnectionInterface::IceGatheringState new_state) {
894   if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
895     // If ICE gathering is completed, generate a NULL ICE candidate,
896     // to signal end of candidates.
897     blink::WebRTCICECandidate null_candidate;
898     client_->didGenerateICECandidate(null_candidate);
899 
900     UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
901                              num_local_candidates_ipv4_);
902 
903     UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
904                              num_local_candidates_ipv6_);
905   } else if (new_state ==
906              webrtc::PeerConnectionInterface::kIceGatheringGathering) {
907     // ICE restarts will change gathering state back to "gathering",
908     // reset the counter.
909     num_local_candidates_ipv6_ = 0;
910     num_local_candidates_ipv4_ = 0;
911   }
912 
913   blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
914       GetWebKitIceGatheringState(new_state);
915   if (peer_connection_tracker_)
916     peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
917   client_->didChangeICEGatheringState(state);
918 }
919 
OnAddStream(webrtc::MediaStreamInterface * stream_interface)920 void RTCPeerConnectionHandler::OnAddStream(
921     webrtc::MediaStreamInterface* stream_interface) {
922   DCHECK(stream_interface);
923   DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
924 
925   RemoteMediaStreamImpl* remote_stream =
926       new RemoteMediaStreamImpl(stream_interface);
927   remote_streams_.insert(
928       std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
929           stream_interface, remote_stream));
930 
931   if (peer_connection_tracker_)
932     peer_connection_tracker_->TrackAddStream(
933         this, remote_stream->webkit_stream(),
934         PeerConnectionTracker::SOURCE_REMOTE);
935 
936   PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
937 
938   track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
939                            stream_interface);
940 
941   client_->didAddRemoteStream(remote_stream->webkit_stream());
942 }
943 
OnRemoveStream(webrtc::MediaStreamInterface * stream_interface)944 void RTCPeerConnectionHandler::OnRemoveStream(
945     webrtc::MediaStreamInterface* stream_interface) {
946   DCHECK(stream_interface);
947   RemoteStreamMap::iterator it = remote_streams_.find(stream_interface);
948   if (it == remote_streams_.end()) {
949     NOTREACHED() << "Stream not found";
950     return;
951   }
952 
953   track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
954                               stream_interface);
955   PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
956 
957   scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
958   const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
959   DCHECK(!webkit_stream.isNull());
960   remote_streams_.erase(it);
961 
962   if (peer_connection_tracker_)
963     peer_connection_tracker_->TrackRemoveStream(
964         this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
965 
966   client_->didRemoveRemoteStream(webkit_stream);
967 }
968 
OnIceCandidate(const webrtc::IceCandidateInterface * candidate)969 void RTCPeerConnectionHandler::OnIceCandidate(
970     const webrtc::IceCandidateInterface* candidate) {
971   DCHECK(candidate);
972   std::string sdp;
973   if (!candidate->ToString(&sdp)) {
974     NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
975     return;
976   }
977   blink::WebRTCICECandidate web_candidate;
978   web_candidate.initialize(base::UTF8ToUTF16(sdp),
979                            base::UTF8ToUTF16(candidate->sdp_mid()),
980                            candidate->sdp_mline_index());
981   if (peer_connection_tracker_)
982     peer_connection_tracker_->TrackAddIceCandidate(
983         this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
984 
985   // Only the first m line's first component is tracked to avoid
986   // miscounting when doing BUNDLE or rtcp mux.
987   if (candidate->sdp_mline_index() == 0 &&
988       candidate->candidate().component() == 1) {
989     if (candidate->candidate().address().family() == AF_INET) {
990       num_local_candidates_ipv4_++;
991     } else if (candidate->candidate().address().family() == AF_INET6) {
992       num_local_candidates_ipv6_++;
993     } else {
994       NOTREACHED();
995     }
996   }
997   client_->didGenerateICECandidate(web_candidate);
998 }
999 
OnDataChannel(webrtc::DataChannelInterface * data_channel)1000 void RTCPeerConnectionHandler::OnDataChannel(
1001     webrtc::DataChannelInterface* data_channel) {
1002   if (peer_connection_tracker_)
1003     peer_connection_tracker_->TrackCreateDataChannel(
1004         this, data_channel, PeerConnectionTracker::SOURCE_REMOTE);
1005 
1006   DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
1007            << data_channel->label();
1008   client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel));
1009 }
1010 
OnRenegotiationNeeded()1011 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1012   if (peer_connection_tracker_)
1013     peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
1014   client_->negotiationNeeded();
1015 }
1016 
peer_connection_tracker()1017 PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
1018   return peer_connection_tracker_;
1019 }
1020 
1021 webrtc::SessionDescriptionInterface*
CreateNativeSessionDescription(const blink::WebRTCSessionDescription & description,webrtc::SdpParseError * error)1022 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1023     const blink::WebRTCSessionDescription& description,
1024     webrtc::SdpParseError* error) {
1025   std::string sdp = base::UTF16ToUTF8(description.sdp());
1026   std::string type = base::UTF16ToUTF8(description.type());
1027   webrtc::SessionDescriptionInterface* native_desc =
1028       dependency_factory_->CreateSessionDescription(type, sdp, error);
1029 
1030   LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
1031                               << " Type: " << type << " SDP: " << sdp;
1032 
1033   return native_desc;
1034 }
1035 
1036 }  // namespace content
1037