Revert 6863 "Refactor StatsCollector and associated types."

Breaks chrome compilation on Mac:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/vector.tcc:252:8:
error: no matching constructor for initialization of
'webrtc::StatsReport'
          _Tp __x_copy = __x;
              ^          ~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h:608:4:
note: in instantiation of member function
'std::vector<webrtc::StatsReport, std::allocator<webrtc::StatsReport>
>::_M_insert_aux' requested here
          _M_insert_aux(end(), __x);
          ^
../../content/renderer/media/mock_peer_connection_impl.cc:282:11:
note: in instantiation of member function
'std::vector<webrtc::StatsReport, std::allocator<webrtc::StatsReport>
>::push_back' requested here
  reports.push_back(report1);
          ^
../../third_party/libjingle/source/talk/app/webrtc/statstypes.h:49:3:
note: candidate constructor not viable: requires 0 arguments, but 1
was provided
  StatsReport() : timestamp(0) {}



> Refactor StatsCollector and associated types.
> * Due to the type changes, I'm going to update the OnCompleted event in two phases to sync with Chrome. This is the first phase.
> * Reports are now managed in a set, not a map, since it's enough to store the id in one place.
> * Report ids are now const.
> * Copying of data has been greatly reduced.
> * This change includes preparation work for making GetStats fully async.
> 
> This is a reland of r6778 which was reverted due to fyi bots failing.
> I found and fixed the issue which was that in a couple of places I needed to replace a report instead of finding+updating an existing one.
> 
> R=xians@webrtc.org
> 
> Review URL: https://webrtc-codereview.appspot.com/15119004

TBR=tommi@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/21169004

git-svn-id: http://webrtc.googlecode.com/svn/trunk/talk@6897 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/app/webrtc/peerconnection.cc b/app/webrtc/peerconnection.cc
index 201269a..5b61048 100644
--- a/app/webrtc/peerconnection.cc
+++ b/app/webrtc/peerconnection.cc
@@ -85,12 +85,11 @@
 };
 
 struct GetStatsMsg : public rtc::MessageData {
-  GetStatsMsg(webrtc::StatsObserver* observer,
-              webrtc::MediaStreamTrackInterface* track)
-      : observer(observer), track(track) {
+  explicit GetStatsMsg(webrtc::StatsObserver* observer)
+      : observer(observer) {
   }
+  webrtc::StatsReports reports;
   rtc::scoped_refptr<webrtc::StatsObserver> observer;
-  rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
 };
 
 // |in_str| should be of format
@@ -447,15 +446,17 @@
 bool PeerConnection::GetStats(StatsObserver* observer,
                               MediaStreamTrackInterface* track,
                               StatsOutputLevel level) {
-  ASSERT(signaling_thread()->IsCurrent());
   if (!VERIFY(observer != NULL)) {
     LOG(LS_ERROR) << "GetStats - observer is NULL.";
     return false;
   }
 
   stats_->UpdateStats(level);
-  signaling_thread()->Post(this, MSG_GETSTATS,
-                           new GetStatsMsg(observer, track));
+  rtc::scoped_ptr<GetStatsMsg> msg(new GetStatsMsg(observer));
+  if (!stats_->GetStats(track, &(msg->reports))) {
+    return false;
+  }
+  signaling_thread()->Post(this, MSG_GETSTATS, msg.release());
   return true;
 }
 
@@ -756,9 +757,7 @@
     }
     case MSG_GETSTATS: {
       GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
-      StatsReports reports;
-      stats_->GetStats(param->track, &reports);
-      param->observer->OnComplete(reports);
+      param->observer->OnComplete(param->reports);
       delete param;
       break;
     }
