Rename TrackExtensions to TrackProperties, to conform to MOQT draft-18 terminology.

Not in production.

PiperOrigin-RevId: 983986263
diff --git a/quiche/quic/moqt/moqt_fetch_stream.cc b/quiche/quic/moqt/moqt_fetch_stream.cc
index 724221e..f80724c 100644
--- a/quiche/quic/moqt/moqt_fetch_stream.cc
+++ b/quiche/quic/moqt/moqt_fetch_stream.cc
@@ -155,9 +155,9 @@
 
 absl::Status MoqtFetchRequestStream::OnControlMessage(
     const MoqtRequestOk& message) {
-  if (!message.extensions.empty()) {
+  if (!message.properties.empty()) {
     OnFatalError(absl::InvalidArgumentError(
-        "REQUEST_UPDATE_OK received with extensions"));
+        "REQUEST_UPDATE_OK received with properties"));
     return absl::OkStatus();
   }
   absl::StatusOr<MessageParameters> old_parameters =
@@ -251,7 +251,7 @@
         if (std::holds_alternative<FetchOkData>(result)) {
           const auto& ok_data = std::get<FetchOkData>(result);
           stream->default_publisher_priority_ =
-              ok_data.extensions.default_publisher_priority();
+              ok_data.properties.default_publisher_priority();
           stream->parameters_.Update(ok_data.parameters);
           stream->SendOrBufferMessageOrFatal(
               stream->framer()->SerializeFetchOk(ok_data));
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc
index e6cc15a..3ce7877 100644
--- a/quiche/quic/moqt/moqt_framer.cc
+++ b/quiche/quic/moqt/moqt_framer.cc
@@ -369,7 +369,7 @@
   std::optional<uint64_t> subgroup_id;
   std::optional<uint64_t> object_id;
   std::optional<uint8_t> publisher_priority;
-  std::optional<absl::string_view> extension_headers;
+  std::optional<absl::string_view> properties;
   uint64_t payload_length = message.payload_length;
   bool is_first_in_stream = !previous_object_in_stream.has_value();
   if (is_first_in_stream) {
@@ -396,19 +396,18 @@
     if (serialization.has_priority()) {
       publisher_priority = message.publisher_priority;
     }
-    if (serialization.has_extensions()) {
-      extension_headers = message.extension_headers;
+    if (serialization.has_properties()) {
+      properties = message.properties;
     }
-    return Serialize(
-        WireOptional<WireMoqVarInt>(stream_type),
-        WireOptional<WireMoqVarInt>(track_id),
-        WireMoqVarInt(serialization.value()),
-        WireOptional<WireMoqVarInt>(group_id),
-        WireOptional<WireMoqVarInt>(subgroup_id),
-        WireOptional<WireMoqVarInt>(object_id),
-        WireOptional<WireUint8>(publisher_priority),
-        WireOptional<WireStringWithMoqVarIntLength>(extension_headers),
-        WireMoqVarInt(payload_length));
+    return Serialize(WireOptional<WireMoqVarInt>(stream_type),
+                     WireOptional<WireMoqVarInt>(track_id),
+                     WireMoqVarInt(serialization.value()),
+                     WireOptional<WireMoqVarInt>(group_id),
+                     WireOptional<WireMoqVarInt>(subgroup_id),
+                     WireOptional<WireMoqVarInt>(object_id),
+                     WireOptional<WireUint8>(publisher_priority),
+                     WireOptional<WireStringWithMoqVarIntLength>(properties),
+                     WireMoqVarInt(payload_length));
   }
   // Subgroup stream.
   if (!message.subgroup_id.has_value()) {
@@ -429,22 +428,22 @@
   if (!is_first_in_stream) {
     *object_id -= (previous_object_in_stream->location.object + 1);
   }
-  if (message_type.AreExtensionHeadersPresent()) {
-    extension_headers = message.extension_headers;
+  if (message_type.ArePropertiesPresent()) {
+    properties = message.properties;
   }
   std::optional<uint64_t> object_status;
   if (payload_length == 0) {
     object_status = static_cast<uint64_t>(message.object_status);
   }
-  return Serialize(
-      WireOptional<WireMoqVarInt>(stream_type),
-      WireOptional<WireMoqVarInt>(track_id),
-      WireOptional<WireMoqVarInt>(group_id),
-      WireOptional<WireMoqVarInt>(subgroup_id),
-      WireOptional<WireUint8>(publisher_priority), WireMoqVarInt(*object_id),
-      WireOptional<WireStringWithMoqVarIntLength>(extension_headers),
-      WireMoqVarInt(message.payload_length),
-      WireOptional<WireMoqVarInt>(object_status));
+  return Serialize(WireOptional<WireMoqVarInt>(stream_type),
+                   WireOptional<WireMoqVarInt>(track_id),
+                   WireOptional<WireMoqVarInt>(group_id),
+                   WireOptional<WireMoqVarInt>(subgroup_id),
+                   WireOptional<WireUint8>(publisher_priority),
+                   WireMoqVarInt(*object_id),
+                   WireOptional<WireStringWithMoqVarIntLength>(properties),
+                   WireMoqVarInt(message.payload_length),
+                   WireOptional<WireMoqVarInt>(object_status));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeObjectDatagram(
@@ -461,7 +460,7 @@
     return quiche::QuicheBuffer();
   }
   MoqtDatagramType datagram_type(
-      !payload.empty(), !message.extension_headers.empty(),
+      !payload.empty(), !message.properties.empty(),
       message.object_status == MoqtObjectStatus::kEndOfGroup,
       message.publisher_priority == default_priority, message.object_id == 0);
   std::optional<uint64_t> object_id =
@@ -471,9 +470,9 @@
       datagram_type.has_default_priority()
           ? std::nullopt
           : std::optional<uint8_t>(message.publisher_priority);
-  std::optional<absl::string_view> extensions =
-      datagram_type.has_extension()
-          ? std::optional<absl::string_view>(message.extension_headers)
+  std::optional<absl::string_view> properties =
+      datagram_type.has_properties()
+          ? std::optional<absl::string_view>(message.properties)
           : std::nullopt;
   std::optional<uint64_t> object_status =
       payload.empty() ? std::optional<uint64_t>(
@@ -486,7 +485,7 @@
       WireMoqVarInt(datagram_type.value()), WireMoqVarInt(message.track_alias),
       WireMoqVarInt(message.group_id), WireOptional<WireMoqVarInt>(object_id),
       WireOptional<WireUint8>(publisher_priority),
-      WireOptional<WireStringWithMoqVarIntLength>(extensions),
+      WireOptional<WireStringWithMoqVarIntLength>(properties),
       WireOptional<WireMoqVarInt>(object_status),
       WireOptional<WireBytes>(raw_payload));
 }
@@ -505,7 +504,7 @@
   return SerializeControlMessage(
       MoqtMessageType::kRequestOk,
       WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
-      WireKeyValuePairList(message.extensions, false));
+      WireKeyValuePairList(message.properties, false));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeSubscribe(
@@ -518,15 +517,15 @@
 
 quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk(
     const MoqtSubscribeOk& message, MoqtMessageType message_type) {
-  if (!message.extensions.Validate()) {
+  if (!message.properties.Validate()) {
     QUICHE_BUG(QUICHE_BUG_serialize_subscribe_ok_01)
-        << "Subscribe OK extensions are ill-formed";
+        << "Subscribe OK properties are ill-formed";
     return quiche::QuicheBuffer();
   }
   return SerializeControlMessage(
       message_type, WireMoqVarInt(message.track_alias),
       WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
-      WireKeyValuePairList(message.extensions, false));
+      WireKeyValuePairList(message.properties, false));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeRequestError(
@@ -655,7 +654,7 @@
                         ? 0
                         : (message.end_location.object + 1)),
       WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
-      WireKeyValuePairList(message.extensions, false));
+      WireKeyValuePairList(message.properties, false));
 }
 
 
@@ -665,7 +664,7 @@
       WireFullTrackName(message.full_track_name),
       WireMoqVarInt(message.track_alias),
       WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
-      WireKeyValuePairList(message.extensions, false));
+      WireKeyValuePairList(message.properties, false));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeObjectAck(
diff --git a/quiche/quic/moqt/moqt_framer_test.cc b/quiche/quic/moqt/moqt_framer_test.cc
index f173cc5..0be2932 100644
--- a/quiche/quic/moqt/moqt_framer_test.cc
+++ b/quiche/quic/moqt/moqt_framer_test.cc
@@ -101,7 +101,7 @@
     previous_object->location =
         Location(message.group_id, message.object_id - change_in_object_id);
     previous_object->subgroup = message.subgroup_id;
-    previous_object->extensions = message.extension_headers;
+    previous_object->properties = message.properties;
     previous_object->status = message.object_status;
     previous_object->publisher_priority = message.publisher_priority;
   }
@@ -277,7 +277,7 @@
     auto middler = std::make_unique<StreamMiddlerFetchMessage>(flags);
     // Populate previous object metadata.
     previous.emplace(Location(object.group_id, object.object_id),
-                     object.subgroup_id, object.extension_headers,
+                     object.subgroup_id, object.properties,
                      object.object_status, object.publisher_priority);
     auto buffer2 = framer_.SerializeObjectHeader(
         std::get<MoqtObject>(middler->structured_data()),
@@ -297,7 +297,7 @@
       /*group_id=*/5,
       /*object_id=*/6,
       /*publisher_priority=*/7,
-      std::string(kDefaultExtensionBlob.data(), kDefaultExtensionBlob.size()),
+      std::string(kDefaultPropertyBlob.data(), kDefaultPropertyBlob.size()),
       /*object_status=*/MoqtObjectStatus::kObjectDoesNotExist,
       /*subgroup_id=*/8,
       /*first_object_in_subgroup=*/true,
@@ -320,7 +320,7 @@
       /*group_id=*/5,
       /*object_id=*/6,
       /*publisher_priority=*/7,
-      std::string(kDefaultExtensionBlob),
+      std::string(kDefaultPropertyBlob),
       /*object_status=*/MoqtObjectStatus::kNormal,
       /*subgroup_id=*/std::nullopt,
       /*first_object_in_subgroup=*/std::nullopt,
@@ -411,7 +411,7 @@
       /*end_of_track=*/false,
       /*end_location=*/Location{4, kMaxObjectId},
       MessageParameters(),
-      TrackExtensions(),
+      TrackProperties(),
   };
   quiche::QuicheBuffer buffer = framer_.SerializeFetchOk(fetch_ok);
   // Check that object ID is zero.
diff --git a/quiche/quic/moqt/moqt_integration_test.cc b/quiche/quic/moqt/moqt_integration_test.cc
index 01aea7f..ec75f16 100644
--- a/quiche/quic/moqt/moqt_integration_test.cc
+++ b/quiche/quic/moqt/moqt_integration_test.cc
@@ -977,7 +977,7 @@
   MoqtResponseCallback server_response_callback;
   server_->session()->callbacks().incoming_publish_callback =
       [&](const FullTrackName& name, const MessageParameters& parameters,
-          const TrackExtensions& extensions, MoqtResponseCallback callback) {
+          const TrackProperties& properties, MoqtResponseCallback callback) {
         EXPECT_EQ(name, full_track_name);
         server_response_callback = std::move(callback);
         server_received_publish = true;
@@ -996,9 +996,9 @@
       };
 
   MessageParameters publish_parameters;
-  TrackExtensions publish_extensions;
+  TrackProperties publish_properties;
   bool publish_submitted =
-      client_->session()->Publish(queue, publish_parameters, publish_extensions,
+      client_->session()->Publish(queue, publish_parameters, publish_properties,
                                   std::move(client_publish_callback));
   ASSERT_TRUE(publish_submitted);
 
diff --git a/quiche/quic/moqt/moqt_key_value_pair.cc b/quiche/quic/moqt/moqt_key_value_pair.cc
index c8520b8..ce63ffe 100644
--- a/quiche/quic/moqt/moqt_key_value_pair.cc
+++ b/quiche/quic/moqt/moqt_key_value_pair.cc
@@ -100,104 +100,104 @@
   }
 }
 
