[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / content / renderer / media / peer_connection_tracker.cc
blob2075cdd00420e0abc7665b0f90ad5c72dfb309d2
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/string_number_conversions.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "content/common/media/peer_connection_tracker_messages.h"
10 #include "content/renderer/media/rtc_media_constraints.h"
11 #include "content/renderer/media/rtc_peer_connection_handler.h"
12 #include "content/renderer/render_thread_impl.h"
13 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
14 #include "third_party/WebKit/public/platform/WebMediaStream.h"
15 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
16 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
17 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
18 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
19 #include "third_party/WebKit/public/web/WebDocument.h"
20 #include "third_party/WebKit/public/web/WebFrame.h"
21 #include "third_party/WebKit/public/web/WebUserMediaRequest.h"
23 using std::string;
24 using webrtc::MediaConstraintsInterface;
25 using blink::WebRTCPeerConnectionHandlerClient;
27 namespace content {
29 static string SerializeServers(
30 const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
31 string result = "[";
32 for (size_t i = 0; i < servers.size(); ++i) {
33 result += servers[i].uri;
34 if (i != servers.size() - 1)
35 result += ", ";
37 result += "]";
38 return result;
41 static RTCMediaConstraints GetNativeMediaConstraints(
42 const blink::WebMediaConstraints& constraints) {
43 RTCMediaConstraints native_constraints;
45 if (constraints.isNull())
46 return native_constraints;
48 blink::WebVector<blink::WebMediaConstraint> mandatory;
49 constraints.getMandatoryConstraints(mandatory);
50 for (size_t i = 0; i < mandatory.size(); ++i) {
51 native_constraints.AddMandatory(
52 mandatory[i].m_name.utf8(), mandatory[i].m_value.utf8(), false);
55 blink::WebVector<blink::WebMediaConstraint> optional;
56 constraints.getOptionalConstraints(optional);
57 for (size_t i = 0; i < optional.size(); ++i) {
58 native_constraints.AddOptional(
59 optional[i].m_name.utf8(), optional[i].m_value.utf8(), false);
61 return native_constraints;
64 static string SerializeMediaConstraints(
65 const RTCMediaConstraints& constraints) {
66 string result;
67 MediaConstraintsInterface::Constraints mandatory = constraints.GetMandatory();
68 if (!mandatory.empty()) {
69 result += "mandatory: {";
70 for (size_t i = 0; i < mandatory.size(); ++i) {
71 result += mandatory[i].key + ":" + mandatory[i].value;
72 if (i != mandatory.size() - 1)
73 result += ", ";
75 result += "}";
77 MediaConstraintsInterface::Constraints optional = constraints.GetOptional();
78 if (!optional.empty()) {
79 if (!result.empty())
80 result += ", ";
81 result += "optional: {";
82 for (size_t i = 0; i < optional.size(); ++i) {
83 result += optional[i].key + ":" + optional[i].value;
84 if (i != optional.size() - 1)
85 result += ", ";
87 result += "}";
89 return result;
92 static string SerializeMediaStreamComponent(
93 const blink::WebMediaStreamTrack component) {
94 string id = base::UTF16ToUTF8(component.source().id());
95 return id;
98 static string SerializeMediaDescriptor(
99 const blink::WebMediaStream& stream) {
100 string label = base::UTF16ToUTF8(stream.id());
101 string result = "label: " + label;
102 blink::WebVector<blink::WebMediaStreamTrack> tracks;
103 stream.audioTracks(tracks);
104 if (!tracks.isEmpty()) {
105 result += ", audio: [";
106 for (size_t i = 0; i < tracks.size(); ++i) {
107 result += SerializeMediaStreamComponent(tracks[i]);
108 if (i != tracks.size() - 1)
109 result += ", ";
111 result += "]";
113 stream.videoTracks(tracks);
114 if (!tracks.isEmpty()) {
115 result += ", video: [";
116 for (size_t i = 0; i < tracks.size(); ++i) {
117 result += SerializeMediaStreamComponent(tracks[i]);
118 if (i != tracks.size() - 1)
119 result += ", ";
121 result += "]";
123 return result;
126 static std::string SerializeIceTransportType(
127 webrtc::PeerConnectionInterface::IceTransportsType type) {
128 string transport_type;
129 switch (type) {
130 case webrtc::PeerConnectionInterface::kNone:
131 transport_type = "none";
132 break;
133 case webrtc::PeerConnectionInterface::kRelay:
134 transport_type = "relay";
135 break;
136 case webrtc::PeerConnectionInterface::kAll:
137 transport_type = "all";
138 break;
139 case webrtc::PeerConnectionInterface::kNoHost:
140 transport_type = "noHost";
141 break;
142 default:
143 NOTREACHED();
145 return transport_type;
148 #define GET_STRING_OF_STATE(state) \
149 case WebRTCPeerConnectionHandlerClient::state: \
150 result = #state; \
151 break;
153 static string GetSignalingStateString(
154 WebRTCPeerConnectionHandlerClient::SignalingState state) {
155 string result;
156 switch (state) {
157 GET_STRING_OF_STATE(SignalingStateStable)
158 GET_STRING_OF_STATE(SignalingStateHaveLocalOffer)
159 GET_STRING_OF_STATE(SignalingStateHaveRemoteOffer)
160 GET_STRING_OF_STATE(SignalingStateHaveLocalPrAnswer)
161 GET_STRING_OF_STATE(SignalingStateHaveRemotePrAnswer)
162 GET_STRING_OF_STATE(SignalingStateClosed)
163 default:
164 NOTREACHED();
165 break;
167 return result;
170 static string GetIceConnectionStateString(
171 WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
172 string result;
173 switch (state) {
174 GET_STRING_OF_STATE(ICEConnectionStateStarting)
175 GET_STRING_OF_STATE(ICEConnectionStateChecking)
176 GET_STRING_OF_STATE(ICEConnectionStateConnected)
177 GET_STRING_OF_STATE(ICEConnectionStateCompleted)
178 GET_STRING_OF_STATE(ICEConnectionStateFailed)
179 GET_STRING_OF_STATE(ICEConnectionStateDisconnected)
180 GET_STRING_OF_STATE(ICEConnectionStateClosed)
181 default:
182 NOTREACHED();
183 break;
185 return result;
188 static string GetIceGatheringStateString(
189 WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
190 string result;
191 switch (state) {
192 GET_STRING_OF_STATE(ICEGatheringStateNew)
193 GET_STRING_OF_STATE(ICEGatheringStateGathering)
194 GET_STRING_OF_STATE(ICEGatheringStateComplete)
195 default:
196 NOTREACHED();
197 break;
199 return result;
202 // Builds a DictionaryValue from the StatsReport.
203 // The caller takes the ownership of the returned value.
204 // Note:
205 // The format must be consistent with what webrtc_internals.js expects.
206 // If you change it here, you must change webrtc_internals.js as well.
207 static base::DictionaryValue* GetDictValueStats(
208 const webrtc::StatsReport& report) {
209 if (report.values().empty())
210 return NULL;
212 base::DictionaryValue* dict = new base::DictionaryValue();
213 dict->SetDouble("timestamp", report.timestamp());
215 base::ListValue* values = new base::ListValue();
216 dict->Set("values", values);
218 for (const auto& v : report.values()) {
219 values->AppendString(v->display_name());
220 values->AppendString(v->value);
223 return dict;
226 // Builds a DictionaryValue from the StatsReport.
227 // The caller takes the ownership of the returned value.
228 static base::DictionaryValue* GetDictValue(const webrtc::StatsReport& report) {
229 scoped_ptr<base::DictionaryValue> stats, result;
231 stats.reset(GetDictValueStats(report));
232 if (!stats)
233 return NULL;
235 result.reset(new base::DictionaryValue());
236 // Note:
237 // The format must be consistent with what webrtc_internals.js expects.
238 // If you change it here, you must change webrtc_internals.js as well.
239 result->Set("stats", stats.release());
240 result->SetString("id", report.id().ToString());
241 result->SetString("type", report.TypeToString());
243 return result.release();
246 class InternalStatsObserver : public webrtc::StatsObserver {
247 public:
248 InternalStatsObserver(int lid)
249 : lid_(lid), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
251 void OnComplete(const webrtc::StatsReports& reports) override {
252 scoped_ptr<base::ListValue> list(new base::ListValue());
254 for (const auto* r : reports) {
255 base::DictionaryValue* report = GetDictValue(*r);
256 if (report)
257 list->Append(report);
260 if (!list->empty()) {
261 main_thread_->PostTask(FROM_HERE,
262 base::Bind(&InternalStatsObserver::OnCompleteImpl,
263 base::Passed(&list), lid_));
267 protected:
268 ~InternalStatsObserver() override {
269 // Will be destructed on libjingle's signaling thread.
270 // The signaling thread is where libjingle's objects live and from where
271 // libjingle makes callbacks. This may or may not be the same thread as
272 // the main thread.
275 private:
276 // Static since |this| will most likely have been deleted by the time we
277 // get here.
278 static void OnCompleteImpl(scoped_ptr<base::ListValue> list, int lid) {
279 DCHECK(!list->empty());
280 RenderThreadImpl::current()->Send(
281 new PeerConnectionTrackerHost_AddStats(lid, *list.get()));
284 const int lid_;
285 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
288 PeerConnectionTracker::PeerConnectionTracker() : next_lid_(1) {
291 PeerConnectionTracker::~PeerConnectionTracker() {
294 bool PeerConnectionTracker::OnControlMessageReceived(
295 const IPC::Message& message) {
296 bool handled = true;
297 IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message)
298 IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats)
299 IPC_MESSAGE_HANDLER(PeerConnectionTracker_OnSuspend, OnSuspend)
300 IPC_MESSAGE_UNHANDLED(handled = false)
301 IPC_END_MESSAGE_MAP()
302 return handled;
305 void PeerConnectionTracker::OnGetAllStats() {
306 DCHECK(main_thread_.CalledOnValidThread());
308 const std::string empty_track_id;
309 for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
310 it != peer_connection_id_map_.end(); ++it) {
311 rtc::scoped_refptr<InternalStatsObserver> observer(
312 new rtc::RefCountedObject<InternalStatsObserver>(it->second));
314 // The last type parameter is ignored when the track id is empty.
315 it->first->GetStats(
316 observer,
317 webrtc::PeerConnectionInterface::kStatsOutputLevelDebug,
318 empty_track_id, blink::WebMediaStreamSource::TypeAudio);
322 void PeerConnectionTracker::OnSuspend() {
323 DCHECK(main_thread_.CalledOnValidThread());
324 for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
325 it != peer_connection_id_map_.end(); ++it) {
326 it->first->CloseClientPeerConnection();
330 void PeerConnectionTracker::RegisterPeerConnection(
331 RTCPeerConnectionHandler* pc_handler,
332 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
333 const RTCMediaConstraints& constraints,
334 const blink::WebFrame* frame) {
335 DCHECK(main_thread_.CalledOnValidThread());
336 DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
337 PeerConnectionInfo info;
339 info.lid = GetNextLocalID();
340 info.rtc_configuration =
341 "{ servers: " + SerializeServers(config.servers) + ", " +
342 "iceTransportType: " + SerializeIceTransportType(config.type) + " }";
344 info.constraints = SerializeMediaConstraints(constraints);
345 info.url = frame->document().url().spec();
346 RenderThreadImpl::current()->Send(
347 new PeerConnectionTrackerHost_AddPeerConnection(info));
349 DCHECK(peer_connection_id_map_.find(pc_handler) ==
350 peer_connection_id_map_.end());
351 peer_connection_id_map_[pc_handler] = info.lid;
354 void PeerConnectionTracker::UnregisterPeerConnection(
355 RTCPeerConnectionHandler* pc_handler) {
356 DCHECK(main_thread_.CalledOnValidThread());
357 DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()";
359 std::map<RTCPeerConnectionHandler*, int>::iterator it =
360 peer_connection_id_map_.find(pc_handler);
362 if (it == peer_connection_id_map_.end()) {
363 // The PeerConnection might not have been registered if its initilization
364 // failed.
365 return;
368 RenderThreadImpl::current()->Send(
369 new PeerConnectionTrackerHost_RemovePeerConnection(it->second));
371 peer_connection_id_map_.erase(it);
374 void PeerConnectionTracker::TrackCreateOffer(
375 RTCPeerConnectionHandler* pc_handler,
376 const RTCMediaConstraints& constraints) {
377 DCHECK(main_thread_.CalledOnValidThread());
378 SendPeerConnectionUpdate(
379 pc_handler, "createOffer",
380 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
383 void PeerConnectionTracker::TrackCreateAnswer(
384 RTCPeerConnectionHandler* pc_handler,
385 const RTCMediaConstraints& constraints) {
386 DCHECK(main_thread_.CalledOnValidThread());
387 SendPeerConnectionUpdate(
388 pc_handler, "createAnswer",
389 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
392 void PeerConnectionTracker::TrackSetSessionDescription(
393 RTCPeerConnectionHandler* pc_handler,
394 const std::string& sdp, const std::string& type, Source source) {
395 DCHECK(main_thread_.CalledOnValidThread());
396 string value = "type: " + type + ", sdp: " + sdp;
397 SendPeerConnectionUpdate(
398 pc_handler,
399 source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
400 value);
403 void PeerConnectionTracker::TrackUpdateIce(
404 RTCPeerConnectionHandler* pc_handler,
405 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
406 const RTCMediaConstraints& options) {
407 DCHECK(main_thread_.CalledOnValidThread());
408 string servers_string = "servers: " + SerializeServers(config.servers);
410 string transport_type =
411 "iceTransportType: " + SerializeIceTransportType(config.type);
413 string constraints =
414 "constraints: {" + SerializeMediaConstraints(options) + "}";
416 SendPeerConnectionUpdate(
417 pc_handler,
418 "updateIce",
419 servers_string + ", " + transport_type + ", " + constraints);
422 void PeerConnectionTracker::TrackAddIceCandidate(
423 RTCPeerConnectionHandler* pc_handler,
424 const blink::WebRTCICECandidate& candidate,
425 Source source,
426 bool succeeded) {
427 DCHECK(main_thread_.CalledOnValidThread());
428 string value =
429 "sdpMid: " + base::UTF16ToUTF8(candidate.sdpMid()) + ", " +
430 "sdpMLineIndex: " + base::IntToString(candidate.sdpMLineIndex()) + ", " +
431 "candidate: " + base::UTF16ToUTF8(candidate.candidate());
433 // OnIceCandidate always succeeds as it's a callback from the browser.
434 DCHECK(source != SOURCE_LOCAL || succeeded);
436 string event =
437 (source == SOURCE_LOCAL) ? "onIceCandidate"
438 : (succeeded ? "addIceCandidate"
439 : "addIceCandidateFailed");
441 SendPeerConnectionUpdate(pc_handler, event, value);
444 void PeerConnectionTracker::TrackAddStream(
445 RTCPeerConnectionHandler* pc_handler,
446 const blink::WebMediaStream& stream,
447 Source source) {
448 DCHECK(main_thread_.CalledOnValidThread());
449 SendPeerConnectionUpdate(
450 pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
451 SerializeMediaDescriptor(stream));
454 void PeerConnectionTracker::TrackRemoveStream(
455 RTCPeerConnectionHandler* pc_handler,
456 const blink::WebMediaStream& stream,
457 Source source){
458 DCHECK(main_thread_.CalledOnValidThread());
459 SendPeerConnectionUpdate(
460 pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
461 SerializeMediaDescriptor(stream));
464 void PeerConnectionTracker::TrackCreateDataChannel(
465 RTCPeerConnectionHandler* pc_handler,
466 const webrtc::DataChannelInterface* data_channel,
467 Source source) {
468 DCHECK(main_thread_.CalledOnValidThread());
469 string value = "label: " + data_channel->label() +
470 ", reliable: " + (data_channel->reliable() ? "true" : "false");
471 SendPeerConnectionUpdate(
472 pc_handler,
473 source == SOURCE_LOCAL ? "createLocalDataChannel" : "onRemoteDataChannel",
474 value);
477 void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
478 DCHECK(main_thread_.CalledOnValidThread());
479 SendPeerConnectionUpdate(pc_handler, "stop", std::string());
482 void PeerConnectionTracker::TrackSignalingStateChange(
483 RTCPeerConnectionHandler* pc_handler,
484 WebRTCPeerConnectionHandlerClient::SignalingState state) {
485 DCHECK(main_thread_.CalledOnValidThread());
486 SendPeerConnectionUpdate(
487 pc_handler, "signalingStateChange", GetSignalingStateString(state));
490 void PeerConnectionTracker::TrackIceConnectionStateChange(
491 RTCPeerConnectionHandler* pc_handler,
492 WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
493 DCHECK(main_thread_.CalledOnValidThread());
494 SendPeerConnectionUpdate(
495 pc_handler, "iceConnectionStateChange",
496 GetIceConnectionStateString(state));
499 void PeerConnectionTracker::TrackIceGatheringStateChange(
500 RTCPeerConnectionHandler* pc_handler,
501 WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
502 DCHECK(main_thread_.CalledOnValidThread());
503 SendPeerConnectionUpdate(
504 pc_handler, "iceGatheringStateChange",
505 GetIceGatheringStateString(state));
508 void PeerConnectionTracker::TrackSessionDescriptionCallback(
509 RTCPeerConnectionHandler* pc_handler, Action action,
510 const string& callback_type, const string& value) {
511 DCHECK(main_thread_.CalledOnValidThread());
512 string update_type;
513 switch (action) {
514 case ACTION_SET_LOCAL_DESCRIPTION:
515 update_type = "setLocalDescription";
516 break;
517 case ACTION_SET_REMOTE_DESCRIPTION:
518 update_type = "setRemoteDescription";
519 break;
520 case ACTION_CREATE_OFFER:
521 update_type = "createOffer";
522 break;
523 case ACTION_CREATE_ANSWER:
524 update_type = "createAnswer";
525 break;
526 default:
527 NOTREACHED();
528 break;
530 update_type += callback_type;
532 SendPeerConnectionUpdate(pc_handler, update_type, value);
535 void PeerConnectionTracker::TrackOnRenegotiationNeeded(
536 RTCPeerConnectionHandler* pc_handler) {
537 DCHECK(main_thread_.CalledOnValidThread());
538 SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
541 void PeerConnectionTracker::TrackCreateDTMFSender(
542 RTCPeerConnectionHandler* pc_handler,
543 const blink::WebMediaStreamTrack& track) {
544 DCHECK(main_thread_.CalledOnValidThread());
545 SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
546 base::UTF16ToUTF8(track.id()));
549 void PeerConnectionTracker::TrackGetUserMedia(
550 const blink::WebUserMediaRequest& user_media_request) {
551 DCHECK(main_thread_.CalledOnValidThread());
552 RTCMediaConstraints audio_constraints(
553 GetNativeMediaConstraints(user_media_request.audioConstraints()));
554 RTCMediaConstraints video_constraints(
555 GetNativeMediaConstraints(user_media_request.videoConstraints()));
557 RenderThreadImpl::current()->Send(new PeerConnectionTrackerHost_GetUserMedia(
558 user_media_request.securityOrigin().toString().utf8(),
559 user_media_request.audio(),
560 user_media_request.video(),
561 SerializeMediaConstraints(audio_constraints),
562 SerializeMediaConstraints(video_constraints)));
565 int PeerConnectionTracker::GetNextLocalID() {
566 DCHECK(main_thread_.CalledOnValidThread());
567 return next_lid_++;
570 void PeerConnectionTracker::SendPeerConnectionUpdate(
571 RTCPeerConnectionHandler* pc_handler,
572 const std::string& type,
573 const std::string& value) {
574 DCHECK(main_thread_.CalledOnValidThread());
575 if (peer_connection_id_map_.find(pc_handler) == peer_connection_id_map_.end())
576 return;
578 RenderThreadImpl::current()->Send(
579 new PeerConnectionTrackerHost_UpdatePeerConnection(
580 peer_connection_id_map_[pc_handler], type, value));
583 } // namespace content