PeerConnectionInterface::GetStats() with selector argument added.

This exposes the stats selection algorithm[1] on the PeerConnection.

Per-spec, there are four flavors of getStats():
1. RTCPeerConnection.getStats().
2. RTCPeerConnection.getStats(MediaStreamTrack selector).
3. RTCRtpSender.getStats().
4. RTCRtpReceiver.getStats().

1) is the parameterless getStats() which is already shipped.
2) is the same as 3) and 4) except the track is used to look up the
corresponding sender/receiver to use as the selector.
3) and 4) perform stats collection with a filter, which is implemented
in RTCStatsCollector.GetStatsReport(selector).

For technical reasons, it is easier to place GetStats() on the
PeerConnection where the RTCStatsCollector lives than to place it on the
sender/receiver. Passing the selector as an argument or as a "this"
makes little difference other than style. Wiring Chrome up such that the
JavaScript APIs is like the spec is trivial after GetStats() is added to
PeerConnectionInterface.

This CL also adds comments documenting our intent to deprecate and
remove the legacy GetStats() APIs some time in the future.

[1] https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm

Bug: chromium:680172
Change-Id: I09316ba6f20b25d4f9c11785d0a1a1262d6062a1
Reviewed-on: https://webrtc-review.googlesource.com/62900
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22602}
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index d8ec0c9..6fb64fc 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -1592,10 +1592,68 @@
 }
 
 void PeerConnection::GetStats(RTCStatsCollectorCallback* callback) {
+  TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
   RTC_DCHECK(stats_collector_);
+  RTC_DCHECK(callback);
   stats_collector_->GetStatsReport(callback);
 }
 
+void PeerConnection::GetStats(
+    rtc::scoped_refptr<RtpSenderInterface> selector,
+    rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
+  TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
+  RTC_DCHECK(callback);
+  RTC_DCHECK(stats_collector_);
+  rtc::scoped_refptr<RtpSenderInternal> internal_sender;
+  if (selector) {
+    for (const auto& proxy_transceiver : transceivers_) {
+      for (const auto& proxy_sender :
+           proxy_transceiver->internal()->senders()) {
+        if (proxy_sender == selector) {
+          internal_sender = proxy_sender->internal();
+          break;
+        }
+      }
+      if (internal_sender)
+        break;
+    }
+  }
+  // If there is no |internal_sender| then |selector| is either null or does not
+  // belong to the PeerConnection (in Plan B, senders can be removed from the
+  // PeerConnection). This means that "all the stats objects representing the
+  // selector" is an empty set. Invoking GetStatsReport() with a null selector
+  // produces an empty stats report.
+  stats_collector_->GetStatsReport(internal_sender, callback);
+}
+
+void PeerConnection::GetStats(
+    rtc::scoped_refptr<RtpReceiverInterface> selector,
+    rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
+  TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
+  RTC_DCHECK(callback);
+  RTC_DCHECK(stats_collector_);
+  rtc::scoped_refptr<RtpReceiverInternal> internal_receiver;
+  if (selector) {
+    for (const auto& proxy_transceiver : transceivers_) {
+      for (const auto& proxy_receiver :
+           proxy_transceiver->internal()->receivers()) {
+        if (proxy_receiver == selector) {
+          internal_receiver = proxy_receiver->internal();
+          break;
+        }
+      }
+      if (internal_receiver)
+        break;
+    }
+  }
+  // If there is no |internal_receiver| then |selector| is either null or does
+  // not belong to the PeerConnection (in Plan B, receivers can be removed from
+  // the PeerConnection). This means that "all the stats objects representing
+  // the selector" is an empty set. Invoking GetStatsReport() with a null
+  // selector produces an empty stats report.
+  stats_collector_->GetStatsReport(internal_receiver, callback);
+}
+
 PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
   return signaling_state_;
 }