Revert "[Stats] Remove enum-like structs in favor of strings."

This reverts commit ccc87ea3c625e43ab138e00ba2ef1a2d99756199.

Reason for revert: Breaks downstream project

Original change's description:
> [Stats] Remove enum-like structs in favor of strings.
>
> Due to a limitation of RTCStatsMember<T> not supporting enums, as well
> as the fact that in JavaScript enums are represented as basic strings,
> the stats enums have always been represented by T=std::string.
>
> Now that we have WebIDL-ified[1] all RTCStats dictionaries and enum
> values are simply string-copied (example: [2]) it seems safe to assume
> that "stats enums are just strings" is here to stay.
>
> Therefore there is little value in having C++ structs that look like
> enums so I'm deleting those in favor of std::string operator==()
> comparisons, e.g. `if (rtp_stream.kind == "audio")`. This removes some
> lines of code from our code base.
>
> I mostly want to get rid of these because they were taking up about 20%
> of the rtcstats_objects.h real estate...
>
> [1] https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/peerconnection/rtc_stats_report.idl
> [2] https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc;l=667;drc=cf34e84c9df94256abfb1716ba075ed203975755
>
> Bug: webrtc:15245
> Change-Id: Iaf0827d7aecebc1cc02976a61663d5298d684f07
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/308680
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#40295}

