RTCIceCandidatePairStats.[state/priority] added, ConnectionInfo updated.

State and priority added to ConnectionInfo. The Connection::State enum
is replaced by IceCandidatePairState enum class.

At P2PTransportChannel::GetStats, Connection::stats is called, producing
ConnectionInfo for the connection that is then filled in with additional
values from the Connection. This is refactored so that all values are
set by Connection::stats.

RTCStatsCollector is updated to surface the ConnectionInfo stats.

BUG=webrtc:6755, chromium:633550, chromium:627816

Review-Url: https://codereview.webrtc.org/2597423003
Cr-Commit-Position: refs/heads/master@{#15870}
diff --git a/webrtc/api/rtcstats_integrationtest.cc b/webrtc/api/rtcstats_integrationtest.cc
index 577cc06..556907c 100644
--- a/webrtc/api/rtcstats_integrationtest.cc
+++ b/webrtc/api/rtcstats_integrationtest.cc
@@ -359,8 +359,8 @@
         candidate_pair.local_candidate_id, RTCLocalIceCandidateStats::kType);
     verifier.TestMemberIsIDReference(
         candidate_pair.remote_candidate_id, RTCRemoteIceCandidateStats::kType);
-    verifier.TestMemberIsUndefined(candidate_pair.state);
-    verifier.TestMemberIsUndefined(candidate_pair.priority);
+    verifier.TestMemberIsDefined(candidate_pair.state);
+    verifier.TestMemberIsNonNegative<uint64_t>(candidate_pair.priority);
     verifier.TestMemberIsUndefined(candidate_pair.nominated);
     verifier.TestMemberIsDefined(candidate_pair.writable);
     verifier.TestMemberIsUndefined(candidate_pair.readable);
diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc
index 85113e6..4e5e8d9 100644
--- a/webrtc/api/rtcstatscollector.cc
+++ b/webrtc/api/rtcstatscollector.cc
@@ -114,6 +114,23 @@
   }
 }
 
+const char* IceCandidatePairStateToRTCStatsIceCandidatePairState(
+    cricket::IceCandidatePairState state) {
+  switch (state) {
+    case cricket::IceCandidatePairState::WAITING:
+      return RTCStatsIceCandidatePairState::kWaiting;
+    case cricket::IceCandidatePairState::IN_PROGRESS:
+      return RTCStatsIceCandidatePairState::kInProgress;
+    case cricket::IceCandidatePairState::SUCCEEDED:
+      return RTCStatsIceCandidatePairState::kSucceeded;
+    case cricket::IceCandidatePairState::FAILED:
+      return RTCStatsIceCandidatePairState::kFailed;
+    default:
+      RTC_NOTREACHED();
+      return nullptr;
+  }
+}
+
 std::unique_ptr<RTCCodecStats> CodecStatsFromRtpCodecParameters(
     uint64_t timestamp_us, bool inbound, bool audio,
     const RtpCodecParameters& codec_params) {
@@ -646,6 +663,9 @@
             timestamp_us, info.local_candidate, true, report);
         candidate_pair_stats->remote_candidate_id = ProduceIceCandidateStats(
             timestamp_us, info.remote_candidate, false, report);
+        candidate_pair_stats->state =
+            IceCandidatePairStateToRTCStatsIceCandidatePairState(info.state);
+        candidate_pair_stats->priority = info.priority;
         // TODO(hbos): This writable is different than the spec. It goes to
         // false after a certain amount of time without a response passes.
         // crbug.com/633550
diff --git a/webrtc/api/rtcstatscollector_unittest.cc b/webrtc/api/rtcstatscollector_unittest.cc
index ee09054..6e84853 100644
--- a/webrtc/api/rtcstatscollector_unittest.cc
+++ b/webrtc/api/rtcstatscollector_unittest.cc
@@ -1066,6 +1066,8 @@
   connection_info.sent_ping_requests_before_first_response = 2000;
   connection_info.recv_ping_responses = 4321;
   connection_info.sent_ping_responses = 1000;
+  connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
+  connection_info.priority = 5555;
 
   cricket::TransportChannelStats transport_channel_stats;
   transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
@@ -1092,6 +1094,8 @@
   expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
   expected_pair.remote_candidate_id =
       "RTCIceCandidate_" + remote_candidate->id();
+  expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
+  expected_pair.priority = 5555;
   expected_pair.writable = true;
   expected_pair.bytes_sent = 42;
   expected_pair.bytes_received = 1234;
diff --git a/webrtc/api/stats/rtcstats_objects.h b/webrtc/api/stats/rtcstats_objects.h
index d18b248..e85119a 100644
--- a/webrtc/api/stats/rtcstats_objects.h
+++ b/webrtc/api/stats/rtcstats_objects.h
@@ -32,7 +32,6 @@
   static const char* kInProgress;
   static const char* kFailed;
   static const char* kSucceeded;
