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