Bug: webrtc:15245
Change-Id: I05db80ba9f29460239de82cea9d95136e4c708e4
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/308860
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Christoffer Jansson <jansson@webrtc.org>
Owners-Override: Christoffer Jansson <jansson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40298}
diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h
index 3601392..58ca165 100644
--- a/api/stats/rtcstats_objects.h
+++ b/api/stats/rtcstats_objects.h
@@ -23,6 +23,99 @@
 
 namespace webrtc {
 
+// https://w3c.github.io/webrtc-pc/#idl-def-rtcdatachannelstate
+struct RTCDataChannelState {
+  static const char* const kConnecting;
+  static const char* const kOpen;
+  static const char* const kClosing;
+  static const char* const kClosed;
+};
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcstatsicecandidatepairstate
+struct RTCStatsIceCandidatePairState {
+  static const char* const kFrozen;
+  static const char* const kWaiting;
+  static const char* const kInProgress;
+  static const char* const kFailed;
+  static const char* const kSucceeded;
+};
+
+// https://w3c.github.io/webrtc-pc/#rtcicecandidatetype-enum
+struct RTCIceCandidateType {
+  static const char* const kHost;
+  static const char* const kSrflx;
+  static const char* const kPrflx;
+  static const char* const kRelay;
+};
+
+// https://w3c.github.io/webrtc-pc/#idl-def-rtcdtlstransportstate
+struct RTCDtlsTransportState {
+  static const char* const kNew;
+  static const char* const kConnecting;
+  static const char* const kConnected;
+  static const char* const kClosed;
+  static const char* const kFailed;
+};
+
+// `RTCRtpStreamStats::kind` is not an enum in the spec but the only valid
+// values are "audio" and "video" as it comes from `MediaStreamTrack::kind`.
+// https://w3c.github.io/webrtc-stats/#dom-rtcrtpstreamstats-kind
+// https://w3c.github.io/mediacapture-main/#dom-mediadeviceinfo-kind
+struct RTCMediaStreamTrackKind {
+  static const char* const kAudio;
+  static const char* const kVideo;
+};
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcnetworktype
+struct RTCNetworkType {
+  static const char* const kBluetooth;
+  static const char* const kCellular;
+  static const char* const kEthernet;
+  static const char* const kWifi;
+  static const char* const kWimax;
+  static const char* const kVpn;
+  static const char* const kUnknown;
+};
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcqualitylimitationreason
+struct RTCQualityLimitationReason {
+  static const char* const kNone;
+  static const char* const kCpu;
+  static const char* const kBandwidth;
+  static const char* const kOther;
+};
+
+// https://webrtc.org/experiments/rtp-hdrext/video-content-type/
+struct RTCContentType {
+  static const char* const kUnspecified;
+  static const char* const kScreenshare;
+};
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcdtlsrole
+struct RTCDtlsRole {
+  static const char* const kUnknown;
+  static const char* const kClient;
+  static const char* const kServer;
+};
+
+// https://www.w3.org/TR/webrtc/#rtcicerole
+struct RTCIceRole {
+  static const char* const kUnknown;
+  static const char* const kControlled;
+  static const char* const kControlling;
+};
+
+// https://www.w3.org/TR/webrtc/#dom-rtcicetransportstate
+struct RTCIceTransportState {
+  static const char* const kNew;
+  static const char* const kChecking;
+  static const char* const kConnected;
+  static const char* const kCompleted;
+  static const char* const kDisconnected;
+  static const char* const kFailed;
+  static const char* const kClosed;
+};
+
 // https://w3c.github.io/webrtc-stats/#certificatestats-dict*
 class RTC_EXPORT RTCCertificateStats final : public RTCStats {
  public:
@@ -38,6 +131,20 @@
   RTCStatsMember<std::string> issuer_certificate_id;
 };
 
+// Non standard extension mapping to rtc::AdapterType
+struct RTCNetworkAdapterType {
+  static constexpr char kUnknown[] = "unknown";
+  static constexpr char kEthernet[] = "ethernet";
+  static constexpr char kWifi[] = "wifi";
+  static constexpr char kCellular[] = "cellular";
+  static constexpr char kLoopback[] = "loopback";
+  static constexpr char kAny[] = "any";
+  static constexpr char kCellular2g[] = "cellular2g";
+  static constexpr char kCellular3g[] = "cellular3g";
+  static constexpr char kCellular4g[] = "cellular4g";
+  static constexpr char kCellular5g[] = "cellular5g";
+};
+
 // https://w3c.github.io/webrtc-stats/#codec-dict*
 class RTC_EXPORT RTCCodecStats final : public RTCStats {
  public:
@@ -67,6 +174,7 @@
   RTCStatsMember<std::string> label;
   RTCStatsMember<std::string> protocol;
   RTCStatsMember<int32_t> data_channel_identifier;
+  // Enum type RTCDataChannelState.
   RTCStatsMember<std::string> state;
   RTCStatsMember<uint32_t> messages_sent;
   RTCStatsMember<uint64_t> bytes_sent;
@@ -86,6 +194,7 @@
   RTCStatsMember<std::string> transport_id;
   RTCStatsMember<std::string> local_candidate_id;
   RTCStatsMember<std::string> remote_candidate_id;
+  // Enum type RTCStatsIceCandidatePairState.
   RTCStatsMember<std::string> state;
   // Obsolete: priority
   RTCStatsMember<uint64_t> priority;
@@ -131,6 +240,7 @@
   RTCStatsMember<int32_t> port;
   RTCStatsMember<std::string> protocol;
   RTCStatsMember<std::string> relay_protocol;
+  // Enum type RTCIceCandidateType.
   RTCStatsMember<std::string> candidate_type;
   RTCStatsMember<int32_t> priority;
   RTCStatsMember<std::string> url;
@@ -138,6 +248,7 @@
   RTCStatsMember<std::string> related_address;
   RTCStatsMember<int32_t> related_port;
   RTCStatsMember<std::string> username_fragment;
+  // Enum type RTCIceTcpCandidateType.
   RTCStatsMember<std::string> tcp_type;
 
   // The following metrics are NOT exposed to JavaScript. We should consider
@@ -348,6 +459,7 @@
   RTCStatsMember<uint32_t> frames_sent;
   RTCStatsMember<uint32_t> huge_frames_sent;
   RTCStatsMember<double> total_packet_send_delay;
+  // Enum type RTCQualityLimitationReason
   RTCStatsMember<std::string> quality_limitation_reason;
   RTCStatsMember<std::map<std::string, double>> quality_limitation_durations;
   // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges
@@ -464,6 +576,7 @@
   RTCStatsMember<uint64_t> bytes_received;
   RTCStatsMember<uint64_t> packets_received;
   RTCStatsMember<std::string> rtcp_transport_stats_id;
+  // Enum type RTCDtlsTransportState.
   RTCStatsMember<std::string> dtls_state;
   RTCStatsMember<std::string> selected_candidate_pair_id;
   RTCStatsMember<std::string> local_certificate_id;
diff --git a/pc/peer_connection_bundle_unittest.cc b/pc/peer_connection_bundle_unittest.cc
index 7edbe89..a71b513 100644
--- a/pc/peer_connection_bundle_unittest.cc
+++ b/pc/peer_connection_bundle_unittest.cc
@@ -190,8 +190,8 @@
     for (auto* pair_stats :
          report->GetStatsOfType<RTCIceCandidatePairStats>()) {
       if (*pair_stats->remote_candidate_id == matching_candidate_id) {
-        if (*pair_stats->state == "in-progress" ||
-            *pair_stats->state == "succeeded") {
+        if (*pair_stats->state == RTCStatsIceCandidatePairState::kInProgress ||
+            *pair_stats->state == RTCStatsIceCandidatePairState::kSucceeded) {
           return true;
         }
       }
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index 8cba02b..48e8542 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -166,13 +166,13 @@
 
 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) {
   if (type == cricket::LOCAL_PORT_TYPE)
-    return "host";
+    return RTCIceCandidateType::kHost;
   if (type == cricket::STUN_PORT_TYPE)
-    return "srflx";
+    return RTCIceCandidateType::kSrflx;
   if (type == cricket::PRFLX_PORT_TYPE)
-    return "prflx";
+    return RTCIceCandidateType::kPrflx;
   if (type == cricket::RELAY_PORT_TYPE)
-    return "relay";
+    return RTCIceCandidateType::kRelay;
   RTC_DCHECK_NOTREACHED();
   return nullptr;
 }
@@ -181,13 +181,13 @@
     DataChannelInterface::DataState state) {
   switch (state) {
     case DataChannelInterface::kConnecting:
-      return "connecting";
+      return RTCDataChannelState::kConnecting;
     case DataChannelInterface::kOpen:
-      return "open";
+      return RTCDataChannelState::kOpen;
     case DataChannelInterface::kClosing:
-      return "closing";
+      return RTCDataChannelState::kClosing;
     case DataChannelInterface::kClosed:
-      return "closed";
+      return RTCDataChannelState::kClosed;
     default:
       RTC_DCHECK_NOTREACHED();
       return nullptr;
@@ -198,13 +198,13 @@
     cricket::IceCandidatePairState state) {
   switch (state) {
     case cricket::IceCandidatePairState::WAITING:
-      return "waiting";
+      return RTCStatsIceCandidatePairState::kWaiting;
     case cricket::IceCandidatePairState::IN_PROGRESS:
-      return "in-progress";
+      return RTCStatsIceCandidatePairState::kInProgress;
     case cricket::IceCandidatePairState::SUCCEEDED:
-      return "succeeded";
+      return RTCStatsIceCandidatePairState::kSucceeded;
     case cricket::IceCandidatePairState::FAILED:
-      return "failed";
+      return RTCStatsIceCandidatePairState::kFailed;
     default:
       RTC_DCHECK_NOTREACHED();
       return nullptr;
@@ -214,11 +214,11 @@
 const char* IceRoleToRTCIceRole(cricket::IceRole role) {
   switch (role) {
     case cricket::IceRole::ICEROLE_UNKNOWN:
-      return "unknown";
+      return RTCIceRole::kUnknown;
     case cricket::IceRole::ICEROLE_CONTROLLED:
-      return "controlled";
+      return RTCIceRole::kControlled;
     case cricket::IceRole::ICEROLE_CONTROLLING:
-      return "controlling";
+      return RTCIceRole::kControlling;
     default:
       RTC_DCHECK_NOTREACHED();
       return nullptr;
@@ -229,15 +229,15 @@
     DtlsTransportState state) {
   switch (state) {
     case DtlsTransportState::kNew:
-      return "new";
+      return RTCDtlsTransportState::kNew;
     case DtlsTransportState::kConnecting:
-      return "connecting";
+      return RTCDtlsTransportState::kConnecting;
     case DtlsTransportState::kConnected:
-      return "connected";
+      return RTCDtlsTransportState::kConnected;
     case DtlsTransportState::kClosed:
-      return "closed";
+      return RTCDtlsTransportState::kClosed;
     case DtlsTransportState::kFailed:
-      return "failed";
+      return RTCDtlsTransportState::kFailed;
     default:
       RTC_CHECK_NOTREACHED();
       return nullptr;
@@ -247,19 +247,19 @@
 const char* IceTransportStateToRTCIceTransportState(IceTransportState state) {
   switch (state) {
     case IceTransportState::kNew:
-      return "new";
+      return RTCIceTransportState::kNew;
     case IceTransportState::kChecking:
-      return "checking";
+      return RTCIceTransportState::kChecking;
     case IceTransportState::kConnected:
-      return "connected";
+      return RTCIceTransportState::kConnected;
     case IceTransportState::kCompleted:
-      return "completed";
+      return RTCIceTransportState::kCompleted;
     case IceTransportState::kFailed:
-      return "failed";
+      return RTCIceTransportState::kFailed;
     case IceTransportState::kDisconnected:
-      return "disconnected";
+      return RTCIceTransportState::kDisconnected;
     case IceTransportState::kClosed:
-      return "closed";
+      return RTCIceTransportState::kClosed;
     default:
       RTC_CHECK_NOTREACHED();
       return nullptr;
@@ -273,17 +273,17 @@
     case rtc::ADAPTER_TYPE_CELLULAR_3G:
     case rtc::ADAPTER_TYPE_CELLULAR_4G:
     case rtc::ADAPTER_TYPE_CELLULAR_5G:
-      return "cellular";
+      return RTCNetworkType::kCellular;
     case rtc::ADAPTER_TYPE_ETHERNET:
-      return "ethernet";
+      return RTCNetworkType::kEthernet;
     case rtc::ADAPTER_TYPE_WIFI:
-      return "wifi";
+      return RTCNetworkType::kWifi;
     case rtc::ADAPTER_TYPE_VPN:
-      return "vpn";
+      return RTCNetworkType::kVpn;
     case rtc::ADAPTER_TYPE_UNKNOWN:
     case rtc::ADAPTER_TYPE_LOOPBACK:
     case rtc::ADAPTER_TYPE_ANY:
-      return "unknown";
+      return RTCNetworkType::kUnknown;
   }
   RTC_DCHECK_NOTREACHED();
   return nullptr;
@@ -292,25 +292,25 @@
 absl::string_view NetworkTypeToStatsNetworkAdapterType(rtc::AdapterType type) {
   switch (type) {
     case rtc::ADAPTER_TYPE_CELLULAR:
-      return "cellular";
+      return RTCNetworkAdapterType::kCellular;
     case rtc::ADAPTER_TYPE_CELLULAR_2G:
-      return "cellular2g";
+      return RTCNetworkAdapterType::kCellular2g;
     case rtc::ADAPTER_TYPE_CELLULAR_3G:
-      return "cellular3g";
+      return RTCNetworkAdapterType::kCellular3g;
     case rtc::ADAPTER_TYPE_CELLULAR_4G:
-      return "cellular4g";
+      return RTCNetworkAdapterType::kCellular4g;
     case rtc::ADAPTER_TYPE_CELLULAR_5G:
-      return "cellular5g";
+      return RTCNetworkAdapterType::kCellular5g;
     case rtc::ADAPTER_TYPE_ETHERNET:
-      return "ethernet";
+      return RTCNetworkAdapterType::kEthernet;
     case rtc::ADAPTER_TYPE_WIFI:
-      return "wifi";
+      return RTCNetworkAdapterType::kWifi;
     case rtc::ADAPTER_TYPE_UNKNOWN:
-      return "unknown";
+      return RTCNetworkAdapterType::kUnknown;
     case rtc::ADAPTER_TYPE_LOOPBACK:
-      return "loopback";
+      return RTCNetworkAdapterType::kLoopback;
     case rtc::ADAPTER_TYPE_ANY:
-      return "any";
+      return RTCNetworkAdapterType::kAny;
     case rtc::ADAPTER_TYPE_VPN:
       /* should not be handled here. Vpn is modelled as a bool */
       break;
@@ -323,13 +323,13 @@
     QualityLimitationReason reason) {
   switch (reason) {
     case QualityLimitationReason::kNone:
-      return "none";
+      return RTCQualityLimitationReason::kNone;
     case QualityLimitationReason::kCpu:
-      return "cpu";
+      return RTCQualityLimitationReason::kCpu;
     case QualityLimitationReason::kBandwidth:
-      return "bandwidth";
+      return RTCQualityLimitationReason::kBandwidth;
     case QualityLimitationReason::kOther:
-      return "other";
+      return RTCQualityLimitationReason::kOther;
   }
   RTC_CHECK_NOTREACHED();
 }
@@ -661,7 +661,7 @@
   // TODO(bugs.webrtc.org/10529): When info's `content_info` is optional
   // support the "unspecified" value.
   if (video_receiver_info.content_type == VideoContentType::SCREENSHARE)
-    inbound_video->content_type = "screenshare";
+    inbound_video->content_type = RTCContentType::kScreenshare;
   if (!video_receiver_info.decoder_implementation_name.empty()) {
     inbound_video->decoder_implementation =
         video_receiver_info.decoder_implementation_name;
@@ -802,7 +802,7 @@
   // TODO(https://crbug.com/webrtc/10529): When info's `content_info` is
   // optional, support the "unspecified" value.
   if (video_sender_info.content_type == VideoContentType::SCREENSHARE)
-    outbound_video->content_type = "screenshare";
+    outbound_video->content_type = RTCContentType::kScreenshare;
   if (!video_sender_info.encoder_implementation_name.empty()) {
     outbound_video->encoder_implementation =
         video_sender_info.encoder_implementation_name;
@@ -1918,10 +1918,11 @@
       }
 
       if (channel_stats.dtls_role) {
-        transport_stats->dtls_role =
-            *channel_stats.dtls_role == rtc::SSL_CLIENT ? "client" : "server";
+        transport_stats->dtls_role = *channel_stats.dtls_role == rtc::SSL_CLIENT
+                                         ? webrtc::RTCDtlsRole::kClient
+                                         : webrtc::RTCDtlsRole::kServer;
       } else {
-        transport_stats->dtls_role = "unknown";
+        transport_stats->dtls_role = webrtc::RTCDtlsRole::kUnknown;
       }
 
       if (channel_stats.ssl_cipher_suite != rtc::kTlsNullWithNullNull &&
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index a9f326f..a8111bf 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -1652,7 +1652,7 @@
   expected_a_local_host.candidate_type = "host";
   expected_a_local_host.priority = 0;
   expected_a_local_host.vpn = true;
-  expected_a_local_host.network_adapter_type = "ethernet";
+  expected_a_local_host.network_adapter_type = RTCNetworkAdapterType::kEthernet;
   expected_a_local_host.foundation = "foundationIsAString";
   expected_a_local_host.username_fragment = "iceusernamefragment";
 
@@ -1685,7 +1685,8 @@
   expected_a_local_prflx.candidate_type = "prflx";
   expected_a_local_prflx.priority = 2;
   expected_a_local_prflx.vpn = false;
-  expected_a_local_prflx.network_adapter_type = "cellular2g";
+  expected_a_local_prflx.network_adapter_type =
+      RTCNetworkAdapterType::kCellular2g;
   expected_a_local_prflx.foundation = "foundationIsAString";
   expected_a_local_prflx.username_fragment = "iceusernamefragment";
 
@@ -1723,7 +1724,7 @@
   expected_a_local_relay.priority = 1;
   expected_a_local_relay.url = "turn:url1";
   expected_a_local_relay.vpn = false;
-  expected_a_local_relay.network_adapter_type = "unknown";
+  expected_a_local_relay.network_adapter_type = RTCNetworkAdapterType::kUnknown;
   expected_a_local_relay.foundation = "foundationIsAString";
   expected_a_local_relay.username_fragment = "iceusernamefragment";
 
@@ -1744,7 +1745,8 @@
   expected_a_local_relay_prflx.candidate_type = "prflx";
   expected_a_local_relay_prflx.priority = 1;
   expected_a_local_relay_prflx.vpn = false;
-  expected_a_local_relay_prflx.network_adapter_type = "unknown";
+  expected_a_local_relay_prflx.network_adapter_type =
+      RTCNetworkAdapterType::kUnknown;
   expected_a_local_relay_prflx.foundation = "foundationIsAString";
   expected_a_local_relay_prflx.username_fragment = "iceusernamefragment";
 
@@ -1765,7 +1767,8 @@
   expected_a_local_host_not_paired.candidate_type = "host";
   expected_a_local_host_not_paired.priority = 0;
   expected_a_local_host_not_paired.vpn = true;
-  expected_a_local_host_not_paired.network_adapter_type = "ethernet";
+  expected_a_local_host_not_paired.network_adapter_type =
+      RTCNetworkAdapterType::kEthernet;
   expected_a_local_host_not_paired.foundation = "foundationIsAString";
   expected_a_local_host_not_paired.username_fragment = "iceusernamefragment";
 
@@ -1784,7 +1787,7 @@
   expected_b_local.candidate_type = "host";
   expected_b_local.priority = 42;
   expected_b_local.vpn = false;
-  expected_b_local.network_adapter_type = "wifi";
+  expected_b_local.network_adapter_type = RTCNetworkAdapterType::kWifi;
   expected_b_local.foundation = "foundationIsAString";
   expected_b_local.username_fragment = "iceusernamefragment";
 
@@ -1941,7 +1944,7 @@
       "Ttransport" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP);
   expected_pair.local_candidate_id = "I" + local_candidate->id();
   expected_pair.remote_candidate_id = "I" + remote_candidate->id();
-  expected_pair.state = "in-progress";
+  expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
   expected_pair.priority = 5555;
   expected_pair.nominated = false;
   expected_pair.writable = true;
@@ -2040,7 +2043,7 @@
   expected_local_candidate.foundation = "foundationIsAString";
   expected_local_candidate.username_fragment = "local_iceusernamefragment";
   expected_local_candidate.vpn = false;
-  expected_local_candidate.network_adapter_type = "wifi";
+  expected_local_candidate.network_adapter_type = RTCNetworkAdapterType::kWifi;
   ASSERT_TRUE(report->Get(expected_local_candidate.id()));
   EXPECT_EQ(expected_local_candidate,
             report->Get(expected_local_candidate.id())
@@ -2748,12 +2751,12 @@
   expected_rtp_transport.packets_sent = 1;
   expected_rtp_transport.bytes_received = 1337;
   expected_rtp_transport.packets_received = 4;
-  expected_rtp_transport.dtls_state = "new";
-  expected_rtp_transport.dtls_role = "unknown";
+  expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
+  expected_rtp_transport.dtls_role = RTCDtlsRole::kUnknown;
   expected_rtp_transport.selected_candidate_pair_changes = 1;
-  expected_rtp_transport.ice_role = "unknown";
+  expected_rtp_transport.ice_role = RTCIceRole::kUnknown;
   expected_rtp_transport.ice_local_username_fragment = "thelocalufrag";
-  expected_rtp_transport.ice_state = "new";
+  expected_rtp_transport.ice_state = RTCIceTransportState::kNew;
 
   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
   EXPECT_EQ(
@@ -2796,12 +2799,12 @@
   expected_rtcp_transport.packets_sent = 1;
   expected_rtcp_transport.bytes_received = 42;
   expected_rtcp_transport.packets_received = 4;
-  expected_rtcp_transport.dtls_state = "connecting";
-  expected_rtcp_transport.dtls_role = "unknown";
+  expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
+  expected_rtcp_transport.dtls_role = RTCDtlsRole::kUnknown;
   expected_rtcp_transport.selected_candidate_pair_changes = 0;
-  expected_rtcp_transport.ice_role = "unknown";
+  expected_rtcp_transport.ice_role = RTCIceRole::kUnknown;
   expected_rtcp_transport.ice_local_username_fragment = "thelocalufrag";
-  expected_rtcp_transport.ice_state = "checking";
+  expected_rtcp_transport.ice_state = RTCIceTransportState::kChecking;
 
   expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
@@ -2917,19 +2920,19 @@
   RTCTransportStats expected_rtp_transport(
       "Ttransport" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
       report->timestamp());
-  expected_rtp_transport.dtls_state = "connected";
+  expected_rtp_transport.dtls_state = RTCDtlsTransportState::kConnected;
   expected_rtp_transport.selected_candidate_pair_changes = 1;
-  expected_rtp_transport.ice_role = "unknown";
+  expected_rtp_transport.ice_role = RTCIceRole::kUnknown;
   expected_rtp_transport.bytes_sent = 0;
   expected_rtp_transport.bytes_received = 0;
   expected_rtp_transport.packets_sent = 0;
   expected_rtp_transport.packets_received = 0;
-  expected_rtp_transport.ice_role = "controlling";
+  expected_rtp_transport.ice_role = RTCIceRole::kControlling;
   expected_rtp_transport.ice_local_username_fragment = "thelocalufrag";
   expected_rtp_transport.ice_state = "connected";
   // Crypto parameters
   expected_rtp_transport.tls_version = "0203";
-  expected_rtp_transport.dtls_role = "client";
+  expected_rtp_transport.dtls_role = RTCDtlsRole::kClient;
   expected_rtp_transport.dtls_cipher = "TLS_RSA_WITH_AES_128_CBC_SHA";
   expected_rtp_transport.srtp_cipher = "AES_CM_128_HMAC_SHA1_80";
 
diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc
index 31720ad..67cb1c5 100644
--- a/stats/rtcstats_objects.cc
+++ b/stats/rtcstats_objects.cc
@@ -17,6 +17,70 @@
 
 namespace webrtc {
 
+const char* const RTCDataChannelState::kConnecting = "connecting";
+const char* const RTCDataChannelState::kOpen = "open";
+const char* const RTCDataChannelState::kClosing = "closing";
+const char* const RTCDataChannelState::kClosed = "closed";
+
+const char* const RTCStatsIceCandidatePairState::kFrozen = "frozen";
+const char* const RTCStatsIceCandidatePairState::kWaiting = "waiting";
+const char* const RTCStatsIceCandidatePairState::kInProgress = "in-progress";
+const char* const RTCStatsIceCandidatePairState::kFailed = "failed";
+const char* const RTCStatsIceCandidatePairState::kSucceeded = "succeeded";
+
+// Strings defined in https://tools.ietf.org/html/rfc5245.
+const char* const RTCIceCandidateType::kHost = "host";
+const char* const RTCIceCandidateType::kSrflx = "srflx";
+const char* const RTCIceCandidateType::kPrflx = "prflx";
+const char* const RTCIceCandidateType::kRelay = "relay";
+
+const char* const RTCDtlsTransportState::kNew = "new";
+const char* const RTCDtlsTransportState::kConnecting = "connecting";
+const char* const RTCDtlsTransportState::kConnected = "connected";
+const char* const RTCDtlsTransportState::kClosed = "closed";
+const char* const RTCDtlsTransportState::kFailed = "failed";
+
+const char* const RTCMediaStreamTrackKind::kAudio = "audio";
+const char* const RTCMediaStreamTrackKind::kVideo = "video";
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcnetworktype
+const char* const RTCNetworkType::kBluetooth = "bluetooth";
+const char* const RTCNetworkType::kCellular = "cellular";
+const char* const RTCNetworkType::kEthernet = "ethernet";
+const char* const RTCNetworkType::kWifi = "wifi";
+const char* const RTCNetworkType::kWimax = "wimax";
+const char* const RTCNetworkType::kVpn = "vpn";
+const char* const RTCNetworkType::kUnknown = "unknown";
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcqualitylimitationreason
+const char* const RTCQualityLimitationReason::kNone = "none";
+const char* const RTCQualityLimitationReason::kCpu = "cpu";
+const char* const RTCQualityLimitationReason::kBandwidth = "bandwidth";
+const char* const RTCQualityLimitationReason::kOther = "other";
+
+// https://webrtc.org/experiments/rtp-hdrext/video-content-type/
+const char* const RTCContentType::kUnspecified = "unspecified";
+const char* const RTCContentType::kScreenshare = "screenshare";
+
+// https://w3c.github.io/webrtc-stats/#dom-rtcdtlsrole
+const char* const RTCDtlsRole::kUnknown = "unknown";
+const char* const RTCDtlsRole::kClient = "client";
+const char* const RTCDtlsRole::kServer = "server";
+
+// https://www.w3.org/TR/webrtc/#rtcicerole
+const char* const RTCIceRole::kUnknown = "unknown";
+const char* const RTCIceRole::kControlled = "controlled";
+const char* const RTCIceRole::kControlling = "controlling";
+
+// https://www.w3.org/TR/webrtc/#dom-rtcicetransportstate
+const char* const RTCIceTransportState::kNew = "new";
+const char* const RTCIceTransportState::kChecking = "checking";
+const char* const RTCIceTransportState::kConnected = "connected";
+const char* const RTCIceTransportState::kCompleted = "completed";
+const char* const RTCIceTransportState::kDisconnected = "disconnected";
+const char* const RTCIceTransportState::kFailed = "failed";
+const char* const RTCIceTransportState::kClosed = "closed";
+
 // clang-format off
 WEBRTC_RTCSTATS_IMPL(RTCCertificateStats, RTCStats, "certificate",
     &fingerprint,
diff --git a/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc b/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc
index 09fd7c8..49e1657 100644
--- a/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc
+++ b/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc
@@ -42,7 +42,8 @@
   auto stats = report->GetStatsOfType<RTCInboundRtpStreamStats>();
 
   for (auto& stat : stats) {
-    if (!stat->kind.is_defined() || !(*stat->kind == "audio")) {
+    if (!stat->kind.is_defined() ||
+        !(*stat->kind == RTCMediaStreamTrackKind::kAudio)) {
       continue;
     }
 
diff --git a/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc b/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc
index 817b3ca..224eb0c 100644
--- a/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc
+++ b/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc
@@ -74,7 +74,7 @@
     if (!s->kind.is_defined()) {
       continue;
     }
-    if (!(*s->kind == "video")) {
+    if (!(*s->kind == RTCMediaStreamTrackKind::kVideo)) {
       continue;
     }
     if (s->timestamp() > sample.sample_time) {
diff --git a/test/pc/e2e/cross_media_metrics_reporter.cc b/test/pc/e2e/cross_media_metrics_reporter.cc
index aad5946..549eafd 100644
--- a/test/pc/e2e/cross_media_metrics_reporter.cc
+++ b/test/pc/e2e/cross_media_metrics_reporter.cc
@@ -71,7 +71,7 @@
               *audio_stat->kind != *video_stat->kind)
         << "Sync group should consist of one audio and one video stream.";
 
-    if (*audio_stat->kind == "video") {
+    if (*audio_stat->kind == RTCMediaStreamTrackKind::kVideo) {
       std::swap(audio_stat, video_stat);
     }
     // Stream labels of a sync group are same for all polls, so we need it add