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