-  static const char* kCancelled;
 };
 
 // https://w3c.github.io/webrtc-pc/#rtcicecandidatetype-enum
@@ -120,9 +119,7 @@
   RTCStatsMember<std::string> remote_candidate_id;
   // TODO(hbos): Support enum types?
   // "RTCStatsMember<RTCStatsIceCandidatePairState>"?
-  // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/633550
   RTCStatsMember<std::string> state;
-  // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/633550
   RTCStatsMember<uint64_t> priority;
   // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/633550
   RTCStatsMember<bool> nominated;
diff --git a/webrtc/p2p/base/jseptransport.cc b/webrtc/p2p/base/jseptransport.cc
index bf4d86c..46cf4c4e 100644
--- a/webrtc/p2p/base/jseptransport.cc
+++ b/webrtc/p2p/base/jseptransport.cc
@@ -41,6 +41,28 @@
   return true;
 }
 
+ConnectionInfo::ConnectionInfo()
+    : best_connection(false),
+      writable(false),
+      receiving(false),
+      timeout(false),
+      new_connection(false),
+      rtt(0),
+      sent_total_bytes(0),
+      sent_bytes_second(0),
+      sent_discarded_packets(0),
+      sent_total_packets(0),
+      sent_ping_requests_total(0),
+      sent_ping_requests_before_first_response(0),
+      sent_ping_responses(0),
+      recv_total_bytes(0),
+      recv_bytes_second(0),
+      recv_ping_requests(0),
+      recv_ping_responses(0),
+      key(nullptr),
+      state(IceCandidatePairState::WAITING),
+      priority(0) {}
+
 bool BadTransportDescription(const std::string& desc, std::string* err_desc) {
   if (err_desc) {
     *err_desc = desc;
diff --git a/webrtc/p2p/base/jseptransport.h b/webrtc/p2p/base/jseptransport.h
index cc05ec0..ff0edeb 100644
--- a/webrtc/p2p/base/jseptransport.h
+++ b/webrtc/p2p/base/jseptransport.h
@@ -31,6 +31,7 @@
 
 class TransportChannelImpl;
 class TransportChannelImpl;
+enum class IceCandidatePairState;
 
 typedef std::vector<Candidate> Candidates;
 
@@ -83,25 +84,7 @@
 // Stats that we can return about the connections for a transport channel.
 // TODO(hta): Rename to ConnectionStats
 struct ConnectionInfo {
-  ConnectionInfo()
-      : best_connection(false),
-        writable(false),
-        receiving(false),
-        timeout(false),
-        new_connection(false),
-        rtt(0),
-        sent_total_bytes(0),
-        sent_bytes_second(0),
-        sent_discarded_packets(0),
-        sent_total_packets(0),
-        sent_ping_requests_total(0),
-        sent_ping_requests_before_first_response(0),
-        sent_ping_responses(0),
-        recv_total_bytes(0),
-        recv_bytes_second(0),
-        recv_ping_requests(0),
-        recv_ping_responses(0),
-        key(NULL) {}
+  ConnectionInfo();
 
   bool best_connection;      // Is this the best connection we have?
   bool writable;             // Has this connection received a STUN response?
@@ -127,6 +110,10 @@
   Candidate local_candidate;   // The local candidate for this connection.
   Candidate remote_candidate;  // The remote candidate for this connection.
   void* key;                   // A static value that identifies this conn.
+  // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-state
+  IceCandidatePairState state;
+  // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-priority
+  uint64_t priority;
 };
 
 // Information about all the connections of a channel.
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc
index 5f858c4..6071e07 100644
--- a/webrtc/p2p/base/p2ptransportchannel.cc
+++ b/webrtc/p2p/base/p2ptransportchannel.cc
@@ -1012,17 +1012,8 @@
   for (Connection* connection : connections_) {
     ConnectionInfo info = connection->stats();
     info.best_connection = (selected_connection_ == connection);
-    info.receiving = connection->receiving();
-    info.writable = (connection->write_state() == Connection::STATE_WRITABLE);
-    info.timeout =
-        (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
-    info.new_connection = !connection->reported();
+    infos->push_back(std::move(info));
     connection->set_reported(true);
-    info.rtt = connection->rtt();
-    info.local_candidate = connection->local_candidate();
-    info.remote_candidate = connection->remote_candidate();
-    info.key = connection;
-    infos->push_back(info);
   }
 
   return true;
@@ -1559,7 +1550,7 @@
   }
 
   // A failed connection will not be pinged.
-  if (conn->state() == Connection::STATE_FAILED) {
+  if (conn->state() == IceCandidatePairState::FAILED) {
     return false;
   }
 
diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
index 3a9ec18..ae47fa6 100644
--- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
+++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
@@ -4017,14 +4017,14 @@
   ASSERT_TRUE(conn2 != nullptr);
   EXPECT_TRUE_SIMULATED_WAIT(!conn2->active(), kDefaultTimeout, clock);
   // |conn2| should not send a ping yet.
-  EXPECT_EQ(Connection::STATE_WAITING, conn2->state());
+  EXPECT_EQ(IceCandidatePairState::WAITING, conn2->state());
   EXPECT_EQ(TransportChannelState::STATE_COMPLETED, ch.GetState());
   // Wait for |conn1| becoming not receiving.
   EXPECT_TRUE_SIMULATED_WAIT(!conn1->receiving(), kMediumTimeout, clock);
   // Make sure conn2 is not deleted.
   conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2, &clock);
   ASSERT_TRUE(conn2 != nullptr);
-  EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_INPROGRESS, conn2->state(),
+  EXPECT_EQ_SIMULATED_WAIT(IceCandidatePairState::IN_PROGRESS, conn2->state(),
                            kDefaultTimeout, clock);
   conn2->ReceivedPingResponse(LOW_RTT, "id");
   EXPECT_EQ_SIMULATED_WAIT(conn2, ch.selected_connection(), kDefaultTimeout,
diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc
index eb63436..dc99a338 100644
--- a/webrtc/p2p/base/port.cc
+++ b/webrtc/p2p/base/port.cc
@@ -868,7 +868,7 @@
       last_data_received_(0),
       last_ping_response_received_(0),
       reported_(false),
-      state_(STATE_WAITING),
+      state_(IceCandidatePairState::WAITING),
       receiving_timeout_(WEAK_CONNECTION_RECEIVE_TIMEOUT),
       time_created_ms_(rtc::TimeMillis()) {
   // All of our connections start in WAITING state.
@@ -937,8 +937,8 @@
   SignalStateChange(this);
 }
 
-void Connection::set_state(State state) {
-  State old_state = state_;
+void Connection::set_state(IceCandidatePairState state) {
+  IceCandidatePairState old_state = state_;
   state_ = state;
   if (state != old_state) {
     LOG_J(LS_VERBOSE, this) << "set_state";
@@ -1126,12 +1126,12 @@
 }
 
 void Connection::FailAndDestroy() {
-  set_state(Connection::STATE_FAILED);
+  set_state(IceCandidatePairState::FAILED);
   Destroy();
 }
 
 void Connection::FailAndPrune() {
-  set_state(Connection::STATE_FAILED);
+  set_state(IceCandidatePairState::FAILED);
   Prune();
 }
 
@@ -1223,7 +1223,7 @@
                           << ", id=" << rtc::hex_encode(req->id())
                           << ", nomination=" << nomination_;
   requests_.Send(req);
-  state_ = STATE_INPROGRESS;
+  state_ = IceCandidatePairState::IN_PROGRESS;
   num_pings_sent_++;
 }
 
@@ -1250,7 +1250,7 @@
   last_ping_response_received_ = rtc::TimeMillis();
   UpdateReceiving(last_ping_response_received_);
   set_write_state(STATE_WRITABLE);
-  set_state(STATE_SUCCEEDED);
+  set_state(IceCandidatePairState::SUCCEEDED);
   rtt_samples_++;
   rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1);
 }
@@ -1331,8 +1331,8 @@
      << ":" << remote.protocol() << ":" << remote.address().ToSensitiveString()
      << "|" << CONNECT_STATE_ABBREV[connected()]
      << RECEIVE_STATE_ABBREV[receiving()] << WRITE_STATE_ABBREV[write_state()]
-     << ICESTATE[state()] << "|" << remote_nomination() << "|" << nomination()
-     << "|" << priority() << "|";
+     << ICESTATE[static_cast<int>(state())] << "|" << remote_nomination() << "|"
+     << nomination() << "|" << priority() << "|";
   if (rtt_ < DEFAULT_RTT) {
     ss << rtt_ << "]";
   } else {
@@ -1471,6 +1471,16 @@
   stats_.recv_total_bytes = recv_rate_tracker_.TotalSampleCount();
   stats_.sent_bytes_second = round(send_rate_tracker_.ComputeRate());
   stats_.sent_total_bytes = send_rate_tracker_.TotalSampleCount();
+  stats_.receiving = receiving_;
+  stats_.writable = write_state_ == STATE_WRITABLE;
+  stats_.timeout = write_state_ == STATE_WRITE_TIMEOUT;
+  stats_.new_connection = !reported_;
+  stats_.rtt = rtt_;
+  stats_.local_candidate = local_candidate();
+  stats_.remote_candidate = remote_candidate();
+  stats_.key = this;
+  stats_.state = state_;
+  stats_.priority = priority();
   return stats_;
 }
 
diff --git a/webrtc/p2p/base/port.h b/webrtc/p2p/base/port.h
index 6b1a551..f3c4ed1 100644
--- a/webrtc/p2p/base/port.h
+++ b/webrtc/p2p/base/port.h
@@ -92,6 +92,16 @@
   ICE_TYPE_PREFERENCE_HOST = 126
 };
 
+// States are from RFC 5245. http://tools.ietf.org/html/rfc5245#section-5.7.4
+enum class IceCandidatePairState {
+  WAITING = 0,  // Check has not been performed, Waiting pair on CL.
+  IN_PROGRESS,  // Check has been sent, transaction is in progress.
+  SUCCEEDED,    // Check already done, produced a successful result.
+  FAILED,       // Check for this connection failed.
+  // According to spec there should also be a frozen state, but nothing is ever
+  // frozen because we have not implemented ICE freezing logic.
+};
+
 const char* ProtoToString(ProtocolType proto);
 bool StringToProto(const char* value, ProtocolType* proto);
 
@@ -419,14 +429,6 @@
     uint32_t nomination;
   };
 
