Home | History | Annotate | Download | only in media
      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
     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
     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
     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
    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 
    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:
    168   SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler,
    169                                    PeerConnectionTracker::Action action)
    170       : handler_(handler), action_(action) {}
    171 
    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 
    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:
    199   explicit CreateSessionDescriptionRequest(
    200       const blink::WebRTCSessionDescriptionRequest& request,
    201       RTCPeerConnectionHandler* handler,
    202       PeerConnectionTracker::Action action)
    203       : webkit_request_(request), tracker_(handler, action) {}
    204 
    205   virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE {
    206     tracker_.TrackOnSuccess(desc);
    207     webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
    208     delete desc;
    209   }
    210   virtual void OnFailure(const std::string& error) OVERRIDE {
    211     tracker_.TrackOnFailure(error);
    212     webkit_request_.requestFailed(base::UTF8ToUTF16(error));
    213   }
    214 
    215  protected:
    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:
    228   explicit SetSessionDescriptionRequest(
    229       const blink::WebRTCVoidRequest& request,
    230       RTCPeerConnectionHandler* handler,
    231       PeerConnectionTracker::Action action)
    232       : webkit_request_(request), tracker_(handler, action) {}
    233 
    234   virtual void OnSuccess() OVERRIDE {
    235     tracker_.TrackOnSuccess(NULL);
    236     webkit_request_.requestSucceeded();
    237   }
    238   virtual void OnFailure(const std::string& error) OVERRIDE {
    239     tracker_.TrackOnFailure(error);
    240     webkit_request_.requestFailed(base::UTF8ToUTF16(error));
    241   }
    242 
    243  protected:
    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:
    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 
    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:
    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 
    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.
    300 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
    301     : impl_(impl),
    302       response_(NULL) {
    303 }
    304 
    305 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
    306 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
    307 
    308 bool LocalRTCStatsRequest::hasSelector() const {
    309   return impl_.hasSelector();
    310 }
    311 
    312 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
    313   return impl_.component();
    314 }
    315 
    316 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
    317   DCHECK(!response_);
    318   response_ = new rtc::RefCountedObject<LocalRTCStatsResponse>(
    319       impl_.createResponse());
    320   return response_.get();
    321 }
    322 
    323 void LocalRTCStatsRequest::requestSucceeded(
    324     const LocalRTCStatsResponse* response) {
    325   impl_.requestSucceeded(response->webKitStatsResponse());
    326 }
    327 
    328 // Implementation of LocalRTCStatsResponse.
    329 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
    330   return impl_;
    331 }
    332 
    333 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
    334                                         blink::WebString id,
    335                                         double timestamp) {
    336   return impl_.addReport(type, id, timestamp);
    337 }
    338 
    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:
    349   PeerConnectionUMAObserver() {}
    350   virtual ~PeerConnectionUMAObserver() {}
    351 
    352   virtual void IncrementCounter(
    353       webrtc::PeerConnectionUMAMetricsCounter counter) OVERRIDE {
    354     UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
    355                               counter,
    356                               webrtc::kBoundary);
    357   }
    358 
    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 
    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 
    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
    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 
    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 
    447 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
    448   DCHECK(frame);
    449   frame_ = frame;
    450 }
    451 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    787 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
    788   client_->closePeerConnection();
    789 }
    790 
    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 
    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 
    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 
    854 void RTCPeerConnectionHandler::OnError() {
    855   // TODO(perkj): Implement.
    856   NOTIMPLEMENTED();
    857 }
    858 
    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
    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
    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 
    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 
    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 
    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 
   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 
   1011 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
   1012   if (peer_connection_tracker_)
   1013     peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
   1014   client_->negotiationNeeded();
   1015 }
   1016 
   1017 PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
   1018   return peer_connection_tracker_;
   1019 }
   1020 
   1021 webrtc::SessionDescriptionInterface*
   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