Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / media / peer_connection_tracker.cc
blob5aac78c3fd50bceb41dfbdc590b656b7862295d2
1 // Copyright (c) 2013 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 #include "content/renderer/media/peer_connection_tracker.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "content/common/media/peer_connection_tracker_messages.h"
8 #include "content/renderer/media/rtc_media_constraints.h"
9 #include "content/renderer/media/rtc_peer_connection_handler.h"
10 #include "content/renderer/render_thread_impl.h"
11 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
12 #include "third_party/WebKit/public/platform/WebMediaStream.h"
13 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
14 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
15 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
16 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
17 #include "third_party/WebKit/public/web/WebDocument.h"
18 #include "third_party/WebKit/public/web/WebFrame.h"
19 #include "third_party/WebKit/public/web/WebUserMediaRequest.h"
21 using std::string;
22 using webrtc::MediaConstraintsInterface;
23 using blink::WebRTCPeerConnectionHandlerClient;
25 namespace content {
27 static string SerializeServers(
28 const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
29 string result = "[";
30 for (size_t i = 0; i < servers.size(); ++i) {
31 result += servers[i].uri;
32 if (i != servers.size() - 1)
33 result += ", ";
35 result += "]";
36 return result;
39 static RTCMediaConstraints GetNativeMediaConstraints(
40 const blink::WebMediaConstraints& constraints) {
41 RTCMediaConstraints native_constraints;
43 if (constraints.isNull())
44 return native_constraints;
46 blink::WebVector<blink::WebMediaConstraint> mandatory;
47 constraints.getMandatoryConstraints(mandatory);
48 for (size_t i = 0; i < mandatory.size(); ++i) {
49 native_constraints.AddMandatory(
50 mandatory[i].m_name.utf8(), mandatory[i].m_value.utf8(), false);
53 blink::WebVector<blink::WebMediaConstraint> optional;
54 constraints.getOptionalConstraints(optional);
55 for (size_t i = 0; i < optional.size(); ++i) {
56 native_constraints.AddOptional(
57 optional[i].m_name.utf8(), optional[i].m_value.utf8(), false);
59 return native_constraints;
62 static string SerializeMediaConstraints(
63 const RTCMediaConstraints& constraints) {
64 string result;
65 MediaConstraintsInterface::Constraints mandatory = constraints.GetMandatory();
66 if (!mandatory.empty()) {
67 result += "mandatory: {";
68 for (size_t i = 0; i < mandatory.size(); ++i) {
69 result += mandatory[i].key + ":" + mandatory[i].value;
70 if (i != mandatory.size() - 1)
71 result += ", ";
73 result += "}";
75 MediaConstraintsInterface::Constraints optional = constraints.GetOptional();
76 if (!optional.empty()) {
77 if (!result.empty())
78 result += ", ";
79 result += "optional: {";
80 for (size_t i = 0; i < optional.size(); ++i) {
81 result += optional[i].key + ":" + optional[i].value;
82 if (i != optional.size() - 1)
83 result += ", ";
85 result += "}";
87 return result;
90 static string SerializeMediaStreamComponent(
91 const blink::WebMediaStreamTrack component) {
92 string id = base::UTF16ToUTF8(component.source().id());
93 return id;
96 static string SerializeMediaDescriptor(
97 const blink::WebMediaStream& stream) {
98 string label = base::UTF16ToUTF8(stream.id());
99 string result = "label: " + label;
100 blink::WebVector<blink::WebMediaStreamTrack> tracks;
101 stream.audioTracks(tracks);
102 if (!tracks.isEmpty()) {
103 result += ", audio: [";
104 for (size_t i = 0; i < tracks.size(); ++i) {
105 result += SerializeMediaStreamComponent(tracks[i]);
106 if (i != tracks.size() - 1)
107 result += ", ";
109 result += "]";
111 stream.videoTracks(tracks);
112 if (!tracks.isEmpty()) {
113 result += ", video: [";
114 for (size_t i = 0; i < tracks.size(); ++i) {
115 result += SerializeMediaStreamComponent(tracks[i]);
116 if (i != tracks.size() - 1)
117 result += ", ";
119 result += "]";
121 return result;
124 static std::string SerializeIceTransportType(
125 webrtc::PeerConnectionInterface::IceTransportsType type) {
126 string transport_type;
127 switch (type) {
128 case webrtc::PeerConnectionInterface::kNone:
129 transport_type = "none";
130 break;
131 case webrtc::PeerConnectionInterface::kRelay:
132 transport_type = "relay";
133 break;
134 case webrtc::PeerConnectionInterface::kAll:
135 transport_type = "all";
136 break;
137 case webrtc::PeerConnectionInterface::kNoHost:
138 transport_type = "noHost";
139 break;
140 default:
141 NOTREACHED();
143 return transport_type;
146 #define GET_STRING_OF_STATE(state) \
147 case WebRTCPeerConnectionHandlerClient::state: \
148 result = #state; \
149 break;
151 static string GetSignalingStateString(
152 WebRTCPeerConnectionHandlerClient::SignalingState state) {
153 string result;
154 switch (state) {
155 GET_STRING_OF_STATE(SignalingStateStable)
156 GET_STRING_OF_STATE(SignalingStateHaveLocalOffer)
157 GET_STRING_OF_STATE(SignalingStateHaveRemoteOffer)
158 GET_STRING_OF_STATE(SignalingStateHaveLocalPrAnswer)
159 GET_STRING_OF_STATE(SignalingStateHaveRemotePrAnswer)
160 GET_STRING_OF_STATE(SignalingStateClosed)
161 default:
162 NOTREACHED();
163 break;
165 return result;
168 static string GetIceConnectionStateString(
169 WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
170 string result;
171 switch (state) {
172 GET_STRING_OF_STATE(ICEConnectionStateStarting)
173 GET_STRING_OF_STATE(ICEConnectionStateChecking)
174 GET_STRING_OF_STATE(ICEConnectionStateConnected)
175 GET_STRING_OF_STATE(ICEConnectionStateCompleted)
176 GET_STRING_OF_STATE(ICEConnectionStateFailed)
177 GET_STRING_OF_STATE(ICEConnectionStateDisconnected)
178 GET_STRING_OF_STATE(ICEConnectionStateClosed)
179 default:
180 NOTREACHED();
181 break;
183 return result;
186 static string GetIceGatheringStateString(
187 WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
188 string result;
189 switch (state) {
190 GET_STRING_OF_STATE(ICEGatheringStateNew)
191 GET_STRING_OF_STATE(ICEGatheringStateGathering)
192 GET_STRING_OF_STATE(ICEGatheringStateComplete)
193 default:
194 NOTREACHED();
195 break;
197 return result;
200 // Builds a DictionaryValue from the StatsReport.
201 // The caller takes the ownership of the returned value.
202 // Note:
203 // The format must be consistent with what webrtc_internals.js expects.
204 // If you change it here, you must change webrtc_internals.js as well.
205 static base::DictionaryValue* GetDictValueStats(
206 const webrtc::StatsReport& report) {
207 if (report.values.empty())
208 return NULL;
210 base::DictionaryValue* dict = new base::DictionaryValue();
211 dict->SetDouble("timestamp", report.timestamp);
213 base::ListValue* values = new base::ListValue();
214 dict->Set("values", values);
216 for (size_t i = 0; i < report.values.size(); ++i) {
217 values->AppendString(report.values[i].display_name());
218 values->AppendString(report.values[i].value);
220 return dict;
223 // Builds a DictionaryValue from the StatsReport.
224 // The caller takes the ownership of the returned value.
225 static base::DictionaryValue* GetDictValue(const webrtc::StatsReport& report) {
226 scoped_ptr<base::DictionaryValue> stats, result;
228 stats.reset(GetDictValueStats(report));
229 if (!stats)
230 return NULL;
232 result.reset(new base::DictionaryValue());
233 // Note:
234 // The format must be consistent with what webrtc_internals.js expects.
235 // If you change it here, you must change webrtc_internals.js as well.
236 result->Set("stats", stats.release());
237 result->SetString("id", report.id);
238 result->SetString("type", report.type);
240 return result.release();
243 class InternalStatsObserver : public webrtc::StatsObserver {
244 public:
245 InternalStatsObserver(int lid)
246 : lid_(lid){}
248 virtual void OnComplete(
249 const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
250 base::ListValue list;
252 for (size_t i = 0; i < reports.size(); ++i) {
253 base::DictionaryValue* report = GetDictValue(reports[i]);
254 if (report)
255 list.Append(report);
258 if (!list.empty())
259 RenderThreadImpl::current()->Send(
260 new PeerConnectionTrackerHost_AddStats(lid_, list));
263 protected:
264 virtual ~InternalStatsObserver() {}
266 private:
267 int lid_;
270 PeerConnectionTracker::PeerConnectionTracker() : next_lid_(1) {
273 PeerConnectionTracker::~PeerConnectionTracker() {
276 bool PeerConnectionTracker::OnControlMessageReceived(
277 const IPC::Message& message) {
278 bool handled = true;
279 IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message)
280 IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats)
281 IPC_MESSAGE_UNHANDLED(handled = false)
282 IPC_END_MESSAGE_MAP()
283 return handled;
286 void PeerConnectionTracker::OnGetAllStats() {
287 for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
288 it != peer_connection_id_map_.end(); ++it) {
290 rtc::scoped_refptr<InternalStatsObserver> observer(
291 new rtc::RefCountedObject<InternalStatsObserver>(it->second));
293 it->first->GetStats(
294 observer,
295 NULL,
296 webrtc::PeerConnectionInterface::kStatsOutputLevelDebug);
300 void PeerConnectionTracker::RegisterPeerConnection(
301 RTCPeerConnectionHandler* pc_handler,
302 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
303 const RTCMediaConstraints& constraints,
304 const blink::WebFrame* frame) {
305 DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
306 PeerConnectionInfo info;
308 info.lid = GetNextLocalID();
309 info.rtc_configuration =
310 "{ servers: " + SerializeServers(config.servers) + ", " +
311 "iceTransportType: " + SerializeIceTransportType(config.type) + " }";
313 info.constraints = SerializeMediaConstraints(constraints);
314 info.url = frame->document().url().spec();
315 RenderThreadImpl::current()->Send(
316 new PeerConnectionTrackerHost_AddPeerConnection(info));
318 DCHECK(peer_connection_id_map_.find(pc_handler) ==
319 peer_connection_id_map_.end());
320 peer_connection_id_map_[pc_handler] = info.lid;
323 void PeerConnectionTracker::UnregisterPeerConnection(
324 RTCPeerConnectionHandler* pc_handler) {
325 DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()";
327 std::map<RTCPeerConnectionHandler*, int>::iterator it =
328 peer_connection_id_map_.find(pc_handler);
330 if (it == peer_connection_id_map_.end()) {
331 // The PeerConnection might not have been registered if its initilization
332 // failed.
333 return;
336 RenderThreadImpl::current()->Send(
337 new PeerConnectionTrackerHost_RemovePeerConnection(it->second));
339 peer_connection_id_map_.erase(it);
342 void PeerConnectionTracker::TrackCreateOffer(
343 RTCPeerConnectionHandler* pc_handler,
344 const RTCMediaConstraints& constraints) {
345 SendPeerConnectionUpdate(
346 pc_handler, "createOffer",
347 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
350 void PeerConnectionTracker::TrackCreateAnswer(
351 RTCPeerConnectionHandler* pc_handler,
352 const RTCMediaConstraints& constraints) {
353 SendPeerConnectionUpdate(
354 pc_handler, "createAnswer",
355 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
358 void PeerConnectionTracker::TrackSetSessionDescription(
359 RTCPeerConnectionHandler* pc_handler,
360 const blink::WebRTCSessionDescription& desc,
361 Source source) {
362 string sdp = base::UTF16ToUTF8(desc.sdp());
363 string type = base::UTF16ToUTF8(desc.type());
365 string value = "type: " + type + ", sdp: " + sdp;
366 SendPeerConnectionUpdate(
367 pc_handler,
368 source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
369 value);
372 void PeerConnectionTracker::TrackUpdateIce(
373 RTCPeerConnectionHandler* pc_handler,
374 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
375 const RTCMediaConstraints& options) {
376 string servers_string = "servers: " + SerializeServers(config.servers);
378 string transport_type =
379 "iceTransportType: " + SerializeIceTransportType(config.type);
381 string constraints =
382 "constraints: {" + SerializeMediaConstraints(options) + "}";
384 SendPeerConnectionUpdate(
385 pc_handler,
386 "updateIce",
387 servers_string + ", " + transport_type + ", " + constraints);
390 void PeerConnectionTracker::TrackAddIceCandidate(
391 RTCPeerConnectionHandler* pc_handler,
392 const blink::WebRTCICECandidate& candidate,
393 Source source) {
394 string value = "mid: " + base::UTF16ToUTF8(candidate.sdpMid()) + ", " +
395 "candidate: " + base::UTF16ToUTF8(candidate.candidate());
396 SendPeerConnectionUpdate(
397 pc_handler,
398 source == SOURCE_LOCAL ? "onIceCandidate" : "addIceCandidate", value);
401 void PeerConnectionTracker::TrackAddStream(
402 RTCPeerConnectionHandler* pc_handler,
403 const blink::WebMediaStream& stream,
404 Source source){
405 SendPeerConnectionUpdate(
406 pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
407 SerializeMediaDescriptor(stream));
410 void PeerConnectionTracker::TrackRemoveStream(
411 RTCPeerConnectionHandler* pc_handler,
412 const blink::WebMediaStream& stream,
413 Source source){
414 SendPeerConnectionUpdate(
415 pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
416 SerializeMediaDescriptor(stream));
419 void PeerConnectionTracker::TrackCreateDataChannel(
420 RTCPeerConnectionHandler* pc_handler,
421 const webrtc::DataChannelInterface* data_channel,
422 Source source) {
423 string value = "label: " + data_channel->label() +
424 ", reliable: " + (data_channel->reliable() ? "true" : "false");
425 SendPeerConnectionUpdate(
426 pc_handler,
427 source == SOURCE_LOCAL ? "createLocalDataChannel" : "onRemoteDataChannel",
428 value);
431 void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
432 SendPeerConnectionUpdate(pc_handler, "stop", std::string());
435 void PeerConnectionTracker::TrackSignalingStateChange(
436 RTCPeerConnectionHandler* pc_handler,
437 WebRTCPeerConnectionHandlerClient::SignalingState state) {
438 SendPeerConnectionUpdate(
439 pc_handler, "signalingStateChange", GetSignalingStateString(state));
442 void PeerConnectionTracker::TrackIceConnectionStateChange(
443 RTCPeerConnectionHandler* pc_handler,
444 WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
445 SendPeerConnectionUpdate(
446 pc_handler, "iceConnectionStateChange",
447 GetIceConnectionStateString(state));
450 void PeerConnectionTracker::TrackIceGatheringStateChange(
451 RTCPeerConnectionHandler* pc_handler,
452 WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
453 SendPeerConnectionUpdate(
454 pc_handler, "iceGatheringStateChange",
455 GetIceGatheringStateString(state));
458 void PeerConnectionTracker::TrackSessionDescriptionCallback(
459 RTCPeerConnectionHandler* pc_handler, Action action,
460 const string& callback_type, const string& value) {
461 string update_type;
462 switch (action) {
463 case ACTION_SET_LOCAL_DESCRIPTION:
464 update_type = "setLocalDescription";
465 break;
466 case ACTION_SET_REMOTE_DESCRIPTION:
467 update_type = "setRemoteDescription";
468 break;
469 case ACTION_CREATE_OFFER:
470 update_type = "createOffer";
471 break;
472 case ACTION_CREATE_ANSWER:
473 update_type = "createAnswer";
474 break;
475 default:
476 NOTREACHED();
477 break;
479 update_type += callback_type;
481 SendPeerConnectionUpdate(pc_handler, update_type, value);
484 void PeerConnectionTracker::TrackOnRenegotiationNeeded(
485 RTCPeerConnectionHandler* pc_handler) {
486 SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
489 void PeerConnectionTracker::TrackCreateDTMFSender(
490 RTCPeerConnectionHandler* pc_handler,
491 const blink::WebMediaStreamTrack& track) {
492 SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
493 base::UTF16ToUTF8(track.id()));
496 void PeerConnectionTracker::TrackGetUserMedia(
497 const blink::WebUserMediaRequest& user_media_request) {
498 RTCMediaConstraints audio_constraints(
499 GetNativeMediaConstraints(user_media_request.audioConstraints()));
500 RTCMediaConstraints video_constraints(
501 GetNativeMediaConstraints(user_media_request.videoConstraints()));
503 RenderThreadImpl::current()->Send(new PeerConnectionTrackerHost_GetUserMedia(
504 user_media_request.securityOrigin().toString().utf8(),
505 user_media_request.audio(),
506 user_media_request.video(),
507 SerializeMediaConstraints(audio_constraints),
508 SerializeMediaConstraints(video_constraints)));
511 int PeerConnectionTracker::GetNextLocalID() {
512 return next_lid_++;
515 void PeerConnectionTracker::SendPeerConnectionUpdate(
516 RTCPeerConnectionHandler* pc_handler,
517 const std::string& type,
518 const std::string& value) {
519 if (peer_connection_id_map_.find(pc_handler) == peer_connection_id_map_.end())
520 return;
522 RenderThreadImpl::current()->Send(
523 new PeerConnectionTrackerHost_UpdatePeerConnection(
524 peer_connection_id_map_[pc_handler], type, value));
527 } // namespace content