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