• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
5 
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/WebMediaStream.h"
12 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
13 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
14 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
15 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
16 #include "third_party/WebKit/public/web/WebDocument.h"
17 #include "third_party/WebKit/public/web/WebFrame.h"
18 
19 using std::string;
20 using webrtc::MediaConstraintsInterface;
21 using blink::WebRTCPeerConnectionHandlerClient;
22 
23 namespace content {
24 
SerializeServers(const std::vector<webrtc::PeerConnectionInterface::IceServer> & servers)25 static string SerializeServers(
26     const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
27   string result = "[";
28   for (size_t i = 0; i < servers.size(); ++i) {
29     result += servers[i].uri;
30     if (i != servers.size() - 1)
31       result += ", ";
32   }
33   result += "]";
34   return result;
35 }
36 
SerializeMediaConstraints(const RTCMediaConstraints & constraints)37 static string SerializeMediaConstraints(
38     const RTCMediaConstraints& constraints) {
39   string result;
40   MediaConstraintsInterface::Constraints mandatory = constraints.GetMandatory();
41   if (!mandatory.empty()) {
42     result += "mandatory: {";
43     for (size_t i = 0; i < mandatory.size(); ++i) {
44       result += mandatory[i].key + ":" + mandatory[i].value;
45       if (i != mandatory.size() - 1)
46         result += ", ";
47     }
48     result += "}";
49   }
50   MediaConstraintsInterface::Constraints optional = constraints.GetOptional();
51   if (!optional.empty()) {
52     if (!result.empty())
53       result += ", ";
54     result += "optional: {";
55     for (size_t i = 0; i < optional.size(); ++i) {
56       result += optional[i].key + ":" + optional[i].value;
57       if (i != optional.size() - 1)
58         result += ", ";
59     }
60     result += "}";
61   }
62   return result;
63 }
64 
SerializeMediaStreamComponent(const blink::WebMediaStreamTrack component)65 static string SerializeMediaStreamComponent(
66     const blink::WebMediaStreamTrack component) {
67   string id = UTF16ToUTF8(component.source().id());
68   return id;
69 }
70 
SerializeMediaDescriptor(const blink::WebMediaStream & stream)71 static string SerializeMediaDescriptor(
72     const blink::WebMediaStream& stream) {
73   string label = UTF16ToUTF8(stream.id());
74   string result = "label: " + label;
75   blink::WebVector<blink::WebMediaStreamTrack> tracks;
76   stream.audioTracks(tracks);
77   if (!tracks.isEmpty()) {
78     result += ", audio: [";
79     for (size_t i = 0; i < tracks.size(); ++i) {
80       result += SerializeMediaStreamComponent(tracks[i]);
81       if (i != tracks.size() - 1)
82         result += ", ";
83     }
84     result += "]";
85   }
86   stream.videoTracks(tracks);
87   if (!tracks.isEmpty()) {
88     result += ", video: [";
89     for (size_t i = 0; i < tracks.size(); ++i) {
90       result += SerializeMediaStreamComponent(tracks[i]);
91       if (i != tracks.size() - 1)
92         result += ", ";
93     }
94     result += "]";
95   }
96   return result;
97 }
98 
99 #define GET_STRING_OF_STATE(state)                \
100   case WebRTCPeerConnectionHandlerClient::state:  \
101     result = #state;                              \
102     break;
103 
GetSignalingStateString(WebRTCPeerConnectionHandlerClient::SignalingState state)104 static string GetSignalingStateString(
105     WebRTCPeerConnectionHandlerClient::SignalingState state) {
106   string result;
107   switch (state) {
108     GET_STRING_OF_STATE(SignalingStateStable)
109     GET_STRING_OF_STATE(SignalingStateHaveLocalOffer)
110     GET_STRING_OF_STATE(SignalingStateHaveRemoteOffer)
111     GET_STRING_OF_STATE(SignalingStateHaveLocalPrAnswer)
112     GET_STRING_OF_STATE(SignalingStateHaveRemotePrAnswer)
113     GET_STRING_OF_STATE(SignalingStateClosed)
114     default:
115       NOTREACHED();
116       break;
117   }
118   return result;
119 }
120 
GetIceConnectionStateString(WebRTCPeerConnectionHandlerClient::ICEConnectionState state)121 static string GetIceConnectionStateString(
122     WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
123   string result;
124   switch (state) {
125     GET_STRING_OF_STATE(ICEConnectionStateStarting)
126     GET_STRING_OF_STATE(ICEConnectionStateChecking)
127     GET_STRING_OF_STATE(ICEConnectionStateConnected)
128     GET_STRING_OF_STATE(ICEConnectionStateCompleted)
129     GET_STRING_OF_STATE(ICEConnectionStateFailed)
130     GET_STRING_OF_STATE(ICEConnectionStateDisconnected)
131     GET_STRING_OF_STATE(ICEConnectionStateClosed)
132     default:
133       NOTREACHED();
134       break;
135   }
136   return result;
137 }
138 
GetIceGatheringStateString(WebRTCPeerConnectionHandlerClient::ICEGatheringState state)139 static string GetIceGatheringStateString(
140     WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
141   string result;
142   switch (state) {
143     GET_STRING_OF_STATE(ICEGatheringStateNew)
144     GET_STRING_OF_STATE(ICEGatheringStateGathering)
145     GET_STRING_OF_STATE(ICEGatheringStateComplete)
146     default:
147       NOTREACHED();
148       break;
149   }
150   return result;
151 }
152 
153 // Builds a DictionaryValue from the StatsReport.
154 // The caller takes the ownership of the returned value.
155 // Note:
156 // The format must be consistent with what webrtc_internals.js expects.
157 // If you change it here, you must change webrtc_internals.js as well.
GetDictValueStats(const webrtc::StatsReport & report)158 static base::DictionaryValue* GetDictValueStats(
159     const webrtc::StatsReport& report) {
160   if (report.values.empty())
161     return NULL;
162 
163   DictionaryValue* dict = new base::DictionaryValue();
164   dict->SetDouble("timestamp", report.timestamp);
165 
166   base::ListValue* values = new base::ListValue();
167   dict->Set("values", values);
168 
169   for (size_t i = 0; i < report.values.size(); ++i) {
170     values->AppendString(report.values[i].name);
171     values->AppendString(report.values[i].value);
172   }
173   return dict;
174 }
175 
176 // Builds a DictionaryValue from the StatsReport.
177 // The caller takes the ownership of the returned value.
GetDictValue(const webrtc::StatsReport & report)178 static base::DictionaryValue* GetDictValue(const webrtc::StatsReport& report) {
179   scoped_ptr<base::DictionaryValue> stats, result;
180 
181   stats.reset(GetDictValueStats(report));
182   if (!stats)
183     return NULL;
184 
185   result.reset(new base::DictionaryValue());
186   // Note:
187   // The format must be consistent with what webrtc_internals.js expects.
188   // If you change it here, you must change webrtc_internals.js as well.
189   result->Set("stats", stats.release());
190   result->SetString("id", report.id);
191   result->SetString("type", report.type);
192 
193   return result.release();
194 }
195 
196 class InternalStatsObserver : public webrtc::StatsObserver {
197  public:
InternalStatsObserver(int lid)198   InternalStatsObserver(int lid)
199       : lid_(lid){}
200 
OnComplete(const std::vector<webrtc::StatsReport> & reports)201   virtual void OnComplete(
202       const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
203     base::ListValue list;
204 
205     for (size_t i = 0; i < reports.size(); ++i) {
206       base::DictionaryValue* report = GetDictValue(reports[i]);
207       if (report)
208         list.Append(report);
209     }
210 
211     if (!list.empty())
212       RenderThreadImpl::current()->Send(
213           new PeerConnectionTrackerHost_AddStats(lid_, list));
214   }
215 
216  protected:
~InternalStatsObserver()217   virtual ~InternalStatsObserver() {}
218 
219  private:
220   int lid_;
221 };
222 
PeerConnectionTracker()223 PeerConnectionTracker::PeerConnectionTracker() : next_lid_(1) {
224 }
225 
~PeerConnectionTracker()226 PeerConnectionTracker::~PeerConnectionTracker() {
227 }
228 
OnControlMessageReceived(const IPC::Message & message)229 bool PeerConnectionTracker::OnControlMessageReceived(
230     const IPC::Message& message) {
231   bool handled = true;
232   IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message)
233     IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats)
234     IPC_MESSAGE_UNHANDLED(handled = false)
235   IPC_END_MESSAGE_MAP()
236   return handled;
237 }
238 
OnGetAllStats()239 void PeerConnectionTracker::OnGetAllStats() {
240   for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
241        it != peer_connection_id_map_.end(); ++it) {
242 
243     talk_base::scoped_refptr<InternalStatsObserver> observer(
244         new talk_base::RefCountedObject<InternalStatsObserver>(it->second));
245 
246     it->first->GetStats(observer, NULL);
247   }
248 }
249 
RegisterPeerConnection(RTCPeerConnectionHandler * pc_handler,const std::vector<webrtc::PeerConnectionInterface::IceServer> & servers,const RTCMediaConstraints & constraints,const blink::WebFrame * frame)250 void PeerConnectionTracker::RegisterPeerConnection(
251     RTCPeerConnectionHandler* pc_handler,
252     const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
253     const RTCMediaConstraints& constraints,
254     const blink::WebFrame* frame) {
255   DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
256   PeerConnectionInfo info;
257 
258   info.lid = GetNextLocalID();
259   info.servers = SerializeServers(servers);
260   info.constraints = SerializeMediaConstraints(constraints);
261   info.url = frame->document().url().spec();
262   RenderThreadImpl::current()->Send(
263       new PeerConnectionTrackerHost_AddPeerConnection(info));
264 
265   DCHECK(peer_connection_id_map_.find(pc_handler) ==
266          peer_connection_id_map_.end());
267   peer_connection_id_map_[pc_handler] = info.lid;
268 }
269 
UnregisterPeerConnection(RTCPeerConnectionHandler * pc_handler)270 void PeerConnectionTracker::UnregisterPeerConnection(
271     RTCPeerConnectionHandler* pc_handler) {
272   DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()";
273 
274   std::map<RTCPeerConnectionHandler*, int>::iterator it =
275       peer_connection_id_map_.find(pc_handler);
276 
277   if (it == peer_connection_id_map_.end()) {
278     // The PeerConnection might not have been registered if its initilization
279     // failed.
280     return;
281   }
282 
283   RenderThreadImpl::current()->Send(
284       new PeerConnectionTrackerHost_RemovePeerConnection(it->second));
285 
286   peer_connection_id_map_.erase(it);
287 }
288 
TrackCreateOffer(RTCPeerConnectionHandler * pc_handler,const RTCMediaConstraints & constraints)289 void PeerConnectionTracker::TrackCreateOffer(
290     RTCPeerConnectionHandler* pc_handler,
291     const RTCMediaConstraints& constraints) {
292   SendPeerConnectionUpdate(
293       pc_handler, "createOffer",
294       "constraints: {" + SerializeMediaConstraints(constraints) + "}");
295 }
296 
TrackCreateAnswer(RTCPeerConnectionHandler * pc_handler,const RTCMediaConstraints & constraints)297 void PeerConnectionTracker::TrackCreateAnswer(
298     RTCPeerConnectionHandler* pc_handler,
299     const RTCMediaConstraints& constraints) {
300   SendPeerConnectionUpdate(
301       pc_handler, "createAnswer",
302       "constraints: {" + SerializeMediaConstraints(constraints) + "}");
303 }
304 
TrackSetSessionDescription(RTCPeerConnectionHandler * pc_handler,const blink::WebRTCSessionDescription & desc,Source source)305 void PeerConnectionTracker::TrackSetSessionDescription(
306     RTCPeerConnectionHandler* pc_handler,
307     const blink::WebRTCSessionDescription& desc,
308     Source source) {
309   string sdp = UTF16ToUTF8(desc.sdp());
310   string type = UTF16ToUTF8(desc.type());
311 
312   string value = "type: " + type + ", sdp: " + sdp;
313   SendPeerConnectionUpdate(
314       pc_handler,
315       source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
316       value);
317 }
318 
TrackUpdateIce(RTCPeerConnectionHandler * pc_handler,const std::vector<webrtc::PeerConnectionInterface::IceServer> & servers,const RTCMediaConstraints & options)319 void PeerConnectionTracker::TrackUpdateIce(
320       RTCPeerConnectionHandler* pc_handler,
321       const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
322       const RTCMediaConstraints& options) {
323   string servers_string = "servers: " + SerializeServers(servers);
324   string constraints =
325       "constraints: {" + SerializeMediaConstraints(options) + "}";
326 
327   SendPeerConnectionUpdate(
328       pc_handler, "updateIce", servers_string + ", " + constraints);
329 }
330 
TrackAddIceCandidate(RTCPeerConnectionHandler * pc_handler,const blink::WebRTCICECandidate & candidate,Source source)331 void PeerConnectionTracker::TrackAddIceCandidate(
332       RTCPeerConnectionHandler* pc_handler,
333       const blink::WebRTCICECandidate& candidate,
334       Source source) {
335   string value = "mid: " + UTF16ToUTF8(candidate.sdpMid()) + ", " +
336                  "candidate: " + UTF16ToUTF8(candidate.candidate());
337   SendPeerConnectionUpdate(
338       pc_handler,
339       source == SOURCE_LOCAL ? "onIceCandidate" : "addIceCandidate", value);
340 }
341 
TrackAddStream(RTCPeerConnectionHandler * pc_handler,const blink::WebMediaStream & stream,Source source)342 void PeerConnectionTracker::TrackAddStream(
343     RTCPeerConnectionHandler* pc_handler,
344     const blink::WebMediaStream& stream,
345     Source source){
346   SendPeerConnectionUpdate(
347       pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
348       SerializeMediaDescriptor(stream));
349 }
350 
TrackRemoveStream(RTCPeerConnectionHandler * pc_handler,const blink::WebMediaStream & stream,Source source)351 void PeerConnectionTracker::TrackRemoveStream(
352     RTCPeerConnectionHandler* pc_handler,
353     const blink::WebMediaStream& stream,
354     Source source){
355   SendPeerConnectionUpdate(
356       pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
357       SerializeMediaDescriptor(stream));
358 }
359 
TrackCreateDataChannel(RTCPeerConnectionHandler * pc_handler,const webrtc::DataChannelInterface * data_channel,Source source)360 void PeerConnectionTracker::TrackCreateDataChannel(
361     RTCPeerConnectionHandler* pc_handler,
362     const webrtc::DataChannelInterface* data_channel,
363     Source source) {
364   string value = "label: " + data_channel->label() +
365                  ", reliable: " + (data_channel->reliable() ? "true" : "false");
366   SendPeerConnectionUpdate(
367       pc_handler,
368       source == SOURCE_LOCAL ? "createLocalDataChannel" : "onRemoteDataChannel",
369       value);
370 }
371 
TrackStop(RTCPeerConnectionHandler * pc_handler)372 void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
373   SendPeerConnectionUpdate(pc_handler, "stop", std::string());
374 }
375 
TrackSignalingStateChange(RTCPeerConnectionHandler * pc_handler,WebRTCPeerConnectionHandlerClient::SignalingState state)376 void PeerConnectionTracker::TrackSignalingStateChange(
377       RTCPeerConnectionHandler* pc_handler,
378       WebRTCPeerConnectionHandlerClient::SignalingState state) {
379   SendPeerConnectionUpdate(
380       pc_handler, "signalingStateChange", GetSignalingStateString(state));
381 }
382 
TrackIceConnectionStateChange(RTCPeerConnectionHandler * pc_handler,WebRTCPeerConnectionHandlerClient::ICEConnectionState state)383 void PeerConnectionTracker::TrackIceConnectionStateChange(
384       RTCPeerConnectionHandler* pc_handler,
385       WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
386   SendPeerConnectionUpdate(
387       pc_handler, "iceConnectionStateChange",
388       GetIceConnectionStateString(state));
389 }
390 
TrackIceGatheringStateChange(RTCPeerConnectionHandler * pc_handler,WebRTCPeerConnectionHandlerClient::ICEGatheringState state)391 void PeerConnectionTracker::TrackIceGatheringStateChange(
392       RTCPeerConnectionHandler* pc_handler,
393       WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
394   SendPeerConnectionUpdate(
395       pc_handler, "iceGatheringStateChange",
396       GetIceGatheringStateString(state));
397 }
398 
TrackSessionDescriptionCallback(RTCPeerConnectionHandler * pc_handler,Action action,const string & callback_type,const string & value)399 void PeerConnectionTracker::TrackSessionDescriptionCallback(
400     RTCPeerConnectionHandler* pc_handler, Action action,
401     const string& callback_type, const string& value) {
402   string update_type;
403   switch (action) {
404     case ACTION_SET_LOCAL_DESCRIPTION:
405       update_type = "setLocalDescription";
406       break;
407     case ACTION_SET_REMOTE_DESCRIPTION:
408       update_type = "setRemoteDescription";
409       break;
410     case ACTION_CREATE_OFFER:
411       update_type = "createOffer";
412       break;
413     case ACTION_CREATE_ANSWER:
414       update_type = "createAnswer";
415       break;
416     default:
417       NOTREACHED();
418       break;
419   }
420   update_type += callback_type;
421 
422   SendPeerConnectionUpdate(pc_handler, update_type, value);
423 }
424 
TrackOnRenegotiationNeeded(RTCPeerConnectionHandler * pc_handler)425 void PeerConnectionTracker::TrackOnRenegotiationNeeded(
426     RTCPeerConnectionHandler* pc_handler) {
427   SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
428 }
429 
TrackCreateDTMFSender(RTCPeerConnectionHandler * pc_handler,const blink::WebMediaStreamTrack & track)430 void PeerConnectionTracker::TrackCreateDTMFSender(
431     RTCPeerConnectionHandler* pc_handler,
432     const blink::WebMediaStreamTrack& track) {
433   SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
434                            UTF16ToUTF8(track.id()));
435 }
436 
GetNextLocalID()437 int PeerConnectionTracker::GetNextLocalID() {
438   return next_lid_++;
439 }
440 
SendPeerConnectionUpdate(RTCPeerConnectionHandler * pc_handler,const std::string & type,const std::string & value)441 void PeerConnectionTracker::SendPeerConnectionUpdate(
442     RTCPeerConnectionHandler* pc_handler,
443     const std::string& type,
444     const std::string& value) {
445   if (peer_connection_id_map_.find(pc_handler) == peer_connection_id_map_.end())
446     return;
447 
448   RenderThreadImpl::current()->Send(
449       new PeerConnectionTrackerHost_UpdatePeerConnection(
450           peer_connection_id_map_[pc_handler], type, value));
451 }
452 
453 }  // namespace content
454