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/logging.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/stl_util.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "content/public/common/content_switches.h"
     17 #include "content/renderer/media/media_stream_dependency_factory.h"
     18 #include "content/renderer/media/peer_connection_tracker.h"
     19 #include "content/renderer/media/remote_media_stream_impl.h"
     20 #include "content/renderer/media/rtc_data_channel_handler.h"
     21 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
     22 #include "content/renderer/media/rtc_media_constraints.h"
     23 #include "content/renderer/media/webrtc_audio_capturer.h"
     24 #include "content/renderer/media/webrtc_audio_device_impl.h"
     25 #include "content/renderer/render_thread_impl.h"
     26 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
     27 // TODO(hta): Move the following include to WebRTCStatsRequest.h file.
     28 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
     29 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
     30 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
     31 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
     32 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
     33 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
     34 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
     35 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
     36 #include "third_party/WebKit/public/platform/WebRTCStatsRequest.h"
     37 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
     38 #include "third_party/WebKit/public/platform/WebURL.h"
     39 #include "third_party/WebKit/public/web/WebFrame.h"
     40 
     41 namespace content {
     42 
     43 // Converter functions from libjingle types to WebKit types.
     44 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
     45 GetWebKitIceGatheringState(
     46     webrtc::PeerConnectionInterface::IceGatheringState state) {
     47   using blink::WebRTCPeerConnectionHandlerClient;
     48   switch (state) {
     49     case webrtc::PeerConnectionInterface::kIceGatheringNew:
     50       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
     51     case webrtc::PeerConnectionInterface::kIceGatheringGathering:
     52       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering;
     53     case webrtc::PeerConnectionInterface::kIceGatheringComplete:
     54       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete;
     55     default:
     56       NOTREACHED();
     57       return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
     58   }
     59 }
     60 
     61 static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
     62 GetWebKitIceConnectionState(
     63     webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
     64   using blink::WebRTCPeerConnectionHandlerClient;
     65   switch (ice_state) {
     66     case webrtc::PeerConnectionInterface::kIceConnectionNew:
     67       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
     68     case webrtc::PeerConnectionInterface::kIceConnectionChecking:
     69       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking;
     70     case webrtc::PeerConnectionInterface::kIceConnectionConnected:
     71       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected;
     72     case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
     73       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted;
     74     case webrtc::PeerConnectionInterface::kIceConnectionFailed:
     75       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed;
     76     case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
     77       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected;
     78     case webrtc::PeerConnectionInterface::kIceConnectionClosed:
     79       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
     80     default:
     81       NOTREACHED();
     82       return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed;
     83   }
     84 }
     85 
     86 static blink::WebRTCPeerConnectionHandlerClient::SignalingState
     87 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
     88   using blink::WebRTCPeerConnectionHandlerClient;
     89   switch (state) {
     90     case webrtc::PeerConnectionInterface::kStable:
     91       return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
     92     case webrtc::PeerConnectionInterface::kHaveLocalOffer:
     93       return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer;
     94     case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
     95       return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer;
     96     case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
     97       return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer;
     98     case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
     99       return
    100           WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer;
    101     case webrtc::PeerConnectionInterface::kClosed:
    102       return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
    103     default:
    104       NOTREACHED();
    105       return WebRTCPeerConnectionHandlerClient::SignalingStateClosed;
    106   }
    107 }
    108 
    109 static blink::WebRTCSessionDescription
    110 CreateWebKitSessionDescription(
    111     const webrtc::SessionDescriptionInterface* native_desc) {
    112   blink::WebRTCSessionDescription description;
    113   if (!native_desc) {
    114     LOG(ERROR) << "Native session description is null.";
    115     return description;
    116   }
    117 
    118   std::string sdp;
    119   if (!native_desc->ToString(&sdp)) {
    120     LOG(ERROR) << "Failed to get SDP string of native session description.";
    121     return description;
    122   }
    123 
    124   description.initialize(UTF8ToUTF16(native_desc->type()), UTF8ToUTF16(sdp));
    125   return description;
    126 }
    127 
    128 // Converter functions from WebKit types to libjingle types.
    129 
    130 static void GetNativeIceServers(
    131     const blink::WebRTCConfiguration& server_configuration,
    132     webrtc::PeerConnectionInterface::IceServers* servers) {
    133   if (server_configuration.isNull() || !servers)
    134     return;
    135   for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) {
    136     webrtc::PeerConnectionInterface::IceServer server;
    137     const blink::WebRTCICEServer& webkit_server =
    138         server_configuration.server(i);
    139     server.username = UTF16ToUTF8(webkit_server.username());
    140     server.password = UTF16ToUTF8(webkit_server.credential());
    141     server.uri = webkit_server.uri().spec();
    142     servers->push_back(server);
    143   }
    144 }
    145 
    146 class SessionDescriptionRequestTracker {
    147  public:
    148   SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler,
    149                                    PeerConnectionTracker::Action action)
    150       : handler_(handler), action_(action) {}
    151 
    152   void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
    153     std::string value;
    154     if (desc) {
    155       desc->ToString(&value);
    156       value = "type: " + desc->type() + ", sdp: " + value;
    157     }
    158     if (handler_->peer_connection_tracker())
    159       handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
    160           handler_, action_, "OnSuccess", value);
    161   }
    162 
    163   void TrackOnFailure(const std::string& error) {
    164     if (handler_->peer_connection_tracker())
    165       handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
    166           handler_, action_, "OnFailure", error);
    167   }
    168 
    169  private:
    170   RTCPeerConnectionHandler* handler_;
    171   PeerConnectionTracker::Action action_;
    172 };
    173 
    174 // Class mapping responses from calls to libjingle CreateOffer/Answer and
    175 // the blink::WebRTCSessionDescriptionRequest.
    176 class CreateSessionDescriptionRequest
    177     : public webrtc::CreateSessionDescriptionObserver {
    178  public:
    179   explicit CreateSessionDescriptionRequest(
    180       const blink::WebRTCSessionDescriptionRequest& request,
    181       RTCPeerConnectionHandler* handler,
    182       PeerConnectionTracker::Action action)
    183       : webkit_request_(request), tracker_(handler, action) {}
    184 
    185   virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE {
    186     tracker_.TrackOnSuccess(desc);
    187     webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
    188   }
    189   virtual void OnFailure(const std::string& error) OVERRIDE {
    190     tracker_.TrackOnFailure(error);
    191     webkit_request_.requestFailed(UTF8ToUTF16(error));
    192   }
    193 
    194  protected:
    195   virtual ~CreateSessionDescriptionRequest() {}
    196 
    197  private:
    198   blink::WebRTCSessionDescriptionRequest webkit_request_;
    199   SessionDescriptionRequestTracker tracker_;
    200 };
    201 
    202 // Class mapping responses from calls to libjingle
    203 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
    204 class SetSessionDescriptionRequest
    205     : public webrtc::SetSessionDescriptionObserver {
    206  public:
    207   explicit SetSessionDescriptionRequest(
    208       const blink::WebRTCVoidRequest& request,
    209       RTCPeerConnectionHandler* handler,
    210       PeerConnectionTracker::Action action)
    211       : webkit_request_(request), tracker_(handler, action) {}
    212 
    213   virtual void OnSuccess() OVERRIDE {
    214     tracker_.TrackOnSuccess(NULL);
    215     webkit_request_.requestSucceeded();
    216   }
    217   virtual void OnFailure(const std::string& error) OVERRIDE {
    218     tracker_.TrackOnFailure(error);
    219     webkit_request_.requestFailed(UTF8ToUTF16(error));
    220   }
    221 
    222  protected:
    223   virtual ~SetSessionDescriptionRequest() {}
    224 
    225  private:
    226   blink::WebRTCVoidRequest webkit_request_;
    227   SessionDescriptionRequestTracker tracker_;
    228 };
    229 
    230 // Class mapping responses from calls to libjingle
    231 // GetStats into a blink::WebRTCStatsCallback.
    232 class StatsResponse : public webrtc::StatsObserver {
    233  public:
    234   explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
    235       : request_(request.get()), response_(request_->createResponse().get()) {}
    236 
    237   virtual void OnComplete(
    238       const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
    239     for (std::vector<webrtc::StatsReport>::const_iterator it = reports.begin();
    240          it != reports.end(); ++it) {
    241       if (it->values.size() > 0) {
    242         AddReport(*it);
    243       }
    244     }
    245     request_->requestSucceeded(response_);
    246   }
    247 
    248  private:
    249   void AddReport(const webrtc::StatsReport& report) {
    250     int idx = response_->addReport(blink::WebString::fromUTF8(report.id),
    251                                    blink::WebString::fromUTF8(report.type),
    252                                    report.timestamp);
    253     for (webrtc::StatsReport::Values::const_iterator value_it =
    254          report.values.begin();
    255          value_it != report.values.end(); ++value_it) {
    256       AddStatistic(idx, value_it->name, value_it->value);
    257     }
    258   }
    259 
    260   void AddStatistic(int idx, const std::string& name,
    261                     const std::string& value) {
    262     response_->addStatistic(idx,
    263                             blink::WebString::fromUTF8(name),
    264                             blink::WebString::fromUTF8(value));
    265   }
    266 
    267   talk_base::scoped_refptr<LocalRTCStatsRequest> request_;
    268   talk_base::scoped_refptr<LocalRTCStatsResponse> response_;
    269 };
    270 
    271 // Implementation of LocalRTCStatsRequest.
    272 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
    273     : impl_(impl),
    274       response_(NULL) {
    275 }
    276 
    277 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
    278 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
    279 
    280 bool LocalRTCStatsRequest::hasSelector() const {
    281   return impl_.hasSelector();
    282 }
    283 
    284 blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
    285   return impl_.component();
    286 }
    287 
    288 scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
    289   DCHECK(!response_);
    290   response_ = new talk_base::RefCountedObject<LocalRTCStatsResponse>(
    291       impl_.createResponse());
    292   return response_.get();
    293 }
    294 
    295 void LocalRTCStatsRequest::requestSucceeded(
    296     const LocalRTCStatsResponse* response) {
    297   impl_.requestSucceeded(response->webKitStatsResponse());
    298 }
    299 
    300 // Implementation of LocalRTCStatsResponse.
    301 blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
    302   return impl_;
    303 }
    304 
    305 size_t LocalRTCStatsResponse::addReport(blink::WebString type,
    306                                         blink::WebString id,
    307                                         double timestamp) {
    308   return impl_.addReport(type, id, timestamp);
    309 }
    310 
    311 void LocalRTCStatsResponse::addStatistic(size_t report,
    312                                          blink::WebString name,
    313                                          blink::WebString value) {
    314   impl_.addStatistic(report, name, value);
    315 }
    316 
    317 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
    318     blink::WebRTCPeerConnectionHandlerClient* client,
    319     MediaStreamDependencyFactory* dependency_factory)
    320     : PeerConnectionHandlerBase(dependency_factory),
    321       client_(client),
    322       frame_(NULL),
    323       peer_connection_tracker_(NULL) {
    324 }
    325 
    326 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
    327   if (peer_connection_tracker_)
    328     peer_connection_tracker_->UnregisterPeerConnection(this);
    329   STLDeleteValues(&remote_streams_);
    330 }
    331 
    332 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
    333   DCHECK(frame);
    334   frame_ = frame;
    335 }
    336 
    337 bool RTCPeerConnectionHandler::initialize(
    338     const blink::WebRTCConfiguration& server_configuration,
    339     const blink::WebMediaConstraints& options) {
    340   DCHECK(frame_);
    341 
    342   peer_connection_tracker_ =
    343       RenderThreadImpl::current()->peer_connection_tracker();
    344 
    345   webrtc::PeerConnectionInterface::IceServers servers;
    346   GetNativeIceServers(server_configuration, &servers);
    347 
    348   RTCMediaConstraints constraints(options);
    349 
    350   native_peer_connection_ =
    351       dependency_factory_->CreatePeerConnection(
    352           servers, &constraints, frame_, this);
    353   if (!native_peer_connection_.get()) {
    354     LOG(ERROR) << "Failed to initialize native PeerConnection.";
    355     return false;
    356   }
    357   if (peer_connection_tracker_)
    358     peer_connection_tracker_->RegisterPeerConnection(
    359         this, servers, constraints, frame_);
    360 
    361   return true;
    362 }
    363 
    364 bool RTCPeerConnectionHandler::InitializeForTest(
    365     const blink::WebRTCConfiguration& server_configuration,
    366     const blink::WebMediaConstraints& options,
    367     PeerConnectionTracker* peer_connection_tracker) {
    368   webrtc::PeerConnectionInterface::IceServers servers;
    369   GetNativeIceServers(server_configuration, &servers);
    370 
    371   RTCMediaConstraints constraints(options);
    372   native_peer_connection_ =
    373       dependency_factory_->CreatePeerConnection(
    374           servers, &constraints, NULL, this);
    375   if (!native_peer_connection_.get()) {
    376     LOG(ERROR) << "Failed to initialize native PeerConnection.";
    377     return false;
    378   }
    379   peer_connection_tracker_ = peer_connection_tracker;
    380   return true;
    381 }
    382 
    383 void RTCPeerConnectionHandler::createOffer(
    384     const blink::WebRTCSessionDescriptionRequest& request,
    385     const blink::WebMediaConstraints& options) {
    386   scoped_refptr<CreateSessionDescriptionRequest> description_request(
    387       new talk_base::RefCountedObject<CreateSessionDescriptionRequest>(
    388           request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
    389   RTCMediaConstraints constraints(options);
    390   native_peer_connection_->CreateOffer(description_request.get(), &constraints);
    391 
    392   if (peer_connection_tracker_)
    393     peer_connection_tracker_->TrackCreateOffer(this, constraints);
    394 }
    395 
    396 void RTCPeerConnectionHandler::createAnswer(
    397     const blink::WebRTCSessionDescriptionRequest& request,
    398     const blink::WebMediaConstraints& options) {
    399   scoped_refptr<CreateSessionDescriptionRequest> description_request(
    400       new talk_base::RefCountedObject<CreateSessionDescriptionRequest>(
    401           request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER));
    402   RTCMediaConstraints constraints(options);
    403   native_peer_connection_->CreateAnswer(description_request.get(),
    404                                         &constraints);
    405 
    406   if (peer_connection_tracker_)
    407     peer_connection_tracker_->TrackCreateAnswer(this, constraints);
    408 }
    409 
    410 void RTCPeerConnectionHandler::setLocalDescription(
    411     const blink::WebRTCVoidRequest& request,
    412     const blink::WebRTCSessionDescription& description) {
    413   webrtc::SdpParseError error;
    414   webrtc::SessionDescriptionInterface* native_desc =
    415       CreateNativeSessionDescription(description, &error);
    416   if (!native_desc) {
    417     std::string reason_str = "Failed to parse SessionDescription. ";
    418     reason_str.append(error.line);
    419     reason_str.append(" ");
    420     reason_str.append(error.description);
    421     LOG(ERROR) << reason_str;
    422     request.requestFailed(blink::WebString::fromUTF8(reason_str));
    423     return;
    424   }
    425   if (peer_connection_tracker_)
    426     peer_connection_tracker_->TrackSetSessionDescription(
    427         this, description, PeerConnectionTracker::SOURCE_LOCAL);
    428 
    429   scoped_refptr<SetSessionDescriptionRequest> set_request(
    430       new talk_base::RefCountedObject<SetSessionDescriptionRequest>(
    431           request, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
    432   native_peer_connection_->SetLocalDescription(set_request.get(), native_desc);
    433 }
    434 
    435 void RTCPeerConnectionHandler::setRemoteDescription(
    436     const blink::WebRTCVoidRequest& request,
    437     const blink::WebRTCSessionDescription& description) {
    438   webrtc::SdpParseError error;
    439   webrtc::SessionDescriptionInterface* native_desc =
    440       CreateNativeSessionDescription(description, &error);
    441   if (!native_desc) {
    442     std::string reason_str = "Failed to parse SessionDescription. ";
    443     reason_str.append(error.line);
    444     reason_str.append(" ");
    445     reason_str.append(error.description);
    446     LOG(ERROR) << reason_str;
    447     request.requestFailed(blink::WebString::fromUTF8(reason_str));
    448     return;
    449   }
    450   if (peer_connection_tracker_)
    451     peer_connection_tracker_->TrackSetSessionDescription(
    452         this, description, PeerConnectionTracker::SOURCE_REMOTE);
    453 
    454   scoped_refptr<SetSessionDescriptionRequest> set_request(
    455       new talk_base::RefCountedObject<SetSessionDescriptionRequest>(
    456           request, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
    457   native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc);
    458 }
    459 
    460 blink::WebRTCSessionDescription
    461 RTCPeerConnectionHandler::localDescription() {
    462   const webrtc::SessionDescriptionInterface* native_desc =
    463       native_peer_connection_->local_description();
    464   blink::WebRTCSessionDescription description =
    465       CreateWebKitSessionDescription(native_desc);
    466   return description;
    467 }
    468 
    469 blink::WebRTCSessionDescription
    470 RTCPeerConnectionHandler::remoteDescription() {
    471   const webrtc::SessionDescriptionInterface* native_desc =
    472       native_peer_connection_->remote_description();
    473   blink::WebRTCSessionDescription description =
    474       CreateWebKitSessionDescription(native_desc);
    475   return description;
    476 }
    477 
    478 bool RTCPeerConnectionHandler::updateICE(
    479     const blink::WebRTCConfiguration& server_configuration,
    480     const blink::WebMediaConstraints& options) {
    481   webrtc::PeerConnectionInterface::IceServers servers;
    482   GetNativeIceServers(server_configuration, &servers);
    483   RTCMediaConstraints constraints(options);
    484 
    485   if (peer_connection_tracker_)
    486     peer_connection_tracker_->TrackUpdateIce(this, servers, constraints);
    487 
    488   return native_peer_connection_->UpdateIce(servers,
    489                                             &constraints);
    490 }
    491 
    492 bool RTCPeerConnectionHandler::addICECandidate(
    493   const blink::WebRTCVoidRequest& request,
    494   const blink::WebRTCICECandidate& candidate) {
    495   // Libjingle currently does not accept callbacks for addICECandidate.
    496   // For that reason we are going to call callbacks from here.
    497   bool result = addICECandidate(candidate);
    498   base::MessageLoop::current()->PostTask(
    499       FROM_HERE,
    500       base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
    501                  base::Unretained(this), request, result));
    502   // On failure callback will be triggered.
    503   return true;
    504 }
    505 
    506 bool RTCPeerConnectionHandler::addICECandidate(
    507     const blink::WebRTCICECandidate& candidate) {
    508   scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
    509       dependency_factory_->CreateIceCandidate(
    510           UTF16ToUTF8(candidate.sdpMid()),
    511           candidate.sdpMLineIndex(),
    512           UTF16ToUTF8(candidate.candidate())));
    513   if (!native_candidate) {
    514     LOG(ERROR) << "Could not create native ICE candidate.";
    515     return false;
    516   }
    517 
    518   bool return_value =
    519       native_peer_connection_->AddIceCandidate(native_candidate.get());
    520   LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
    521 
    522   if (peer_connection_tracker_)
    523     peer_connection_tracker_->TrackAddIceCandidate(
    524         this, candidate, PeerConnectionTracker::SOURCE_REMOTE);
    525 
    526   return return_value;
    527 }
    528 
    529 void RTCPeerConnectionHandler::OnaddICECandidateResult(
    530     const blink::WebRTCVoidRequest& webkit_request, bool result) {
    531   if (!result) {
    532     // We don't have the actual error code from the libjingle, so for now
    533     // using a generic error string.
    534     return webkit_request.requestFailed(
    535         UTF8ToUTF16("Error processing ICE candidate"));
    536   }
    537 
    538   return webkit_request.requestSucceeded();
    539 }
    540 
    541 bool RTCPeerConnectionHandler::addStream(
    542     const blink::WebMediaStream& stream,
    543     const blink::WebMediaConstraints& options) {
    544   RTCMediaConstraints constraints(options);
    545 
    546   if (peer_connection_tracker_)
    547     peer_connection_tracker_->TrackAddStream(
    548         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
    549 
    550   // A media stream is connected to a peer connection, enable the
    551   // peer connection mode for the capturer.
    552   WebRtcAudioDeviceImpl* audio_device =
    553       dependency_factory_->GetWebRtcAudioDevice();
    554   if (audio_device) {
    555     WebRtcAudioCapturer* capturer = audio_device->GetDefaultCapturer();
    556     if (capturer)
    557       capturer->EnablePeerConnectionMode();
    558   }
    559 
    560   return AddStream(stream, &constraints);
    561 }
    562 
    563 void RTCPeerConnectionHandler::removeStream(
    564     const blink::WebMediaStream& stream) {
    565   RemoveStream(stream);
    566   if (peer_connection_tracker_)
    567     peer_connection_tracker_->TrackRemoveStream(
    568         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
    569 }
    570 
    571 void RTCPeerConnectionHandler::getStats(
    572     const blink::WebRTCStatsRequest& request) {
    573   scoped_refptr<LocalRTCStatsRequest> inner_request(
    574       new talk_base::RefCountedObject<LocalRTCStatsRequest>(request));
    575   getStats(inner_request.get());
    576 }
    577 
    578 void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
    579   talk_base::scoped_refptr<webrtc::StatsObserver> observer(
    580       new talk_base::RefCountedObject<StatsResponse>(request));
    581   webrtc::MediaStreamTrackInterface* track = NULL;
    582   if (request->hasSelector()) {
    583       track = MediaStreamDependencyFactory::GetNativeMediaStreamTrack(
    584           request->component());
    585     if (!track) {
    586       DVLOG(1) << "GetStats: Track not found.";
    587       // TODO(hta): Consider how to get an error back.
    588       std::vector<webrtc::StatsReport> no_reports;
    589       observer->OnComplete(no_reports);
    590       return;
    591     }
    592   }
    593   GetStats(observer, track);
    594 }
    595 
    596 void RTCPeerConnectionHandler::GetStats(
    597     webrtc::StatsObserver* observer,
    598     webrtc::MediaStreamTrackInterface* track) {
    599   if (!native_peer_connection_->GetStats(observer, track)) {
    600     DVLOG(1) << "GetStats failed.";
    601     // TODO(hta): Consider how to get an error back.
    602     std::vector<webrtc::StatsReport> no_reports;
    603     observer->OnComplete(no_reports);
    604     return;
    605   }
    606 }
    607 
    608 blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
    609     const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
    610   DVLOG(1) << "createDataChannel label " << UTF16ToUTF8(label);
    611 
    612   webrtc::DataChannelInit config;
    613   // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
    614   // to handle that.
    615   config.reliable = false;
    616   config.id = init.id;
    617   config.ordered = init.ordered;
    618   config.negotiated = init.negotiated;
    619   config.maxRetransmits = init.maxRetransmits;
    620   config.maxRetransmitTime = init.maxRetransmitTime;
    621   config.protocol = UTF16ToUTF8(init.protocol);
    622 
    623   talk_base::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
    624       native_peer_connection_->CreateDataChannel(UTF16ToUTF8(label), &config));
    625   if (!webrtc_channel) {
    626     DLOG(ERROR) << "Could not create native data channel.";
    627     return NULL;
    628   }
    629   if (peer_connection_tracker_)
    630     peer_connection_tracker_->TrackCreateDataChannel(
    631         this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
    632 
    633   return new RtcDataChannelHandler(webrtc_channel);
    634 }
    635 
    636 blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
    637     const blink::WebMediaStreamTrack& track) {
    638   DVLOG(1) << "createDTMFSender.";
    639 
    640   if (track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
    641     DLOG(ERROR) << "Could not create DTMF sender from a non-audio track.";
    642     return NULL;
    643   }
    644 
    645   webrtc::AudioTrackInterface* audio_track =
    646       static_cast<webrtc::AudioTrackInterface*>(
    647           MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track));
    648 
    649   talk_base::scoped_refptr<webrtc::DtmfSenderInterface> sender(
    650       native_peer_connection_->CreateDtmfSender(audio_track));
    651   if (!sender) {
    652     DLOG(ERROR) << "Could not create native DTMF sender.";
    653     return NULL;
    654   }
    655   if (peer_connection_tracker_)
    656     peer_connection_tracker_->TrackCreateDTMFSender(this, track);
    657 
    658   return new RtcDtmfSenderHandler(sender);
    659 }
    660 
    661 void RTCPeerConnectionHandler::stop() {
    662   DVLOG(1) << "RTCPeerConnectionHandler::stop";
    663 
    664   if (peer_connection_tracker_)
    665     peer_connection_tracker_->TrackStop(this);
    666   native_peer_connection_->Close();
    667 }
    668 
    669 void RTCPeerConnectionHandler::OnError() {
    670   // TODO(perkj): Implement.
    671   NOTIMPLEMENTED();
    672 }
    673 
    674 void RTCPeerConnectionHandler::OnSignalingChange(
    675     webrtc::PeerConnectionInterface::SignalingState new_state) {
    676   blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
    677       GetWebKitSignalingState(new_state);
    678   if (peer_connection_tracker_)
    679     peer_connection_tracker_->TrackSignalingStateChange(this, state);
    680   client_->didChangeSignalingState(state);
    681 }
    682 
    683 // Called any time the IceConnectionState changes
    684 void RTCPeerConnectionHandler::OnIceConnectionChange(
    685     webrtc::PeerConnectionInterface::IceConnectionState new_state) {
    686   blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
    687       GetWebKitIceConnectionState(new_state);
    688   if (peer_connection_tracker_)
    689     peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
    690   client_->didChangeICEConnectionState(state);
    691 }
    692 
    693 // Called any time the IceGatheringState changes
    694 void RTCPeerConnectionHandler::OnIceGatheringChange(
    695     webrtc::PeerConnectionInterface::IceGatheringState new_state) {
    696   if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
    697     // If ICE gathering is completed, generate a NULL ICE candidate,
    698     // to signal end of candidates.
    699     blink::WebRTCICECandidate null_candidate;
    700     client_->didGenerateICECandidate(null_candidate);
    701   }
    702 
    703   blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
    704       GetWebKitIceGatheringState(new_state);
    705   if (peer_connection_tracker_)
    706     peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
    707   client_->didChangeICEGatheringState(state);
    708 }
    709 
    710 void RTCPeerConnectionHandler::OnAddStream(
    711     webrtc::MediaStreamInterface* stream_interface) {
    712   DCHECK(stream_interface);
    713   DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
    714 
    715   RemoteMediaStreamImpl* remote_stream =
    716       new RemoteMediaStreamImpl(stream_interface);
    717   remote_streams_.insert(
    718       std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
    719           stream_interface, remote_stream));
    720 
    721   if (peer_connection_tracker_)
    722     peer_connection_tracker_->TrackAddStream(
    723         this, remote_stream->webkit_stream(),
    724         PeerConnectionTracker::SOURCE_REMOTE);
    725 
    726   client_->didAddRemoteStream(remote_stream->webkit_stream());
    727 }
    728 
    729 void RTCPeerConnectionHandler::OnRemoveStream(
    730     webrtc::MediaStreamInterface* stream_interface) {
    731   DCHECK(stream_interface);
    732   RemoteStreamMap::iterator it = remote_streams_.find(stream_interface);
    733   if (it == remote_streams_.end()) {
    734     NOTREACHED() << "Stream not found";
    735     return;
    736   }
    737 
    738   scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
    739   const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
    740   DCHECK(!webkit_stream.isNull());
    741   remote_streams_.erase(it);
    742 
    743   if (peer_connection_tracker_)
    744     peer_connection_tracker_->TrackRemoveStream(
    745         this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
    746 
    747   client_->didRemoveRemoteStream(webkit_stream);
    748 }
    749 
    750 void RTCPeerConnectionHandler::OnIceCandidate(
    751     const webrtc::IceCandidateInterface* candidate) {
    752   DCHECK(candidate);
    753   std::string sdp;
    754   if (!candidate->ToString(&sdp)) {
    755     NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
    756     return;
    757   }
    758   blink::WebRTCICECandidate web_candidate;
    759   web_candidate.initialize(UTF8ToUTF16(sdp),
    760                            UTF8ToUTF16(candidate->sdp_mid()),
    761                            candidate->sdp_mline_index());
    762   if (peer_connection_tracker_)
    763     peer_connection_tracker_->TrackAddIceCandidate(
    764         this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL);
    765 
    766   client_->didGenerateICECandidate(web_candidate);
    767 }
    768 
    769 void RTCPeerConnectionHandler::OnDataChannel(
    770     webrtc::DataChannelInterface* data_channel) {
    771   if (peer_connection_tracker_)
    772     peer_connection_tracker_->TrackCreateDataChannel(
    773         this, data_channel, PeerConnectionTracker::SOURCE_REMOTE);
    774 
    775   DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
    776            << data_channel->label();
    777   client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel));
    778 }
    779 
    780 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
    781   if (peer_connection_tracker_)
    782     peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
    783   client_->negotiationNeeded();
    784 }
    785 
    786 PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
    787   return peer_connection_tracker_;
    788 }
    789 
    790 webrtc::SessionDescriptionInterface*
    791 RTCPeerConnectionHandler::CreateNativeSessionDescription(
    792     const blink::WebRTCSessionDescription& description,
    793     webrtc::SdpParseError* error) {
    794   std::string sdp = UTF16ToUTF8(description.sdp());
    795   std::string type = UTF16ToUTF8(description.type());
    796   webrtc::SessionDescriptionInterface* native_desc =
    797       dependency_factory_->CreateSessionDescription(type, sdp, error);
    798 
    799   LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
    800                               << " Type: " << type << " SDP: " << sdp;
    801 
    802   return native_desc;
    803 }
    804 
    805 }  // namespace content
    806