RTCStatsCollector: Utilize network thread to minimize thread hops.

(This is a re-upload of https://codereview.webrtc.org/2567243003/, the
CQ stopped working there.)

The previously used WebRtcSession::GetTransportStats did a synchronous
invoke per channel (voice, video, data) on the signaling thread to the
network thread - e.g. 3 blocking invokes.

It is replaced by WebRtcSession::GetStats[_s] which can be invoked on
the signaling thread or on any thread if a ChannelNamePairs argument is
present (provided by WebRtcSession::GetChannelNamePairs on the signaling
thread).

With these changes, and changes allowing the getting of certificates
from any thread, the RTCStatsCollector can turn the 3 blocking thread
invokes into 1 non-blocking invoke.

BUG=webrtc:6875, chromium:627816

Review-Url: https://codereview.webrtc.org/2583883002
Cr-Commit-Position: refs/heads/master@{#15672}
diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc
index b05862d..ea724a3 100644
--- a/webrtc/api/webrtcsession.cc
+++ b/webrtc/api/webrtcsession.cc
@@ -970,50 +970,43 @@
   return true;
 }
 
-bool WebRtcSession::GetTransportStats(SessionStats* stats) {
+std::unique_ptr<SessionStats> WebRtcSession::GetStats_s() {
   ASSERT(signaling_thread()->IsCurrent());
-  return (GetChannelTransportStats(voice_channel(), stats) &&
-          GetChannelTransportStats(video_channel(), stats) &&
-          GetChannelTransportStats(data_channel(), stats));
+  ChannelNamePairs channel_name_pairs;
+  if (voice_channel()) {
+    channel_name_pairs.voice = rtc::Optional<ChannelNamePair>(ChannelNamePair(
+        voice_channel()->content_name(), voice_channel()->transport_name()));
+  }
+  if (video_channel()) {
+    channel_name_pairs.video = rtc::Optional<ChannelNamePair>(ChannelNamePair(
+        video_channel()->content_name(), video_channel()->transport_name()));
+  }
+  if (data_channel()) {
+    channel_name_pairs.data = rtc::Optional<ChannelNamePair>(ChannelNamePair(
+        data_channel()->content_name(), data_channel()->transport_name()));
+  }
+  return GetStats(channel_name_pairs);
 }
 
-bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch,
-                                             SessionStats* stats) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!ch) {
-    // Not using this channel.
-    return true;
+std::unique_ptr<SessionStats> WebRtcSession::GetStats(
+    const ChannelNamePairs& channel_name_pairs) {
+  if (network_thread()->IsCurrent()) {
+    return GetStats_n(channel_name_pairs);
   }
-
-  const std::string& content_name = ch->content_name();
-  const std::string& transport_name = ch->transport_name();
-  stats->proxy_to_transport[content_name] = transport_name;
-  if (stats->transport_stats.find(transport_name) !=
-      stats->transport_stats.end()) {
-    // Transport stats already done for this transport.
-    return true;
-  }
-
-  cricket::TransportStats tstats;
-  if (!transport_controller_->GetStats(transport_name, &tstats)) {
-    return false;
-  }
-
-  stats->transport_stats[transport_name] = tstats;
-  return true;
+  return network_thread()->Invoke<std::unique_ptr<SessionStats>>(
+      RTC_FROM_HERE,
+      rtc::Bind(&WebRtcSession::GetStats_n, this, channel_name_pairs));
 }
 
 bool WebRtcSession::GetLocalCertificate(
     const std::string& transport_name,
     rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
-  ASSERT(signaling_thread()->IsCurrent());
   return transport_controller_->GetLocalCertificate(transport_name,
                                                     certificate);
 }
 
 std::unique_ptr<rtc::SSLCertificate> WebRtcSession::GetRemoteSSLCertificate(
     const std::string& transport_name) {
-  ASSERT(signaling_thread()->IsCurrent());
   return transport_controller_->GetRemoteSSLCertificate(transport_name);
 }
 
@@ -1716,6 +1709,28 @@
   return true;
 }
 
+std::unique_ptr<SessionStats> WebRtcSession::GetStats_n(
+    const ChannelNamePairs& channel_name_pairs) {
+  ASSERT(network_thread()->IsCurrent());
+  std::unique_ptr<SessionStats> session_stats(new SessionStats());
+  for (const auto channel_name_pair : { &channel_name_pairs.voice,
+                                        &channel_name_pairs.video,
+                                        &channel_name_pairs.data }) {
+    if (*channel_name_pair) {
+      cricket::TransportStats transport_stats;
+      if (!transport_controller_->GetStats((*channel_name_pair)->transport_name,
+                                           &transport_stats)) {
+        return nullptr;
+      }
+      session_stats->proxy_to_transport[(*channel_name_pair)->content_name] =
+          (*channel_name_pair)->transport_name;
+      session_stats->transport_stats[(*channel_name_pair)->transport_name] =
+          std::move(transport_stats);
+    }
+  }
+  return session_stats;
+}
+
 void WebRtcSession::OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp) {
   SetError(ERROR_TRANSPORT,
            rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);