diff --git a/app/webrtc/peerconnectioninterface.h b/app/webrtc/peerconnectioninterface.h
index 6ef4847..59785e8 100644
--- a/app/webrtc/peerconnectioninterface.h
+++ b/app/webrtc/peerconnectioninterface.h
@@ -113,18 +113,7 @@
 
 class StatsObserver : public rtc::RefCountInterface {
  public:
-  // TODO(tommi): Remove.
-  virtual void OnComplete(const std::vector<StatsReport>& reports) {}
-
-  // TODO(tommi): Make pure virtual and remove implementation.
-  virtual void OnComplete(const StatsReports& reports) {
-    std::vector<StatsReportCopyable> report_copies;
-    for (size_t i = 0; i < reports.size(); ++i)
-      report_copies.push_back(StatsReportCopyable(*reports[i]));
-    std::vector<StatsReport>* r =
-        reinterpret_cast<std::vector<StatsReport>*>(&report_copies);
-     OnComplete(*r);
-   }
+  virtual void OnComplete(const std::vector<StatsReport>& reports) = 0;
 
  protected:
   virtual ~StatsObserver() {}
diff --git a/app/webrtc/statscollector.cc b/app/webrtc/statscollector.cc
index 5271827..9e2d75b 100644
--- a/app/webrtc/statscollector.cc
+++ b/app/webrtc/statscollector.cc
@@ -234,6 +234,7 @@
 }
 
 namespace {
+typedef std::map<std::string, StatsReport> StatsMap;
 
 double GetTimeNow() {
   return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec;
@@ -293,16 +294,17 @@
   return false;
 }
 
-void AddTrackReport(StatsSet* reports, const std::string& track_id) {
+void AddTrackReport(StatsMap* reports, const std::string& track_id) {
   // Adds an empty track report.
-  StatsReport* report = reports->ReplaceOrAddNew(
-      StatsId(StatsReport::kStatsReportTypeTrack, track_id));
-  report->type = StatsReport::kStatsReportTypeTrack;
-  report->AddValue(StatsReport::kStatsValueNameTrackId, track_id);
+  StatsReport report;
+  report.type = StatsReport::kStatsReportTypeTrack;
+  report.id = StatsId(StatsReport::kStatsReportTypeTrack, track_id);
+  report.AddValue(StatsReport::kStatsValueNameTrackId, track_id);
+  (*reports)[report.id] = report;
 }
 
 template <class TrackVector>
-void CreateTrackReports(const TrackVector& tracks, StatsSet* reports) {
+void CreateTrackReports(const TrackVector& tracks, StatsMap* reports) {
   for (size_t j = 0; j < tracks.size(); ++j) {
     webrtc::MediaStreamTrackInterface* track = tracks[j];
     AddTrackReport(reports, track->id());
@@ -467,7 +469,7 @@
                   double stats_gathering_started,
                   PeerConnectionInterface::StatsOutputLevel level,
                   StatsReport* report) {
-  ASSERT(report->id == StatsReport::kStatsReportVideoBweId);
+  report->id = StatsReport::kStatsReportVideoBweId;
   report->type = StatsReport::kStatsReportTypeBwe;
 
   // Clear out stats from previous GatherStats calls if any.
@@ -581,9 +583,9 @@
 
   // Create the kStatsReportTypeTrack report for the new track if there is no
   // report yet.
-  StatsReport* found = reports_.Find(
+  StatsMap::iterator it = reports_.find(
       StatsId(StatsReport::kStatsReportTypeTrack, audio_track->id()));
-  if (!found)
+  if (it == reports_.end())
     AddTrackReport(&reports_, audio_track->id());
 }
 
@@ -601,46 +603,49 @@
   ASSERT(false);
 }
 
-void StatsCollector::GetStats(MediaStreamTrackInterface* track,
+bool StatsCollector::GetStats(MediaStreamTrackInterface* track,
                               StatsReports* reports) {
   ASSERT(reports != NULL);
-  ASSERT(reports->empty());
+  reports->clear();
 
+  StatsMap::iterator it;
   if (!track) {
-    StatsSet::const_iterator it;
-    for (it = reports_.begin(); it != reports_.end(); ++it)
-      reports->push_back(&(*it));
-    return;
+    for (it = reports_.begin(); it != reports_.end(); ++it) {
+      reports->push_back(it->second);
+    }
+    return true;
   }
 
-  StatsReport* report =
-      reports_.Find(StatsId(StatsReport::kStatsReportTypeSession,
-                            session_->id()));
-  if (report)
-    reports->push_back(report);
+  it = reports_.find(StatsId(StatsReport::kStatsReportTypeSession,
+                             session_->id()));
+  if (it != reports_.end()) {
+    reports->push_back(it->second);
+  }
 
-  report = reports_.Find(
-      StatsId(StatsReport::kStatsReportTypeTrack, track->id()));
+  it = reports_.find(StatsId(StatsReport::kStatsReportTypeTrack, track->id()));
 
-  if (!report)
-    return;
+  if (it == reports_.end()) {
+    LOG(LS_WARNING) << "No StatsReport is available for "<< track->id();
+    return false;
+  }
 
-  reports->push_back(report);
+  reports->push_back(it->second);
 
   std::string track_id;
-  for (StatsSet::const_iterator it = reports_.begin(); it != reports_.end();
-       ++it) {
-    if (it->type != StatsReport::kStatsReportTypeSsrc)
+  for (it = reports_.begin(); it != reports_.end(); ++it) {
+    if (it->second.type != StatsReport::kStatsReportTypeSsrc) {
       continue;
-
-    if (ExtractValueFromReport(*it,
+    }
+    if (ExtractValueFromReport(it->second,
                                StatsReport::kStatsValueNameTrackId,
                                &track_id)) {
       if (track_id == track->id()) {
-        reports->push_back(&(*it));
+        reports->push_back(it->second);
       }
     }
   }
+
+  return true;
 }
 
 void
@@ -667,13 +672,13 @@
     const std::string& transport_id,
     TrackDirection direction) {
   const std::string ssrc_id = rtc::ToString<uint32>(ssrc);
-  StatsReport* report = reports_.Find(
-      StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id, direction));
+  StatsMap::iterator it = reports_.find(StatsId(
+      StatsReport::kStatsReportTypeSsrc, ssrc_id, direction));
 
   // Use the ID of the track that is currently mapped to the SSRC, if any.
   std::string track_id;
   if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) {
-    if (!report) {
+    if (it == reports_.end()) {
       // The ssrc is not used by any track or existing report, return NULL
       // in such case to indicate no report is prepared for the ssrc.
       return NULL;
@@ -681,13 +686,13 @@
 
     // The ssrc is not used by any existing track. Keeps the old track id
     // since we want to report the stats for inactive ssrc.
-    ExtractValueFromReport(*report,
+    ExtractValueFromReport(it->second,
                            StatsReport::kStatsValueNameTrackId,
                            &track_id);
   }
 
-  report = GetOrCreateReport(
-      StatsReport::kStatsReportTypeSsrc, ssrc_id, direction);
+  StatsReport* report = GetOrCreateReport(StatsReport::kStatsReportTypeSsrc,
+                                          ssrc_id, direction);
 
   // Clear out stats from previous GatherStats calls if any.
   // This is required since the report will be returned for the new values.
@@ -710,13 +715,13 @@
     const std::string& transport_id,
     TrackDirection direction) {
   const std::string ssrc_id = rtc::ToString<uint32>(ssrc);
-  StatsReport* report = reports_.Find(
-      StatsId(StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction));
+  StatsMap::iterator it = reports_.find(StatsId(
+      StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction));
 
   // Use the ID of the track that is currently mapped to the SSRC, if any.
   std::string track_id;
   if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) {
-    if (!report) {
+    if (it == reports_.end()) {
       // The ssrc is not used by any track or existing report, return NULL
       // in such case to indicate no report is prepared for the ssrc.
       return NULL;
@@ -724,12 +729,12 @@
 
     // The ssrc is not used by any existing track. Keeps the old track id
     // since we want to report the stats for inactive ssrc.
-    ExtractValueFromReport(*report,
+    ExtractValueFromReport(it->second,
                            StatsReport::kStatsValueNameTrackId,
                            &track_id);
   }
 
-  report = GetOrCreateReport(
+  StatsReport* report = GetOrCreateReport(
       StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction);
 
   // Clear out stats from previous GatherStats calls if any.
@@ -773,17 +778,18 @@
   rtc::Base64::EncodeFromArray(
       der_buffer.data(), der_buffer.length(), &der_base64);
 
-  StatsReport* report = reports_.ReplaceOrAddNew(
-      StatsId(StatsReport::kStatsReportTypeCertificate, fingerprint));
-  report->type = StatsReport::kStatsReportTypeCertificate;
-  report->timestamp = stats_gathering_started_;
-  report->AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint);
-  report->AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm,
-                   digest_algorithm);
-  report->AddValue(StatsReport::kStatsValueNameDer, der_base64);
+  StatsReport report;
+  report.type = StatsReport::kStatsReportTypeCertificate;
+  report.id = StatsId(report.type, fingerprint);
+  report.timestamp = stats_gathering_started_;
+  report.AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint);
+  report.AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm,
+                  digest_algorithm);
+  report.AddValue(StatsReport::kStatsValueNameDer, der_base64);
   if (!issuer_id.empty())
-    report->AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id);
-  return report->id;
+    report.AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id);
+  reports_[report.id] = report;
+  return report.id;
 }
 
 std::string StatsCollector::AddCertificateReports(
@@ -813,13 +819,15 @@
 
 void StatsCollector::ExtractSessionInfo() {
   // Extract information from the base session.
-  StatsReport* report = reports_.ReplaceOrAddNew(
-      StatsId(StatsReport::kStatsReportTypeSession, session_->id()));
-  report->type = StatsReport::kStatsReportTypeSession;
-  report->timestamp = stats_gathering_started_;
-  report->values.clear();
-  report->AddBoolean(StatsReport::kStatsValueNameInitiator,
-                     session_->initiator());
+  StatsReport report;
+  report.id = StatsId(StatsReport::kStatsReportTypeSession, session_->id());
+  report.type = StatsReport::kStatsReportTypeSession;
+  report.timestamp = stats_gathering_started_;
+  report.values.clear();
+  report.AddBoolean(StatsReport::kStatsValueNameInitiator,
+                    session_->initiator());
+
+  reports_[report.id] = report;
 
   cricket::SessionStats stats;
   if (session_->GetStats(&stats)) {
@@ -857,58 +865,61 @@
                = transport_iter->second.channel_stats.begin();
            channel_iter != transport_iter->second.channel_stats.end();
            ++channel_iter) {
+        StatsReport channel_report;
         std::ostringstream ostc;
         ostc << "Channel-" << transport_iter->second.content_name
              << "-" << channel_iter->component;
-        StatsReport* channel_report = reports_.ReplaceOrAddNew(ostc.str());
-        channel_report->type = StatsReport::kStatsReportTypeComponent;
-        channel_report->timestamp = stats_gathering_started_;
-        channel_report->AddValue(StatsReport::kStatsValueNameComponent,
-                                 channel_iter->component);
+        channel_report.id = ostc.str();
+        channel_report.type = StatsReport::kStatsReportTypeComponent;
+        channel_report.timestamp = stats_gathering_started_;
+        channel_report.AddValue(StatsReport::kStatsValueNameComponent,
+                                channel_iter->component);
         if (!local_cert_report_id.empty())
-          channel_report->AddValue(
+          channel_report.AddValue(
               StatsReport::kStatsValueNameLocalCertificateId,
               local_cert_report_id);
         if (!remote_cert_report_id.empty())
-          channel_report->AddValue(
+          channel_report.AddValue(
               StatsReport::kStatsValueNameRemoteCertificateId,
               remote_cert_report_id);
+        reports_[channel_report.id] = channel_report;
         for (size_t i = 0;
              i < channel_iter->connection_infos.size();
              ++i) {
+          StatsReport report;
+          const cricket::ConnectionInfo& info
+              = channel_iter->connection_infos[i];
           std::ostringstream ost;
           ost << "Conn-" << transport_iter->first << "-"
               << channel_iter->component << "-" << i;
-          StatsReport* report = reports_.ReplaceOrAddNew(ost.str());
-          report->type = StatsReport::kStatsReportTypeCandidatePair;
-          report->timestamp = stats_gathering_started_;
+          report.id = ost.str();
+          report.type = StatsReport::kStatsReportTypeCandidatePair;
+          report.timestamp = stats_gathering_started_;
           // Link from connection to its containing channel.
-          report->AddValue(StatsReport::kStatsValueNameChannelId,
-                           channel_report->id);
-
-          const cricket::ConnectionInfo& info =
-              channel_iter->connection_infos[i];
-          report->AddValue(StatsReport::kStatsValueNameBytesSent,
-                           info.sent_total_bytes);
-          report->AddValue(StatsReport::kStatsValueNameBytesReceived,
-                           info.recv_total_bytes);
-          report->AddBoolean(StatsReport::kStatsValueNameWritable,
-                             info.writable);
-          report->AddBoolean(StatsReport::kStatsValueNameReadable,
-                             info.readable);
-          report->AddBoolean(StatsReport::kStatsValueNameActiveConnection,
-                             info.best_connection);
-          report->AddValue(StatsReport::kStatsValueNameLocalAddress,
-                           info.local_candidate.address().ToString());
-          report->AddValue(StatsReport::kStatsValueNameRemoteAddress,
-                           info.remote_candidate.address().ToString());
-          report->AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
-          report->AddValue(StatsReport::kStatsValueNameTransportType,
-                           info.local_candidate.protocol());
-          report->AddValue(StatsReport::kStatsValueNameLocalCandidateType,
-                           info.local_candidate.type());
-          report->AddValue(StatsReport::kStatsValueNameRemoteCandidateType,
-                           info.remote_candidate.type());
+          report.AddValue(StatsReport::kStatsValueNameChannelId,
+                          channel_report.id);
+          report.AddValue(StatsReport::kStatsValueNameBytesSent,
+                          info.sent_total_bytes);
+          report.AddValue(StatsReport::kStatsValueNameBytesReceived,
+                          info.recv_total_bytes);
+          report.AddBoolean(StatsReport::kStatsValueNameWritable,
+                            info.writable);
+          report.AddBoolean(StatsReport::kStatsValueNameReadable,
+                            info.readable);
+          report.AddBoolean(StatsReport::kStatsValueNameActiveConnection,
+                            info.best_connection);
+          report.AddValue(StatsReport::kStatsValueNameLocalAddress,
+                          info.local_candidate.address().ToString());
+          report.AddValue(StatsReport::kStatsValueNameRemoteAddress,
+                          info.remote_candidate.address().ToString());
+          report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
+          report.AddValue(StatsReport::kStatsValueNameTransportType,
+                          info.local_candidate.protocol());
+          report.AddValue(StatsReport::kStatsValueNameLocalCandidateType,
+                          info.local_candidate.type());
+          report.AddValue(StatsReport::kStatsValueNameRemoteCandidateType,
+                          info.remote_candidate.type());
+          reports_[report.id] = report;
         }
       }
     }
@@ -965,8 +976,7 @@
   if (video_info.bw_estimations.size() != 1) {
     LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size();
   } else {
-    StatsReport* report =
-        reports_.FindOrAddNew(StatsReport::kStatsReportVideoBweId);
+    StatsReport* report = &reports_[StatsReport::kStatsReportVideoBweId];
     ExtractStats(
         video_info.bw_estimations[0], stats_gathering_started_, level, report);
   }
@@ -977,7 +987,13 @@
                                        TrackDirection direction) {
   ASSERT(type == StatsReport::kStatsReportTypeSsrc ||
          type == StatsReport::kStatsReportTypeRemoteSsrc);
-  return reports_.Find(StatsId(type, id, direction));
+  std::string statsid = StatsId(type, id, direction);
+  StatsReport* report = NULL;
+  std::map<std::string, StatsReport>::iterator it = reports_.find(statsid);
+  if (it != reports_.end())
+    report = &(it->second);
+
+  return report;
 }
 
 StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
@@ -988,8 +1004,8 @@
   StatsReport* report = GetReport(type, id, direction);
   if (report == NULL) {
     std::string statsid = StatsId(type, id, direction);
-    report = reports_.FindOrAddNew(statsid);
-    ASSERT(report->id == statsid);
+    report = &reports_[statsid];  // Create new element.
+    report->id = statsid;
     report->type = type;
   }
 
diff --git a/app/webrtc/statscollector.h b/app/webrtc/statscollector.h
index db2d788..a039813 100644
--- a/app/webrtc/statscollector.h
+++ b/app/webrtc/statscollector.h
@@ -72,11 +72,7 @@
   // be called before this function to get the most recent stats. |selector| is
   // a track label or empty string. The most recent reports are stored in
   // |reports|.
-  // TODO(tommi): Change this contract to accept a callback object instead
-  // of filling in |reports|.  As is, there's a requirement that the caller
-  // uses |reports| immediately without allowing any async activity on
-  // the thread (message handling etc) and then discard the results.
-  void GetStats(MediaStreamTrackInterface* track,
+  bool GetStats(MediaStreamTrackInterface* track,
                 StatsReports* reports);
 
   // Prepare an SSRC report for the given ssrc. Used internally
@@ -125,7 +121,7 @@
                         TrackDirection direction);
 
   // A map from the report id to the report.
-  StatsSet reports_;
+  std::map<std::string, StatsReport> reports_;
   // Raw pointer to the session the statistics are gathered from.
   WebRtcSession* const session_;
   double stats_gathering_started_;
diff --git a/app/webrtc/statscollector_unittest.cc b/app/webrtc/statscollector_unittest.cc
index 2f4c130..f264545 100644
--- a/app/webrtc/statscollector_unittest.cc
+++ b/app/webrtc/statscollector_unittest.cc
@@ -168,10 +168,10 @@
     return kNoReports;
   }
   for (size_t i = 0; i < reports.size(); ++i) {
-    if (reports[i]->type != type)
+    if (reports[i].type != type)
       continue;
     std::string ret;
-    if (GetValue(reports[i], name, &ret)) {
+    if (GetValue(&reports[i], name, &ret)) {
       return ret;
     }
   }
@@ -184,10 +184,10 @@
 const StatsReport* FindNthReportByType(
     const StatsReports& reports, const std::string& type, int n) {
   for (size_t i = 0; i < reports.size(); ++i) {
-    if (reports[i]->type == type) {
+    if (reports[i].type == type) {
       n--;
       if (n == 0)
-        return reports[i];
+        return &reports[i];
     }
   }
   return NULL;
@@ -196,8 +196,8 @@
 const StatsReport* FindReportById(const StatsReports& reports,
                                   const std::string& id) {
   for (size_t i = 0; i < reports.size(); ++i) {
-    if (reports[i]->id == id) {
-      return reports[i];
+    if (reports[i].id == id) {
+      return &reports[i];
     }
   }
   return NULL;
@@ -433,7 +433,7 @@
 class StatsCollectorTest : public testing::Test {
  protected:
   StatsCollectorTest()
-    : media_engine_(new cricket::FakeMediaEngine()),
+    : media_engine_(new cricket::FakeMediaEngine),
       channel_manager_(
           new cricket::ChannelManager(media_engine_,
                                       new cricket::FakeDeviceManager(),
@@ -443,8 +443,6 @@
     EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
   }
 
-  ~StatsCollectorTest() {}
-
   // This creates a standard setup with a transport called "trspname"
   // having one transport channel
   // and the specified virtual connection name.
@@ -788,7 +786,7 @@
   stats.GetStats(NULL, &reports);
   EXPECT_EQ((size_t)1, reports.size());
   EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack),
-            reports[0]->type);
+            reports[0].type);
 
   std::string trackValue =
       ExtractStatsValue(StatsReport::kStatsReportTypeTrack,
@@ -834,7 +832,6 @@
   EXPECT_TRUE(track_report);
 
   // Get report for the specific |track|.
-  reports.clear();
   stats.GetStats(track_, &reports);
   // |reports| should contain at least one session report, one track report,
   // and one ssrc report.
@@ -1399,7 +1396,6 @@
   VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
 
   // Get stats for the remote track.
-  reports.clear();
   stats.GetStats(remote_track.get(), &reports);
   track_report = FindNthReportByType(reports,
                                      StatsReport::kStatsReportTypeSsrc, 1);
@@ -1456,7 +1452,6 @@
   cricket::VoiceSenderInfo new_voice_sender_info;
   InitVoiceSenderInfo(&new_voice_sender_info);
   cricket::VoiceMediaInfo new_stats_read;
-  reports.clear();
   SetupAndVerifyAudioTrackStats(
       new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName,
       media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports);
diff --git a/app/webrtc/statstypes.h b/app/webrtc/statstypes.h
index 590ed9c..2b1317a 100644
--- a/app/webrtc/statstypes.h
+++ b/app/webrtc/statstypes.h
@@ -31,7 +31,6 @@
 #ifndef TALK_APP_WEBRTC_STATSTYPES_H_
 #define TALK_APP_WEBRTC_STATSTYPES_H_
 
-#include <set>
 #include <string>
 #include <vector>
 
@@ -40,49 +39,14 @@
 
 namespace webrtc {
 
-// TODO(tommi): Move all the implementation that's in this file and
-// statscollector.cc related to these types, into a new, statstypes.cc file.
-
 class StatsReport {
  public:
-  // TODO(tommi): Remove this ctor.
-  StatsReport() : timestamp(0) {}
-
-  // TODO(tommi): Make protected and disallow copy completely once not needed.
-  explicit StatsReport(const StatsReport& src)
-    : id(src.id),
-      type(src.type),
-      timestamp(src.timestamp),
-      values(src.values) {}
-
-  // TODO(tommi): Make this copy constructor protected.
-  StatsReport& operator=(const StatsReport& src) {
-    ASSERT(id == src.id);
-    type = src.type;
-    timestamp = src.timestamp;
-    values = src.values;
-    return *this;
-  }
-
-  // Constructor is protected to force use of StatsSet.
-  // TODO(tommi): Make this ctor protected.
-  explicit StatsReport(const std::string& id) : id(id), timestamp(0) {}
-
-  // Operators provided for STL container/algorithm support.
-  bool operator<(const StatsReport& other) const { return id < other.id; }
-  bool operator==(const StatsReport& other) const { return id == other.id; }
-  // Special support for being able to use std::find on a container
-  // without requiring a new StatsReport instance.
-  bool operator==(const std::string& other_id) const { return id == other_id; }
+  StatsReport() : timestamp(0) { }
 
   // TODO(tommi): Change this to be an enum type that holds all the
   // kStatsValueName constants.
   typedef const char* StatsValueName;
 
-  // The unique identifier for this object.
-  // This is used as a key for this report in ordered containers,
-  // so it must never be changed.
-  // TODO(tommi): Make this member variable const.
   std::string id;  // See below for contents.
   std::string type;  // See below for contents.
 
@@ -275,70 +239,7 @@
   static const char kStatsValueNameDecodingPLCCNG[];
 };
 
-// This class is provided for the cases where we need to keep
-// snapshots of reports around.  This is an edge case.
-// TODO(tommi): Move into the private section of StatsSet.
-class StatsReportCopyable : public StatsReport {
- public:
-  StatsReportCopyable(const std::string& id) : StatsReport(id) {}
-  explicit StatsReportCopyable(const StatsReport& src)
-      : StatsReport(src) {}
-
-  using StatsReport::operator=;
-};
-
-// Typedef for an array of const StatsReport pointers.
-// Ownership of the pointers held by this implementation is assumed to lie
-// elsewhere and lifetime guarantees are made by the implementation that uses
-// this type.  In the StatsCollector, object ownership lies with the StatsSet
-// class.
-typedef std::vector<const StatsReport*> StatsReports;
-
-// A map from the report id to the report.
-// This class wraps an STL container and provides a limited set of
-// functionality in order to keep things simple.
-// TODO(tommi): Use a thread checker here (currently not in libjingle).
-class StatsSet {
- public:
-  StatsSet() {}
-  ~StatsSet() {}
-
-  typedef std::set<StatsReportCopyable> Container;
-  typedef Container::iterator iterator;
-  typedef Container::const_iterator const_iterator;
-
-  const_iterator begin() const { return list_.begin(); }
-  const_iterator end() const { return list_.end(); }
-
-  // Creates a new report object with |id| that does not already
-  // exist in the list of reports.
-  StatsReport* InsertNew(const std::string& id) {
-    ASSERT(Find(id) == NULL);
-    const StatsReport* ret = &(*list_.insert(StatsReportCopyable(id)).first);
-    return const_cast<StatsReport*>(ret);
-  }
-
-  StatsReport* FindOrAddNew(const std::string& id) {
-    StatsReport* ret = Find(id);
-    return ret ? ret : InsertNew(id);
-  }
-
-  StatsReport* ReplaceOrAddNew(const std::string& id) {
-    list_.erase(id);
-    return InsertNew(id);
-  }
-
-  // Looks for a report with the given |id|.  If one is not found, NULL
-  // will be returned.
-  StatsReport* Find(const std::string& id) {
-    const_iterator it = std::find(begin(), end(), id);
-    return it == end() ? NULL :
-        const_cast<StatsReport*>(static_cast<const StatsReport*>(&(*it)));
-  }
-
- private:
-  Container list_;
-};
+typedef std::vector<StatsReport> StatsReports;
 
 }  // namespace webrtc
 
diff --git a/app/webrtc/test/mockpeerconnectionobservers.h b/app/webrtc/test/mockpeerconnectionobservers.h
index 174b80b..884c7a8 100644
--- a/app/webrtc/test/mockpeerconnectionobservers.h
+++ b/app/webrtc/test/mockpeerconnectionobservers.h
@@ -120,13 +120,9 @@
   MockStatsObserver()
       : called_(false) {}
   virtual ~MockStatsObserver() {}
-  virtual void OnComplete(const StatsReports& reports) {
+  virtual void OnComplete(const std::vector<webrtc::StatsReport>& reports) {
     called_ = true;
-    reports_.clear();
-    reports_.reserve(reports.size());
-    StatsReports::const_iterator it;
-    for (it = reports.begin(); it != reports.end(); ++it)
-      reports_.push_back(StatsReportCopyable(*(*it)));
+    reports_ = reports;
   }
 
   bool called() const { return called_; }
@@ -152,7 +148,7 @@
   }
 
  private:
-  int GetSsrcStatsValue(StatsReport::StatsValueName name) {
+  int GetSsrcStatsValue(const std::string name) {
     if (reports_.empty()) {
       return 0;
     }
@@ -171,7 +167,7 @@
   }
 
   bool called_;
-  std::vector<StatsReportCopyable> reports_;
+  std::vector<webrtc::StatsReport> reports_;
 };
 
 }  // namespace webrtc