Plumbing in preparation for standardized getStats() in webrtc-internals.

This CL implements the calling chain from webrtc_internals.js all the
way to getStats() and back, including process hops and layering.
- This adds the calling chain for standard getStats() API. The original
calling chain for legacy getStats() remains intact, but is renamed.

rtc_peer_connection_handler.cc implements invoking the standard API and
formats the result in the way that webrtc_internals.js expects stats to
be formatted.

These are roughly the layers:
- webrtc_internals.js "get[Legacy/Standard]Stats"
- WebRTCInternalsMessageHandler::OnGet[Legacy/Standard]Stats
- PeerConnectionTracker::OnGet[Legacy/Standard]Stats
- webrtc::PeerConnectionInterface::GetStats
- Internal[Legacy/Standard]StatsObserver::[OnComplete/OnStatsDelivered]
- PeerConnectionTrackerHost::OnAdd[Legacy/Standard]Stats
- WebRTCInternals::OnAdd[Legacy/Standard]Stats
- WebRTCInternalsMessageHandler::OnUpdate
- webrtc_internals.js "add[Legacy/Standard]Stats"

This CL is split up from
https://chromium-review.googlesource.com/c/chromium/src/+/1536186
to ease reviewing. The new calling chain is NOT exercised in this CL,
this will be handled in a follow-up CL.

Bug: 803014
Change-Id: Ied4b0b8f136f92aaad4633edb38ccb288e41ef3f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1565327
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Auto-Submit: Henrik Boström <hbos@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#653118}
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
index d42379f..fcf0db94 100644
--- a/content/browser/renderer_host/media/peer_connection_tracker_host.cc
+++ b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -26,7 +26,10 @@
   IPC_BEGIN_MESSAGE_MAP(PeerConnectionTrackerHost, message)
     IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddPeerConnection,
                         OnAddPeerConnection)
-    IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddStats, OnAddStats)
+    IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddStandardStats,
+                        OnAddStandardStats)
+    IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddLegacyStats,
+                        OnAddLegacyStats)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -143,11 +146,20 @@
                                      base::OnceCallback<void(bool)>());
 }
 
-void PeerConnectionTrackerHost::OnAddStats(int lid,
-                                           const base::ListValue& value) {
+void PeerConnectionTrackerHost::OnAddStandardStats(
+    int lid,
+    const base::ListValue& value) {
   WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
   if (webrtc_internals) {
-    webrtc_internals->OnAddStats(peer_pid(), lid, value);
+    webrtc_internals->OnAddStandardStats(peer_pid(), lid, value);
+  }
+}
+
+void PeerConnectionTrackerHost::OnAddLegacyStats(int lid,
+                                                 const base::ListValue& value) {
+  WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
+  if (webrtc_internals) {
+    webrtc_internals->OnAddLegacyStats(peer_pid(), lid, value);
   }
 }
 
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.h b/content/browser/renderer_host/media/peer_connection_tracker_host.h
index 6e4c322..e1533b3 100644
--- a/content/browser/renderer_host/media/peer_connection_tracker_host.h
+++ b/content/browser/renderer_host/media/peer_connection_tracker_host.h
@@ -50,7 +50,8 @@
  private:
   // Handlers for IPC messages coming from the renderer.
   void OnAddPeerConnection(const PeerConnectionInfo& info);
-  void OnAddStats(int lid, const base::ListValue& value);
+  void OnAddStandardStats(int lid, const base::ListValue& value);
+  void OnAddLegacyStats(int lid, const base::ListValue& value);
   void SendOnSuspendOnUIThread();
 
   // mojom::PeerConnectionTrackerHost implementation.
diff --git a/content/browser/resources/media/webrtc_internals.js b/content/browser/resources/media/webrtc_internals.js
index c4de346..a4be433 100644
--- a/content/browser/resources/media/webrtc_internals.js
+++ b/content/browser/resources/media/webrtc_internals.js
@@ -110,7 +110,9 @@
 /** Sends a request to the browser to get peer connection statistics. */
 function requestStats() {
   if (Object.keys(peerConnectionDataStore).length > 0) {
-    chrome.send('getAllStats');
+    // TODO(https://crbug.com/803014): Use the getStandardStats codepath to use
+    // the standard getStats() API.
+    chrome.send('getLegacyStats');
   }
 }
 
@@ -249,9 +251,8 @@
   requestStats();
 }
 
