• 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