-TrackExtensions::TrackExtensions(
+TrackProperties::TrackProperties(
     std::optional<quic::QuicTimeDelta> delivery_timeout,
     std::optional<quic::QuicTimeDelta> max_cache_duration,
     std::optional<MoqtPriority> publisher_priority,
     std::optional<MoqtDeliveryOrder> group_order,
     std::optional<bool> dynamic_groups,
-    std::optional<absl::string_view> immutable_extensions) {
+    std::optional<absl::string_view> immutable_properties) {
   if (delivery_timeout.has_value() &&
       *delivery_timeout != kDefaultDeliveryTimeout) {
-    insert(static_cast<uint64_t>(ExtensionHeader::kDeliveryTimeout),
+    insert(static_cast<uint64_t>(PropertyType::kDeliveryTimeout),
            static_cast<uint64_t>(delivery_timeout->ToMilliseconds()));
   }
   if (max_cache_duration.has_value() &&
       *max_cache_duration != kDefaultMaxCacheDuration) {
-    insert(static_cast<uint64_t>(ExtensionHeader::kMaxCacheDuration),
+    insert(static_cast<uint64_t>(PropertyType::kMaxCacheDuration),
            static_cast<uint64_t>(max_cache_duration->ToMilliseconds()));
   }
-  if (immutable_extensions.has_value() && !immutable_extensions->empty()) {
-    insert(static_cast<uint64_t>(ExtensionHeader::kImmutableExtensions),
-           *immutable_extensions);
+  if (immutable_properties.has_value() && !immutable_properties->empty()) {
+    insert(static_cast<uint64_t>(PropertyType::kImmutableProperties),
+           *immutable_properties);
   }
   if (publisher_priority.has_value() &&
       *publisher_priority != kDefaultPublisherPriority) {
-    insert(static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherPriority),
+    insert(static_cast<uint64_t>(PropertyType::kDefaultPublisherPriority),
            static_cast<uint64_t>(*publisher_priority));
   }
   if (group_order.has_value() && *group_order != kDefaultGroupOrder) {
-    insert(static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherGroupOrder),
+    insert(static_cast<uint64_t>(PropertyType::kDefaultPublisherGroupOrder),
            static_cast<uint64_t>(*group_order));
   }
   if (dynamic_groups.has_value() && *dynamic_groups != kDefaultDynamicGroups) {
-    insert(static_cast<uint64_t>(ExtensionHeader::kDynamicGroups),
+    insert(static_cast<uint64_t>(PropertyType::kDynamicGroups),
            *dynamic_groups ? 1ULL : 0ULL);
   }
 }
 
-quic::QuicTimeDelta TrackExtensions::delivery_timeout() const {
+quic::QuicTimeDelta TrackProperties::delivery_timeout() const {
   std::optional<uint64_t> value =
-      GetValueIfExactlyOne(ExtensionHeader::kDeliveryTimeout);
+      GetValueIfExactlyOne(PropertyType::kDeliveryTimeout);
   return value.has_value() ? quic::QuicTimeDelta::FromMilliseconds(*value)
                            : kDefaultDeliveryTimeout;
 }
 
-quic::QuicTimeDelta TrackExtensions::max_cache_duration() const {
+quic::QuicTimeDelta TrackProperties::max_cache_duration() const {
   std::optional<uint64_t> value =
-      GetValueIfExactlyOne(ExtensionHeader::kMaxCacheDuration);
+      GetValueIfExactlyOne(PropertyType::kMaxCacheDuration);
   return value.has_value() ? quic::QuicTimeDelta::FromMilliseconds(*value)
                            : kDefaultMaxCacheDuration;
 }
-absl::string_view TrackExtensions::immutable_extensions() const {
+absl::string_view TrackProperties::immutable_properties() const {
   ValueVector values =
-      Get(static_cast<uint64_t>(ExtensionHeader::kImmutableExtensions));
+      Get(static_cast<uint64_t>(PropertyType::kImmutableProperties));
   return (values.size() != 1 ||
           !std::holds_alternative<absl::string_view>(values[0]))
              ? ""
              : std::get<absl::string_view>(values[0]);
 }
-MoqtPriority TrackExtensions::default_publisher_priority() const {
+MoqtPriority TrackProperties::default_publisher_priority() const {
   std::optional<uint64_t> value =
-      GetValueIfExactlyOne(ExtensionHeader::kDefaultPublisherPriority);
+      GetValueIfExactlyOne(PropertyType::kDefaultPublisherPriority);
   return (!value.has_value() || *value > kMaxPriority)
              ? kDefaultPublisherPriority
              : static_cast<MoqtPriority>(*value);
 }
-MoqtDeliveryOrder TrackExtensions::default_publisher_group_order() const {
+MoqtDeliveryOrder TrackProperties::default_publisher_group_order() const {
   std::optional<uint64_t> value =
-      GetValueIfExactlyOne(ExtensionHeader::kDefaultPublisherGroupOrder);
+      GetValueIfExactlyOne(PropertyType::kDefaultPublisherGroupOrder);
   return (!value.has_value() || *value > kMaxMoqtDeliveryOrder ||
           *value < kMinMoqtDeliveryOrder)
              ? kDefaultGroupOrder
              : static_cast<MoqtDeliveryOrder>(*value);
 }
-bool TrackExtensions::dynamic_groups() const {
+bool TrackProperties::dynamic_groups() const {
   std::optional<uint64_t> value =
-      GetValueIfExactlyOne(ExtensionHeader::kDynamicGroups);
+      GetValueIfExactlyOne(PropertyType::kDynamicGroups);
   return (!value.has_value() || *value > 1) ? kDefaultDynamicGroups
                                             : (*value == 1);
 }
 
-bool TrackExtensions::Validate() const {
-  // TODO(martinduke): If immutable extensions include an immutable extensions
-  // extension, the track is malformed.
-  return (ValidateInner(ExtensionHeader::kDeliveryTimeout, std::nullopt,
+bool TrackProperties::Validate() const {
+  // TODO(martinduke): If immutable properties include an immutable properties
+  // property, the track is malformed.
+  return (ValidateInner(PropertyType::kDeliveryTimeout, std::nullopt,
                         std::nullopt) &&
-          ValidateInner(ExtensionHeader::kMaxCacheDuration, std::nullopt,
+          ValidateInner(PropertyType::kMaxCacheDuration, std::nullopt,
                         std::nullopt) &&
-          ValidateInner(ExtensionHeader::kDefaultPublisherPriority,
-                        std::nullopt, kMaxPriority) &&
-          ValidateInner(ExtensionHeader::kDefaultPublisherGroupOrder,
+          ValidateInner(PropertyType::kDefaultPublisherPriority, std::nullopt,
+                        kMaxPriority) &&
+          ValidateInner(PropertyType::kDefaultPublisherGroupOrder,
                         kMinMoqtDeliveryOrder, kMaxMoqtDeliveryOrder) &&
-          ValidateInner(ExtensionHeader::kDynamicGroups, 0, 1) &&
-          count(static_cast<uint64_t>(ExtensionHeader::kImmutableExtensions)) <=
+          ValidateInner(PropertyType::kDynamicGroups, 0, 1) &&
+          count(static_cast<uint64_t>(PropertyType::kImmutableProperties)) <=
               1);
 }
 
 // private
-std::optional<uint64_t> TrackExtensions::GetValueIfExactlyOne(
-    ExtensionHeader header) const {
+std::optional<uint64_t> TrackProperties::GetValueIfExactlyOne(
+    PropertyType header) const {
   QUICHE_BUG_IF(moqt_bug_must_be_even, (static_cast<uint64_t>(header) % 2) == 1)
       << "MoqtKeyValuePair extracting integer from odd key.";
   ValueVector values = Get(static_cast<uint64_t>(header));
@@ -207,7 +207,7 @@
   return std::get<uint64_t>(values[0]);
 }
 
-bool TrackExtensions::ValidateInner(ExtensionHeader header,
+bool TrackProperties::ValidateInner(PropertyType header,
                                     std::optional<uint64_t> min,
                                     std::optional<uint64_t> max) const {
   ValueVector values = Get(static_cast<uint64_t>(header));
diff --git a/quiche/quic/moqt/moqt_key_value_pair.h b/quiche/quic/moqt/moqt_key_value_pair.h
index 4d81519..c6f9b01 100644
--- a/quiche/quic/moqt/moqt_key_value_pair.h
+++ b/quiche/quic/moqt/moqt_key_value_pair.h
@@ -24,7 +24,7 @@
 
 namespace moqt {
 
-// Encodes a list of key-value pairs common to both parameters and extensions.
+// Encodes a list of key-value pairs common to both parameters and properties.
 // If the key is odd, it is a length-prefixed string (which may encode further
 // item-specific structure). If the key is even, it is a varint.
 // This class does not interpret the semantic meaning of the keys and values.
@@ -157,7 +157,7 @@
   // Indicates support for OACK messages.
   kSupportObjectAcks = 0xbbf1438,
 };
-// TODO(martinduke): Refactor this to be more like TrackExtensions.
+// TODO(martinduke): Refactor this to be more like TrackProperties.
 struct QUICHE_EXPORT SetupParameters {
   SetupParameters() = default;
   // Constructors for tests.
@@ -198,7 +198,7 @@
     quic::QuicTimeDelta::Infinite();
 constexpr quic::QuicTimeDelta kDefaultExpires = quic::QuicTimeDelta::Infinite();
 constexpr bool kDefaultForward = true;
-// TODO(martinduke): Refactor this to be more like TrackExtensions.
+// TODO(martinduke): Refactor this to be more like TrackProperties.
 struct MessageParameters {
   MessageParameters() = default;
   MessageParameters(const MessageParameters&) = default;
@@ -243,10 +243,10 @@
   std::optional<bool> forward_;
 };
 
-enum class ExtensionHeader : uint64_t {
+enum class PropertyType : uint64_t {
   kDeliveryTimeout = 0x02,
   kMaxCacheDuration = 0x04,
-  kImmutableExtensions = 0x0b,
+  kImmutableProperties = 0x0b,
   kDefaultPublisherPriority = 0x0e,
   kDefaultPublisherGroupOrder = 0x22,
   kDynamicGroups = 0x30,
@@ -255,50 +255,48 @@
 };
 inline constexpr quic::QuicTimeDelta kDefaultMaxCacheDuration =
     quic::QuicTimeDelta::Infinite();
-inline constexpr bool kDefaultImmutableExtensions = false;
+inline constexpr bool kDefaultImmutableProperties = false;
 inline constexpr MoqtDeliveryOrder kDefaultGroupOrder =
     MoqtDeliveryOrder::kAscending;
 inline constexpr bool kDefaultDynamicGroups = false;
-class TrackExtensions : public KeyValuePairList {
+class TrackProperties : public KeyValuePairList {
  public:
-  TrackExtensions() = default;
-  TrackExtensions(const TrackExtensions&) = default;
-  // Constructor for Original publishers to create their extensions.
-  TrackExtensions(std::optional<quic::QuicTimeDelta> delivery_timeout,
+  TrackProperties() = default;
+  TrackProperties(const TrackProperties&) = default;
+  // Constructor for Original publishers to create their track properties.
+  TrackProperties(std::optional<quic::QuicTimeDelta> delivery_timeout,
                   std::optional<quic::QuicTimeDelta> max_cache_duration,
                   std::optional<MoqtPriority> publisher_priority,
                   std::optional<MoqtDeliveryOrder> group_order,
                   std::optional<bool> dynamic_groups,
-                  std::optional<absl::string_view> immutable_extensions);
+                  std::optional<absl::string_view> immutable_properties);
 
-  // If present and well-formed, returns the value of the extension. Returns the
+  // If present and well-formed, returns the value of the property. Returns the
   // default value if missing or ill-formed.
   quic::QuicTimeDelta delivery_timeout() const;
   quic::QuicTimeDelta max_cache_duration() const;
-  absl::string_view immutable_extensions() const;
+  absl::string_view immutable_properties() const;
   MoqtPriority default_publisher_priority() const;
   MoqtDeliveryOrder default_publisher_group_order() const;
   bool dynamic_groups() const;
   bool empty() const { return size() == 0; }
 
-  // Returns false if the extension list contains illegal values or illegally
-  // duplicated extensions.
+  // Returns false if the property list contains illegal values or illegally
+  // duplicated properties.
   bool Validate() const;
-  bool operator==(const TrackExtensions& other) const = default;
-  TrackExtensions& operator=(const TrackExtensions& other) = default;
+  bool operator==(const TrackProperties& other) const = default;
+  TrackProperties& operator=(const TrackProperties& other) = default;
 
  private:
-  // Returns the value of the extension if there is exactly one, otherwise
-  // returns std::nullopt. Must not be called on odd extension types.
-  std::optional<uint64_t> GetValueIfExactlyOne(ExtensionHeader header) const;
-  // Verifies that there is no more that one instance of an extension, and if
+  // Returns the value of the property if there is exactly one, otherwise
+  // returns std::nullopt. Must not be called on odd property types.
+  std::optional<uint64_t> GetValueIfExactlyOne(PropertyType header) const;
+  // Verifies that there is no more that one instance of an property, and if
   // present, that the value is acceptable.
-  bool ValidateInner(ExtensionHeader header, std::optional<uint64_t> min_value,
+  bool ValidateInner(PropertyType header, std::optional<uint64_t> min_value,
                      std::optional<uint64_t> max_value) const;
 };
 
-// TODO(martinduke): Extension Headers (MOQT draft-16 Sec 11)
-
 }  // namespace moqt
 
 #endif  // QUICHE_QUIC_MOQT_MOQT_KEY_VALUE_PAIR_H_
diff --git a/quiche/quic/moqt/moqt_key_value_pair_test.cc b/quiche/quic/moqt/moqt_key_value_pair_test.cc
index d91793c..0d776a2 100644
--- a/quiche/quic/moqt/moqt_key_value_pair_test.cc
+++ b/quiche/quic/moqt/moqt_key_value_pair_test.cc
@@ -258,116 +258,108 @@
   EXPECT_EQ(p1.new_group_request, 1);
 }
 
-class TrackExtensionsTest : public quic::test::QuicTest {};
+class TrackPropertiesTest : public quic::test::QuicTest {};
 
-TEST_F(TrackExtensionsTest, DefaultConstructor) {
-  TrackExtensions extensions;
-  EXPECT_TRUE(extensions.Validate());
-  EXPECT_EQ(extensions.delivery_timeout(), kDefaultDeliveryTimeout);
-  EXPECT_EQ(extensions.max_cache_duration(), kDefaultMaxCacheDuration);
-  EXPECT_EQ(extensions.default_publisher_priority(), kDefaultPublisherPriority);
-  EXPECT_EQ(extensions.default_publisher_group_order(), kDefaultGroupOrder);
-  EXPECT_EQ(extensions.dynamic_groups(), kDefaultDynamicGroups);
-  EXPECT_TRUE(extensions.immutable_extensions().empty());
+TEST_F(TrackPropertiesTest, DefaultConstructor) {
+  TrackProperties properties;
+  EXPECT_TRUE(properties.Validate());
+  EXPECT_EQ(properties.delivery_timeout(), kDefaultDeliveryTimeout);
+  EXPECT_EQ(properties.max_cache_duration(), kDefaultMaxCacheDuration);
+  EXPECT_EQ(properties.default_publisher_priority(), kDefaultPublisherPriority);
+  EXPECT_EQ(properties.default_publisher_group_order(), kDefaultGroupOrder);
+  EXPECT_EQ(properties.dynamic_groups(), kDefaultDynamicGroups);
+  EXPECT_TRUE(properties.immutable_properties().empty());
 }
 
-TEST_F(TrackExtensionsTest, AllExtensions) {
-  TrackExtensions extensions(quic::QuicTimeDelta::FromMilliseconds(1),
+TEST_F(TrackPropertiesTest, AllProperties) {
+  TrackProperties properties(quic::QuicTimeDelta::FromMilliseconds(1),
                              quic::QuicTimeDelta::FromMilliseconds(2),
                              MoqtPriority(10), MoqtDeliveryOrder::kDescending,
-                             true, "extensions");
-  EXPECT_TRUE(extensions.Validate());
-  EXPECT_EQ(extensions.delivery_timeout(),
+                             true, "properties");
+  EXPECT_TRUE(properties.Validate());
+  EXPECT_EQ(properties.delivery_timeout(),
             quic::QuicTimeDelta::FromMilliseconds(1));
-  EXPECT_EQ(extensions.max_cache_duration(),
+  EXPECT_EQ(properties.max_cache_duration(),
             quic::QuicTimeDelta::FromMilliseconds(2));
-  EXPECT_EQ(extensions.default_publisher_priority(), MoqtPriority(10));
-  EXPECT_EQ(extensions.default_publisher_group_order(),
+  EXPECT_EQ(properties.default_publisher_priority(), MoqtPriority(10));
+  EXPECT_EQ(properties.default_publisher_group_order(),
             MoqtDeliveryOrder::kDescending);
-  EXPECT_TRUE(extensions.dynamic_groups());
-  EXPECT_EQ(extensions.immutable_extensions(), "extensions");
+  EXPECT_TRUE(properties.dynamic_groups());
+  EXPECT_EQ(properties.immutable_properties(), "properties");
 }
 
-TEST_F(TrackExtensionsTest, ExplicitDefaults) {
-  TrackExtensions extensions(kDefaultDeliveryTimeout, kDefaultMaxCacheDuration,
+TEST_F(TrackPropertiesTest, ExplicitDefaults) {
+  TrackProperties properties(kDefaultDeliveryTimeout, kDefaultMaxCacheDuration,
                              kDefaultPublisherPriority, kDefaultGroupOrder,
                              kDefaultDynamicGroups, "");
-  EXPECT_TRUE(extensions.Validate());
-  EXPECT_EQ(extensions.size(), 0);
-  EXPECT_EQ(extensions.delivery_timeout(), kDefaultDeliveryTimeout);
-  EXPECT_EQ(extensions.max_cache_duration(), kDefaultMaxCacheDuration);
-  EXPECT_EQ(extensions.default_publisher_priority(), kDefaultPublisherPriority);
-  EXPECT_EQ(extensions.default_publisher_group_order(), kDefaultGroupOrder);
-  EXPECT_EQ(extensions.dynamic_groups(), kDefaultDynamicGroups);
-  EXPECT_TRUE(extensions.immutable_extensions().empty());
+  EXPECT_TRUE(properties.Validate());
+  EXPECT_EQ(properties.size(), 0);
+  EXPECT_EQ(properties.delivery_timeout(), kDefaultDeliveryTimeout);
+  EXPECT_EQ(properties.max_cache_duration(), kDefaultMaxCacheDuration);
+  EXPECT_EQ(properties.default_publisher_priority(), kDefaultPublisherPriority);
+  EXPECT_EQ(properties.default_publisher_group_order(), kDefaultGroupOrder);
+  EXPECT_EQ(properties.dynamic_groups(), kDefaultDynamicGroups);
+  EXPECT_TRUE(properties.immutable_properties().empty());
 }
 
-TEST_F(TrackExtensionsTest, Validate) {
-  TrackExtensions extensions;
-  // Unknown extension.
-  extensions.insert(0x42, 15ULL);
-  extensions.insert(0x42, 25ULL);
-  EXPECT_TRUE(extensions.Validate());
+TEST_F(TrackPropertiesTest, Validate) {
+  TrackProperties properties;
+  // Unknown property.
+  properties.insert(0x42, 15ULL);
+  properties.insert(0x42, 25ULL);
+  EXPECT_TRUE(properties.Validate());
 
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDeliveryTimeout),
+  properties.insert(static_cast<uint64_t>(PropertyType::kDeliveryTimeout),
                     5ULL);
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDeliveryTimeout),
+  properties.insert(static_cast<uint64_t>(PropertyType::kDeliveryTimeout),
                     6ULL);
-  EXPECT_FALSE(extensions.Validate());
+  EXPECT_FALSE(properties.Validate());
 
-  extensions.clear();
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kMaxCacheDuration),
+  properties.clear();
+  properties.insert(static_cast<uint64_t>(PropertyType::kMaxCacheDuration),
                     5ULL);
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kMaxCacheDuration),
+  properties.insert(static_cast<uint64_t>(PropertyType::kMaxCacheDuration),
                     6ULL);
-  EXPECT_FALSE(extensions.Validate());
+  EXPECT_FALSE(properties.Validate());
 
-  extensions.clear();
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherPriority),
-      256ULL);
-  EXPECT_FALSE(extensions.Validate());
-  extensions.clear();
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherPriority), 0ULL);
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherPriority), 1ULL);
-  EXPECT_FALSE(extensions.Validate());
+  properties.clear();
+  properties.insert(
+      static_cast<uint64_t>(PropertyType::kDefaultPublisherPriority), 256ULL);
+  EXPECT_FALSE(properties.Validate());
+  properties.clear();
+  properties.insert(
+      static_cast<uint64_t>(PropertyType::kDefaultPublisherPriority), 0ULL);
+  properties.insert(
+      static_cast<uint64_t>(PropertyType::kDefaultPublisherPriority), 1ULL);
+  EXPECT_FALSE(properties.Validate());
 
-  extensions.clear();
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherGroupOrder),
-      0ULL);
-  EXPECT_FALSE(extensions.Validate());
-  extensions.clear();
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kDefaultPublisherGroupOrder),
-      3ULL);
-  EXPECT_FALSE(extensions.Validate());
-  extensions.clear();
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDynamicGroups),
-                    2ULL);
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDynamicGroups),
-                    1ULL);
-  EXPECT_FALSE(extensions.Validate());
+  properties.clear();
+  properties.insert(
+      static_cast<uint64_t>(PropertyType::kDefaultPublisherGroupOrder), 0ULL);
+  EXPECT_FALSE(properties.Validate());
+  properties.clear();
+  properties.insert(
+      static_cast<uint64_t>(PropertyType::kDefaultPublisherGroupOrder), 3ULL);
+  EXPECT_FALSE(properties.Validate());
+  properties.clear();
+  properties.insert(static_cast<uint64_t>(PropertyType::kDynamicGroups), 2ULL);
+  properties.insert(static_cast<uint64_t>(PropertyType::kDynamicGroups), 1ULL);
+  EXPECT_FALSE(properties.Validate());
 
-  extensions.clear();
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDynamicGroups),
-                    2ULL);
-  EXPECT_FALSE(extensions.Validate());
-  extensions.clear();
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDynamicGroups),
-                    0ULL);
-  extensions.insert(static_cast<uint64_t>(ExtensionHeader::kDynamicGroups),
-                    1ULL);
-  EXPECT_FALSE(extensions.Validate());
+  properties.clear();
+  properties.insert(static_cast<uint64_t>(PropertyType::kDynamicGroups), 2ULL);
+  EXPECT_FALSE(properties.Validate());
+  properties.clear();
+  properties.insert(static_cast<uint64_t>(PropertyType::kDynamicGroups), 0ULL);
+  properties.insert(static_cast<uint64_t>(PropertyType::kDynamicGroups), 1ULL);
+  EXPECT_FALSE(properties.Validate());
 
-  extensions.clear();
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kImmutableExtensions), "foo");
-  extensions.insert(
-      static_cast<uint64_t>(ExtensionHeader::kImmutableExtensions), "bar");
-  EXPECT_FALSE(extensions.Validate());
+  properties.clear();
+  properties.insert(static_cast<uint64_t>(PropertyType::kImmutableProperties),
+                    "foo");
+  properties.insert(static_cast<uint64_t>(PropertyType::kImmutableProperties),
+                    "bar");
+  EXPECT_FALSE(properties.Validate());
 }
 
 }  // namespace moqt::test
diff --git a/quiche/quic/moqt/moqt_live_publisher.cc b/quiche/quic/moqt/moqt_live_publisher.cc
index 3a886e4..d48dad3 100644
--- a/quiche/quic/moqt/moqt_live_publisher.cc
+++ b/quiche/quic/moqt/moqt_live_publisher.cc
@@ -98,7 +98,7 @@
     // Tell the session that pending stream priority has changed.
     MoqtPriority publisher_priority =
         pending_streams_.rbegin()->second.publisher_priority.value_or(
-            track_publisher_->extensions().default_publisher_priority());
+            track_publisher_->properties().default_publisher_priority());
     MoqtTrackPriority old_track_priority = {old_priority, publisher_priority};
     if (visitor() == nullptr) {
       return;
@@ -136,15 +136,15 @@
   subscribe_ok.track_alias = track_alias_;
   subscribe_ok.parameters.expires = track_publisher_->expiration();
   subscribe_ok.parameters.largest_object = parameters_.largest_object;
-  subscribe_ok.extensions = track_publisher_->extensions();
+  subscribe_ok.properties = track_publisher_->properties();
   if (!parameters_.group_order.has_value()) {
     parameters_.group_order =
-        subscribe_ok.extensions.default_publisher_group_order();
+        subscribe_ok.properties.default_publisher_group_order();
   }
   // TODO(martinduke): Support sending DELIVERY_TIMEOUT parameter as the
   // publisher.
   default_publisher_priority_ =
-      subscribe_ok.extensions.default_publisher_priority();
+      subscribe_ok.properties.default_publisher_priority();
   bidi_stream_->SendOrBufferMessageOrFatal(
       framer_.SerializeSubscribeOk(subscribe_ok));
   // TODO(martinduke): If we buffer objects that arrived previously, the arrival
@@ -347,7 +347,7 @@
   header.group_id = object->metadata.location.group;
   header.object_id = object->metadata.location.object;
   header.publisher_priority = object->metadata.publisher_priority;
-  header.extension_headers = object->metadata.extensions;
+  header.properties = object->metadata.properties;
   header.object_status = object->metadata.status;
   header.subgroup_id = std::nullopt;
   header.payload_length = object->metadata.payload_length;
diff --git a/quiche/quic/moqt/moqt_live_publisher_test.cc b/quiche/quic/moqt/moqt_live_publisher_test.cc
index df1850d..0360d4c 100644
--- a/quiche/quic/moqt/moqt_live_publisher_test.cc
+++ b/quiche/quic/moqt/moqt_live_publisher_test.cc
@@ -94,7 +94,7 @@
   object.metadata.subgroup = subgroup;
   object.metadata.status = MoqtObjectStatus::kNormal;
   object.metadata.publisher_priority = publisher_priority;
-  object.metadata.extensions = "extensions";
+  object.metadata.properties = "properties";
   object.metadata.first_object_in_subgroup =
       subgroup.has_value() ? std::optional<bool>(location.object == 0)
                            : std::nullopt;
@@ -227,7 +227,7 @@
   StrictMock<MockPublishingMonitorInterface> monitoring_interface_;
   MoqtTraceRecorder trace_recorder_;
   std::unique_ptr<LivePublisher> publisher_;
-  const TrackExtensions extensions_;
+  const TrackProperties properties_;
   quic::MockClock mock_clock_;
   MoqtSessionCallbacks callbacks_;
   quic::test::TestAlarmFactory alarm_factory_;
@@ -240,8 +240,8 @@
       .WillOnce(Return(Location(1, 2)));
   EXPECT_CALL(*track_publisher_, expiration)
       .WillOnce(Return(quic::QuicTimeDelta::FromSeconds(10)));
-  EXPECT_CALL(*track_publisher_, extensions)
-      .WillRepeatedly(ReturnRef(extensions_));
+  EXPECT_CALL(*track_publisher_, properties)
+      .WillRepeatedly(ReturnRef(properties_));
   EXPECT_CALL(mock_bidi_stream_,
               Writev(ControlMessageOfType(MoqtMessageType::kSubscribeOk), _))
       .WillOnce(Return(absl::OkStatus()));
@@ -254,7 +254,7 @@
 TEST_F(LivePublisherTest, OnSubscribeAcceptedWithFilter) {
   publisher_->parameters().subscription_filter =
       SubscriptionFilter(MoqtFilterType::kLargestObject);
-  const TrackExtensions extensions(std::nullopt, std::nullopt,
+  const TrackProperties properties(std::nullopt, std::nullopt,
                                    /*default_publisher_priority=*/64,
                                    std::nullopt, std::nullopt, std::nullopt);
   EXPECT_CALL(mock_bidi_stream_, CanWrite()).WillRepeatedly(Return(true));
@@ -262,8 +262,8 @@
       .WillOnce(Return(Location(1, 2)));
   EXPECT_CALL(*track_publisher_, expiration)
       .WillOnce(Return(quic::QuicTimeDelta::FromSeconds(10)));
-  EXPECT_CALL(*track_publisher_, extensions)
-      .WillRepeatedly(ReturnRef(extensions));
+  EXPECT_CALL(*track_publisher_, properties)
+      .WillRepeatedly(ReturnRef(properties));
   EXPECT_CALL(mock_bidi_stream_,
               Writev(ControlMessageOfType(MoqtMessageType::kSubscribeOk), _))
       .WillOnce(Return(absl::OkStatus()));
@@ -323,8 +323,8 @@
   CreatePendingStream(Location(1, 0), 0, 64);
   MessageParameters new_params;
   new_params.subscriber_priority = 20;
-  EXPECT_CALL(*track_publisher_, extensions())
-      .WillRepeatedly(ReturnRef(extensions_));
+  EXPECT_CALL(*track_publisher_, properties())
+      .WillRepeatedly(ReturnRef(properties_));
   EXPECT_CALL(visitor_, UpdateTrackPriority(track_publisher_->GetTrackName(),
                                             std::optional<MoqtTrackPriority>(
                                                 {subscriber_priority(), 64}),
@@ -360,8 +360,8 @@
   EXPECT_CALL(monitoring_interface_, OnNewObjectEnqueued(Location(1, 0)));
   EXPECT_CALL(webtrans_, SendOrQueueDatagram)
       .WillOnce(Return(DatagramStatus(DatagramStatusCode::kSuccess, "")));
-  EXPECT_CALL(*track_publisher_, extensions())
-      .WillRepeatedly(ReturnRef(extensions_));
+  EXPECT_CALL(*track_publisher_, properties())
+      .WillRepeatedly(ReturnRef(properties_));
   publisher_->OnNewObjectAvailable(Location(1, 0), std::nullopt, 128);
 }
 
diff --git a/quiche/quic/moqt/moqt_messages.cc b/quiche/quic/moqt/moqt_messages.cc
index a965006..1ac1208 100644
--- a/quiche/quic/moqt/moqt_messages.cc
+++ b/quiche/quic/moqt/moqt_messages.cc
@@ -122,7 +122,7 @@
 
 std::string MoqtDatagramTypeToString(MoqtDatagramType type) {
   return absl::StrCat("DATAGRAM", type.has_status() ? "_STATUS" : "",
-                      type.has_extension() ? "_EXTENSION" : "");
+                      type.has_properties() ? "_PROPERTIES" : "");
 }
 
 std::string MoqtFetchSerializationToString(MoqtFetchSerialization type) {
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h
index ebbf785..79b27be 100644
--- a/quiche/quic/moqt/moqt_messages.h
+++ b/quiche/quic/moqt/moqt_messages.h
@@ -42,7 +42,7 @@
   static constexpr uint64_t kFetch = 0x05;
   static constexpr uint64_t kPadding = 0x26d3;
   static constexpr uint64_t kSubgroup = 0x10;
-  static constexpr uint64_t kExtensions = 0x01;
+  static constexpr uint64_t kProperties = 0x01;
   static constexpr uint64_t kEndOfGroup = 0x08;
   static constexpr uint64_t kDefaultPriority = 0x20;
   static constexpr uint64_t kHasFirstObject = 0x40;
@@ -60,7 +60,7 @@
     if (!(value & kSubgroup)) {
       return std::nullopt;
     }
-    if (value > (kSubgroup | kExtensions | kEndOfGroup | kDefaultPriority |
+    if (value > (kSubgroup | kProperties | kEndOfGroup | kDefaultPriority |
                  kFirstObjectId | kSubgroupId | kHasFirstObject)) {
       // Reserved bits.
       return std::nullopt;
@@ -72,12 +72,14 @@
   }
   static MoqtDataStreamType Fetch() { return MoqtDataStreamType(kFetch); }
   static MoqtDataStreamType Padding() { return MoqtDataStreamType(kPadding); }
-  static MoqtDataStreamType Subgroup(
-      uint64_t subgroup_id, uint64_t first_object_id, bool no_extension_headers,
-      bool default_priority, bool has_first_object, bool end_of_group = false) {
+  static MoqtDataStreamType Subgroup(uint64_t subgroup_id,
+                                     uint64_t first_object_id,
+                                     bool no_properties, bool default_priority,
+                                     bool has_first_object,
+                                     bool end_of_group = false) {
     uint64_t value = kSubgroup;
-    if (!no_extension_headers) {
-      value |= kExtensions;
+    if (!no_properties) {
+      value |= kProperties;
     }
     if (end_of_group) {
       value |= kEndOfGroup;
@@ -111,8 +113,8 @@
   bool SubgroupIsFirstObjectId() const {
     return IsSubgroup() && (value_ & kFirstObjectId);
   }
-  bool AreExtensionHeadersPresent() const {
-    return IsSubgroup() && (value_ & kExtensions);
+  bool ArePropertiesPresent() const {
+    return IsSubgroup() && (value_ & kProperties);
   }
   bool EndOfGroupInStream() const {
     return IsSubgroup() && (value_ & kEndOfGroup);
@@ -135,14 +137,14 @@
 
 class QUICHE_EXPORT MoqtDatagramType {
  public:
-  static constexpr uint64_t kExtensions = 0x01;
+  static constexpr uint64_t kProperties = 0x01;
   static constexpr uint64_t kEndOfGroup = 0x02;
   static constexpr uint64_t kZeroObjectId = 0x04;
   static constexpr uint64_t kDefaultPriority = 0x08;
   static constexpr uint64_t kStatus = 0x20;
   // The arguments here are properties of the object. The constructor creates
   // the appropriate type given those properties and the spec restrictions.
-  MoqtDatagramType(bool payload, bool extension, bool end_of_group,
+  MoqtDatagramType(bool payload, bool properties, bool end_of_group,
                    bool default_priority, bool zero_object_id)
       : value_(0) {
     // Avoid illegal types. Status cannot coexist with the zero-object-id flag
@@ -159,8 +161,8 @@
       // it's more readable.
       end_of_group = false;
     }
-    if (extension) {
-      value_ |= kExtensions;
+    if (properties) {
+      value_ |= kProperties;
     }
     if (end_of_group) {
       value_ |= kEndOfGroup;
@@ -176,7 +178,7 @@
     }
   }
   static std::optional<MoqtDatagramType> FromValue(uint64_t value) {
-    if (value > (kExtensions | kEndOfGroup | kZeroObjectId | kDefaultPriority |
+    if (value > (kProperties | kEndOfGroup | kZeroObjectId | kDefaultPriority |
                  kStatus)) {
       return std::nullopt;
     }
@@ -189,7 +191,7 @@
   bool has_default_priority() const { return value_ & kDefaultPriority; }
   bool has_object_id() const { return !(value_ & kZeroObjectId); }
   bool end_of_group() const { return value_ & kEndOfGroup; }
-  bool has_extension() const { return value_ & kExtensions; }
+  bool has_properties() const { return value_ & kProperties; }
   uint64_t value() const { return value_; }
 
   bool operator==(const MoqtDatagramType& other) const = default;
@@ -251,7 +253,7 @@
   uint64_t group_id;
   uint64_t object_id;
   MoqtPriority publisher_priority;
-  std::string extension_headers;  // Raw, unparsed extension headers.
+  std::string properties;  // Raw, unparsed properties.
   MoqtObjectStatus object_status;
   std::optional<uint64_t> subgroup_id;           // Only for subgroup objects.
   std::optional<bool> first_object_in_subgroup;  // Only for subgroup objects.
@@ -268,11 +270,11 @@
   static constexpr uint64_t kHasObjectId = 0x04;
   static constexpr uint64_t kHasGroupId = 0x08;
   static constexpr uint64_t kHasPriority = 0x10;
-  static constexpr uint64_t kHasExtensions = 0x20;
+  static constexpr uint64_t kHasProperties = 0x20;
   static constexpr uint64_t kIsDatagram = 0x40;
 
   static constexpr uint64_t kMaxFetchSerialization =
-      kIsDatagram | kHasExtensions | kHasPriority | kHasGroupId | kHasObjectId |
+      kIsDatagram | kHasProperties | kHasPriority | kHasGroupId | kHasObjectId |
       kSubgroupIdMask;
 
   static constexpr uint64_t kEndOfNonExistentRange = 0x8c;
@@ -291,8 +293,8 @@
       }
     }
     value_ |= (kHasGroupId | kHasObjectId | kHasPriority);
-    if (!object.extension_headers.empty()) {
-      value_ |= kHasExtensions;
+    if (!object.properties.empty()) {
+      value_ |= kHasProperties;
     }
   }
   // Serialization for a subsequent object in a stream.
@@ -321,8 +323,8 @@
     if (object.publisher_priority != previous_object.publisher_priority) {
       value |= kHasPriority;
     }
-    if (!object.extension_headers.empty()) {
-      value |= kHasExtensions;
+    if (!object.properties.empty()) {
+      value |= kHasProperties;
     }
     value_ = value;
   }
@@ -349,7 +351,7 @@
   bool has_object_id() const { return value_ & kHasObjectId; }
   bool has_group_id() const { return value_ & kHasGroupId; }
   bool has_priority() const { return value_ & kHasPriority; }
-  bool has_extensions() const { return value_ & kHasExtensions; }
+  bool has_properties() const { return value_ & kHasProperties; }
   bool is_datagram() const { return value_ & kIsDatagram; }
   bool end_of_non_existent_range() const {
     return value_ == kEndOfNonExistentRange;
@@ -373,7 +375,7 @@
 struct QUICHE_EXPORT MoqtSubscribeOk {
   uint64_t track_alias;
   MessageParameters parameters;
-  TrackExtensions extensions;
+  TrackProperties properties;
 };
 
 struct QUICHE_EXPORT MoqtPublishDone {
@@ -483,7 +485,7 @@
   FullTrackName full_track_name;
   uint64_t track_alias;
   MessageParameters parameters;
-  TrackExtensions extensions;
+  TrackProperties properties;
 };
 
 // All of the three values in this message are encoded as varints.
diff --git a/quiche/quic/moqt/moqt_messages_test.cc b/quiche/quic/moqt/moqt_messages_test.cc
index c40dca1..4d7b79d 100644
--- a/quiche/quic/moqt/moqt_messages_test.cc
+++ b/quiche/quic/moqt/moqt_messages_test.cc
@@ -13,15 +13,15 @@
 
 TEST(MoqtMessagesTest, MoqtDatagramType) {
   for (bool payload : {false, true}) {
-    for (bool extension : {false, true}) {
+    for (bool properties : {false, true}) {
       for (bool end_of_group : {false, true}) {
         for (bool default_priority : {false, true}) {
           for (bool zero_object_id : {false, true}) {
-            MoqtDatagramType type(payload, extension, end_of_group,
+            MoqtDatagramType type(payload, properties, end_of_group,
                                   default_priority, zero_object_id);
             EXPECT_EQ(type.has_status(),
                       !payload && (!end_of_group || !zero_object_id));
-            EXPECT_EQ(type.has_extension(), extension);
+            EXPECT_EQ(type.has_properties(), properties);
             EXPECT_EQ(type.end_of_group(),
                       end_of_group && (payload || zero_object_id));
             EXPECT_EQ(type.has_object_id(),
diff --git a/quiche/quic/moqt/moqt_namespace_stream.cc b/quiche/quic/moqt/moqt_namespace_stream.cc
index d5bf200..8de7dfa 100644
--- a/quiche/quic/moqt/moqt_namespace_stream.cc
+++ b/quiche/quic/moqt/moqt_namespace_stream.cc
@@ -47,9 +47,9 @@
 
 absl::Status MoqtSubscribeNamespaceRequestStream::OnControlMessage(
     const MoqtRequestOk& message) {
-  if (!message.extensions.empty()) {
+  if (!message.properties.empty()) {
     OnFatalError(
-        absl::InvalidArgumentError("REQUEST_OK received with extensions"));
+        absl::InvalidArgumentError("REQUEST_OK received with properties"));
     return absl::OkStatus();
   }
   if (response_callback_ != nullptr) {
diff --git a/quiche/quic/moqt/moqt_object.h b/quiche/quic/moqt/moqt_object.h
index 996a5e7..11fc220 100644
--- a/quiche/quic/moqt/moqt_object.h
+++ b/quiche/quic/moqt/moqt_object.h
@@ -26,7 +26,7 @@
 struct PublishedObjectMetadata {
   Location location;
   std::optional<uint64_t> subgroup;  // nullopt for datagrams.
-  std::string extensions;
+  std::string properties;
   MoqtObjectStatus status = MoqtObjectStatus::kNormal;
   MoqtPriority publisher_priority = kDefaultPublisherPriority;
   // `first_object_in_subgroup` is only available in objects communicated via
diff --git a/quiche/quic/moqt/moqt_object_subscriber.cc b/quiche/quic/moqt/moqt_object_subscriber.cc
index 1db5534..ad4b321 100644
--- a/quiche/quic/moqt/moqt_object_subscriber.cc
+++ b/quiche/quic/moqt/moqt_object_subscriber.cc
@@ -53,10 +53,10 @@
     parameters().subscription_filter->OnLargestObject(
         data.parameters.largest_object);
   }
-  publisher_delivery_timeout_ = data.extensions.delivery_timeout();
+  publisher_delivery_timeout_ = data.properties.delivery_timeout();
   // TODO(martinduke): Is there anything to do with EXPIRES?
-  default_publisher_priority_ = data.extensions.default_publisher_priority();
-  dynamic_groups_ = data.extensions.dynamic_groups();
+  default_publisher_priority_ = data.properties.default_publisher_priority();
+  dynamic_groups_ = data.properties.dynamic_groups();
   visitor_->OnReply(full_track_name(), data);
   error_is_allowed_ = false;
 }
diff --git a/quiche/quic/moqt/moqt_object_subscriber_test.cc b/quiche/quic/moqt/moqt_object_subscriber_test.cc
index de32e4f..b50987c 100644
--- a/quiche/quic/moqt/moqt_object_subscriber_test.cc
+++ b/quiche/quic/moqt/moqt_object_subscriber_test.cc
@@ -253,7 +253,7 @@
       /*group_id=*/3,
       /*object_id=*/0,
       /*publisher_priority=*/128,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*object_status=*/MoqtObjectStatus::kNormal,
       /*subgroup_id=*/1,
       /*first_object_in_subgroup=*/true,
@@ -306,7 +306,7 @@
       /*group_id=*/3,
       /*object_id=*/0,
       /*publisher_priority=*/128,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*object_status=*/MoqtObjectStatus::kEndOfGroup,
       /*subgroup_id=*/0,
       /*first_object_in_subgroup=*/true,
@@ -329,7 +329,7 @@
       /*group_id=*/3,
       /*object_id=*/0,
       /*publisher_priority=*/128,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*object_status=*/MoqtObjectStatus::kNormal,
       /*subgroup_id=*/0,
       /*first_object_in_subgroup=*/true,
diff --git a/quiche/quic/moqt/moqt_object_test.cc b/quiche/quic/moqt/moqt_object_test.cc
index df9090b..fc6e2bb 100644
--- a/quiche/quic/moqt/moqt_object_test.cc
+++ b/quiche/quic/moqt/moqt_object_test.cc
@@ -77,7 +77,7 @@
   other.publisher_priority = 5;
   EXPECT_TRUE(metadata.IsMalformed(other));
 
-  // arrival_time, payload_length, and extensions being different should NOT
+  // arrival_time, payload_length, and properties being different should NOT
   // make it malformed.
   other = metadata;
   other.arrival_time =
@@ -85,7 +85,7 @@
   EXPECT_FALSE(metadata.IsMalformed(other));
   other.payload_length = 20;
   EXPECT_FALSE(metadata.IsMalformed(other));
-  other.extensions = "ext";
+  other.properties = "ext";
   EXPECT_FALSE(metadata.IsMalformed(other));
 }
 
@@ -96,7 +96,7 @@
   metadata.status = MoqtObjectStatus::kNormal;
   metadata.publisher_priority = 4;
   metadata.payload_length = 10;
-  metadata.extensions = "ext";
+  metadata.properties = "ext";
   metadata.arrival_time =
       quic::QuicTime::Zero() + quic::QuicTimeDelta::FromSeconds(1);
 
@@ -123,7 +123,7 @@
   EXPECT_NE(metadata, other);
   other = metadata;
 
-  other.extensions = "something else";
+  other.properties = "something else";
   EXPECT_NE(metadata, other);
   other = metadata;
 
diff --git a/quiche/quic/moqt/moqt_outgoing_queue.cc b/quiche/quic/moqt/moqt_outgoing_queue.cc
index 2cbb522..29dda1a 100644
--- a/quiche/quic/moqt/moqt_outgoing_queue.cc
+++ b/quiche/quic/moqt/moqt_outgoing_queue.cc
@@ -179,7 +179,7 @@
     ObjectsInDescendingOrder(objects);
   }
   FetchOkData ok(closed_ && adjusted_end == largest_location(), adjusted_end,
-                 MessageParameters(), extensions_);
+                 MessageParameters(), properties_);
   std::move(callback)(ok);
   return std::make_unique<FetchTask>(this, std::move(objects));
 }
diff --git a/quiche/quic/moqt/moqt_outgoing_queue.h b/quiche/quic/moqt/moqt_outgoing_queue.h
index 15d6c24..c2696eb 100644
--- a/quiche/quic/moqt/moqt_outgoing_queue.h
+++ b/quiche/quic/moqt/moqt_outgoing_queue.h
@@ -50,7 +50,7 @@
       quiche::MultiUseCallback<void()> new_group_callback = nullptr)
       : clock_(clock),
         track_(std::move(track)),
-        extensions_(std::nullopt, std::nullopt, std::nullopt, std::nullopt,
+        properties_(std::nullopt, std::nullopt, std::nullopt, std::nullopt,
                     new_group_callback != nullptr ? std::optional<bool>(true)
                                                   : std::nullopt,
                     std::nullopt),
@@ -74,7 +74,7 @@
                          const MessageParameters& parameters) override {
     listeners_.insert(listener);
     listener->OnSubscribeAccepted();
-    if (extensions_.dynamic_groups() && !expect_new_group_ &&
+    if (properties_.dynamic_groups() && !expect_new_group_ &&
         parameters.new_group_request.has_value() &&
         (*parameters.new_group_request == 0 || queue_.empty() ||
          *parameters.new_group_request > current_group_id_) &&
@@ -91,7 +91,7 @@
   std::optional<quic::QuicTimeDelta> expiration() const override {
     return quic::QuicTimeDelta::Zero();
   }
-  const TrackExtensions& extensions() const override { return extensions_; }
+  const TrackProperties& properties() const override { return properties_; }
 
   std::unique_ptr<MoqtFetchTask> StandaloneFetch(
       Location start, Location end, MoqtDeliveryOrder order,
@@ -124,7 +124,7 @@
 
  protected:
   MoqtPriority default_publisher_priority() const {
-    return extensions_.default_publisher_priority();
+    return properties_.default_publisher_priority();
   }
 
  private:
@@ -171,7 +171,7 @@
 
   const quic::QuicClock* clock_;
   FullTrackName track_;
-  TrackExtensions extensions_;
+  TrackProperties properties_;
   bool closed_ = false;
   absl::InlinedVector<Group, kMaxQueuedGroups> queue_;
   uint64_t current_group_id_ = -1;
diff --git a/quiche/quic/moqt/moqt_outgoing_queue_test.cc b/quiche/quic/moqt/moqt_outgoing_queue_test.cc
index 93267b7..0d60cb3 100644
--- a/quiche/quic/moqt/moqt_outgoing_queue_test.cc
+++ b/quiche/quic/moqt/moqt_outgoing_queue_test.cc
@@ -555,14 +555,14 @@
 
 TEST(MoqtOutgoingQueue, DynamicGroupsExtension) {
   TestMoqtOutgoingQueue queue_without_callback;
-  EXPECT_FALSE(queue_without_callback.extensions().dynamic_groups());
-  EXPECT_FALSE(queue_without_callback.extensions().contains(
-      static_cast<uint64_t>(ExtensionHeader::kDynamicGroups)));
+  EXPECT_FALSE(queue_without_callback.properties().dynamic_groups());
+  EXPECT_FALSE(queue_without_callback.properties().contains(
+      static_cast<uint64_t>(PropertyType::kDynamicGroups)));
 
   TestMoqtOutgoingQueue queue_with_callback([]() {});
-  EXPECT_TRUE(queue_with_callback.extensions().dynamic_groups());
-  EXPECT_TRUE(queue_with_callback.extensions().contains(
-      static_cast<uint64_t>(ExtensionHeader::kDynamicGroups)));
+  EXPECT_TRUE(queue_with_callback.properties().dynamic_groups());
+  EXPECT_TRUE(queue_with_callback.properties().contains(
+      static_cast<uint64_t>(PropertyType::kDynamicGroups)));
 }
 
 }  // namespace
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index 040104a..d03b67a 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -672,9 +672,9 @@
   QUICHE_RETURN_IF_ERROR(ParseKeyValuePairList(reader, pairs));
   QUICHE_RETURN_IF_ERROR(subscribe_ok.parameters.FromKeyValuePairList(pairs));
   QUICHE_RETURN_IF_ERROR(
-      ParseKeyValuePairListWithNoPrefix(reader, subscribe_ok.extensions));
-  if (!subscribe_ok.extensions.Validate()) {
-    return absl::InvalidArgumentError("Invalid SUBSCRIBE_OK track extensions");
+      ParseKeyValuePairListWithNoPrefix(reader, subscribe_ok.properties));
+  if (!subscribe_ok.properties.Validate()) {
+    return absl::InvalidArgumentError("Invalid SUBSCRIBE_OK track properties");
   }
   QUICHE_RETURN_IF_ERROR(CheckForTrailingData(reader));
   return subscribe_ok;
@@ -774,9 +774,9 @@
   QUICHE_RETURN_IF_ERROR(
       FillAndValidateMessageParameters(reader, request_ok.parameters));
   QUICHE_RETURN_IF_ERROR(
-      ParseKeyValuePairListWithNoPrefix(reader, request_ok.extensions));
-  if (!request_ok.extensions.Validate()) {
-    return absl::InvalidArgumentError("Invalid REQUEST_OK track extensions");
+      ParseKeyValuePairListWithNoPrefix(reader, request_ok.properties));
+  if (!request_ok.properties.Validate()) {
+    return absl::InvalidArgumentError("Invalid REQUEST_OK track properties");
   }
   QUICHE_RETURN_IF_ERROR(CheckForTrailingData(reader));
   return request_ok;
@@ -916,9 +916,9 @@
   QUICHE_RETURN_IF_ERROR(
       FillAndValidateMessageParameters(reader, fetch_ok.parameters));
   QUICHE_RETURN_IF_ERROR(
-      ParseKeyValuePairListWithNoPrefix(reader, fetch_ok.extensions));
-  if (!fetch_ok.extensions.Validate()) {
-    return absl::InvalidArgumentError("Invalid FETCH_OK track extensions");
+      ParseKeyValuePairListWithNoPrefix(reader, fetch_ok.properties));
+  if (!fetch_ok.properties.Validate()) {
+    return absl::InvalidArgumentError("Invalid FETCH_OK track properties");
   }
   QUICHE_RETURN_IF_ERROR(CheckForTrailingData(reader));
   return fetch_ok;
@@ -939,9 +939,9 @@
   QUICHE_RETURN_IF_ERROR(
       FillAndValidateMessageParameters(reader, publish.parameters));
   QUICHE_RETURN_IF_ERROR(
-      ParseKeyValuePairListWithNoPrefix(reader, publish.extensions));
-  if (!publish.extensions.Validate()) {
-    return absl::InvalidArgumentError("Invalid PUBLISH track extensions");
+      ParseKeyValuePairListWithNoPrefix(reader, publish.properties));
+  if (!publish.properties.Validate()) {
+    return absl::InvalidArgumentError("Invalid PUBLISH track properties");
   }
   QUICHE_RETURN_IF_ERROR(CheckForTrailingData(reader));
   return publish;
@@ -1047,7 +1047,7 @@
                                                MoqtObject& object_metadata,
                                                bool& use_default_priority) {
   uint64_t type_raw, object_status_raw;
-  absl::string_view extensions;
+  absl::string_view properties;
   quic::QuicDataReader reader(data);
   object_metadata = MoqtObject();
   if (!reader.ReadMoqVarInt(&type_raw) ||
@@ -1084,15 +1084,15 @@
       !reader.ReadUInt8(&object_metadata.publisher_priority)) {
     return std::nullopt;
   }
-  if (datagram_type->has_extension()) {
-    if (!reader.ReadStringPieceMoqVarInt(&extensions)) {
+  if (datagram_type->has_properties()) {
+    if (!reader.ReadStringPieceMoqVarInt(&properties)) {
       return std::nullopt;
     }
-    if (extensions.empty()) {
+    if (properties.empty()) {
       // This is a session error.
       return std::nullopt;
     }
-    object_metadata.extension_headers = std::string(extensions);
+    object_metadata.properties = std::string(properties);
   }
   if (datagram_type->has_status()) {
     object_metadata.payload_length = 0;
@@ -1196,12 +1196,12 @@
         }
         [[fallthrough]];
       case kPublisherPriority:
-        if (fetch_serialization_.has_extensions()) {
-          return kExtensionSize;
+        if (fetch_serialization_.has_properties()) {
+          return kPropertiesSize;
         }
-        metadata_.extension_headers = "";
+        metadata_.properties = "";
         return kObjectPayloadLength;
-      case kExtensionBody:
+      case kPropertiesBody:
         return kObjectPayloadLength;
       case kData:
         return kSerializationFlags;
@@ -1210,7 +1210,7 @@
       case kAwaitingNextByte:
       case kStatus:
       case kFailed:
-      case kExtensionSize:
+      case kPropertiesSize:
       case kPadding:
         QUICHE_NOTREACHED();
         return next_input_;
@@ -1248,11 +1248,11 @@
         metadata_.first_object_in_subgroup =
             type_.HasFirstObject() && num_objects_read_ == 0;
       }
-      if (type_.AreExtensionHeadersPresent()) {
-        return kExtensionSize;
+      if (type_.ArePropertiesPresent()) {
+        return kPropertiesSize;
       }
       [[fallthrough]];
-    case kExtensionBody:
+    case kPropertiesBody:
       return kObjectPayloadLength;
     case kStatus:
     case kData:
@@ -1260,7 +1260,7 @@
       return kObjectId;
     case kRequestId:
     case kSerializationFlags:
-    case kExtensionSize:
+    case kPropertiesSize:
     case kObjectPayloadLength:
     case kPadding:
     case kFailed:
@@ -1382,12 +1382,13 @@
       return;
     }
 
-    case kExtensionSize: {
+    case kPropertiesSize: {
       std::optional<uint64_t> value_read = ReadMoqVarIntNoFin();
       if (value_read.has_value()) {
-        metadata_.extension_headers.clear();
+        metadata_.properties.clear();
         payload_length_remaining_ = *value_read;
-        next_input_ = (value_read == 0) ? kObjectPayloadLength : kExtensionBody;
+        next_input_ =
+            (value_read == 0) ? kObjectPayloadLength : kPropertiesBody;
       }
       return;
     }
@@ -1436,7 +1437,7 @@
       return;
     }
 
-    case kExtensionBody:
+    case kPropertiesBody:
     case kData: {
       while (payload_length_remaining_ > 0) {
         webtransport::Stream::PeekResult peek_result =
@@ -1483,7 +1484,7 @@
             }
           }
         } else {
-          absl::StrAppend(&metadata_.extension_headers,
+          absl::StrAppend(&metadata_.properties,
                           peek_result.peeked_data.substr(0, chunk_size));
           if (stream_.SkipBytes(chunk_size)) {
             ParseError("FIN received at an unexpected point in the stream");
diff --git a/quiche/quic/moqt/moqt_parser.h b/quiche/quic/moqt/moqt_parser.h
index aa28ab4..01107af 100644
--- a/quiche/quic/moqt/moqt_parser.h
+++ b/quiche/quic/moqt/moqt_parser.h
@@ -317,8 +317,8 @@
     kSubgroupId,
     kPublisherPriority,
     kObjectId,
-    kExtensionSize,
-    kExtensionBody,
+    kPropertiesSize,
+    kPropertiesBody,
     kObjectPayloadLength,
     kStatus,
     kData,
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc
index 2067e06..c4d1c83 100644
--- a/quiche/quic/moqt/moqt_parser_test.cc
+++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -391,7 +391,7 @@
   MoqtMessageType type = std::get<MoqtMessageType>(message_type_);
   if (type == MoqtMessageType::kSubscribeOk ||
       type == MoqtMessageType::kFetchOk || type == MoqtMessageType::kPublish) {
-    // These message types have extensions, which use the length field to
+    // These message types have properties, which use the length field to
     // determine the size. It is therefore not processed correctly.
     return;
   }
@@ -526,7 +526,7 @@
   EXPECT_FALSE(data_visitor.parsing_error().has_value());
 }
 
-TEST_F(MoqtMessageSpecificTest, ObjectSplitInExtension) {
+TEST_F(MoqtMessageSpecificTest, ObjectSplitInProperty) {
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtParserTestVisitor data_visitor;
   MoqtDataParser parser(&stream, &data_visitor);
@@ -951,14 +951,14 @@
             HasSubstr("FIN received at an unexpected point in the stream")));
 }
 
-TEST_F(MoqtMessageSpecificTest, FinMidExtension) {
+TEST_F(MoqtMessageSpecificTest, FinMidProperty) {
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtParserTestVisitor data_visitor;
   MoqtDataParser parser(&stream, &data_visitor);
   MoqtDataStreamType type =
       MoqtDataStreamType::Subgroup(0, 1, false, false, true);
   auto message = std::make_unique<StreamHeaderSubgroupMessage>(type);
-  // Read up to the extension body and then FIN.
+  // Read up to the property body and then FIN.
   stream.Receive(message->PacketSample().substr(0, 7), true);
   parser.ReadAllData();
   EXPECT_EQ(data_visitor.messages_received(), 0);
@@ -1378,7 +1378,7 @@
   EXPECT_EQ(ExtractMoqtErrorForStatus(parsed.status()),
             MoqtError::kProtocolViolation);
   EXPECT_THAT(parsed.status().message(),
-              HasSubstr("Invalid SUBSCRIBE_OK track extensions"));
+              HasSubstr("Invalid SUBSCRIBE_OK track properties"));
 }
 
 TEST_F(MoqtMessageSpecificTest, SubscribeOkExpirationIsZero) {
@@ -1705,7 +1705,7 @@
 
 TEST_F(MoqtDataParserStateMachineTest, IntegerOverflowObjectId) {
   MoqtDataStreamType type = MoqtDataStreamType::Subgroup(
-      0, 1, /*no_extension_headers=*/true, /*default_priority=*/false,
+      0, 1, /*no_properties=*/true, /*default_priority=*/false,
       /*has_first_object=*/true);
   stream_.Receive(StreamHeaderSubgroupMessage(type).PacketSample());
   char buffer[32];
@@ -1723,7 +1723,7 @@
 
 TEST_F(MoqtDataParserStateMachineTest, SubgroupHasFirstObjectTrue) {
   MoqtDataStreamType type = MoqtDataStreamType::Subgroup(
-      0, 1, /*no_extension_headers=*/true, /*default_priority=*/false,
+      0, 1, /*no_properties=*/true, /*default_priority=*/false,
       /*has_first_object=*/true);
   stream_.Receive(StreamHeaderSubgroupMessage(type).PacketSample());
   stream_.Receive(StreamMiddlerSubgroupMessage(type).PacketSample(),
@@ -1742,7 +1742,7 @@
 
 TEST_F(MoqtDataParserStateMachineTest, SubgroupHasFirstObjectFalse) {
   MoqtDataStreamType type = MoqtDataStreamType::Subgroup(
-      0, 1, /*no_extension_headers=*/true, /*default_priority=*/false,
+      0, 1, /*no_properties=*/true, /*default_priority=*/false,
       /*has_first_object=*/false);
   stream_.Receive(StreamHeaderSubgroupMessage(type).PacketSample());
   stream_.Receive(StreamMiddlerSubgroupMessage(type).PacketSample(),
diff --git a/quiche/quic/moqt/moqt_publish_namespace_stream.cc b/quiche/quic/moqt/moqt_publish_namespace_stream.cc
index 227adc5..c2795a0 100644
--- a/quiche/quic/moqt/moqt_publish_namespace_stream.cc
+++ b/quiche/quic/moqt/moqt_publish_namespace_stream.cc
@@ -36,9 +36,9 @@
 
 absl::Status MoqtPublishNamespaceRequestStream::OnControlMessage(
     const MoqtRequestOk& message) {
-  if (!message.extensions.empty()) {
+  if (!message.properties.empty()) {
     OnFatalError(
-        absl::InvalidArgumentError("REQUEST_OK received with extensions"));
+        absl::InvalidArgumentError("REQUEST_OK received with properties"));
     return absl::OkStatus();
   }
   if (response_callback_ != nullptr) {
diff --git a/quiche/quic/moqt/moqt_publish_stream.cc b/quiche/quic/moqt/moqt_publish_stream.cc
index 6c36172..51c7c51 100644
--- a/quiche/quic/moqt/moqt_publish_stream.cc
+++ b/quiche/quic/moqt/moqt_publish_stream.cc
@@ -53,10 +53,10 @@
   SendOrBufferMessageOrFatal(framer()->SerializePublish(MoqtPublish{
       publisher_->request_id(), publisher_->publisher().GetTrackName(),
       publisher_->track_alias(), publisher_->parameters(),
-      publisher_->publisher().extensions()}));
+      publisher_->publisher().properties()}));
   // Use the default group order.
   publisher_->parameters().group_order =
-      publisher_->publisher().extensions().default_publisher_group_order();
+      publisher_->publisher().properties().default_publisher_group_order();
 }
 
 absl::Status MoqtPublishRequestStream::OnRawControlMessage(
@@ -67,9 +67,9 @@
 
 absl::Status MoqtPublishRequestStream::OnControlMessage(
     const MoqtRequestOk& message) {
-  if (!message.extensions.empty()) {
+  if (!message.properties.empty()) {
     OnFatalError(
-        absl::InvalidArgumentError("REQUEST_OK received with extensions"));
+        absl::InvalidArgumentError("REQUEST_OK received with properties"));
     return absl::OkStatus();
   }
   std::move(response_callback_)(message.parameters);
@@ -136,7 +136,7 @@
   if (subscriber_->visitor() == nullptr) {
     // There was no existing SUBSCRIBE, so invoke the callback.
     subscriber_->set_visitor((*incoming_publish_callback_)(
-        message.full_track_name, message.parameters, message.extensions,
+        message.full_track_name, message.parameters, message.properties,
         [weakptr = weak_ptr_factory_.Create()](
             const std::variant<MessageParameters, MoqtRequestErrorInfo>
                 response) {
@@ -169,7 +169,7 @@
   }
   // Notify the visitor.
   subscriber_->OnObjectOrOk(
-      SubscribeOkData{message.parameters, message.extensions});
+      SubscribeOkData{message.parameters, message.properties});
   return absl::OkStatus();
 }
 
@@ -186,9 +186,9 @@
 
 absl::Status MoqtPublishResponseStream::OnControlMessage(
     const MoqtRequestOk& message) {
-  if (!message.extensions.empty()) {
+  if (!message.properties.empty()) {
     OnFatalError(
-        absl::InvalidArgumentError("REQUEST_OK received with extensions"));
+        absl::InvalidArgumentError("REQUEST_OK received with properties"));
     return absl::OkStatus();
   }
   // TODO(martinduke): Process REQUEST_OK parameters.
diff --git a/quiche/quic/moqt/moqt_publish_stream_test.cc b/quiche/quic/moqt/moqt_publish_stream_test.cc
index b10f1c9..b175a5e 100644
--- a/quiche/quic/moqt/moqt_publish_stream_test.cc
+++ b/quiche/quic/moqt/moqt_publish_stream_test.cc
@@ -250,7 +250,7 @@
 
   MoqtPublish DefaultPublish() {
     return MoqtPublish{kRequestId, kTrackName, kTrackAlias, MessageParameters(),
-                       TrackExtensions()};
+                       TrackProperties()};
   }
 
   MoqtFramer framer_;
@@ -261,7 +261,7 @@
       error_callback_;
 
   testing::MockFunction<SubscribeVisitor*(
-      const FullTrackName&, const MessageParameters&, const TrackExtensions&,
+      const FullTrackName&, const MessageParameters&, const TrackProperties&,
       MoqtResponseCallback)>
       incoming_publish_callback_mock_;
   MoqtIncomingPublishCallback incoming_publish_callback_;
@@ -284,7 +284,7 @@
           });
   EXPECT_CALL(incoming_publish_callback_mock_, Call(kTrackName, _, _, _))
       .WillOnce([this](const FullTrackName&, const MessageParameters&,
-                       const TrackExtensions&, MoqtResponseCallback callback) {
+                       const TrackProperties&, MoqtResponseCallback callback) {
         captured_response_callback_ = std::move(callback);
         return &mock_subscribe_visitor_;
       });
@@ -438,7 +438,7 @@
   MoqtPublish publish = DefaultPublish();
   EXPECT_CALL(incoming_publish_callback_mock_, Call(kTrackName, _, _, _))
       .WillOnce([this](const FullTrackName&, const MessageParameters&,
-                       const TrackExtensions&, MoqtResponseCallback callback) {
+                       const TrackProperties&, MoqtResponseCallback callback) {
         captured_response_callback_ = std::move(callback);
         return &mock_subscribe_visitor_;
       });
@@ -524,7 +524,7 @@
   testing::MockFunction<bool(LiveSubscriber*)> mock_add_callback2;
   testing::MockFunction<void(LiveSubscriber*)> mock_remove_callback2;
   testing::MockFunction<SubscribeVisitor*(
-      const FullTrackName&, const MessageParameters&, const TrackExtensions&,
+      const FullTrackName&, const MessageParameters&, const TrackProperties&,
       MoqtResponseCallback)>
       incoming_publish_callback_mock2;
   MoqtIncomingPublishCallback incoming_publish_callback2 =
diff --git a/quiche/quic/moqt/moqt_publisher.h b/quiche/quic/moqt/moqt_publisher.h
index 88a28c7..6c3b9a1 100644
--- a/quiche/quic/moqt/moqt_publisher.h
+++ b/quiche/quic/moqt/moqt_publisher.h
@@ -105,7 +105,7 @@
   // Track alias is not present because MoqtSession always uses locally
   // generated values.
   virtual std::optional<Location> largest_location() const = 0;
-  virtual const TrackExtensions& extensions() const = 0;
+  virtual const TrackProperties& properties() const = 0;
   virtual std::optional<quic::QuicTimeDelta> expiration() const = 0;
 
   // Performs a fetch for the specified range of objects. Should also be used
diff --git a/quiche/quic/moqt/moqt_relay_track_publisher.cc b/quiche/quic/moqt/moqt_relay_track_publisher.cc
index d257c26..abdee6f 100644
--- a/quiche/quic/moqt/moqt_relay_track_publisher.cc
+++ b/quiche/quic/moqt/moqt_relay_track_publisher.cc
@@ -50,7 +50,7 @@
       ok_data.parameters.expires.value_or(kDefaultExpires);
   expiration_ = expires.IsInfinite() ? quic::QuicTime::Infinite()
                                      : clock_->Now() + expires;
-  extensions_ = ok_data.extensions;
+  properties_ = ok_data.properties;
   if (ok_data.parameters.largest_object.has_value() &&
       ok_data.parameters.largest_object->Next() > next_location_) {
     // We may have already received objects that exceed what's reported in
@@ -208,7 +208,7 @@
   }
   if (duplicate_object != nullptr) {
     if (metadata.IsMalformed(duplicate_object->metadata())) {
-      // Something besides the arrival time and extension headers changed.
+      // Something besides the arrival time and properties changed.
       OnMalformedTrack(full_track_name);
       return;
     }
@@ -395,7 +395,7 @@
     pending_new_group_request_ = upstream_parameters.new_group_request;
   } else {
     if (parameters.new_group_request.has_value() &&
-        (!got_response_ || extensions_.dynamic_groups()) &&
+        (!got_response_ || properties_.dynamic_groups()) &&
         (*parameters.new_group_request == 0 ||
          *parameters.new_group_request > next_location_.group) &&
         (!pending_new_group_request_.has_value() ||
diff --git a/quiche/quic/moqt/moqt_relay_track_publisher.h b/quiche/quic/moqt/moqt_relay_track_publisher.h
index 03eaa84..3390e5a 100644
--- a/quiche/quic/moqt/moqt_relay_track_publisher.h
+++ b/quiche/quic/moqt/moqt_relay_track_publisher.h
@@ -99,7 +99,7 @@
                          const MessageParameters& parameters) override;
   void RemoveObjectListener(MoqtObjectListener* listener) override;
   std::optional<Location> largest_location() const override;
-  const TrackExtensions& extensions() const override { return extensions_; }
+  const TrackProperties& properties() const override { return properties_; }
   std::optional<quic::QuicTimeDelta> expiration() const override;
   std::optional<quic::QuicTimeDelta> oack_window_size() const {
     return oack_window_size_;
@@ -171,7 +171,7 @@
   FullTrackName track_;
   quiche::QuicheWeakPtr<MoqtSessionInterface> upstream_;
   DeleteTrackCallback delete_track_callback_;
-  TrackExtensions extensions_;
+  TrackProperties properties_;
   std::optional<uint64_t> pending_new_group_request_;
   // TODO(martinduke): This publisher should destroy itself when the expiration
   // time passes.
diff --git a/quiche/quic/moqt/moqt_relay_track_publisher_test.cc b/quiche/quic/moqt/moqt_relay_track_publisher_test.cc
index e2f3809..40bd853 100644
--- a/quiche/quic/moqt/moqt_relay_track_publisher_test.cc
+++ b/quiche/quic/moqt/moqt_relay_track_publisher_test.cc
@@ -47,7 +47,7 @@
     parameters.largest_object = kLargestLocation;
     parameters.expires = quic::QuicTimeDelta::FromSeconds(30);
     publisher_.OnReply(kTrackName,
-                       SubscribeOkData{parameters, TrackExtensions()});
+                       SubscribeOkData{parameters, TrackProperties()});
   }
 
   void ObjectArrives(Location location, uint64_t subgroup,
@@ -104,7 +104,7 @@
   parameters.largest_object = kLargestLocation;
   parameters.expires = quic::QuicTimeDelta::FromSeconds(30);
   publisher_.OnReply(kTrackName,
-                     SubscribeOkData{parameters, TrackExtensions()});
+                     SubscribeOkData{parameters, TrackProperties()});
   EXPECT_LT(publisher_.expiration(), quic::QuicTimeDelta::FromSeconds(31));
 }
 
@@ -326,7 +326,7 @@
   MessageParameters parameters;
   parameters.largest_object = kLargestLocation;
   publisher_.OnReply(kTrackName,
-                     SubscribeOkData{parameters, TrackExtensions()});
+                     SubscribeOkData{parameters, TrackProperties()});
 }
 
 TEST_F(MoqtRelayTrackPublisherTest, OnMalformedObject) {
@@ -643,14 +643,14 @@
   MessageParameters ok_parameters;
   ok_parameters.largest_object = kLargestLocation;  // Location(3, 2)
   ok_parameters.expires = quic::QuicTimeDelta::FromSeconds(30);
-  TrackExtensions extensions(
+  TrackProperties properties(
       /*delivery_timeout=*/std::nullopt,
       /*max_cache_duration=*/std::nullopt,
       /*publisher_priority=*/std::nullopt,
       /*group_order=*/std::nullopt,
       /*dynamic_groups=*/true,
-      /*immutable_extensions=*/std::nullopt);
-  publisher_.OnReply(kTrackName, SubscribeOkData{ok_parameters, extensions});
+      /*immutable_properties=*/std::nullopt);
+  publisher_.OnReply(kTrackName, SubscribeOkData{ok_parameters, properties});
 
   // Requests with new_group_request <= 4 (including 4 and 0) do not trigger
   // SubscribeUpdate because pending_new_group_request_ is still 4.
@@ -729,7 +729,7 @@
 
   // Before OnReply (!got_response_ is true and next_location_ == (0, 0)), a
   // new_group_request = 0 triggers SubscribeUpdate(0) (not next_location_.group
-  // + 1) even though extensions_.dynamic_groups() is false.
+  // + 1) even though properties_.dynamic_groups() is false.
   MockMoqtObjectListener listener_zero;
   MessageParameters params_zero;
   params_zero.new_group_request = 0;
@@ -795,14 +795,14 @@
   MessageParameters ok_parameters;
   ok_parameters.largest_object = Location(5, 2);
   ok_parameters.expires = quic::QuicTimeDelta::FromSeconds(30);
-  TrackExtensions extensions(
+  TrackProperties properties(
       /*delivery_timeout=*/std::nullopt,
       /*max_cache_duration=*/std::nullopt,
       /*publisher_priority=*/std::nullopt,
       /*group_order=*/std::nullopt,
       /*dynamic_groups=*/true,
-      /*immutable_extensions=*/std::nullopt);
-  publisher_.OnReply(kTrackName, SubscribeOkData{ok_parameters, extensions});
+      /*immutable_properties=*/std::nullopt);
+  publisher_.OnReply(kTrackName, SubscribeOkData{ok_parameters, properties});
 
   MockMoqtObjectListener listener6;
   EXPECT_CALL(listener6, OnSubscribeAccepted);
@@ -820,7 +820,7 @@
        NewGroupRequestAfterResponseWithoutDynamicGroups) {
   SubscribeAndOk();
 
-  // After OnReply, extensions_.dynamic_groups() is false by default, so
+  // After OnReply, properties_.dynamic_groups() is false by default, so
   // NEW_GROUP_REQUEST is ignored.
   MockMoqtObjectListener listener2;
   EXPECT_CALL(listener2, OnSubscribeAccepted);
@@ -843,14 +843,14 @@
   MessageParameters ok_parameters;
   ok_parameters.largest_object = kLargestLocation;  // Location(3, 2)
   ok_parameters.expires = quic::QuicTimeDelta::FromSeconds(30);
-  TrackExtensions extensions(
+  TrackProperties properties(
       /*delivery_timeout=*/std::nullopt,
       /*max_cache_duration=*/std::nullopt,
       /*publisher_priority=*/std::nullopt,
       /*group_order=*/std::nullopt,
       /*dynamic_groups=*/true,
-      /*immutable_extensions=*/std::nullopt);
-  publisher_.OnReply(kTrackName, SubscribeOkData{ok_parameters, extensions});
+      /*immutable_properties=*/std::nullopt);
+  publisher_.OnReply(kTrackName, SubscribeOkData{ok_parameters, properties});
 
   // 1. No new_group_request parameter -> ignored.
   MockMoqtObjectListener listener_no_param;
diff --git a/quiche/quic/moqt/moqt_session.cc b/quiche/quic/moqt/moqt_session.cc
index fb5e4f6..e2a9a7a 100644
--- a/quiche/quic/moqt/moqt_session.cc
+++ b/quiche/quic/moqt/moqt_session.cc
@@ -231,7 +231,7 @@
   QUICHE_CHECK(!track->is_fetch());
   SubscribeVisitor* visitor = track->visitor();
   if (visitor != nullptr) {
-    // TODO(martinduke): Handle extension headers.
+    // TODO(martinduke): Handle properties.
     PublishedObjectMetadata metadata;
     metadata.location = Location(message.group_id, message.object_id);
     metadata.subgroup = std::nullopt;
@@ -553,7 +553,7 @@
 
 bool MoqtSession::Publish(
     std::shared_ptr<MoqtTrackPublisher> absl_nonnull publisher,
-    const MessageParameters& parameters, const TrackExtensions& extensions,
+    const MessageParameters& parameters, const TrackProperties& properties,
     MoqtResponseCallback response_callback) {
   if (received_goaway_ || sent_goaway_) {
     QUICHE_DLOG(INFO) << ENDPOINT << "Tried to send PUBLISH after GOAWAY";
diff --git a/quiche/quic/moqt/moqt_session.h b/quiche/quic/moqt/moqt_session.h
index 557c0e7..a545325 100644
--- a/quiche/quic/moqt/moqt_session.h
+++ b/quiche/quic/moqt/moqt_session.h
@@ -103,7 +103,7 @@
   void Unsubscribe(const FullTrackName& name) override;
   bool Publish(std::shared_ptr<MoqtTrackPublisher> absl_nonnull publisher,
                const MessageParameters& parameters,
-               const TrackExtensions& extensions,
+               const TrackProperties& properties,
                MoqtResponseCallback response_callback) override;
   std::unique_ptr<MoqtFetchTask> Fetch(
       const FullTrackName& name, FetchResponseCallback callback, Location start,
diff --git a/quiche/quic/moqt/moqt_session_callbacks.h b/quiche/quic/moqt/moqt_session_callbacks.h
index 2a8f847..e222136 100644
--- a/quiche/quic/moqt/moqt_session_callbacks.h
+++ b/quiche/quic/moqt/moqt_session_callbacks.h
@@ -32,7 +32,7 @@
 
 struct SubscribeOkData {
   MessageParameters parameters;
-  TrackExtensions extensions;
+  TrackProperties properties;
 };
 
 class SubscribeVisitor {
@@ -69,7 +69,7 @@
   bool end_of_track = false;
   Location end_location;
   MessageParameters parameters;
-  TrackExtensions extensions;
+  TrackProperties properties;
   bool operator==(const FetchOkData& other) const = default;
 };
 
@@ -78,7 +78,7 @@
 
 struct TrackStatusOkData {
   MessageParameters parameters;
-  TrackExtensions extensions;
+  TrackProperties properties;
   bool operator==(const TrackStatusOkData& other) const = default;
 };
 
@@ -105,7 +105,7 @@
 // track until either MoqtResponseCallback returns with an error or the
 // application calls Unsubscribe.
 using MoqtIncomingPublishCallback = quiche::MultiUseCallback<SubscribeVisitor*(
-    const FullTrackName&, const MessageParameters&, const TrackExtensions&,
+    const FullTrackName&, const MessageParameters&, const TrackProperties&,
     MoqtResponseCallback)>;
 
 // Called whenever a PUBLISH_NAMESPACE or PUBLISH_NAMESPACE_DONE message is
@@ -162,7 +162,7 @@
 }
 
 inline SubscribeVisitor* DefaultIncomingPublishCallback(
-    const FullTrackName&, const MessageParameters&, const TrackExtensions&,
+    const FullTrackName&, const MessageParameters&, const TrackProperties&,
     MoqtResponseCallback) {
   return nullptr;
 }
diff --git a/quiche/quic/moqt/moqt_session_interface.h b/quiche/quic/moqt/moqt_session_interface.h
index f39c82b..3332701 100644
--- a/quiche/quic/moqt/moqt_session_interface.h
+++ b/quiche/quic/moqt/moqt_session_interface.h
@@ -109,7 +109,7 @@
   // failure will be covered by |response_callback|.
   virtual bool Publish(
       std::shared_ptr<MoqtTrackPublisher> absl_nonnull publisher,
-      const MessageParameters& parameters, const TrackExtensions& extensions,
+      const MessageParameters& parameters, const TrackProperties& properties,
       MoqtResponseCallback response_callback) = 0;
 
   // Sends a FETCH for a pre-specified object range. Once a FETCH_OK or a
diff --git a/quiche/quic/moqt/moqt_session_test.cc b/quiche/quic/moqt/moqt_session_test.cc
index 0786636..c380d92 100644
--- a/quiche/quic/moqt/moqt_session_test.cc
+++ b/quiche/quic/moqt/moqt_session_test.cc
@@ -71,7 +71,7 @@
 const MoqtDataStreamType kDefaultSubgroupStreamType =
     MoqtDataStreamType::Subgroup(2, 4, false, false, true);
 constexpr MoqtPriority kDefaultPublisherPriority = 0x80;
-const TrackExtensions kNoExtensions;
+const TrackProperties kNoProperties;
 
 std::vector<quiche::QuicheMemSlice> PayloadFromString(absl::string_view s) {
   std::vector<quiche::QuicheMemSlice> payload;
@@ -147,8 +147,8 @@
     publisher_.Add(publisher);
     ON_CALL(*publisher, largest_location()).WillByDefault(Return(std::nullopt));
     ON_CALL(*publisher, expiration()).WillByDefault(Return(std::nullopt));
-    ON_CALL(*publisher, extensions())
-        .WillByDefault(testing::ReturnRef(kNoExtensions));
+    ON_CALL(*publisher, properties())
+        .WillByDefault(testing::ReturnRef(kNoProperties));
     return publisher.get();
   }
 
@@ -235,7 +235,7 @@
   MoqtObjectListener* ReceiveSubscribeSynchronousOk(
       MockTrackPublisher* publisher, MoqtSubscribe& subscribe,
       MoqtBidiStreamTestWrapper* control_parser, uint64_t track_alias = 0,
-      TrackExtensions extensions = TrackExtensions()) {
+      TrackProperties properties = TrackProperties()) {
     MoqtObjectListener* listener_ptr = nullptr;
     EXPECT_CALL(*publisher, AddObjectListener)
         .WillOnce([&](MoqtObjectListener* listener, const MessageParameters&) {
@@ -245,7 +245,7 @@
     MessageParameters parameters;
     parameters.expires = publisher->expiration();
     parameters.largest_object = publisher->largest_location();
-    MoqtSubscribeOk expected_ok(track_alias, parameters, extensions);
+    MoqtSubscribeOk expected_ok(track_alias, parameters, properties);
     EXPECT_CALL(mock_bidi_stream_,
                 Writev(SerializedControlMessage(expected_ok), _));
     control_parser->ReceiveMessage(subscribe);
@@ -863,7 +863,7 @@
   MessageParameters parameters(SubscribeForTest());
   session_.Subscribe(FullTrackName("foo", "bar"), &remote_track_visitor_,
                      parameters);
-  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackExtensions());
+  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackProperties());
   EXPECT_CALL(remote_track_visitor_, OnReply)
       .WillOnce(
           [&](const FullTrackName& ftn,
@@ -883,7 +883,7 @@
               Writev(SerializedControlMessage(subscribe), _));
   session_.Subscribe(FullTrackName("foo", "bar"), &remote_track_visitor_,
                      subscribe.parameters);
-  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackExtensions());
+  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackProperties());
   EXPECT_CALL(remote_track_visitor_, OnReply)
       .WillOnce(
           [&](const FullTrackName& ftn,
@@ -902,7 +902,7 @@
   parameters.subscription_filter.emplace(Location(1, 0), 10);
   session_.Subscribe(FullTrackName("foo", "bar"), &remote_track_visitor_,
                      parameters);
-  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackExtensions());
+  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackProperties());
   EXPECT_CALL(remote_track_visitor_, OnReply);
   bidi_wrapper_->ReceiveMessage(ok);
   EXPECT_CALL(mock_bidi_stream_,
@@ -1125,7 +1125,7 @@
   session_.Subscribe(FullTrackName("foo", "bar"), &remote_track_visitor_,
                      MessageParameters());
   MoqtSubscribeOk subscribe_ok(/*track_alias=*/2, MessageParameters(),
-                               TrackExtensions());
+                               TrackProperties());
   bidi_wrapper_->ReceiveMessage(subscribe_ok);
   // Second subscribe, but OK has the same track alias.
   webtransport::test::MockStream bidi_stream_2;
@@ -1148,12 +1148,12 @@
   const MoqtPriority kLocalDefaultPriority = 0x20;
   bidi_wrapper_ = std::make_unique<MoqtBidiStreamTestWrapper>(
       ResponseStream(kSubscribeByte));
-  TrackExtensions extensions(std::nullopt, std::nullopt, kLocalDefaultPriority,
+  TrackProperties properties(std::nullopt, std::nullopt, kLocalDefaultPriority,
                              std::nullopt, std::nullopt, std::nullopt);
-  EXPECT_CALL(*track, extensions)
-      .WillRepeatedly(testing::ReturnRef(extensions));
+  EXPECT_CALL(*track, properties)
+      .WillRepeatedly(testing::ReturnRef(properties));
   MoqtObjectListener* listener = ReceiveSubscribeSynchronousOk(
-      track, request, bidi_wrapper_.get(), /*track_alias=*/0, extensions);
+      track, request, bidi_wrapper_.get(), /*track_alias=*/0, properties);
   EXPECT_CALL(*track, RemoveObjectListener(listener));
   bidi_wrapper_->stream().OnResetStreamReceived(kResetCodeCancelled);
 }
@@ -1168,7 +1168,7 @@
   session_.Subscribe(ftn, &remote_track_visitor_, MessageParameters());
   MoqtSubscribeOk ok(
       2, MessageParameters(),
-      TrackExtensions(std::nullopt, std::nullopt, kPeerDefaultPriority,
+      TrackProperties(std::nullopt, std::nullopt, kPeerDefaultPriority,
                       std::nullopt, std::nullopt, std::nullopt));
   EXPECT_CALL(remote_track_visitor_, OnReply);
   bidi_wrapper_->ReceiveMessage(ok);
@@ -1178,7 +1178,7 @@
       /*group_sequence=*/0,
       /*object_sequence=*/0,
       /*publisher_priority=*/0,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*object_status=*/MoqtObjectStatus::kNormal,
       /*subgroup_id=*/std::nullopt,
       /*first_object_in_subgroup=*/std::nullopt,
@@ -1212,7 +1212,7 @@
   session_.Subscribe(ftn, &remote_track_visitor_, MessageParameters());
   MoqtSubscribeOk ok(
       2, MessageParameters(),
-      TrackExtensions(std::nullopt, std::nullopt, kPeerDefaultPriority,
+      TrackProperties(std::nullopt, std::nullopt, kPeerDefaultPriority,
                       std::nullopt, std::nullopt, std::nullopt));
   EXPECT_CALL(remote_track_visitor_, OnReply);
   bidi_wrapper_->ReceiveMessage(ok);
@@ -1255,12 +1255,12 @@
   // Create the publisher and the SUBSCRIBE with kLocalDefaultPriority.
   MockTrackPublisher* track = CreateTrackPublisher();
   std::make_shared<MockTrackPublisher>(request.full_track_name);
-  TrackExtensions extensions(std::nullopt, std::nullopt, kLocalDefaultPriority,
+  TrackProperties properties(std::nullopt, std::nullopt, kLocalDefaultPriority,
                              std::nullopt, std::nullopt, std::nullopt);
-  EXPECT_CALL(*track, extensions)
-      .WillRepeatedly(testing::ReturnRef(extensions));
+  EXPECT_CALL(*track, properties)
+      .WillRepeatedly(testing::ReturnRef(properties));
   MoqtObjectListener* listener = ReceiveSubscribeSynchronousOk(
-      track, request, bidi_wrapper_.get(), /*track_alias=*/0, extensions);
+      track, request, bidi_wrapper_.get(), /*track_alias=*/0, properties);
 
   // Deliver an object with kLocalDefaultPriority; stream_type will omit
   // the priority.
@@ -1342,7 +1342,7 @@
   session_.Subscribe(ftn, &remote_track_visitor_, params);
   MoqtSubscribeOk ok(
       2, MessageParameters(),
-      TrackExtensions(std::nullopt, std::nullopt, kPeerDefaultPriority,
+      TrackProperties(std::nullopt, std::nullopt, kPeerDefaultPriority,
                       std::nullopt, std::nullopt, std::nullopt));
   EXPECT_CALL(remote_track_visitor_, OnReply);
   bidi_wrapper_->ReceiveMessage(ok);
@@ -1862,16 +1862,16 @@
   MessageParameters parameters;
   parameters.largest_object = Location(2, 0);
   subscribe_wrapper->ReceiveMessage(
-      MoqtSubscribeOk(0, parameters, TrackExtensions()));
+      MoqtSubscribeOk(0, parameters, TrackProperties()));
   bidi_wrapper_->ReceiveMessage(MoqtFetchOk(
-      false, Location(2, 0), MessageParameters(), TrackExtensions()));
+      false, Location(2, 0), MessageParameters(), TrackProperties()));
   // Packet arrives on FETCH stream.
   MoqtObject object = {
       /*request_id=*/2,
       /*group_id, object_id=*/2,
       0,
       /*publisher_priority=*/128,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*status=*/MoqtObjectStatus::kNormal,
       /*subgroup=*/0,
       /*first_object_in_subgroup=*/true,
@@ -2077,7 +2077,7 @@
       /*group_id, object_id=*/0,
       0,
       /*publisher_priority=*/128,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*status=*/MoqtObjectStatus::kNormal,
       /*subgroup=*/0,
       /*first_object_in_subgroup=*/true,
@@ -2146,7 +2146,7 @@
       /*group_id, object_id=*/0,
       0,
       /*publisher_priority=*/128,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*status=*/MoqtObjectStatus::kNormal,
       /*subgroup=*/0,
       /*first_object_in_subgroup=*/true,
@@ -2506,7 +2506,7 @@
   parameters.subscription_filter.emplace(MoqtFilterType::kLargestObject);
   EXPECT_TRUE(session_.Subscribe(FullTrackName("foo", "bar"),
                                  &remote_track_visitor_, parameters));
-  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackExtensions());
+  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackProperties());
   EXPECT_CALL(remote_track_visitor_, OnReply)
       .WillOnce(
           [&](const FullTrackName& ftn,
@@ -2520,7 +2520,7 @@
       /*group_id=*/0,
       /*object_id=*/0,
       /*publisher_priority=*/7,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*object_status=*/MoqtObjectStatus::kEndOfGroup,
       /*subgroup_id=*/0,
       /*first_object_in_subgroup=*/true,
@@ -2544,7 +2544,7 @@
   parameters.subscription_filter.emplace(MoqtFilterType::kLargestObject);
   EXPECT_TRUE(session_.Subscribe(FullTrackName("foo", "bar"),
                                  &remote_track_visitor_, parameters));
-  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackExtensions());
+  MoqtSubscribeOk ok(/*track_alias=*/2, MessageParameters(), TrackProperties());
   EXPECT_CALL(remote_track_visitor_, OnReply)
       .WillOnce(
           [&](const FullTrackName& ftn,
@@ -2558,7 +2558,7 @@
       /*group_id=*/0,
       /*object_id=*/0,
       /*publisher_priority=*/7,
-      /*extension_headers=*/"",
+      /*properties=*/"",
       /*object_status=*/MoqtObjectStatus::kEndOfGroup,
       /*subgroup_id=*/0,
       /*first_object_in_subgroup=*/true,
@@ -2732,7 +2732,7 @@
 
   std::optional<std::variant<MessageParameters, MoqtRequestErrorInfo>> response;
   ASSERT_TRUE(session_.Publish(
-      track_publisher, MessageParameters(), TrackExtensions(),
+      track_publisher, MessageParameters(), TrackProperties(),
       [&](std::variant<MessageParameters, MoqtRequestErrorInfo> resp) {
         response = resp;
       }));
@@ -2754,7 +2754,7 @@
   EXPECT_CALL(mock_session_, CanOpenNextOutgoingBidirectionalStream())
       .WillOnce(Return(false));
   EXPECT_FALSE(session_.Publish(
-      track_publisher, MessageParameters(), TrackExtensions(),
+      track_publisher, MessageParameters(), TrackProperties(),
       [&](std::variant<MessageParameters, MoqtRequestErrorInfo> response) {}));
 }
 
@@ -2768,7 +2768,7 @@
   std::shared_ptr<MoqtTrackPublisher> track_publisher =
       publisher_.GetTrack(kDefaultTrackName());
   EXPECT_FALSE(session_.Publish(
-      track_publisher, MessageParameters(), TrackExtensions(),
+      track_publisher, MessageParameters(), TrackProperties(),
       [&](std::variant<MessageParameters, MoqtRequestErrorInfo>) {}));
 }
 
@@ -2784,14 +2784,14 @@
   bool incoming_publish_callback_called = false;
   session_.callbacks().incoming_publish_callback =
       [&](const FullTrackName&, const MessageParameters&,
-          const TrackExtensions&, MoqtResponseCallback callback) {
+          const TrackProperties&, MoqtResponseCallback callback) {
         incoming_publish_callback_called = true;
         return nullptr;
       };
 
   // Prepare PUBLISH message.
   MoqtPublish publish{1, kDefaultTrackName(), 10, MessageParameters(),
-                      TrackExtensions()};
+                      TrackProperties()};
   webtransport::test::MockStream publish_stream;
   std::unique_ptr<MoqtBidiStreamTestWrapper> publish_wrapper =
       std::make_unique<MoqtBidiStreamTestWrapper>(
diff --git a/quiche/quic/moqt/moqt_subscribe_stream.cc b/quiche/quic/moqt/moqt_subscribe_stream.cc
index b6186e8..6793bd1 100644
--- a/quiche/quic/moqt/moqt_subscribe_stream.cc
+++ b/quiche/quic/moqt/moqt_subscribe_stream.cc
@@ -74,7 +74,7 @@
   }
   add_callback_ = nullptr;
 
-  track_->OnObjectOrOk(SubscribeOkData(message.parameters, message.extensions));
+  track_->OnObjectOrOk(SubscribeOkData(message.parameters, message.properties));
   return absl::OkStatus();
 }
 
@@ -86,9 +86,9 @@
         absl::InvalidArgumentError("REQUEST_OK received before SUBSCRIBE_OK"));
     return absl::OkStatus();
   }
-  if (!message.extensions.empty()) {
+  if (!message.properties.empty()) {
     OnFatalError(absl::InvalidArgumentError(
-        "REQUEST_UPDATE_OK received with extensions"));
+        "REQUEST_UPDATE_OK received with properties"));
     return absl::OkStatus();
   }
   absl::StatusOr<MessageParameters> old_parameters =
diff --git a/quiche/quic/moqt/moqt_subscribe_stream_test.cc b/quiche/quic/moqt/moqt_subscribe_stream_test.cc
index 301ee16..1e10f1f 100644
--- a/quiche/quic/moqt/moqt_subscribe_stream_test.cc
+++ b/quiche/quic/moqt/moqt_subscribe_stream_test.cc
@@ -126,7 +126,7 @@
   EXPECT_CALL(mock_remove_callback_, Call);
 }
 
-TEST_F(MoqtSubscribeRequestStreamTest, RequestOkWithExtensions) {
+TEST_F(MoqtSubscribeRequestStreamTest, RequestOkWithProperties) {
   EXPECT_CALL(mock_stream_,
               Writev(ControlMessageOfType(MoqtMessageType::kSubscribe), _))
       .WillOnce(Return(absl::OkStatus()));
@@ -139,7 +139,7 @@
   EXPECT_CALL(error_callback_, Call(MoqtError::kProtocolViolation, _));
   MoqtRequestOk request_ok(
       MessageParameters(),
-      TrackExtensions(quic::QuicTimeDelta::FromSeconds(5), std::nullopt,
+      TrackProperties(quic::QuicTimeDelta::FromSeconds(5), std::nullopt,
                       std::nullopt, std::nullopt, std::nullopt, std::nullopt));
   QUICHE_EXPECT_OK(stream_->OnControlMessage(request_ok));
   // Test cleanup.
diff --git a/quiche/quic/moqt/moqt_track_status_stream.cc b/quiche/quic/moqt/moqt_track_status_stream.cc
index 3af18fa..5a56d4e 100644
--- a/quiche/quic/moqt/moqt_track_status_stream.cc
+++ b/quiche/quic/moqt/moqt_track_status_stream.cc
@@ -134,7 +134,7 @@
   parameters.expires = publisher_->expiration();
   parameters.largest_object = publisher_->largest_location();
   // Since `fin` is true, this will also reset `publisher_`.
-  CheckStatus(SendRequestOk(parameters, publisher_->extensions()));
+  CheckStatus(SendRequestOk(parameters, publisher_->properties()));
 }
 
 void MoqtTrackStatusResponseStream::OnSubscribeRejected(
@@ -162,9 +162,9 @@
 }
 
 absl::Status MoqtTrackStatusResponseStream::SendRequestOk(
-    const MessageParameters& parameters, const TrackExtensions& extensions) {
+    const MessageParameters& parameters, const TrackProperties& properties) {
   return SendOrBufferMessage(
-      framer()->SerializeRequestOk(MoqtRequestOk(parameters, extensions)),
+      framer()->SerializeRequestOk(MoqtRequestOk(parameters, properties)),
       /*fin=*/true);
 }
 
diff --git a/quiche/quic/moqt/moqt_track_status_stream.h b/quiche/quic/moqt/moqt_track_status_stream.h
index 95d0f09..d2bc178 100644
--- a/quiche/quic/moqt/moqt_track_status_stream.h
+++ b/quiche/quic/moqt/moqt_track_status_stream.h
@@ -87,9 +87,9 @@
   void Detach() override;
 
  private:
-  // Unlike other REQUEST_OK, TRACK_STATUS_OK has extensions and a FIN.
+  // Unlike other REQUEST_OK, TRACK_STATUS_OK has properties and a FIN.
   absl::Status SendRequestOk(const MessageParameters& parameters,
-                             const TrackExtensions& extensions);
+                             const TrackProperties& properties);
   SessionToPublisherInterface* absl_nullable session() const {
     return session_.GetIfAvailable();
   }
diff --git a/quiche/quic/moqt/moqt_track_status_stream_test.cc b/quiche/quic/moqt/moqt_track_status_stream_test.cc
index 1da3741..7bac2cb 100644
--- a/quiche/quic/moqt/moqt_track_status_stream_test.cc
+++ b/quiche/quic/moqt/moqt_track_status_stream_test.cc
@@ -117,7 +117,7 @@
 
   MoqtRequestOk ok(
       MessageParameters(),
-      TrackExtensions(quic::QuicTimeDelta::FromSeconds(5),
+      TrackProperties(quic::QuicTimeDelta::FromSeconds(5),
                       quic::QuicTimeDelta::FromSeconds(10), std::nullopt,
                       std::nullopt, std::nullopt, std::nullopt));
   ok.parameters.expires = quic::QuicTimeDelta::FromSeconds(10);
diff --git a/quiche/quic/moqt/moqt_uni_stream.cc b/quiche/quic/moqt/moqt_uni_stream.cc
index 924a002..866e58d 100644
--- a/quiche/quic/moqt/moqt_uni_stream.cc
+++ b/quiche/quic/moqt/moqt_uni_stream.cc
@@ -52,7 +52,7 @@
   header.subgroup_id = object.metadata.subgroup;
   header.object_id = object.metadata.location.object;
   header.publisher_priority = object.metadata.publisher_priority;
-  header.extension_headers = object.metadata.extensions;
+  header.properties = object.metadata.properties;
   header.object_status = object.metadata.status;
   header.payload_length = object.metadata.payload_length;
 
@@ -173,13 +173,13 @@
       // No class access below this line.
       return;
     }
-    // Always include extension header length, because it's difficult to know
+    // Always include property header length, because it's difficult to know
     // a priori if they're going to appear on a stream.
     if (!last_object().has_value()) {
       type_ = MoqtDataStreamType::Subgroup(
           index_.subgroup, next_object_, false,
           object->metadata.publisher_priority ==
-              publisher_->extensions().default_publisher_priority(),
+              publisher_->properties().default_publisher_priority(),
           object->metadata.first_object_in_subgroup.value_or(true));
     }
     uint64_t start_offset = already_delivered_;
@@ -456,7 +456,7 @@
       PublishedObjectMetadata metadata;
       metadata.location = Location(message.group_id, message.object_id);
       metadata.subgroup = message.subgroup_id;
-      metadata.extensions = message.extension_headers;
+      metadata.properties = message.properties;
       metadata.status = message.object_status;
       metadata.publisher_priority = message.publisher_priority;
       metadata.first_object_in_subgroup = message.first_object_in_subgroup;
diff --git a/quiche/quic/moqt/moqt_uni_stream_test.cc b/quiche/quic/moqt/moqt_uni_stream_test.cc
index 0cfe405..61d7ee8 100644
--- a/quiche/quic/moqt/moqt_uni_stream_test.cc
+++ b/quiche/quic/moqt/moqt_uni_stream_test.cc
@@ -127,7 +127,7 @@
   std::shared_ptr<StrictMock<MockTrackPublisher>> track_publisher_;
   StrictMock<MockLivePublisherInterface> visitor_;
   MoqtTraceRecorder trace_recorder_;
-  TrackExtensions track_extensions_;
+  TrackProperties track_properties_;
   quic::MockClock mock_clock_;
   quic::test::MockAlarmFactory alarm_factory_;
   std::unique_ptr<OutgoingSubgroupStream> stream_;
@@ -162,8 +162,8 @@
       .WillOnce(Return(quic::QuicTimeDelta::FromSeconds(1)));
   EXPECT_CALL(visitor_, alternate_delivery_timeout()).WillOnce(Return(false));
   EXPECT_CALL(visitor_, clock()).WillOnce(Return(&mock_clock_));
-  EXPECT_CALL(*track_publisher_, extensions())
-      .WillRepeatedly(ReturnRef(track_extensions_));
+  EXPECT_CALL(*track_publisher_, properties())
+      .WillRepeatedly(ReturnRef(track_properties_));
   EXPECT_CALL(mock_stream_, Writev).WillOnce(Return(absl::OkStatus()));
   EXPECT_CALL(visitor_, OnObjectSent(Location(0, 0)));
   stream_->OnCanWrite();
@@ -206,8 +206,8 @@
       .WillOnce(Return(quic::QuicTimeDelta::FromSeconds(1)));
   EXPECT_CALL(visitor_, alternate_delivery_timeout()).WillOnce(Return(false));
   EXPECT_CALL(visitor_, clock).WillOnce(Return(&mock_clock_));
-  EXPECT_CALL(*track_publisher_, extensions())
-      .WillRepeatedly(ReturnRef(track_extensions_));
+  EXPECT_CALL(*track_publisher_, properties())
+      .WillRepeatedly(ReturnRef(track_properties_));
   EXPECT_CALL(mock_stream_, Writev)
       .WillOnce(Return(absl::InternalError("error")));
   EXPECT_CALL(mock_stream_, ResetWithUserCode(kResetCodeInternalError));
@@ -232,8 +232,8 @@
       .WillRepeatedly(Return(false));
   EXPECT_CALL(visitor_, clock).WillOnce(Return(&mock_clock_));
 
-  EXPECT_CALL(*track_publisher_, extensions())
-      .WillRepeatedly(ReturnRef(track_extensions_));
+  EXPECT_CALL(*track_publisher_, properties())
+      .WillRepeatedly(ReturnRef(track_properties_));
   EXPECT_CALL(mock_stream_, Writev)
       .WillOnce([&](absl::Span<quiche::QuicheMemSlice> data,
                     const webtransport::StreamWriteOptions& options) {
@@ -296,8 +296,8 @@
   EXPECT_CALL(visitor_, alternate_delivery_timeout())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(visitor_, clock()).WillRepeatedly(Return(&mock_clock_));
-  EXPECT_CALL(*track_publisher_, extensions())
-      .WillRepeatedly(ReturnRef(track_extensions_));
+  EXPECT_CALL(*track_publisher_, properties())
+      .WillRepeatedly(ReturnRef(track_properties_));
   EXPECT_CALL(mock_stream_, Writev)
       .WillOnce([&](absl::Span<quiche::QuicheMemSlice> data,
                     const webtransport::StreamWriteOptions& options) {
@@ -462,7 +462,7 @@
     0,     // group_id
     0,     // object_id
     0x80,  // publisher_priority
-    "",    // extension_headers
+    "",    // properties
     MoqtObjectStatus::kNormal,
     0,     // subgroup_id
     true,  // first_object_in_subgroup
@@ -578,7 +578,7 @@
         EXPECT_EQ(track_name, ftn_);
         EXPECT_EQ(metadata.location, Location(0, 0));
         EXPECT_EQ(metadata.subgroup, 0);
-        EXPECT_EQ(metadata.extensions, "");
+        EXPECT_EQ(metadata.properties, "");
         EXPECT_EQ(metadata.status, MoqtObjectStatus::kNormal);
         EXPECT_EQ(metadata.publisher_priority, 0x80);
         EXPECT_EQ(metadata.payload_length, 8);
@@ -672,7 +672,7 @@
 
   const MoqtObject sent_object = MoqtObject(
       /*request_id=*/0, /*group_id=*/0,
-      /*object_id=*/0, /*publisher_priority=*/0x80, /*extension_headers=*/"",
+      /*object_id=*/0, /*publisher_priority=*/0x80, /*properties=*/"",
       MoqtObjectStatus::kNormal, /*subgroup_id=*/0,
       /*first_object_in_subgroup=*/true, /*payload_length=*/12);
   EXPECT_CALL(mock_fetch_task_, HasObject).WillOnce(Return(false));
@@ -681,7 +681,7 @@
         EXPECT_EQ(message.group_id, sent_object.group_id);
         EXPECT_EQ(message.object_id, sent_object.object_id);
         EXPECT_EQ(message.publisher_priority, sent_object.publisher_priority);
-        EXPECT_EQ(message.extension_headers, sent_object.extension_headers);
+        EXPECT_EQ(message.properties, sent_object.properties);
         EXPECT_EQ(message.object_status, sent_object.object_status);
         EXPECT_EQ(message.subgroup_id, sent_object.subgroup_id);
         EXPECT_EQ(message.first_object_in_subgroup,
diff --git a/quiche/quic/moqt/test_tools/mock_moqt_session.h b/quiche/quic/moqt/test_tools/mock_moqt_session.h
index 06889b3..5aa79d4 100644
--- a/quiche/quic/moqt/test_tools/mock_moqt_session.h
+++ b/quiche/quic/moqt/test_tools/mock_moqt_session.h
@@ -83,7 +83,7 @@
   MOCK_METHOD(bool, Publish,
               (std::shared_ptr<MoqtTrackPublisher> publisher,
                const MessageParameters& parameters,
-               const TrackExtensions& extensions,
+               const TrackProperties& properties,
                MoqtResponseCallback response_callback),
               (override));
   MOCK_METHOD(std::unique_ptr<MoqtFetchTask>, Fetch,
diff --git a/quiche/quic/moqt/test_tools/moqt_mock_visitor.h b/quiche/quic/moqt/test_tools/moqt_mock_visitor.h
index a237fde..09d2e86 100644
--- a/quiche/quic/moqt/test_tools/moqt_mock_visitor.h
+++ b/quiche/quic/moqt/test_tools/moqt_mock_visitor.h
@@ -76,7 +76,7 @@
  public:
   explicit MockTrackPublisher(FullTrackName name)
       : track_name_(std::move(name)) {
-    ON_CALL(*this, extensions()).WillByDefault(testing::ReturnRef(extensions_));
+    ON_CALL(*this, properties()).WillByDefault(testing::ReturnRef(properties_));
   }
   const FullTrackName& GetTrackName() const override { return track_name_; }
 
@@ -90,7 +90,7 @@
   MOCK_METHOD(void, RemoveObjectListener, (MoqtObjectListener * listener),
               (override));
   MOCK_METHOD(std::optional<Location>, largest_location, (), (const, override));
-  MOCK_METHOD(const TrackExtensions&, extensions, (), (const, override));
+  MOCK_METHOD(const TrackProperties&, properties, (), (const, override));
   MOCK_METHOD(std::optional<quic::QuicTimeDelta>, expiration, (),
               (const, override));
   MOCK_METHOD(std::unique_ptr<MoqtFetchTask>, StandaloneFetch,
@@ -103,7 +103,7 @@
 
  private:
   FullTrackName track_name_;
-  const TrackExtensions extensions_;
+  const TrackProperties properties_;
 };
 
 // A very simple MoqtTrackPublisher that allows tests to add arbitrary objects.
@@ -133,7 +133,7 @@
   std::optional<Location> largest_location() const override {
     return largest_location_;
   }
-  const TrackExtensions& extensions() const override { return extensions_; }
+  const TrackProperties& properties() const override { return properties_; }
   std::optional<quic::QuicTimeDelta> expiration() const override {
     return quic::QuicTimeDelta::Infinite();
   }
@@ -171,7 +171,7 @@
     PublishedObjectMetadata metadata;
     metadata.location = location;
     metadata.subgroup = subgroup;
-    metadata.extensions = "";
+    metadata.properties = "";
     metadata.status = MoqtObjectStatus::kNormal;
     metadata.publisher_priority = 128;
     metadata.first_object_in_subgroup = location.object == 0;
@@ -202,7 +202,7 @@
   absl::flat_hash_set<MoqtObjectListener*> listeners_;
   std::map<Location, CachedObject> objects_;
   std::optional<Location> largest_location_;
-  TrackExtensions extensions_;
+  TrackProperties properties_;
 };
 
 // TODO(martinduke): Rename to MockSubscribeVisitor.
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h
index 04b9b34..a0c813a 100644
--- a/quiche/quic/moqt/test_tools/moqt_test_message.h
+++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -35,17 +35,17 @@
 
 namespace moqt::test {
 
-inline constexpr absl::string_view kDefaultExtensionBlob(
+inline constexpr absl::string_view kDefaultPropertyBlob(
     "\x00\x0c\x01\x03\x66\x6f\x6f", 7);
 
 inline std::vector<MoqtDatagramType> AllMoqtDatagramTypes() {
   std::vector<MoqtDatagramType> types;
   for (bool payload : {false, true}) {
-    for (bool extension : {false, true}) {
+    for (bool property : {false, true}) {
       for (bool end_of_group : {false, true}) {
         for (bool default_priority : {false, true}) {
           for (bool zero_object_id : {false, true}) {
-            types.push_back(MoqtDatagramType(payload, extension, end_of_group,
+            types.push_back(MoqtDatagramType(payload, property, end_of_group,
                                              default_priority, zero_object_id));
           }
         }
@@ -75,13 +75,13 @@
   types.push_back(MoqtDataStreamType::Fetch());
   uint64_t first_object_id = 1;
   for (uint64_t subgroup_id : {0, 1, 2}) {
-    for (bool no_extension_headers : {true, false}) {
+    for (bool no_properties : {true, false}) {
       for (bool default_priority : {true, false}) {
         for (bool has_first_object : {true, false}) {
           for (bool end_of_group : {false, true}) {
             types.push_back(MoqtDataStreamType::Subgroup(
-                subgroup_id, first_object_id, no_extension_headers,
-                default_priority, has_first_object, end_of_group));
+                subgroup_id, first_object_id, no_properties, default_priority,
+                has_first_object, end_of_group));
           }
         }
       }
@@ -252,8 +252,8 @@
       QUIC_LOG(INFO) << "OBJECT Publisher Priority mismatch";
       return false;
     }
-    if (cast.extension_headers != object_.extension_headers) {
-      QUIC_LOG(INFO) << "OBJECT Extension Header mismatch";
+    if (cast.properties != object_.properties) {
+      QUIC_LOG(INFO) << "OBJECT Property Header mismatch";
       return false;
     }
     if (cast.object_status != object_.object_status) {
@@ -281,7 +281,7 @@
       .group_id = 5,
       .object_id = 6,
       .publisher_priority = 7,
-      .extension_headers = std::string(kDefaultExtensionBlob),
+      .properties = std::string(kDefaultPropertyBlob),
       .object_status = MoqtObjectStatus::kNormal,
       .subgroup_id = 8,
       .first_object_in_subgroup = false,
@@ -303,8 +303,8 @@
                                   : MoqtObjectStatus::kNormal;
       object_.payload_length = 3;
     }
-    object_.extension_headers =
-        datagram_type.has_extension() ? std::string(kDefaultExtensionBlob) : "";
+    object_.properties =
+        datagram_type.has_properties() ? std::string(kDefaultPropertyBlob) : "";
     object_.object_id = datagram_type.has_object_id() ? 6 : 0;
     object_.subgroup_id = std::nullopt;
     quic::QuicDataWriter writer(sizeof(raw_packet_),
@@ -317,8 +317,8 @@
     if (!datagram_type.has_default_priority()) {
       EXPECT_TRUE(writer.WriteStringPiece(kRawPriority));
     }
-    if (datagram_type.has_extension()) {
-      EXPECT_TRUE(writer.WriteStringPiece(kRawExtensions));
+    if (datagram_type.has_properties()) {
+      EXPECT_TRUE(writer.WriteStringPiece(kRawProperties));
     }
     if (datagram_type.has_status()) {
       EXPECT_TRUE(
@@ -338,7 +338,7 @@
     if (!datagram_type_.has_default_priority()) {
       varints += "-";  // priority
     }
-    if (datagram_type_.has_extension()) {
+    if (datagram_type_.has_properties()) {
       varints += "v-------";
     }
     if (datagram_type_.has_status()) {
@@ -355,8 +355,8 @@
   static constexpr absl::string_view kRawAliasGroup = "\x04\x05";
   static constexpr absl::string_view kRawObject = "\x06";
   static constexpr absl::string_view kRawPriority = "\x07";
-  static constexpr absl::string_view kRawExtensions{
-      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultExtensionBlob
+  static constexpr absl::string_view kRawProperties{
+      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultPropertyBlob
   static constexpr absl::string_view kRawPayload = "foo";
 };
 
@@ -372,8 +372,8 @@
     } else if (type.SubgroupIsFirstObjectId()) {
       object_.subgroup_id = object_.object_id;
     }
-    if (!type.AreExtensionHeadersPresent()) {
-      object_.extension_headers = "";
+    if (!type.ArePropertiesPresent()) {
+      object_.properties = "";
     }
     // Build raw_packet_ from the type.
     quic::QuicDataWriter writer(sizeof(raw_packet_), raw_packet_);
@@ -389,9 +389,9 @@
                                     kRawPublisherPriority.length()));
     }
     EXPECT_TRUE(writer.WriteBytes(kRawObjectId.data(), kRawObjectId.length()));
-    if (type.AreExtensionHeadersPresent()) {
+    if (type.ArePropertiesPresent()) {
       EXPECT_TRUE(
-          writer.WriteBytes(kRawExtensions.data(), kRawExtensions.length()));
+          writer.WriteBytes(kRawProperties.data(), kRawProperties.length()));
     }
     payload_length_offset_ = writer.length();
     EXPECT_TRUE(writer.WriteBytes(kRawPayload.data(), kRawPayload.length()));
@@ -408,7 +408,7 @@
       varints += "-";  // priority
     }
     varints += "v";  // object ID
-    if (type_.AreExtensionHeadersPresent()) {
+    if (type_.ArePropertiesPresent()) {
       varints += "v-------";
     }
     varints += "v---";  // payload with length
@@ -441,8 +441,8 @@
   static constexpr absl::string_view kRawSubgroupId = "\x08";
   static constexpr absl::string_view kRawPublisherPriority = "\x07";
   static constexpr absl::string_view kRawObjectId = "\x06";
-  static constexpr absl::string_view kRawExtensions{
-      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultExtensionBlob
+  static constexpr absl::string_view kRawProperties{
+      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultPropertyBlob
   static constexpr absl::string_view kRawPayload = "\x03\x66\x6f\x6f";
   char raw_packet_[18];
   size_t payload_length_offset_;
@@ -462,9 +462,9 @@
     object_.object_id = 9;
     quic::QuicDataWriter writer(sizeof(raw_packet_), raw_packet_);
     EXPECT_TRUE(writer.WriteMoqVarInt(2));  // Object ID delta - 1
-    if (type.AreExtensionHeadersPresent()) {
+    if (type.ArePropertiesPresent()) {
       EXPECT_TRUE(
-          writer.WriteBytes(kRawExtensions.data(), kRawExtensions.length()));
+          writer.WriteBytes(kRawProperties.data(), kRawProperties.length()));
     }
     EXPECT_TRUE(writer.WriteBytes(kRawPayload.data(), kRawPayload.length()));
     EXPECT_LE(writer.length(), kMaxMessageHeaderSize);
@@ -472,7 +472,7 @@
   }
 
   void ExpandVarints() override {
-    if (type_.AreExtensionHeadersPresent()) {
+    if (type_.ArePropertiesPresent()) {
       ExpandVarintsImpl("vv-------v---", false);
     } else {
       ExpandVarintsImpl("vv---", false);
@@ -481,8 +481,8 @@
 
  private:
   MoqtDataStreamType type_;
-  static constexpr absl::string_view kRawExtensions{
-      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultExtensionBlob
+  static constexpr absl::string_view kRawProperties{
+      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultPropertyBlob
   static constexpr absl::string_view kRawPayload = "\x03\x62\x61\x72";
   char raw_packet_[13];
 };
@@ -515,8 +515,8 @@
       0x04,              // request ID
       0x3f,              // object serialization flag
       0x05, 0x08, 0x06,  // sequence
-      0x07, 0x07,        // publisher priority, 7B extensions
-      0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f,  // extensions
+      0x07, 0x07,        // publisher priority, 7B properties
+      0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f,  // properties
       0x03, 0x66, 0x6f, 0x6f,                    // payload = "foo"
   };
 };
@@ -557,12 +557,12 @@
       raw_packet_[length++] = 0x09;
       object_.publisher_priority = MoqtPriority(0x09);
     }
-    if (serialization.has_extensions()) {
-      memcpy(&raw_packet_[length], kRawExtensions.data(),
-             kRawExtensions.length());
-      length += kRawExtensions.length();
+    if (serialization.has_properties()) {
+      memcpy(&raw_packet_[length], kRawProperties.data(),
+             kRawProperties.length());
+      length += kRawProperties.length();
     } else {
-      object_.extension_headers = "";
+      object_.properties = "";
     }
     memcpy(&raw_packet_[length], kRawPayload.data(), kRawPayload.length());
     length += kRawPayload.length();
@@ -584,7 +584,7 @@
     if (serialization_.has_priority()) {
       varints += "-";
     }
-    if (serialization_.has_extensions()) {
+    if (serialization_.has_properties()) {
       varints += "v-------";
     }
     varints += "v---";
@@ -594,8 +594,8 @@
  private:
   MoqtFetchSerialization serialization_;
   uint8_t raw_packet_[17];
-  static constexpr absl::string_view kRawExtensions{
-      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultExtensionBlob
+  static constexpr absl::string_view kRawProperties{
+      "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8};  // see kDefaultPropertyBlob
   static constexpr absl::string_view kRawPayload = "\x03\x62\x61\x72";
 };
 
@@ -765,8 +765,8 @@
       QUIC_LOG(INFO) << "SUBSCRIBE OK parameter mismatch";
       return false;
     }
-    if (cast.extensions != subscribe_ok_.extensions) {
-      QUIC_LOG(INFO) << "SUBSCRIBE OK extensions mismatch";
+    if (cast.properties != subscribe_ok_.properties) {
+      QUIC_LOG(INFO) << "SUBSCRIBE OK properties mismatch";
       return false;
     }
     return true;
@@ -788,13 +788,13 @@
   MoqtSubscribeOk subscribe_ok_ = {
       /*track_alias=*/2,
       MessageParameters(),  // Set in the constructor.
-      TrackExtensions(
+      TrackProperties(
           /*delivery_timeout=*/quic::QuicTimeDelta::FromMilliseconds(10000),
           /*max_cache_duration=*/quic::QuicTimeDelta::FromMilliseconds(10000),
           /*publisher_priority=*/std::nullopt,
           /*group_order=*/MoqtDeliveryOrder::kDescending,
           /*dynamic_groups=*/std::nullopt,
-          /*immutable_extensions=*/std::nullopt),
+          /*immutable_properties=*/std::nullopt),
   };
 
  private:
@@ -802,7 +802,7 @@
       0x04, 0x00, 0x10, 0x02, 0x02,  // alias, 2 params
       0x08, 0x03,                    // expires = 3
       0x01, 0x02, 0x0c, 0x14,        // largest_location = (12, 20)
-      // Extensions
+      // Properties
       0x02, 0xa7, 0x10,  // delivery_timeout = 10000
       0x02, 0xa7, 0x10,  // max_cache_duration = 10000
       0x1e, 0x02         // default_publisher_group_order = 2
@@ -1078,8 +1078,8 @@
       QUIC_LOG(INFO) << "REQUEST_OK parameter mismatch";
       return false;
     }
-    if (cast.extensions != request_ok_.extensions) {
-      QUIC_LOG(INFO) << "REQUEST_OK extensions mismatch";
+    if (cast.properties != request_ok_.properties) {
+      QUIC_LOG(INFO) << "REQUEST_OK properties mismatch";
       return false;
     }
     return true;
@@ -1096,7 +1096,7 @@
       0x07, 0x00, 0x0d,
       0x01,                    // 1 parameter
       0x09, 0x02, 0x05, 0x01,  // Largest Object = (5, 1)
-      // Extensions
+      // Properties
       0x02, 0xa7, 0x10,  // delivery_timeout = 10000
       0x02, 0xa7, 0x10,  // max_cache_duration = 10000
       0x1e, 0x02         // default_publisher_group_order = 2
@@ -1104,13 +1104,13 @@
 
   MoqtRequestOk request_ok_ = {
       MessageParameters(),  // Set in the constructor.
-      TrackExtensions(
+      TrackProperties(
           /*delivery_timeout=*/quic::QuicTimeDelta::FromMilliseconds(10000),
           /*max_cache_duration=*/quic::QuicTimeDelta::FromMilliseconds(10000),
           /*publisher_priority=*/std::nullopt,
           /*group_order=*/MoqtDeliveryOrder::kDescending,
           /*dynamic_groups=*/std::nullopt,
-          /*immutable_extensions=*/std::nullopt),
+          /*immutable_properties=*/std::nullopt),
   };
 };
 
@@ -1474,8 +1474,8 @@
       QUIC_LOG(INFO) << "FETCH_OK parameters mismatch";
       return false;
     }
-    if (cast.extensions != fetch_ok_.extensions) {
-      QUIC_LOG(INFO) << "FETCH_OK extensions mismatch";
+    if (cast.properties != fetch_ok_.properties) {
+      QUIC_LOG(INFO) << "FETCH_OK properties mismatch";
       return false;
     }
     return true;
@@ -1501,7 +1501,7 @@
       /*end_of_track=*/false,
       /*end_location=*/Location{5, 3},
       MessageParameters(),
-      TrackExtensions(std::nullopt,
+      TrackProperties(std::nullopt,
                       quic::QuicTimeDelta::FromMilliseconds(10000),
                       std::nullopt, MoqtDeliveryOrder::kDescending,
                       std::nullopt, std::nullopt),
@@ -1535,8 +1535,8 @@
       QUIC_LOG(INFO) << "PUBLISH parameters mismatch";
       return false;
     }
-    if (cast.extensions != publish_.extensions) {
-      QUIC_LOG(INFO) << "PUBLISH extensions mismatch";
+    if (cast.properties != publish_.properties) {
+      QUIC_LOG(INFO) << "PUBLISH properties mismatch";
       return false;
     }
     return true;
@@ -1569,7 +1569,7 @@
       FullTrackName("foo", "bar"),
       /*track_alias=*/4,
       MessageParameters(),
-      TrackExtensions(std::nullopt, std::nullopt, std::nullopt,
+      TrackProperties(std::nullopt, std::nullopt, std::nullopt,
                       MoqtDeliveryOrder::kDescending, std::nullopt,
                       std::nullopt),
   };