-  // States are from RFC 5245. http://tools.ietf.org/html/rfc5245#section-5.7.4
-  enum State {
-    STATE_WAITING = 0,  // Check has not been performed, Waiting pair on CL.
-    STATE_INPROGRESS,   // Check has been sent, transaction is in progress.
-    STATE_SUCCEEDED,    // Check already done, produced a successful result.
-    STATE_FAILED        // Check for this connection failed.
-  };
-
   virtual ~Connection();
 
   // The local port where this connection sends and receives packets.
@@ -467,6 +469,8 @@
   // Estimate of the round-trip time over this connection.
   int rtt() const { return rtt_; }
 
+  // Gets the |ConnectionInfo| stats, where |best_connection| has not been
+  // populated (default value false).
   ConnectionInfo stats();
 
   sigslot::signal1<Connection*> SignalStateChange;
@@ -575,7 +579,7 @@
   // Invoked when Connection receives STUN error response with 487 code.
   void HandleRoleConflictFromPeer();
 
-  State state() const { return state_; }
+  IceCandidatePairState state() const { return state_; }
 
   int num_pings_sent() const { return num_pings_sent_; }
 
@@ -630,7 +634,7 @@
   // Changes the state and signals if necessary.
   void set_write_state(WriteState value);
   void UpdateReceiving(int64_t now);
