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