Don't send a SHChangeNotify for creating an app icon when creating a shortcut.
[chromium-blink-merge.git] / content / renderer / media / peer_connection_tracker.cc
blob728f218db531664e50e5bd098a2971075a764f6d
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 webrtc::StatsReport;
26 using webrtc::StatsReports;
27 using blink::WebRTCPeerConnectionHandlerClient;
29 namespace content {
31 static string SerializeServers(
32 const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
33 string result = "[";
34 for (size_t i = 0; i < servers.size(); ++i) {
35 result += servers[i].uri;
36 if (i != servers.size() - 1)
37 result += ", ";
39 result += "]";
40 return result;
43 static RTCMediaConstraints GetNativeMediaConstraints(
44 const blink::WebMediaConstraints& constraints) {
45 RTCMediaConstraints native_constraints;
47 if (constraints.isNull())
48 return native_constraints;
50 blink::WebVector<blink::WebMediaConstraint> mandatory;
51 constraints.getMandatoryConstraints(mandatory);
52 for (size_t i = 0; i < mandatory.size(); ++i) {
53 native_constraints.AddMandatory(
54 mandatory[i].m_name.utf8(), mandatory[i].m_value.utf8(), false);
57 blink::WebVector<blink::WebMediaConstraint> optional;
58 constraints.getOptionalConstraints(optional);
59 for (size_t i = 0; i < optional.size(); ++i) {
60 native_constraints.AddOptional(
61 optional[i].m_name.utf8(), optional[i].m_value.utf8(), false);
63 return native_constraints;
66 static string SerializeMediaConstraints(
67 const RTCMediaConstraints& constraints) {
68 string result;
69 MediaConstraintsInterface::Constraints mandatory = constraints.GetMandatory();
70 if (!mandatory.empty()) {
71 result += "mandatory: {";
72 for (size_t i = 0; i < mandatory.size(); ++i) {
73 result += mandatory[i].key + ":" + mandatory[i].value;
74 if (i != mandatory.size() - 1)
75 result += ", ";
77 result += "}";
79 MediaConstraintsInterface::Constraints optional = constraints.GetOptional();
80 if (!optional.empty()) {
81 if (!result.empty())
82 result += ", ";
83 result += "optional: {";
84 for (size_t i = 0; i < optional.size(); ++i) {
85 result += optional[i].key + ":" + optional[i].value;
86 if (i != optional.size() - 1)
87 result += ", ";
89 result += "}";
91 return result;
94 static string SerializeMediaStreamComponent(
95 const blink::WebMediaStreamTrack component) {
96 string id = base::UTF16ToUTF8(component.source().id());
97 return id;
100 static string SerializeMediaDescriptor(
101 const blink::WebMediaStream& stream) {
102 string label = base::UTF16ToUTF8(stream.id());
103 string result = "label: " + label;
104 blink::WebVector<blink::WebMediaStreamTrack> tracks;
105 stream.audioTracks(tracks);
106 if (!tracks.isEmpty()) {
107 result += ", audio: [";
108 for (size_t i = 0; i < tracks.size(); ++i) {
109 result += SerializeMediaStreamComponent(tracks[i]);
110 if (i != tracks.size() - 1)
111 result += ", ";
113 result += "]";
115 stream.videoTracks(tracks);
116 if (!tracks.isEmpty()) {
117 result += ", video: [";
118 for (size_t i = 0; i < tracks.size(); ++i) {
119 result += SerializeMediaStreamComponent(tracks[i]);
120 if (i != tracks.size() - 1)
121 result += ", ";
123 result += "]";
125 return result;
128 static std::string SerializeIceTransportType(
129 webrtc::PeerConnectionInterface::IceTransportsType type) {
130 string transport_type;
131 switch (type) {
132 case webrtc::PeerConnectionInterface::kNone:
133 transport_type = "none";
134 break;
135 case webrtc::PeerConnectionInterface::kRelay:
136 transport_type = "relay";
137 break;
138 case webrtc::PeerConnectionInterface::kAll:
139 transport_type = "all";
140 break;
141 case webrtc::PeerConnectionInterface::kNoHost:
142 transport_type = "noHost";
143 break;
144 default:
145 NOTREACHED();
147 return transport_type;
150 #define GET_STRING_OF_STATE(state) \
151 case WebRTCPeerConnectionHandlerClient::state: \
152 result = #state; \
153 break;
155 static string GetSignalingStateString(
156 WebRTCPeerConnectionHandlerClient::SignalingState state) {
157 string result;
158 switch (state) {
159 GET_STRING_OF_STATE(SignalingStateStable)
160 GET_STRING_OF_STATE(SignalingStateHaveLocalOffer)
161 GET_STRING_OF_STATE(SignalingStateHaveRemoteOffer)
162 GET_STRING_OF_STATE(SignalingStateHaveLocalPrAnswer)
163 GET_STRING_OF_STATE(SignalingStateHaveRemotePrAnswer)
164 GET_STRING_OF_STATE(SignalingStateClosed)
165 default:
166 NOTREACHED();
167 break;
169 return result;
172 static string GetIceConnectionStateString(
173 WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
174 string result;
175 switch (state) {
176 GET_STRING_OF_STATE(ICEConnectionStateStarting)
177 GET_STRING_OF_STATE(ICEConnectionStateChecking)
178 GET_STRING_OF_STATE(ICEConnectionStateConnected)
179 GET_STRING_OF_STATE(ICEConnectionStateCompleted)
180 GET_STRING_OF_STATE(ICEConnectionStateFailed)
181 GET_STRING_OF_STATE(ICEConnectionStateDisconnected)
182 GET_STRING_OF_STATE(ICEConnectionStateClosed)
183 default:
184 NOTREACHED();
185 break;
187 return result;
190 static string GetIceGatheringStateString(
191 WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
192 string result;
193 switch (state) {
194 GET_STRING_OF_STATE(ICEGatheringStateNew)
195 GET_STRING_OF_STATE(ICEGatheringStateGathering)
196 GET_STRING_OF_STATE(ICEGatheringStateComplete)
197 default:
198 NOTREACHED();
199 break;
201 return result;
204 // Builds a DictionaryValue from the StatsReport.
205 // The caller takes the ownership of the returned value.
206 // Note:
207 // The format must be consistent with what webrtc_internals.js expects.
208 // If you change it here, you must change webrtc_internals.js as well.
209 static base::DictionaryValue* GetDictValueStats(const StatsReport& report) {
210 if (report.values().empty())
211 return NULL;
213 base::DictionaryValue* dict = new base::DictionaryValue();
214 dict->SetDouble("timestamp", report.timestamp());
216 base::ListValue* values = new base::ListValue();
217 dict->Set("values", values);
219 for (const auto& v : report.values()) {
220 const StatsReport::ValuePtr& value = v.second;
221 values->AppendString(value->display_name());
222 switch (value->type()) {
223 case StatsReport::Value::kInt:
224 values->AppendInteger(value->int_val());
225 break;
226 case StatsReport::Value::kFloat:
227 values->AppendDouble(value->float_val());
228 break;
229 case StatsReport::Value::kString:
230 values->AppendString(value->string_val());
231 break;
232 case StatsReport::Value::kStaticString:
233 values->AppendString(value->static_string_val());
234 break;
235 case StatsReport::Value::kBool:
236 values->AppendBoolean(value->bool_val());
237 break;
238 case StatsReport::Value::kInt64: // int64 isn't supported, so use string.
239 case StatsReport::Value::kId:
240 default:
241 values->AppendString(value->ToString());
242 break;
246 return dict;
249 // Builds a DictionaryValue from the StatsReport.
250 // The caller takes the ownership of the returned value.
251 static base::DictionaryValue* GetDictValue(const StatsReport& report) {
252 scoped_ptr<base::DictionaryValue> stats, result;
254 stats.reset(GetDictValueStats(report));
255 if (!stats)
256 return NULL;
258 result.reset(new base::DictionaryValue());
259 // Note:
260 // The format must be consistent with what webrtc_internals.js expects.
261 // If you change it here, you must change webrtc_internals.js as well.
262 result->Set("stats", stats.release());
263 result->SetString("id", report.id()->ToString());
264 result->SetString("type", report.TypeToString());
266 return result.release();
269 class InternalStatsObserver : public webrtc::StatsObserver {
270 public:
271 InternalStatsObserver(int lid)
272 : lid_(lid), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
274 void OnComplete(const StatsReports& reports) override {
275 scoped_ptr<base::ListValue> list(new base::ListValue());
277 for (const auto* r : reports) {
278 base::DictionaryValue* report = GetDictValue(*r);
279 if (report)
280 list->Append(report);
283 if (!list->empty()) {
284 main_thread_->PostTask(FROM_HERE,
285 base::Bind(&InternalStatsObserver::OnCompleteImpl,
286 base::Passed(&list), lid_));
290 protected:
291 ~InternalStatsObserver() override {
292 // Will be destructed on libjingle's signaling thread.
293 // The signaling thread is where libjingle's objects live and from where
294 // libjingle makes callbacks. This may or may not be the same thread as
295 // the main thread.
298 private:
299 // Static since |this| will most likely have been deleted by the time we
300 // get here.
301 static void OnCompleteImpl(scoped_ptr<base::ListValue> list, int lid) {
302 DCHECK(!list->empty());
303 RenderThreadImpl::current()->Send(
304 new PeerConnectionTrackerHost_AddStats(lid, *list.get()));
307 const int lid_;
308 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
311 PeerConnectionTracker::PeerConnectionTracker() : next_lid_(1) {
314 PeerConnectionTracker::~PeerConnectionTracker() {
317 bool PeerConnectionTracker::OnControlMessageReceived(
318 const IPC::Message& message) {
319 bool handled = true;
320 IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message)
321 IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats)
322 IPC_MESSAGE_HANDLER(PeerConnectionTracker_OnSuspend, OnSuspend)
323 IPC_MESSAGE_UNHANDLED(handled = false)
324 IPC_END_MESSAGE_MAP()
325 return handled;
328 void PeerConnectionTracker::OnGetAllStats() {
329 DCHECK(main_thread_.CalledOnValidThread());
331 const std::string empty_track_id;
332 for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
333 it != peer_connection_id_map_.end(); ++it) {
334 rtc::scoped_refptr<InternalStatsObserver> observer(
335 new rtc::RefCountedObject<InternalStatsObserver>(it->second));
337 // The last type parameter is ignored when the track id is empty.
338 it->first->GetStats(
339 observer,
340 webrtc::PeerConnectionInterface::kStatsOutputLevelDebug,
341 empty_track_id, blink::WebMediaStreamSource::TypeAudio);
345 void PeerConnectionTracker::OnSuspend() {
346 DCHECK(main_thread_.CalledOnValidThread());
347 for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
348 it != peer_connection_id_map_.end(); ++it) {
349 it->first->CloseClientPeerConnection();
353 void PeerConnectionTracker::RegisterPeerConnection(
354 RTCPeerConnectionHandler* pc_handler,
355 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
356 const RTCMediaConstraints& constraints,
357 const blink::WebFrame* frame) {
358 DCHECK(main_thread_.CalledOnValidThread());
359 DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
360 PeerConnectionInfo info;
362 info.lid = GetNextLocalID();
363 info.rtc_configuration =
364 "{ servers: " + SerializeServers(config.servers) + ", " +
365 "iceTransportType: " + SerializeIceTransportType(config.type) + " }";
367 info.constraints = SerializeMediaConstraints(constraints);
368 info.url = frame->document().url().spec();
369 RenderThreadImpl::current()->Send(
370 new PeerConnectionTrackerHost_AddPeerConnection(info));
372 DCHECK(peer_connection_id_map_.find(pc_handler) ==
373 peer_connection_id_map_.end());
374 peer_connection_id_map_[pc_handler] = info.lid;
377 void PeerConnectionTracker::UnregisterPeerConnection(
378 RTCPeerConnectionHandler* pc_handler) {
379 DCHECK(main_thread_.CalledOnValidThread());
380 DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()";
382 std::map<RTCPeerConnectionHandler*, int>::iterator it =
383 peer_connection_id_map_.find(pc_handler);
385 if (it == peer_connection_id_map_.end()) {
386 // The PeerConnection might not have been registered if its initilization
387 // failed.
388 return;
391 RenderThreadImpl::current()->Send(
392 new PeerConnectionTrackerHost_RemovePeerConnection(it->second));
394 peer_connection_id_map_.erase(it);
397 void PeerConnectionTracker::TrackCreateOffer(
398 RTCPeerConnectionHandler* pc_handler,
399 const RTCMediaConstraints& constraints) {
400 DCHECK(main_thread_.CalledOnValidThread());
401 SendPeerConnectionUpdate(
402 pc_handler, "createOffer",
403 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
406 void PeerConnectionTracker::TrackCreateAnswer(
407 RTCPeerConnectionHandler* pc_handler,
408 const RTCMediaConstraints& constraints) {
409 DCHECK(main_thread_.CalledOnValidThread());
410 SendPeerConnectionUpdate(
411 pc_handler, "createAnswer",
412 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
415 void PeerConnectionTracker::TrackSetSessionDescription(
416 RTCPeerConnectionHandler* pc_handler,
417 const std::string& sdp, const std::string& type, Source source) {
418 DCHECK(main_thread_.CalledOnValidThread());
419 string value = "type: " + type + ", sdp: " + sdp;
420 SendPeerConnectionUpdate(
421 pc_handler,
422 source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
423 value);
426 void PeerConnectionTracker::TrackUpdateIce(
427 RTCPeerConnectionHandler* pc_handler,
428 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
429 const RTCMediaConstraints& options) {
430 DCHECK(main_thread_.CalledOnValidThread());
431 string servers_string = "servers: " + SerializeServers(config.servers);
433 string transport_type =
434 "iceTransportType: " + SerializeIceTransportType(config.type);
436 string constraints =
437 "constraints: {" + SerializeMediaConstraints(options) + "}";
439 SendPeerConnectionUpdate(
440 pc_handler,
441 "updateIce",
442 servers_string + ", " + transport_type + ", " + constraints);
445 void PeerConnectionTracker::TrackAddIceCandidate(
446 RTCPeerConnectionHandler* pc_handler,
447 const blink::WebRTCICECandidate& candidate,
448 Source source,
449 bool succeeded) {
450 DCHECK(main_thread_.CalledOnValidThread());
451 string value =
452 "sdpMid: " + base::UTF16ToUTF8(candidate.sdpMid()) + ", " +
453 "sdpMLineIndex: " + base::IntToString(candidate.sdpMLineIndex()) + ", " +
454 "candidate: " + base::UTF16ToUTF8(candidate.candidate());
456 // OnIceCandidate always succeeds as it's a callback from the browser.
457 DCHECK(source != SOURCE_LOCAL || succeeded);
459 string event =
460 (source == SOURCE_LOCAL) ? "onIceCandidate"
461 : (succeeded ? "addIceCandidate"
462 : "addIceCandidateFailed");
464 SendPeerConnectionUpdate(pc_handler, event, value);
467 void PeerConnectionTracker::TrackAddStream(
468 RTCPeerConnectionHandler* pc_handler,
469 const blink::WebMediaStream& stream,
470 Source source) {
471 DCHECK(main_thread_.CalledOnValidThread());
472 SendPeerConnectionUpdate(
473 pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
474 SerializeMediaDescriptor(stream));
477 void PeerConnectionTracker::TrackRemoveStream(
478 RTCPeerConnectionHandler* pc_handler,
479 const blink::WebMediaStream& stream,
480 Source source){
481 DCHECK(main_thread_.CalledOnValidThread());
482 SendPeerConnectionUpdate(
483 pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
484 SerializeMediaDescriptor(stream));
487 void PeerConnectionTracker::TrackCreateDataChannel(
488 RTCPeerConnectionHandler* pc_handler,
489 const webrtc::DataChannelInterface* data_channel,
490 Source source) {
491 DCHECK(main_thread_.CalledOnValidThread());
492 string value = "label: " + data_channel->label() +
493 ", reliable: " + (data_channel->reliable() ? "true" : "false");
494 SendPeerConnectionUpdate(
495 pc_handler,
496 source == SOURCE_LOCAL ? "createLocalDataChannel" : "onRemoteDataChannel",
497 value);
500 void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
501 DCHECK(main_thread_.CalledOnValidThread());
502 SendPeerConnectionUpdate(pc_handler, "stop", std::string());
505 void PeerConnectionTracker::TrackSignalingStateChange(
506 RTCPeerConnectionHandler* pc_handler,
507 WebRTCPeerConnectionHandlerClient::SignalingState state) {
508 DCHECK(main_thread_.CalledOnValidThread());
509 SendPeerConnectionUpdate(
510 pc_handler, "signalingStateChange", GetSignalingStateString(state));
513 void PeerConnectionTracker::TrackIceConnectionStateChange(
514 RTCPeerConnectionHandler* pc_handler,
515 WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
516 DCHECK(main_thread_.CalledOnValidThread());
517 SendPeerConnectionUpdate(
518 pc_handler, "iceConnectionStateChange",
519 GetIceConnectionStateString(state));
522 void PeerConnectionTracker::TrackIceGatheringStateChange(
523 RTCPeerConnectionHandler* pc_handler,
524 WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
525 DCHECK(main_thread_.CalledOnValidThread());
526 SendPeerConnectionUpdate(
527 pc_handler, "iceGatheringStateChange",
528 GetIceGatheringStateString(state));
531 void PeerConnectionTracker::TrackSessionDescriptionCallback(
532 RTCPeerConnectionHandler* pc_handler, Action action,
533 const string& callback_type, const string& value) {
534 DCHECK(main_thread_.CalledOnValidThread());
535 string update_type;
536 switch (action) {
537 case ACTION_SET_LOCAL_DESCRIPTION:
538 update_type = "setLocalDescription";
539 break;
540 case ACTION_SET_REMOTE_DESCRIPTION:
541 update_type = "setRemoteDescription";
542 break;
543 case ACTION_CREATE_OFFER:
544 update_type = "createOffer";
545 break;
546 case ACTION_CREATE_ANSWER:
547 update_type = "createAnswer";
548 break;
549 default:
550 NOTREACHED();
551 break;
553 update_type += callback_type;
555 SendPeerConnectionUpdate(pc_handler, update_type, value);
558 void PeerConnectionTracker::TrackOnRenegotiationNeeded(
559 RTCPeerConnectionHandler* pc_handler) {
560 DCHECK(main_thread_.CalledOnValidThread());
561 SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
564 void PeerConnectionTracker::TrackCreateDTMFSender(
565 RTCPeerConnectionHandler* pc_handler,
566 const blink::WebMediaStreamTrack& track) {
567 DCHECK(main_thread_.CalledOnValidThread());
568 SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
569 base::UTF16ToUTF8(track.id()));
572 void PeerConnectionTracker::TrackGetUserMedia(
573 const blink::WebUserMediaRequest& user_media_request) {
574 DCHECK(main_thread_.CalledOnValidThread());
575 RTCMediaConstraints audio_constraints(
576 GetNativeMediaConstraints(user_media_request.audioConstraints()));
577 RTCMediaConstraints video_constraints(
578 GetNativeMediaConstraints(user_media_request.videoConstraints()));
580 RenderThreadImpl::current()->Send(new PeerConnectionTrackerHost_GetUserMedia(
581 user_media_request.securityOrigin().toString().utf8(),
582 user_media_request.audio(),
583 user_media_request.video(),
584 SerializeMediaConstraints(audio_constraints),
585 SerializeMediaConstraints(video_constraints)));
588 int PeerConnectionTracker::GetNextLocalID() {
589 DCHECK(main_thread_.CalledOnValidThread());
590 return next_lid_++;
593 void PeerConnectionTracker::SendPeerConnectionUpdate(
594 RTCPeerConnectionHandler* pc_handler,
595 const std::string& type,
596 const std::string& value) {
597 DCHECK(main_thread_.CalledOnValidThread());
598 if (peer_connection_id_map_.find(pc_handler) == peer_connection_id_map_.end())
599 return;
601 RenderThreadImpl::current()->Send(
602 new PeerConnectionTrackerHost_UpdatePeerConnection(
603 peer_connection_id_map_[pc_handler], type, value));
606 } // namespace content