-
 /**
- * Handles the report of stats.
+ * Handles the report of stats originating from the standard getStats() API.
  *
  * @param {!Object} data The object containing pid, lid, and reports, where
  *     reports is an array of stats reports. Each report contains id, type,
@@ -259,7 +260,21 @@
  *     which is an array of strings, whose even index entry is the name of the
  *     stat, and the odd index entry is the value.
  */
-function addStats(data) {
+function addStandardStats(data) {
+  // TODO(https://crbug.com/803014): Do different processing on standard stats.
+  addLegacyStats(stats);
+}
+
+/**
+ * Handles the report of stats originating from the legacy getStats() API.
+ *
+ * @param {!Object} data The object containing pid, lid, and reports, where
+ *     reports is an array of stats reports. Each report contains id, type,
+ *     and stats, where stats is the object containing timestamp and values,
+ *     which is an array of strings, whose even index entry is the name of the
+ *     stat, and the odd index entry is the value.
+ */
+function addLegacyStats(data) {
   var peerConnectionElement = $(getPeerConnectionId(data));
   if (!peerConnectionElement) {
     return;
diff --git a/content/browser/webrtc/webrtc_internals.cc b/content/browser/webrtc/webrtc_internals.cc
index 2b3666be..089eff19 100644
--- a/content/browser/webrtc/webrtc_internals.cc
+++ b/content/browser/webrtc/webrtc_internals.cc
@@ -249,8 +249,9 @@
   EnsureLogList(record)->Append(std::move(log_entry));
 }
 
-void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
-                                 const base::ListValue& value) {
+void WebRTCInternals::OnAddStandardStats(base::ProcessId pid,
+                                         int lid,
+                                         const base::ListValue& value) {
   if (!observers_.might_have_observers())
     return;
 
@@ -260,7 +261,22 @@
 
   dict->SetKey("reports", value.Clone());
 
-  SendUpdate("addStats", std::move(dict));
+  SendUpdate("addStandardStats", std::move(dict));
+}
+
+void WebRTCInternals::OnAddLegacyStats(base::ProcessId pid,
+                                       int lid,
+                                       const base::ListValue& value) {
+  if (!observers_.might_have_observers())
+    return;
+
+  auto dict = std::make_unique<base::DictionaryValue>();
+  dict->SetInteger("pid", static_cast<int>(pid));
+  dict->SetInteger("lid", lid);
+
+  dict->SetKey("reports", value.Clone());
+
+  SendUpdate("addLegacyStats", std::move(dict));
 }
 
 void WebRTCInternals::OnGetUserMedia(int rid,
diff --git a/content/browser/webrtc/webrtc_internals.h b/content/browser/webrtc/webrtc_internals.h
index bf6256a..3098a67 100644
--- a/content/browser/webrtc/webrtc_internals.h
+++ b/content/browser/webrtc/webrtc_internals.h
@@ -80,10 +80,16 @@
                               const std::string& type,
                               const std::string& value);
 
-  // This method is called when results from PeerConnectionInterface::GetStats
-  // are available. |pid| is the renderer process id, |lid| is the renderer
-  // local id, |value| is the list of stats reports.
-  void OnAddStats(base::ProcessId pid, int lid, const base::ListValue& value);
+  // These methods are called when results from
+  // PeerConnectionInterface::GetStats (legacy or standard API) are available.
+  // |pid| is the renderer process id, |lid| is the renderer local id, |value|
+  // is the list of stats reports.
+  void OnAddStandardStats(base::ProcessId pid,
+                          int lid,
+                          const base::ListValue& value);
+  void OnAddLegacyStats(base::ProcessId pid,
+                        int lid,
+                        const base::ListValue& value);
 
   // This method is called when getUserMedia is called. |render_process_id| is
   // the id of the render process (not OS pid), which is needed because we might
diff --git a/content/browser/webrtc/webrtc_internals_browsertest.cc b/content/browser/webrtc/webrtc_internals_browsertest.cc
index 2cd0a8d7..b29ae911 100644
--- a/content/browser/webrtc/webrtc_internals_browsertest.cc
+++ b/content/browser/webrtc/webrtc_internals_browsertest.cc
@@ -331,7 +331,7 @@
            "reports:[" << "{id:'" << id << "', type:'" << type << "', "
                            "stats:" << stats.GetString() << "}]}";
 
-    ASSERT_TRUE(ExecuteJavascript("addStats(" + ss.str() + ")"));
+    ASSERT_TRUE(ExecuteJavascript("addLegacyStats(" + ss.str() + ")"));
     VerifyStatsTable(pc, entry);
   }
 
diff --git a/content/browser/webrtc/webrtc_internals_message_handler.cc b/content/browser/webrtc/webrtc_internals_message_handler.cc
index 80580be3..62fa8da 100644
--- a/content/browser/webrtc/webrtc_internals_message_handler.cc
+++ b/content/browser/webrtc/webrtc_internals_message_handler.cc
@@ -33,8 +33,12 @@
 
 void WebRTCInternalsMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getAllStats",
-      base::BindRepeating(&WebRTCInternalsMessageHandler::OnGetAllStats,
+      "getStandardStats",
+      base::BindRepeating(&WebRTCInternalsMessageHandler::OnGetStandardStats,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getLegacyStats",
+      base::BindRepeating(&WebRTCInternalsMessageHandler::OnGetLegacyStats,
                           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
@@ -84,12 +88,21 @@
   return host;
 }
 
-void WebRTCInternalsMessageHandler::OnGetAllStats(
+void WebRTCInternalsMessageHandler::OnGetStandardStats(
+    const base::ListValue* /* unused_list */) {
+  for (RenderProcessHost::iterator i(
+           content::RenderProcessHost::AllHostsIterator());
+       !i.IsAtEnd(); i.Advance()) {
+    i.GetCurrentValue()->Send(new PeerConnectionTracker_GetStandardStats());
+  }
+}
+
+void WebRTCInternalsMessageHandler::OnGetLegacyStats(
     const base::ListValue* /* unused_list */) {
   for (RenderProcessHost::iterator i(
        content::RenderProcessHost::AllHostsIterator());
        !i.IsAtEnd(); i.Advance()) {
-    i.GetCurrentValue()->Send(new PeerConnectionTracker_GetAllStats());
+    i.GetCurrentValue()->Send(new PeerConnectionTracker_GetLegacyStats());
   }
 }
 
diff --git a/content/browser/webrtc/webrtc_internals_message_handler.h b/content/browser/webrtc/webrtc_internals_message_handler.h
index b353617..4e5943d9 100644
--- a/content/browser/webrtc/webrtc_internals_message_handler.h
+++ b/content/browser/webrtc/webrtc_internals_message_handler.h
@@ -43,7 +43,8 @@
   RenderFrameHost* GetWebRTCInternalsHost() const;
 
   // Javascript message handler.
-  void OnGetAllStats(const base::ListValue* list);
+  void OnGetStandardStats(const base::ListValue* list);
+  void OnGetLegacyStats(const base::ListValue* list);
   void OnSetAudioDebugRecordingsEnabled(bool enable,
                                         const base::ListValue* list);
   void OnSetEventLogRecordingsEnabled(bool enable, const base::ListValue* list);
diff --git a/content/browser/webrtc/webrtc_internals_unittest.cc b/content/browser/webrtc/webrtc_internals_unittest.cc
index ac7ffcc..6fb9ab0 100644
--- a/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -407,7 +407,7 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(WebRtcInternalsTest, OnAddStats) {
+TEST_F(WebRtcInternalsTest, OnAddStandardStats) {
   const int rid = 0, pid = 1, lid = 2;
   base::RunLoop loop;
   MockWebRtcInternalsProxy observer(&loop);
@@ -419,11 +419,40 @@
   base::ListValue list;
   list.AppendString("xxx");
   list.AppendString("yyy");
-  webrtc_internals.OnAddStats(pid, lid, list);
+  webrtc_internals.OnAddStandardStats(pid, lid, list);
 
   loop.Run();
 
-  EXPECT_EQ("addStats", observer.command());
+  EXPECT_EQ("addStandardStats", observer.command());
+  ASSERT_TRUE(observer.value());
+
+  base::DictionaryValue* dict = nullptr;
+  EXPECT_TRUE(observer.value()->GetAsDictionary(&dict));
+
+  VerifyInt(dict, "pid", pid);
+  VerifyInt(dict, "lid", lid);
+  VerifyList(dict, "reports", list);
+
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(WebRtcInternalsTest, OnAddLegacyStats) {
+  const int rid = 0, pid = 1, lid = 2;
+  base::RunLoop loop;
+  MockWebRtcInternalsProxy observer(&loop);
+  WebRTCInternalsForTest webrtc_internals;
+  webrtc_internals.AddObserver(&observer);
+  webrtc_internals.OnAddPeerConnection(rid, pid, lid, kUrl, kRtcConfiguration,
+                                       kContraints);
+
+  base::ListValue list;
+  list.AppendString("xxx");
+  list.AppendString("yyy");
+  webrtc_internals.OnAddLegacyStats(pid, lid, list);
+
+  loop.Run();
+
+  EXPECT_EQ("addLegacyStats", observer.command());
   ASSERT_TRUE(observer.value());
 
   base::DictionaryValue* dict = nullptr;
diff --git a/content/common/media/peer_connection_tracker_messages.h b/content/common/media/peer_connection_tracker_messages.h
index 6d1455f..231725e 100644
--- a/content/common/media/peer_connection_tracker_messages.h
+++ b/content/common/media/peer_connection_tracker_messages.h
@@ -29,12 +29,16 @@
 // Messages sent from PeerConnectionTracker to PeerConnectionTrackerHost.
 IPC_MESSAGE_CONTROL1(PeerConnectionTrackerHost_AddPeerConnection,
                      PeerConnectionInfo /* info */)
-IPC_MESSAGE_CONTROL2(PeerConnectionTrackerHost_AddStats,
+IPC_MESSAGE_CONTROL2(PeerConnectionTrackerHost_AddStandardStats,
+                     int /* lid */,
+                     base::ListValue /* value */)
+IPC_MESSAGE_CONTROL2(PeerConnectionTrackerHost_AddLegacyStats,
                      int /* lid */,
                      base::ListValue /* value */)
 
 // Messages sent to PeerConnectionTracker.
-IPC_MESSAGE_CONTROL0(PeerConnectionTracker_GetAllStats)
+IPC_MESSAGE_CONTROL0(PeerConnectionTracker_GetStandardStats)
+IPC_MESSAGE_CONTROL0(PeerConnectionTracker_GetLegacyStats)
 IPC_MESSAGE_CONTROL0(PeerConnectionTracker_OnSuspend)
 IPC_MESSAGE_CONTROL2(PeerConnectionTracker_StartEventLog,
                      int /* peer_connection_local_id */,
diff --git a/content/renderer/media/webrtc/peer_connection_tracker.cc b/content/renderer/media/webrtc/peer_connection_tracker.cc
index f2f2b0b1..c21bed7 100644
--- a/content/renderer/media/webrtc/peer_connection_tracker.cc
+++ b/content/renderer/media/webrtc/peer_connection_tracker.cc
@@ -433,10 +433,16 @@
   return result;
 }
 
-class InternalStatsObserver : public webrtc::StatsObserver {
+// chrome://webrtc-internals displays stats and stats graphs. The call path
+// involves thread and process hops (IPC). This is the webrtc::StatsObserver
+// that is used when webrtc-internals wants legacy stats. It starts in
+// webrtc_internals.js performing requestLegacyStats and the result gets
+// asynchronously delivered to webrtc_internals.js at addLegacyStats.
+class InternalLegacyStatsObserver : public webrtc::StatsObserver {
  public:
-  InternalStatsObserver(int lid,
-                        scoped_refptr<base::SingleThreadTaskRunner> main_thread)
+  InternalLegacyStatsObserver(
+      int lid,
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread)
       : lid_(lid), main_thread_(std::move(main_thread)) {}
 
   void OnComplete(const StatsReports& reports) override {
@@ -450,13 +456,14 @@
 
     if (!list->empty()) {
       main_thread_->PostTask(
-          FROM_HERE, base::BindOnce(&InternalStatsObserver::OnCompleteImpl,
-                                    std::move(list), lid_));
+          FROM_HERE,
+          base::BindOnce(&InternalLegacyStatsObserver::OnCompleteImpl,
+                         std::move(list), lid_));
     }
   }
 
  protected:
-  ~InternalStatsObserver() override {
+  ~InternalLegacyStatsObserver() override {
     // Will be destructed on libjingle's signaling thread.
     // The signaling thread is where libjingle's objects live and from where
     // libjingle makes callbacks.  This may or may not be the same thread as
@@ -469,7 +476,107 @@
   static void OnCompleteImpl(std::unique_ptr<base::ListValue> list, int lid) {
     DCHECK(!list->empty());
     RenderThreadImpl::current()->Send(
-        new PeerConnectionTrackerHost_AddStats(lid, *list.get()));
+        new PeerConnectionTrackerHost_AddLegacyStats(lid, *list.get()));
+  }
+
+  const int lid_;
+  const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+};
+
+// chrome://webrtc-internals displays stats and stats graphs. The call path
+// involves thread and process hops (IPC). This is the ----webrtc::StatsObserver
+// that is used when webrtc-internals wants standard stats. It starts in
+// webrtc_internals.js performing requestStandardStats and the result gets
+// asynchronously delivered to webrtc_internals.js at addStandardStats.
+class InternalStandardStatsObserver : public webrtc::RTCStatsCollectorCallback {
+ public:
+  InternalStandardStatsObserver(
+      int lid,
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread)
+      : lid_(lid), main_thread_(std::move(main_thread)) {}
+
+  void OnStatsDelivered(
+      const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override {
+    // We're on the signaling thread.
+    DCHECK(!main_thread_->BelongsToCurrentThread());
+    main_thread_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &InternalStandardStatsObserver::OnStatsDeliveredOnMainThread,
+            scoped_refptr<InternalStandardStatsObserver>(this), report));
+  }
+
+ protected:
+  ~InternalStandardStatsObserver() override {}
+
+ private:
+  void OnStatsDeliveredOnMainThread(
+      rtc::scoped_refptr<const webrtc::RTCStatsReport> report) {
+    auto list = ReportToList(report);
+    RenderThreadImpl::current()->Send(
+        new PeerConnectionTrackerHost_AddStandardStats(lid_, *list.get()));
+  }
+
+  std::unique_ptr<base::ListValue> ReportToList(
+      const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) {
+    std::unique_ptr<base::ListValue> result_list(new base::ListValue());
+    for (const auto& stats : *report) {
+      // The format of "stats_subdictionary" is:
+      // {timestamp:<milliseconds>, values: [<key-value pairs>]}
+      auto stats_subdictionary = std::make_unique<base::DictionaryValue>();
+      // Timestamp is reported in milliseconds.
+      stats_subdictionary->SetDouble("timestamp",
+                                     stats.timestamp_us() / 1000.0);
+      // Values are reported as
+      // "values": ["member1", value, "member2", value...]
+      auto name_value_pairs = std::make_unique<base::ListValue>();
+      for (const auto* member : stats.Members()) {
+        if (!member->is_defined())
+          continue;
+        name_value_pairs->AppendString(member->name());
+        name_value_pairs->Append(MemberToValue(*member));
+      }
+      stats_subdictionary->Set("values", std::move(name_value_pairs));
+
+      // The format of "stats_dictionary" is:
+      // {id:<string>, stats:<stats_subdictionary>, type:<string>}
+      auto stats_dictionary = std::make_unique<base::DictionaryValue>();
+      stats_dictionary->Set("stats", std::move(stats_subdictionary));
+      stats_dictionary->SetString("id", stats.id());
+      stats_dictionary->SetString("type", stats.type());
+      result_list->Append(std::move(stats_dictionary));
+    }
+    return result_list;
+  }
+
+  std::unique_ptr<base::Value> MemberToValue(
+      const webrtc::RTCStatsMemberInterface& member) {
+    switch (member.type()) {
+      // Types supported by base::Value are passed as the appropriate type.
+      case webrtc::RTCStatsMemberInterface::Type::kBool:
+        return std::make_unique<base::Value>(
+            *member.cast_to<webrtc::RTCStatsMember<bool>>());
+      case webrtc::RTCStatsMemberInterface::Type::kInt32:
+        return std::make_unique<base::Value>(
+            *member.cast_to<webrtc::RTCStatsMember<int32_t>>());
+      case webrtc::RTCStatsMemberInterface::Type::kString:
+        return std::make_unique<base::Value>(
+            *member.cast_to<webrtc::RTCStatsMember<std::string>>());
+      // Types not supported by base::Value are converted to string.
+      case webrtc::RTCStatsMemberInterface::Type::kUint32:
+      case webrtc::RTCStatsMemberInterface::Type::kInt64:
+      case webrtc::RTCStatsMemberInterface::Type::kUint64:
+      case webrtc::RTCStatsMemberInterface::Type::kDouble:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceBool:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceInt32:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceUint32:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceInt64:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceUint64:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceDouble:
+      case webrtc::RTCStatsMemberInterface::Type::kSequenceString:
+      default:
+        return std::make_unique<base::Value>(member.ValueToString());
+    }
   }
 
   const int lid_;
@@ -497,7 +604,9 @@
     const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message)
-    IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats)
+    IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetStandardStats,
+                        OnGetStandardStats)
+    IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetLegacyStats, OnGetLegacyStats)
     IPC_MESSAGE_HANDLER(PeerConnectionTracker_OnSuspend, OnSuspend)
     IPC_MESSAGE_HANDLER(PeerConnectionTracker_StartEventLog, OnStartEventLog)
     IPC_MESSAGE_HANDLER(PeerConnectionTracker_StopEventLog, OnStopEventLog)
@@ -506,19 +615,30 @@
   return handled;
 }
 
-void PeerConnectionTracker::OnGetAllStats() {
+void PeerConnectionTracker::OnGetStandardStats() {
   DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
 
   const std::string empty_track_id;
-  for (auto it = peer_connection_local_id_map_.begin();
-       it != peer_connection_local_id_map_.end(); ++it) {
-    rtc::scoped_refptr<InternalStatsObserver> observer(
-        new rtc::RefCountedObject<InternalStatsObserver>(
-            it->second, main_thread_task_runner_));
+  for (const auto& pair : peer_connection_local_id_map_) {
+    scoped_refptr<InternalStandardStatsObserver> observer(
+        new rtc::RefCountedObject<InternalStandardStatsObserver>(
+            pair.second, main_thread_task_runner_));
+    pair.first->GetStandardStatsForTracker(observer);
+  }
+}
 
-    it->first->GetStats(observer,
-                        webrtc::PeerConnectionInterface::kStatsOutputLevelDebug,
-                        nullptr);
+void PeerConnectionTracker::OnGetLegacyStats() {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
+
+  const std::string empty_track_id;
+  for (const auto& pair : peer_connection_local_id_map_) {
+    rtc::scoped_refptr<InternalLegacyStatsObserver> observer(
+        new rtc::RefCountedObject<InternalLegacyStatsObserver>(
+            pair.second, main_thread_task_runner_));
+
+    pair.first->GetStats(
+        observer, webrtc::PeerConnectionInterface::kStatsOutputLevelDebug,
+        nullptr);
   }
 }
 
diff --git a/content/renderer/media/webrtc/peer_connection_tracker.h b/content/renderer/media/webrtc/peer_connection_tracker.h
index aafaf03..ee33830 100644
--- a/content/renderer/media/webrtc/peer_connection_tracker.h
+++ b/content/renderer/media/webrtc/peer_connection_tracker.h
@@ -221,7 +221,8 @@
                         size_t transceiver_index);
 
   // IPC Message handler for getting all stats.
-  void OnGetAllStats();
+  void OnGetStandardStats();
+  void OnGetLegacyStats();
 
   // Called when the browser process reports a suspend event from the OS.
   void OnSuspend();
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
index 0781bb4..390c837 100644
--- a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
+++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -1505,6 +1505,11 @@
   return webkit_request.RequestSucceeded();
 }
 
+void RTCPeerConnectionHandler::GetStandardStatsForTracker(
+    scoped_refptr<webrtc::RTCStatsCollectorCallback> observer) {
+  native_peer_connection_->GetStats(observer.get());
+}
+
 void RTCPeerConnectionHandler::GetStats(
     const blink::WebRTCStatsRequest& request) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.h b/content/renderer/media/webrtc/rtc_peer_connection_handler.h
index ffc6f6e..69c3fb1 100644
--- a/content/renderer/media/webrtc/rtc_peer_connection_handler.h
+++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.h
@@ -31,6 +31,7 @@
 #include "third_party/blink/public/platform/web_rtc_stats_request.h"
 #include "third_party/blink/public/platform/web_rtc_stats_response.h"
 #include "third_party/webrtc/api/stats/rtc_stats.h"
+#include "third_party/webrtc/api/stats/rtc_stats_collector_callback.h"
 
 namespace blink {
 class WebLocalFrame;
@@ -185,6 +186,8 @@
 
   // Asynchronously calls native_peer_connection_->getStats on the signaling
   // thread.
+  void GetStandardStatsForTracker(
+      scoped_refptr<webrtc::RTCStatsCollectorCallback> observer);
   void GetStats(webrtc::StatsObserver* observer,
                 webrtc::PeerConnectionInterface::StatsOutputLevel level,
                 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> selector);