- add sources.
[platform/framework/web/crosswalk.git] / src / content / renderer / media / rtc_peer_connection_handler.cc
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 WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState
45 GetWebKitIceGatheringState(
46     webrtc::PeerConnectionInterface::IceGatheringState state) {
47   using WebKit::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 WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState
62 GetWebKitIceConnectionState(
63     webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
64   using WebKit::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 WebKit::WebRTCPeerConnectionHandlerClient::SignalingState
87 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
88   using WebKit::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 WebKit::WebRTCSessionDescription
110 CreateWebKitSessionDescription(
111     const webrtc::SessionDescriptionInterface* native_desc) {
112   WebKit::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 WebKit::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 WebKit::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 WebKit::WebRTCSessionDescriptionRequest.
176 class CreateSessionDescriptionRequest
177     : public webrtc::CreateSessionDescriptionObserver {
178  public:
179   explicit CreateSessionDescriptionRequest(
180       const WebKit::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   WebKit::WebRTCSessionDescriptionRequest webkit_request_;
199   SessionDescriptionRequestTracker tracker_;
200 };
201
202 // Class mapping responses from calls to libjingle
203 // SetLocalDescription/SetRemoteDescription and a WebKit::WebRTCVoidRequest.
204 class SetSessionDescriptionRequest
205     : public webrtc::SetSessionDescriptionObserver {
206  public:
207   explicit SetSessionDescriptionRequest(
208       const WebKit::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   WebKit::WebRTCVoidRequest webkit_request_;
227   SessionDescriptionRequestTracker tracker_;
228 };
229
230 // Class mapping responses from calls to libjingle
231 // GetStats into a WebKit::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(WebKit::WebString::fromUTF8(report.id),
251                                    WebKit::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                             WebKit::WebString::fromUTF8(name),
264                             WebKit::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(WebKit::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 WebKit::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 WebKit::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
302   return impl_;
303 }
304
305 size_t LocalRTCStatsResponse::addReport(WebKit::WebString type,
306                                         WebKit::WebString id,
307                                         double timestamp) {
308   return impl_.addReport(type, id, timestamp);
309 }
310
311 void LocalRTCStatsResponse::addStatistic(size_t report,
312                                          WebKit::WebString name,
313                                          WebKit::WebString value) {
314   impl_.addStatistic(report, name, value);
315 }
316
317 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
318     WebKit::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(WebKit::WebFrame* frame) {
333   DCHECK(frame);
334   frame_ = frame;
335 }
336
337 bool RTCPeerConnectionHandler::initialize(
338     const WebKit::WebRTCConfiguration& server_configuration,
339     const WebKit::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 WebKit::WebRTCConfiguration& server_configuration,
366     const WebKit::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 WebKit::WebRTCSessionDescriptionRequest& request,
385     const WebKit::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 WebKit::WebRTCSessionDescriptionRequest& request,
398     const WebKit::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 WebKit::WebRTCVoidRequest& request,
412     const WebKit::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(WebKit::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 WebKit::WebRTCVoidRequest& request,
437     const WebKit::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(WebKit::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 WebKit::WebRTCSessionDescription
461 RTCPeerConnectionHandler::localDescription() {
462   const webrtc::SessionDescriptionInterface* native_desc =
463       native_peer_connection_->local_description();
464   WebKit::WebRTCSessionDescription description =
465       CreateWebKitSessionDescription(native_desc);
466   return description;
467 }
468
469 WebKit::WebRTCSessionDescription
470 RTCPeerConnectionHandler::remoteDescription() {
471   const webrtc::SessionDescriptionInterface* native_desc =
472       native_peer_connection_->remote_description();
473   WebKit::WebRTCSessionDescription description =
474       CreateWebKitSessionDescription(native_desc);
475   return description;
476 }
477
478 bool RTCPeerConnectionHandler::updateICE(
479     const WebKit::WebRTCConfiguration& server_configuration,
480     const WebKit::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 WebKit::WebRTCICECandidate& candidate) {
494   scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
495       dependency_factory_->CreateIceCandidate(
496           UTF16ToUTF8(candidate.sdpMid()),
497           candidate.sdpMLineIndex(),
498           UTF16ToUTF8(candidate.candidate())));
499   if (!native_candidate) {
500     LOG(ERROR) << "Could not create native ICE candidate.";
501     return false;
502   }
503
504   bool return_value =
505       native_peer_connection_->AddIceCandidate(native_candidate.get());
506   LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
507
508   if (peer_connection_tracker_)
509     peer_connection_tracker_->TrackAddIceCandidate(
510         this, candidate, PeerConnectionTracker::SOURCE_REMOTE);
511
512   return return_value;
513 }
514
515 bool RTCPeerConnectionHandler::addStream(
516     const WebKit::WebMediaStream& stream,
517     const WebKit::WebMediaConstraints& options) {
518   RTCMediaConstraints constraints(options);
519
520   if (peer_connection_tracker_)
521     peer_connection_tracker_->TrackAddStream(
522         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
523
524   // A media stream is connected to a peer connection, enable the
525   // peer connection mode for the capturer.
526   WebRtcAudioDeviceImpl* audio_device =
527       dependency_factory_->GetWebRtcAudioDevice();
528   if (audio_device) {
529     WebRtcAudioCapturer* capturer = audio_device->GetDefaultCapturer();
530     if (capturer)
531       capturer->EnablePeerConnectionMode();
532   }
533
534   return AddStream(stream, &constraints);
535 }
536
537 void RTCPeerConnectionHandler::removeStream(
538     const WebKit::WebMediaStream& stream) {
539   RemoveStream(stream);
540   if (peer_connection_tracker_)
541     peer_connection_tracker_->TrackRemoveStream(
542         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
543 }
544
545 void RTCPeerConnectionHandler::getStats(
546     const WebKit::WebRTCStatsRequest& request) {
547   scoped_refptr<LocalRTCStatsRequest> inner_request(
548       new talk_base::RefCountedObject<LocalRTCStatsRequest>(request));
549   getStats(inner_request.get());
550 }
551
552 void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
553   talk_base::scoped_refptr<webrtc::StatsObserver> observer(
554       new talk_base::RefCountedObject<StatsResponse>(request));
555   webrtc::MediaStreamTrackInterface* track = NULL;
556   if (request->hasSelector()) {
557       track = MediaStreamDependencyFactory::GetNativeMediaStreamTrack(
558           request->component());
559     if (!track) {
560       DVLOG(1) << "GetStats: Track not found.";
561       // TODO(hta): Consider how to get an error back.
562       std::vector<webrtc::StatsReport> no_reports;
563       observer->OnComplete(no_reports);
564       return;
565     }
566   }
567   GetStats(observer, track);
568 }
569
570 void RTCPeerConnectionHandler::GetStats(
571     webrtc::StatsObserver* observer,
572     webrtc::MediaStreamTrackInterface* track) {
573   if (!native_peer_connection_->GetStats(observer, track)) {
574     DVLOG(1) << "GetStats failed.";
575     // TODO(hta): Consider how to get an error back.
576     std::vector<webrtc::StatsReport> no_reports;
577     observer->OnComplete(no_reports);
578     return;
579   }
580 }
581
582 WebKit::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
583     const WebKit::WebString& label, const WebKit::WebRTCDataChannelInit& init) {
584   DVLOG(1) << "createDataChannel label " << UTF16ToUTF8(label);
585
586   webrtc::DataChannelInit config;
587   // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
588   // to handle that.
589   config.reliable = false;
590   config.id = init.id;
591   config.ordered = init.ordered;
592   config.negotiated = init.negotiated;
593   config.maxRetransmits = init.maxRetransmits;
594   config.maxRetransmitTime = init.maxRetransmitTime;
595   config.protocol = UTF16ToUTF8(init.protocol);
596
597   talk_base::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
598       native_peer_connection_->CreateDataChannel(UTF16ToUTF8(label), &config));
599   if (!webrtc_channel) {
600     DLOG(ERROR) << "Could not create native data channel.";
601     return NULL;
602   }
603   if (peer_connection_tracker_)
604     peer_connection_tracker_->TrackCreateDataChannel(
605         this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
606
607   return new RtcDataChannelHandler(webrtc_channel);
608 }
609
610 WebKit::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
611     const WebKit::WebMediaStreamTrack& track) {
612   DVLOG(1) << "createDTMFSender.";
613
614   if (track.source().type() != WebKit::WebMediaStreamSource::TypeAudio) {
615     DLOG(ERROR) << "Could not create DTMF sender from a non-audio track.";
616     return NULL;
617   }
618
619   webrtc::AudioTrackInterface* audio_track =
620       static_cast<webrtc::AudioTrackInterface*>(
621           MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track));
622
623   talk_base::scoped_refptr<webrtc::DtmfSenderInterface> sender(
624       native_peer_connection_->CreateDtmfSender(audio_track));
625   if (!sender) {
626     DLOG(ERROR) << "Could not create native DTMF sender.";
627     return NULL;
628   }
629   if (peer_connection_tracker_)
630     peer_connection_tracker_->TrackCreateDTMFSender(this, track);
631
632   return new RtcDtmfSenderHandler(sender);
633 }
634
635 void RTCPeerConnectionHandler::stop() {
636   DVLOG(1) << "RTCPeerConnectionHandler::stop";
637
638   if (peer_connection_tracker_)
639     peer_connection_tracker_->TrackStop(this);
640   native_peer_connection_->Close();
641 }
642
643 void RTCPeerConnectionHandler::OnError() {
644   // TODO(perkj): Implement.
645   NOTIMPLEMENTED();
646 }
647
648 void RTCPeerConnectionHandler::OnSignalingChange(
649     webrtc::PeerConnectionInterface::SignalingState new_state) {
650   WebKit::WebRTCPeerConnectionHandlerClient::SignalingState state =
651       GetWebKitSignalingState(new_state);
652   if (peer_connection_tracker_)
653     peer_connection_tracker_->TrackSignalingStateChange(this, state);
654   client_->didChangeSignalingState(state);
655 }
656
657 // Called any time the IceConnectionState changes
658 void RTCPeerConnectionHandler::OnIceConnectionChange(
659     webrtc::PeerConnectionInterface::IceConnectionState new_state) {
660   WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
661       GetWebKitIceConnectionState(new_state);
662   if (peer_connection_tracker_)
663     peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
664   client_->didChangeICEConnectionState(state);
665 }
666
667 // Called any time the IceGatheringState changes
668 void RTCPeerConnectionHandler::OnIceGatheringChange(
669     webrtc::PeerConnectionInterface::IceGatheringState new_state) {
670   if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
671     // If ICE gathering is completed, generate a NULL ICE candidate,
672     // to signal end of candidates.
673     WebKit::WebRTCICECandidate null_candidate;
674     client_->didGenerateICECandidate(null_candidate);
675   }
676
677   WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
678       GetWebKitIceGatheringState(new_state);
679   if (peer_connection_tracker_)
680     peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
681   client_->didChangeICEGatheringState(state);
682 }
683
684 void RTCPeerConnectionHandler::OnAddStream(
685     webrtc::MediaStreamInterface* stream_interface) {
686   DCHECK(stream_interface);
687   DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
688
689   RemoteMediaStreamImpl* remote_stream =
690       new RemoteMediaStreamImpl(stream_interface);
691   remote_streams_.insert(
692       std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
693           stream_interface, remote_stream));
694
695   if (peer_connection_tracker_)
696     peer_connection_tracker_->TrackAddStream(
697         this, remote_stream->webkit_stream(),
698         PeerConnectionTracker::SOURCE_REMOTE);
699
700   client_->didAddRemoteStream(remote_stream->webkit_stream());
701 }
702
703 void RTCPeerConnectionHandler::OnRemoveStream(
704     webrtc::MediaStreamInterface* stream_interface) {
705   DCHECK(stream_interface);
706   RemoteStreamMap::iterator it = remote_streams_.find(stream_interface);
707   if (it == remote_streams_.end()) {
708     NOTREACHED() << "Stream not found";
709     return;
710   }
711
712   scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
713   const WebKit::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
714   DCHECK(!webkit_stream.isNull());
715   remote_streams_.erase(it);
716
717   if (peer_connection_tracker_)
718     peer_connection_tracker_->TrackRemoveStream(
719         this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
720
721   client_->didRemoveRemoteStream(webkit_stream);
722 }
723
724 void RTCPeerConnectionHandler::OnIceCandidate(
725     const webrtc::IceCandidateInterface* candidate) {
726   DCHECK(candidate);
727   std::string sdp;
728   if (!candidate->ToString(&sdp)) {
729     NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
730     return;
731   }
732   WebKit::WebRTCICECandidate web_candidate;
733   web_candidate.initialize(UTF8ToUTF16(sdp),
734                            UTF8ToUTF16(candidate->sdp_mid()),
735                            candidate->sdp_mline_index());
736   if (peer_connection_tracker_)
737     peer_connection_tracker_->TrackAddIceCandidate(
738         this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL);
739
740   client_->didGenerateICECandidate(web_candidate);
741 }
742
743 void RTCPeerConnectionHandler::OnDataChannel(
744     webrtc::DataChannelInterface* data_channel) {
745   if (peer_connection_tracker_)
746     peer_connection_tracker_->TrackCreateDataChannel(
747         this, data_channel, PeerConnectionTracker::SOURCE_REMOTE);
748
749   DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
750            << data_channel->label();
751   client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel));
752 }
753
754 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
755   if (peer_connection_tracker_)
756     peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
757   client_->negotiationNeeded();
758 }
759
760 PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
761   return peer_connection_tracker_;
762 }
763
764 webrtc::SessionDescriptionInterface*
765 RTCPeerConnectionHandler::CreateNativeSessionDescription(
766     const WebKit::WebRTCSessionDescription& description,
767     webrtc::SdpParseError* error) {
768   std::string sdp = UTF16ToUTF8(description.sdp());
769   std::string type = UTF16ToUTF8(description.type());
770   webrtc::SessionDescriptionInterface* native_desc =
771       dependency_factory_->CreateSessionDescription(type, sdp, error);
772
773   LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
774                               << " Type: " << type << " SDP: " << sdp;
775
776   return native_desc;
777 }
778
779 }  // namespace content