-  void set_state(State state);
+  void set_state(IceCandidatePairState state);
   void set_connected(bool value);
 
   uint32_t nomination() const { return nomination_; }
@@ -686,7 +690,7 @@
   std::vector<SentPing> pings_since_last_response_;
 
   bool reported_;
-  State state_;
+  IceCandidatePairState state_;
   // Time duration to switch from receiving to not receiving.
   int receiving_timeout_;
   int64_t time_created_ms_;
diff --git a/webrtc/p2p/base/turnport_unittest.cc b/webrtc/p2p/base/turnport_unittest.cc
index e0b1420..edad812 100644
--- a/webrtc/p2p/base/turnport_unittest.cc
+++ b/webrtc/p2p/base/turnport_unittest.cc
@@ -334,7 +334,8 @@
   }
 
   bool CheckConnectionFailedAndPruned(Connection* conn) {
-    return conn && !conn->active() && conn->state() == Connection::STATE_FAILED;
+    return conn && !conn->active() &&
+           conn->state() == IceCandidatePairState::FAILED;
   }
 
   // Checks that |turn_port_| has a nonempty set of connections and they are all
diff --git a/webrtc/stats/rtcstats_objects.cc b/webrtc/stats/rtcstats_objects.cc
index d4fea49..487df93 100644
--- a/webrtc/stats/rtcstats_objects.cc
+++ b/webrtc/stats/rtcstats_objects.cc
@@ -19,10 +19,9 @@
 
 const char* RTCStatsIceCandidatePairState::kFrozen = "frozen";
 const char* RTCStatsIceCandidatePairState::kWaiting = "waiting";
-const char* RTCStatsIceCandidatePairState::kInProgress = "inprogress";
+const char* RTCStatsIceCandidatePairState::kInProgress = "in-progress";
 const char* RTCStatsIceCandidatePairState::kFailed = "failed";
 const char* RTCStatsIceCandidatePairState::kSucceeded = "succeeded";
-const char* RTCStatsIceCandidatePairState::kCancelled = "cancelled";
 
 // Strings defined in https://tools.ietf.org/html/rfc5245.
 const char* RTCIceCandidateType::kHost = "host";