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