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