Add MakeUnique from chromium and change StunMessage::AddAttribute to take a unique_ptr.

BUG=NONE

Review-Url: https://codereview.webrtc.org/2757893003
Cr-Commit-Position: refs/heads/master@{#17403}
diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn
index 83d9ebc..7514b07 100644
--- a/webrtc/base/BUILD.gn
+++ b/webrtc/base/BUILD.gn
@@ -138,6 +138,7 @@
     "platform_thread.cc",
     "platform_thread.h",
     "platform_thread_types.h",
+    "ptr_util.h",
     "race_checker.cc",
     "race_checker.h",
     "random.cc",
@@ -849,6 +850,7 @@
       "network_unittest.cc",
       "optionsfile_unittest.cc",
       "proxy_unittest.cc",
+      "ptr_util_unittest.cc",
       "ratelimiter_unittest.cc",
       "rollingaccumulator_unittest.cc",
       "rtccertificate_unittest.cc",
diff --git a/webrtc/base/ptr_util.h b/webrtc/base/ptr_util.h
new file mode 100644
index 0000000..43895c7
--- /dev/null
+++ b/webrtc/base/ptr_util.h
@@ -0,0 +1,82 @@
+/*
+ *  Copyright 2017 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This implementation is borrowed from chromium.
+
+#ifndef WEBRTC_BASE_PTR_UTIL_H_
+#define WEBRTC_BASE_PTR_UTIL_H_
+
+#include <memory>
+#include <utility>
+
+namespace rtc {
+
+// Helper to transfer ownership of a raw pointer to a std::unique_ptr<T>.
+// Note that std::unique_ptr<T> has very different semantics from
+// std::unique_ptr<T[]>: do not use this helper for array allocations.
+template <typename T>
+std::unique_ptr<T> WrapUnique(T* ptr) {
+  return std::unique_ptr<T>(ptr);
+}
+
+namespace internal {
+
+template <typename T>
+struct MakeUniqueResult {
+  using Scalar = std::unique_ptr<T>;
+};
+
+template <typename T>
+struct MakeUniqueResult<T[]> {
+  using Array = std::unique_ptr<T[]>;
+};
+
+template <typename T, size_t N>
+struct MakeUniqueResult<T[N]> {
+  using Invalid = void;
+};
+
+}  // namespace internal
+
+// Helper to construct an object wrapped in a std::unique_ptr. This is an
+// implementation of C++14's std::make_unique that can be used in Chrome.
+//
+// MakeUnique<T>(args) should be preferred over WrapUnique(new T(args)): bare
+// calls to `new` should be treated with scrutiny.
+//
+// Usage:
+//   // ptr is a std::unique_ptr<std::string>
+//   auto ptr = MakeUnique<std::string>("hello world!");
+//
+//   // arr is a std::unique_ptr<int[]>
+//   auto arr = MakeUnique<int[]>(5);
+
+// Overload for non-array types. Arguments are forwarded to T's constructor.
+template <typename T, typename... Args>
+typename internal::MakeUniqueResult<T>::Scalar MakeUnique(Args&&... args) {
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+// Overload for array types of unknown bound, e.g. T[]. The array is allocated
+// with `new T[n]()` and value-initialized: note that this is distinct from
+// `new T[n]`, which default-initializes.
+template <typename T>
+typename internal::MakeUniqueResult<T>::Array MakeUnique(size_t size) {
+  return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
+}
+
+// Overload to reject array types of known bound, e.g. T[n].
+template <typename T, typename... Args>
+typename internal::MakeUniqueResult<T>::Invalid MakeUnique(Args&&... args) =
+    delete;
+
+}  // namespace rtc
+
+#endif  // WEBRTC_BASE_PTR_UTIL_H_
diff --git a/webrtc/base/ptr_util_unittest.cc b/webrtc/base/ptr_util_unittest.cc
new file mode 100644
index 0000000..22669c5
--- /dev/null
+++ b/webrtc/base/ptr_util_unittest.cc
@@ -0,0 +1,69 @@
+/*
+ *  Copyright 2017 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/base/ptr_util.h"
+
+#include <stddef.h>
+#include <string>
+
+#include "webrtc/base/gunit.h"
+
+namespace rtc {
+
+namespace {
+
+class DeleteCounter {
+ public:
+  DeleteCounter() { ++count_; }
+  ~DeleteCounter() { --count_; }
+
+  static size_t count() { return count_; }
+
+ private:
+  static size_t count_;
+};
+
+size_t DeleteCounter::count_ = 0;
+
+}  // namespace
+
+TEST(PtrUtilTest, WrapUnique) {
+  EXPECT_EQ(0u, DeleteCounter::count());
+  DeleteCounter* counter = new DeleteCounter;
+  EXPECT_EQ(1u, DeleteCounter::count());
+  std::unique_ptr<DeleteCounter> owned_counter = WrapUnique(counter);
+  EXPECT_EQ(1u, DeleteCounter::count());
+  owned_counter.reset();
+  EXPECT_EQ(0u, DeleteCounter::count());
+}
+
+TEST(PtrUtilTest, MakeUniqueScalar) {
+  auto s = MakeUnique<std::string>();
+  EXPECT_EQ("", *s);
+
+  auto s2 = MakeUnique<std::string>("test");
+  EXPECT_EQ("test", *s2);
+}
+
+TEST(PtrUtilTest, MakeUniqueScalarWithMoveOnlyType) {
+  using MoveOnly = std::unique_ptr<std::string>;
+  auto p = MakeUnique<MoveOnly>(MakeUnique<std::string>("test"));
+  EXPECT_EQ("test", **p);
+}
+
+TEST(PtrUtilTest, MakeUniqueArray) {
+  EXPECT_EQ(0u, DeleteCounter::count());
+  auto a = MakeUnique<DeleteCounter[]>(5);
+  EXPECT_EQ(5u, DeleteCounter::count());
+  a.reset();
+  EXPECT_EQ(0u, DeleteCounter::count());
+}
+
+}  // namespace rtc
diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
index 9b7a92a..e9d4be6 100644
--- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
+++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
@@ -24,12 +24,13 @@
 #include "webrtc/base/natsocketfactory.h"
 #include "webrtc/base/physicalsocketserver.h"
 #include "webrtc/base/proxyserver.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/socketaddress.h"
 #include "webrtc/base/ssladapter.h"
 #include "webrtc/base/thread.h"
 #include "webrtc/base/virtualsocketserver.h"
-#include "webrtc/p2p/base/icetransportinternal.h"
 #include "webrtc/p2p/base/fakeportallocator.h"
+#include "webrtc/p2p/base/icetransportinternal.h"
 #include "webrtc/p2p/base/p2ptransportchannel.h"
 #include "webrtc/p2p/base/packettransportinternal.h"
 #include "webrtc/p2p/base/testrelayserver.h"
@@ -3043,13 +3044,14 @@
                                uint32_t nomination = 0) {
     IceMessage msg;
     msg.SetType(STUN_BINDING_REQUEST);
-    msg.AddAttribute(new StunByteStringAttribute(
+    msg.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
         STUN_ATTR_USERNAME,
         conn->local_candidate().username() + ":" + remote_ufrag));
-    msg.AddAttribute(new StunUInt32Attribute(STUN_ATTR_PRIORITY, priority));
+    msg.AddAttribute(
+        rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_PRIORITY, priority));
     if (nomination != 0) {
-      msg.AddAttribute(
-          new StunUInt32Attribute(STUN_ATTR_NOMINATION, nomination));
+      msg.AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
+          STUN_ATTR_NOMINATION, nomination));
     }
     msg.SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength));
     msg.AddMessageIntegrity(conn->local_candidate().password());
@@ -3246,11 +3248,11 @@
   // candidate pair while we still don't have remote ICE parameters.
   IceMessage request;
   request.SetType(STUN_BINDING_REQUEST);
-  request.AddAttribute(
-      new StunByteStringAttribute(STUN_ATTR_USERNAME, kIceUfrag[1]));
+  request.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
+      STUN_ATTR_USERNAME, kIceUfrag[1]));
   uint32_t prflx_priority = ICE_TYPE_PREFERENCE_PRFLX << 24;
   request.AddAttribute(
-      new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_PRIORITY, prflx_priority));
   Port* port = GetPort(&ch);
   ASSERT_NE(nullptr, port);
   port->SignalUnknownAddress(port, rtc::SocketAddress("1.1.1.1", 1), PROTO_UDP,
@@ -3415,11 +3417,11 @@
   // Create a minimal STUN message with prflx priority.
   IceMessage request;
   request.SetType(STUN_BINDING_REQUEST);
-  request.AddAttribute(
-      new StunByteStringAttribute(STUN_ATTR_USERNAME, kIceUfrag[1]));
+  request.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
+      STUN_ATTR_USERNAME, kIceUfrag[1]));
   uint32_t prflx_priority = ICE_TYPE_PREFERENCE_PRFLX << 24;
   request.AddAttribute(
-      new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_PRIORITY, prflx_priority));
   EXPECT_NE(prflx_priority, remote_priority);
 
   Port* port = GetPort(&ch);
@@ -3558,11 +3560,11 @@
   // A minimal STUN message with prflx priority.
   IceMessage request;
   request.SetType(STUN_BINDING_REQUEST);
-  request.AddAttribute(
-      new StunByteStringAttribute(STUN_ATTR_USERNAME, kIceUfrag[1]));
+  request.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
+      STUN_ATTR_USERNAME, kIceUfrag[1]));
   uint32_t prflx_priority = ICE_TYPE_PREFERENCE_PRFLX << 24;
   request.AddAttribute(
-      new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_PRIORITY, prflx_priority));
   TestUDPPort* port = static_cast<TestUDPPort*>(GetPort(&ch));
   port->SignalUnknownAddress(port, rtc::SocketAddress("1.1.1.1", 1), PROTO_UDP,
                              &request, kIceUfrag[1], false);
@@ -3600,7 +3602,8 @@
 
   // However if the request contains use_candidate attribute, it will be
   // selected as the selected connection.
-  request.AddAttribute(new StunByteStringAttribute(STUN_ATTR_USE_CANDIDATE));
+  request.AddAttribute(
+      rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_USE_CANDIDATE));
   port->SignalUnknownAddress(port, rtc::SocketAddress("4.4.4.4", 4), PROTO_UDP,
                              &request, kIceUfrag[1], false);
   Connection* conn4 = WaitForConnectionTo(&ch, "4.4.4.4", 4);
@@ -3655,12 +3658,13 @@
   // nominate the selected connection.
   IceMessage request;
   request.SetType(STUN_BINDING_REQUEST);
-  request.AddAttribute(
-      new StunByteStringAttribute(STUN_ATTR_USERNAME, kIceUfrag[1]));
+  request.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
+      STUN_ATTR_USERNAME, kIceUfrag[1]));
   uint32_t prflx_priority = ICE_TYPE_PREFERENCE_PRFLX << 24;
   request.AddAttribute(
-      new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
-  request.AddAttribute(new StunByteStringAttribute(STUN_ATTR_USE_CANDIDATE));
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_PRIORITY, prflx_priority));
+  request.AddAttribute(
+      rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_USE_CANDIDATE));
   Port* port = GetPort(&ch);
   port->SignalUnknownAddress(port, rtc::SocketAddress("3.3.3.3", 3), PROTO_UDP,
                              &request, kIceUfrag[1], false);
diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc
index 559fe72..72f92b2 100644
--- a/webrtc/p2p/base/port.cc
+++ b/webrtc/p2p/base/port.cc
@@ -13,8 +13,6 @@
 #include <algorithm>
 #include <vector>
 
-#include "webrtc/p2p/base/common.h"
-#include "webrtc/p2p/base/portallocator.h"
 #include "webrtc/base/base64.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/crc32.h"
@@ -22,8 +20,11 @@
 #include "webrtc/base/logging.h"
 #include "webrtc/base/messagedigest.h"
 #include "webrtc/base/network.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/stringencode.h"
 #include "webrtc/base/stringutils.h"
+#include "webrtc/p2p/base/common.h"
+#include "webrtc/p2p/base/portallocator.h"
 
 namespace {
 
@@ -598,7 +599,7 @@
   if (retransmit_attr) {
     // Inherit the incoming retransmit value in the response so the other side
     // can see our view of lost pings.
-    response.AddAttribute(new StunUInt32Attribute(
+    response.AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
         STUN_ATTR_RETRANSMIT_COUNT, retransmit_attr->value()));
 
     if (retransmit_attr->value() > CONNECTION_WRITE_CONNECT_FAILURES) {
@@ -608,8 +609,8 @@
     }
   }
 
-  response.AddAttribute(
-      new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, addr));
+  response.AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
+      STUN_ATTR_XOR_MAPPED_ADDRESS, addr));
   response.AddMessageIntegrity(password_);
   response.AddFingerprint();
 
@@ -651,10 +652,10 @@
 
   // When doing GICE, we need to write out the error code incorrectly to
   // maintain backwards compatiblility.
-  StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode();
+  auto error_attr = StunAttribute::CreateErrorCode();
   error_attr->SetCode(error_code);
   error_attr->SetReason(reason);
-  response.AddAttribute(error_attr);
+  response.AddAttribute(std::move(error_attr));
 
   // Per Section 10.1.2, certain error cases don't get a MESSAGE-INTEGRITY,
   // because we don't have enough information to determine the shared secret.
@@ -783,37 +784,37 @@
     connection_->port()->CreateStunUsername(
         connection_->remote_candidate().username(), &username);
     request->AddAttribute(
-        new StunByteStringAttribute(STUN_ATTR_USERNAME, username));
+        rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_USERNAME, username));
 
     // connection_ already holds this ping, so subtract one from count.
     if (connection_->port()->send_retransmit_count_attribute()) {
-      request->AddAttribute(new StunUInt32Attribute(
+      request->AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
           STUN_ATTR_RETRANSMIT_COUNT,
           static_cast<uint32_t>(connection_->pings_since_last_response_.size() -
                                 1)));
     }
     uint32_t network_info = connection_->port()->Network()->id();
     network_info = (network_info << 16) | connection_->port()->network_cost();
-    request->AddAttribute(
-        new StunUInt32Attribute(STUN_ATTR_NETWORK_INFO, network_info));
+    request->AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
+        STUN_ATTR_NETWORK_INFO, network_info));
 
     // Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role.
     if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLING) {
-      request->AddAttribute(new StunUInt64Attribute(
+      request->AddAttribute(rtc::MakeUnique<StunUInt64Attribute>(
           STUN_ATTR_ICE_CONTROLLING, connection_->port()->IceTiebreaker()));
       // We should have either USE_CANDIDATE attribute or ICE_NOMINATION
       // attribute but not both. That was enforced in p2ptransportchannel.
       if (connection_->use_candidate_attr()) {
-        request->AddAttribute(new StunByteStringAttribute(
-            STUN_ATTR_USE_CANDIDATE));
+        request->AddAttribute(
+            rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_USE_CANDIDATE));
       }
       if (connection_->nomination() &&
           connection_->nomination() != connection_->acked_nomination()) {
-        request->AddAttribute(new StunUInt32Attribute(
+        request->AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
             STUN_ATTR_NOMINATION, connection_->nomination()));
       }
     } else if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLED) {
-      request->AddAttribute(new StunUInt64Attribute(
+      request->AddAttribute(rtc::MakeUnique<StunUInt64Attribute>(
           STUN_ATTR_ICE_CONTROLLED, connection_->port()->IceTiebreaker()));
     } else {
       RTC_NOTREACHED();
@@ -832,8 +833,8 @@
     uint32_t prflx_priority =
         type_preference << 24 |
         (connection_->local_candidate().priority() & 0x00FFFFFF);
-    request->AddAttribute(
-        new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
+    request->AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
+        STUN_ATTR_PRIORITY, prflx_priority));
 
     // Adding Message Integrity attribute.
     request->AddMessageIntegrity(connection_->remote_candidate().password());
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc
index 4029118..7cb5275 100644
--- a/webrtc/p2p/base/port_unittest.cc
+++ b/webrtc/p2p/base/port_unittest.cc
@@ -10,15 +10,6 @@
 
 #include <memory>
 
-#include "webrtc/p2p/base/basicpacketsocketfactory.h"
-#include "webrtc/p2p/base/jseptransport.h"
-#include "webrtc/p2p/base/relayport.h"
-#include "webrtc/p2p/base/stunport.h"
-#include "webrtc/p2p/base/tcpport.h"
-#include "webrtc/p2p/base/testrelayserver.h"
-#include "webrtc/p2p/base/teststunserver.h"
-#include "webrtc/p2p/base/testturnserver.h"
-#include "webrtc/p2p/base/turnport.h"
 #include "webrtc/base/arraysize.h"
 #include "webrtc/base/buffer.h"
 #include "webrtc/base/crc32.h"
@@ -28,11 +19,21 @@
 #include "webrtc/base/natserver.h"
 #include "webrtc/base/natsocketfactory.h"
 #include "webrtc/base/physicalsocketserver.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/socketaddress.h"
 #include "webrtc/base/ssladapter.h"
 #include "webrtc/base/stringutils.h"
 #include "webrtc/base/thread.h"
 #include "webrtc/base/virtualsocketserver.h"
+#include "webrtc/p2p/base/basicpacketsocketfactory.h"
+#include "webrtc/p2p/base/jseptransport.h"
+#include "webrtc/p2p/base/relayport.h"
+#include "webrtc/p2p/base/stunport.h"
+#include "webrtc/p2p/base/tcpport.h"
+#include "webrtc/p2p/base/testrelayserver.h"
+#include "webrtc/p2p/base/teststunserver.h"
+#include "webrtc/p2p/base/testturnserver.h"
+#include "webrtc/p2p/base/turnport.h"
 
 using rtc::AsyncPacketSocket;
 using rtc::Buffer;
@@ -760,7 +761,7 @@
                                             const std::string& username) {
     IceMessage* msg = CreateStunMessage(type);
     msg->AddAttribute(
-        new StunByteStringAttribute(STUN_ATTR_USERNAME, username));
+        rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_USERNAME, username));
     return msg;
   }
   TestPort* CreateTestPort(const rtc::SocketAddress& addr,
@@ -1403,11 +1404,11 @@
       CreateStunMessage(STUN_BINDING_REQUEST));
   const StunByteStringAttribute* username_attr = msg->GetByteString(
       STUN_ATTR_USERNAME);
-  modified_req->AddAttribute(new StunByteStringAttribute(
+  modified_req->AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
       STUN_ATTR_USERNAME, username_attr->GetString()));
   // To make sure we receive error response, adding tiebreaker less than
   // what's present in request.
-  modified_req->AddAttribute(new StunUInt64Attribute(
+  modified_req->AddAttribute(rtc::MakeUnique<StunUInt64Attribute>(
       STUN_ATTR_ICE_CONTROLLING, kTiebreaker1 - 1));
   modified_req->AddMessageIntegrity("lpass");
   modified_req->AddFingerprint();
@@ -2060,8 +2061,8 @@
 
   // BINDING-RESPONSE without username, with MESSAGE-INTEGRITY and FINGERPRINT.
   in_msg.reset(CreateStunMessage(STUN_BINDING_RESPONSE));
-  in_msg->AddAttribute(
-      new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
+  in_msg->AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
+      STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
   in_msg->AddMessageIntegrity("rpass");
   in_msg->AddFingerprint();
   WriteStunMessage(in_msg.get(), buf.get());
@@ -2072,8 +2073,9 @@
 
   // BINDING-ERROR-RESPONSE without username, with error, M-I, and FINGERPRINT.
   in_msg.reset(CreateStunMessage(STUN_BINDING_ERROR_RESPONSE));
-  in_msg->AddAttribute(new StunErrorCodeAttribute(STUN_ATTR_ERROR_CODE,
-      STUN_ERROR_SERVER_ERROR, STUN_ERROR_REASON_SERVER_ERROR));
+  in_msg->AddAttribute(rtc::MakeUnique<StunErrorCodeAttribute>(
+      STUN_ATTR_ERROR_CODE, STUN_ERROR_SERVER_ERROR,
+      STUN_ERROR_REASON_SERVER_ERROR));
   in_msg->AddFingerprint();
   WriteStunMessage(in_msg.get(), buf.get());
   EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
@@ -2223,8 +2225,8 @@
 
   // Valid BINDING-RESPONSE, except no FINGERPRINT.
   in_msg.reset(CreateStunMessage(STUN_BINDING_RESPONSE));
-  in_msg->AddAttribute(
-      new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
+  in_msg->AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
+      STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
   in_msg->AddMessageIntegrity("rpass");
   WriteStunMessage(in_msg.get(), buf.get());
   EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
@@ -2241,8 +2243,9 @@
 
   // Valid BINDING-ERROR-RESPONSE, except no FINGERPRINT.
   in_msg.reset(CreateStunMessage(STUN_BINDING_ERROR_RESPONSE));
-  in_msg->AddAttribute(new StunErrorCodeAttribute(STUN_ATTR_ERROR_CODE,
-      STUN_ERROR_SERVER_ERROR, STUN_ERROR_REASON_SERVER_ERROR));
+  in_msg->AddAttribute(rtc::MakeUnique<StunErrorCodeAttribute>(
+      STUN_ATTR_ERROR_CODE, STUN_ERROR_SERVER_ERROR,
+      STUN_ERROR_REASON_SERVER_ERROR));
   in_msg->AddMessageIntegrity("rpass");
   WriteStunMessage(in_msg.get(), buf.get());
   EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
diff --git a/webrtc/p2p/base/relayport.cc b/webrtc/p2p/base/relayport.cc
index 2ab71dc..5eacf6d 100644
--- a/webrtc/p2p/base/relayport.cc
+++ b/webrtc/p2p/base/relayport.cc
@@ -576,36 +576,32 @@
   RelayMessage request;
   request.SetType(STUN_SEND_REQUEST);
 
-  StunByteStringAttribute* magic_cookie_attr =
+  auto magic_cookie_attr =
       StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
   magic_cookie_attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE,
                                sizeof(TURN_MAGIC_COOKIE_VALUE));
-  request.AddAttribute(magic_cookie_attr);
+  request.AddAttribute(std::move(magic_cookie_attr));
 
-  StunByteStringAttribute* username_attr =
-      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  auto username_attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
   username_attr->CopyBytes(port_->username_fragment().c_str(),
                            port_->username_fragment().size());
-  request.AddAttribute(username_attr);
+  request.AddAttribute(std::move(username_attr));
 
-  StunAddressAttribute* addr_attr =
-      StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
+  auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
   addr_attr->SetIP(addr.ipaddr());
   addr_attr->SetPort(addr.port());
-  request.AddAttribute(addr_attr);
+  request.AddAttribute(std::move(addr_attr));
 
   // Attempt to lock
   if (ext_addr_ == addr) {
-    StunUInt32Attribute* options_attr =
-      StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS);
+    auto options_attr = StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS);
     options_attr->SetValue(0x1);
-    request.AddAttribute(options_attr);
+    request.AddAttribute(std::move(options_attr));
   }
 
-  StunByteStringAttribute* data_attr =
-      StunAttribute::CreateByteString(STUN_ATTR_DATA);
+  auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA);
   data_attr->CopyBytes(data, size);
-  request.AddAttribute(data_attr);
+  request.AddAttribute(std::move(data_attr));
 
   // TODO: compute the HMAC.
 
@@ -787,12 +783,11 @@
 void AllocateRequest::Prepare(StunMessage* request) {
   request->SetType(STUN_ALLOCATE_REQUEST);
 
-  StunByteStringAttribute* username_attr =
-      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  auto username_attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
   username_attr->CopyBytes(
       entry_->port()->username_fragment().c_str(),
       entry_->port()->username_fragment().size());
-  request->AddAttribute(username_attr);
+  request->AddAttribute(std::move(username_attr));
 }
 
 void AllocateRequest::OnSent() {
diff --git a/webrtc/p2p/base/relayserver.cc b/webrtc/p2p/base/relayserver.cc
index 442f343..d080d90 100644
--- a/webrtc/p2p/base/relayserver.cc
+++ b/webrtc/p2p/base/relayserver.cc
@@ -60,7 +60,7 @@
   err_msg.SetType(GetStunErrorResponseType(msg.type()));
   err_msg.SetTransactionID(msg.transaction_id());
 
-  StunByteStringAttribute* magic_cookie_attr =
+  auto magic_cookie_attr =
       StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
   if (magic_cookie.size() == 0) {
     magic_cookie_attr->CopyBytes(cricket::TURN_MAGIC_COOKIE_VALUE,
@@ -68,13 +68,13 @@
   } else {
     magic_cookie_attr->CopyBytes(magic_cookie.c_str(), magic_cookie.size());
   }
-  err_msg.AddAttribute(magic_cookie_attr);
+  err_msg.AddAttribute(std::move(magic_cookie_attr));
 
-  StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode();
+  auto err_code = StunAttribute::CreateErrorCode();
   err_code->SetClass(error_code / 100);
   err_code->SetNumber(error_code % 100);
   err_code->SetReason(error_desc);
-  err_msg.AddAttribute(err_code);
+  err_msg.AddAttribute(std::move(err_code));
 
   SendStun(err_msg, socket, remote_addr);
 }
@@ -421,26 +421,24 @@
   response.SetType(STUN_ALLOCATE_RESPONSE);
   response.SetTransactionID(request.transaction_id());
 
-  StunByteStringAttribute* magic_cookie_attr =
+  auto magic_cookie_attr =
       StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
   magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
                                int_conn->binding()->magic_cookie().size());
-  response.AddAttribute(magic_cookie_attr);
+  response.AddAttribute(std::move(magic_cookie_attr));
 
   size_t index = rand() % external_sockets_.size();
   rtc::SocketAddress ext_addr =
       external_sockets_[index]->GetLocalAddress();
 
-  StunAddressAttribute* addr_attr =
-      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   addr_attr->SetIP(ext_addr.ipaddr());
   addr_attr->SetPort(ext_addr.port());
-  response.AddAttribute(addr_attr);
+  response.AddAttribute(std::move(addr_attr));
 
-  StunUInt32Attribute* res_lifetime_attr =
-      StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
+  auto res_lifetime_attr = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
   res_lifetime_attr->SetValue(int_conn->binding()->lifetime() / 1000);
-  response.AddAttribute(res_lifetime_attr);
+  response.AddAttribute(std::move(res_lifetime_attr));
 
   // TODO: Support transport-prefs (preallocate RTCP port).
   // TODO: Support bandwidth restrictions.
@@ -494,16 +492,16 @@
     response.SetType(STUN_SEND_RESPONSE);
     response.SetTransactionID(request.transaction_id());
 
-    StunByteStringAttribute* magic_cookie_attr =
+    auto magic_cookie_attr =
         StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
     magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
                                  int_conn->binding()->magic_cookie().size());
-    response.AddAttribute(magic_cookie_attr);
+    response.AddAttribute(std::move(magic_cookie_attr));
 
-    StunUInt32Attribute* options2_attr =
-      StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS);
+    auto options2_attr =
+        StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS);
     options2_attr->SetValue(0x01);
-    response.AddAttribute(options2_attr);
+    response.AddAttribute(std::move(options2_attr));
 
     int_conn->SendStun(response);
   }
@@ -603,23 +601,21 @@
   RelayMessage msg;
   msg.SetType(STUN_DATA_INDICATION);
 
-  StunByteStringAttribute* magic_cookie_attr =
+  auto magic_cookie_attr =
       StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
   magic_cookie_attr->CopyBytes(binding_->magic_cookie().c_str(),
                                binding_->magic_cookie().size());
-  msg.AddAttribute(magic_cookie_attr);
+  msg.AddAttribute(std::move(magic_cookie_attr));
 
-  StunAddressAttribute* addr_attr =
-      StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
+  auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
   addr_attr->SetIP(from_addr.ipaddr());
   addr_attr->SetPort(from_addr.port());
-  msg.AddAttribute(addr_attr);
+  msg.AddAttribute(std::move(addr_attr));
 
-  StunByteStringAttribute* data_attr =
-      StunAttribute::CreateByteString(STUN_ATTR_DATA);
+  auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA);
   RTC_DCHECK(size <= 65536);
   data_attr->CopyBytes(data, uint16_t(size));
-  msg.AddAttribute(data_attr);
+  msg.AddAttribute(std::move(data_attr));
 
   SendStun(msg);
 }
diff --git a/webrtc/p2p/base/relayserver_unittest.cc b/webrtc/p2p/base/relayserver_unittest.cc
index 1d07a07..0c98286 100644
--- a/webrtc/p2p/base/relayserver_unittest.cc
+++ b/webrtc/p2p/base/relayserver_unittest.cc
@@ -146,29 +146,25 @@
     return msg;
   }
   static void AddMagicCookieAttr(StunMessage* msg) {
-    StunByteStringAttribute* attr =
-        StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
+    auto attr = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
     attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE, sizeof(TURN_MAGIC_COOKIE_VALUE));
-    msg->AddAttribute(attr);
+    msg->AddAttribute(std::move(attr));
   }
   static void AddUsernameAttr(StunMessage* msg, const std::string& val) {
-    StunByteStringAttribute* attr =
-        StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+    auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
     attr->CopyBytes(val.c_str(), val.size());
-    msg->AddAttribute(attr);
+    msg->AddAttribute(std::move(attr));
   }
   static void AddLifetimeAttr(StunMessage* msg, int val) {
-    StunUInt32Attribute* attr =
-        StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
+    auto attr = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
     attr->SetValue(val);
-    msg->AddAttribute(attr);
+    msg->AddAttribute(std::move(attr));
   }
   static void AddDestinationAttr(StunMessage* msg, const SocketAddress& addr) {
-    StunAddressAttribute* attr =
-        StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
+    auto attr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
     attr->SetIP(addr.ipaddr());
     attr->SetPort(addr.port());
-    msg->AddAttribute(attr);
+    msg->AddAttribute(std::move(attr));
   }
 
   std::unique_ptr<rtc::PhysicalSocketServer> pss_;
@@ -458,10 +454,9 @@
     AddUsernameAttr(req.get(), username_);
     AddDestinationAttr(req.get(), client2_addr);
 
-    StunByteStringAttribute* send_data =
-        StunAttribute::CreateByteString(STUN_ATTR_DATA);
+    auto send_data = StunAttribute::CreateByteString(STUN_ATTR_DATA);
     send_data->CopyBytes(msg1);
-    req->AddAttribute(send_data);
+    req->AddAttribute(std::move(send_data));
 
     Send1(req.get());
     EXPECT_EQ(msg1, ReceiveRaw2());
@@ -500,10 +495,9 @@
   AddUsernameAttr(req.get(), username_);
   AddDestinationAttr(req.get(), client2_addr);
 
-  StunByteStringAttribute* data_attr =
-      StunAttribute::CreateByteString(STUN_ATTR_DATA);
+  auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA);
   data_attr->CopyBytes(msg1);
-  req->AddAttribute(data_attr);
+  req->AddAttribute(std::move(data_attr));
 
   Send1(req.get());
   res.reset(Receive1());
diff --git a/webrtc/p2p/base/stun.cc b/webrtc/p2p/base/stun.cc
index af870d1..4d6b21b 100644
--- a/webrtc/p2p/base/stun.cc
+++ b/webrtc/p2p/base/stun.cc
@@ -19,6 +19,7 @@
 #include "webrtc/base/crc32.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/messagedigest.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/stringencode.h"
 
 using rtc::ByteBufferReader;
@@ -66,17 +67,18 @@
   return true;
 }
 
-void StunMessage::AddAttribute(StunAttribute* attr) {
+void StunMessage::AddAttribute(std::unique_ptr<StunAttribute> attr) {
   // Fail any attributes that aren't valid for this type of message.
   RTC_DCHECK_EQ(attr->value_type(), GetAttributeValueType(attr->type()));
 
-  attrs_.emplace_back(attr);
   attr->SetOwner(this);
   size_t attr_length = attr->length();
   if (attr_length % 4 != 0) {
     attr_length += (4 - (attr_length % 4));
   }
   length_ += static_cast<uint16_t>(attr_length + 4);
+
+  attrs_.push_back(std::move(attr));
 }
 
 const StunAddressAttribute* StunMessage::GetAddress(int type) const {
@@ -207,10 +209,10 @@
                                       size_t keylen) {
   // Add the attribute with a dummy value. Since this is a known attribute, it
   // can't fail.
-  StunByteStringAttribute* msg_integrity_attr =
-      new StunByteStringAttribute(STUN_ATTR_MESSAGE_INTEGRITY,
-          std::string(kStunMessageIntegritySize, '0'));
-  AddAttribute(msg_integrity_attr);
+  auto msg_integrity_attr_ptr = rtc::MakeUnique<StunByteStringAttribute>(
+      STUN_ATTR_MESSAGE_INTEGRITY, std::string(kStunMessageIntegritySize, '0'));
+  auto* msg_integrity_attr = msg_integrity_attr_ptr.get();
+  AddAttribute(std::move(msg_integrity_attr_ptr));
 
   // Calculate the HMAC for the message.
   ByteBufferWriter buf;
@@ -269,9 +271,10 @@
 bool StunMessage::AddFingerprint() {
   // Add the attribute with a dummy value. Since this is a known attribute,
   // it can't fail.
-  StunUInt32Attribute* fingerprint_attr =
-     new StunUInt32Attribute(STUN_ATTR_FINGERPRINT, 0);
-  AddAttribute(fingerprint_attr);
+  auto fingerprint_attr_ptr =
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_FINGERPRINT, 0);
+  auto fingerprint_attr = fingerprint_attr_ptr.get();
+  AddAttribute(std::move(fingerprint_attr_ptr));
 
   // Calculate the CRC-32 for the message and insert it.
   ByteBufferWriter buf;
@@ -453,33 +456,40 @@
   }
 }
 
-StunAddressAttribute* StunAttribute::CreateAddress(uint16_t type) {
-  return new StunAddressAttribute(type, 0);
+std::unique_ptr<StunAddressAttribute> StunAttribute::CreateAddress(
+    uint16_t type) {
+  return rtc::MakeUnique<StunAddressAttribute>(type, 0);
 }
 
-StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16_t type) {
-  return new StunXorAddressAttribute(type, 0, NULL);
+std::unique_ptr<StunXorAddressAttribute> StunAttribute::CreateXorAddress(
+    uint16_t type) {
+  return rtc::MakeUnique<StunXorAddressAttribute>(type, 0, nullptr);
 }
 
-StunUInt64Attribute* StunAttribute::CreateUInt64(uint16_t type) {
-  return new StunUInt64Attribute(type);
+std::unique_ptr<StunUInt64Attribute> StunAttribute::CreateUInt64(
+    uint16_t type) {
+  return rtc::MakeUnique<StunUInt64Attribute>(type);
 }
 
-StunUInt32Attribute* StunAttribute::CreateUInt32(uint16_t type) {
-  return new StunUInt32Attribute(type);
+std::unique_ptr<StunUInt32Attribute> StunAttribute::CreateUInt32(
+    uint16_t type) {
+  return rtc::MakeUnique<StunUInt32Attribute>(type);
 }
 
-StunByteStringAttribute* StunAttribute::CreateByteString(uint16_t type) {
-  return new StunByteStringAttribute(type, 0);
+std::unique_ptr<StunByteStringAttribute> StunAttribute::CreateByteString(
+    uint16_t type) {
+  return rtc::MakeUnique<StunByteStringAttribute>(type, 0);
 }
 
-StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
-  return new StunErrorCodeAttribute(
+std::unique_ptr<StunErrorCodeAttribute> StunAttribute::CreateErrorCode() {
+  return rtc::MakeUnique<StunErrorCodeAttribute>(
       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
 }
 
-StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
-  return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
+std::unique_ptr<StunUInt16ListAttribute>
+StunAttribute::CreateUnknownAttributes() {
+  return rtc::MakeUnique<StunUInt16ListAttribute>(STUN_ATTR_UNKNOWN_ATTRIBUTES,
+                                                  0);
 }
 
 StunAddressAttribute::StunAddressAttribute(uint16_t type,
@@ -756,6 +766,8 @@
   SetLength(static_cast<uint16_t>(length));
 }
 
+const uint16_t StunErrorCodeAttribute::MIN_SIZE = 4;
+
 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type,
                                                int code,
                                                const std::string& reason)
diff --git a/webrtc/p2p/base/stun.h b/webrtc/p2p/base/stun.h
index 532fe5b..ab20068 100644
--- a/webrtc/p2p/base/stun.h
+++ b/webrtc/p2p/base/stun.h
@@ -159,8 +159,7 @@
   const StunUInt16ListAttribute* GetUnknownAttributes() const;
 
   // Takes ownership of the specified attribute and adds it to the message.
-  // TODO(zstein): Take a unique_ptr instead of a raw pointer.
-  void AddAttribute(StunAttribute* attr);
+  void AddAttribute(std::unique_ptr<StunAttribute> attr);
 
   // Validates that a raw STUN message has a correct MESSAGE-INTEGRITY value.
   // This can't currently be done on a StunMessage, since it is affected by
@@ -233,13 +232,15 @@
                                StunMessage* owner);
   // TODO: Allow these create functions to take parameters, to reduce
   // the amount of work callers need to do to initialize attributes.
-  static StunAddressAttribute* CreateAddress(uint16_t type);
-  static StunXorAddressAttribute* CreateXorAddress(uint16_t type);
-  static StunUInt32Attribute* CreateUInt32(uint16_t type);
-  static StunUInt64Attribute* CreateUInt64(uint16_t type);
-  static StunByteStringAttribute* CreateByteString(uint16_t type);
-  static StunErrorCodeAttribute* CreateErrorCode();
-  static StunUInt16ListAttribute* CreateUnknownAttributes();
+  static std::unique_ptr<StunAddressAttribute> CreateAddress(uint16_t type);
+  static std::unique_ptr<StunXorAddressAttribute> CreateXorAddress(
+      uint16_t type);
+  static std::unique_ptr<StunUInt32Attribute> CreateUInt32(uint16_t type);
+  static std::unique_ptr<StunUInt64Attribute> CreateUInt64(uint16_t type);
+  static std::unique_ptr<StunByteStringAttribute> CreateByteString(
+      uint16_t type);
+  static std::unique_ptr<StunErrorCodeAttribute> CreateErrorCode();
+  static std::unique_ptr<StunUInt16ListAttribute> CreateUnknownAttributes();
 
  protected:
   StunAttribute(uint16_t type, uint16_t length);
@@ -412,7 +413,7 @@
 // Implements STUN attributes that record an error code.
 class StunErrorCodeAttribute : public StunAttribute {
  public:
-  static const uint16_t MIN_SIZE = 4;
+  static const uint16_t MIN_SIZE;
   StunErrorCodeAttribute(uint16_t type, int code, const std::string& reason);
   StunErrorCodeAttribute(uint16_t type, uint16_t length);
   ~StunErrorCodeAttribute();
diff --git a/webrtc/p2p/base/stun_unittest.cc b/webrtc/p2p/base/stun_unittest.cc
index f12fa82..efc11b2 100644
--- a/webrtc/p2p/base/stun_unittest.cc
+++ b/webrtc/p2p/base/stun_unittest.cc
@@ -10,13 +10,14 @@
 
 #include <string>
 
-#include "webrtc/p2p/base/stun.h"
 #include "webrtc/base/arraysize.h"
 #include "webrtc/base/bytebuffer.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/messagedigest.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/socketaddress.h"
+#include "webrtc/p2p/base/stun.h"
 
 namespace cricket {
 
@@ -822,14 +823,12 @@
 TEST_F(StunTest, CreateIPv6AddressAttribute) {
   rtc::IPAddress test_ip(kIPv6TestAddress2);
 
-  StunAddressAttribute* addr =
-      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
   addr->SetAddress(test_addr);
 
-  CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
-                            kTestMessagePort2, test_ip);
-  delete addr;
+  CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
+                            test_ip);
 }
 
 TEST_F(StunTest, CreateIPv4AddressAttribute) {
@@ -837,36 +836,29 @@
   test_in_addr.s_addr = 0xBEB0B0BE;
   rtc::IPAddress test_ip(test_in_addr);
 
-  StunAddressAttribute* addr =
-      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
   addr->SetAddress(test_addr);
 
-  CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
-                            kTestMessagePort2, test_ip);
-  delete addr;
+  CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
+                            test_ip);
 }
 
 // Test that we don't care what order we set the parts of an address
 TEST_F(StunTest, CreateAddressInArbitraryOrder) {
-  StunAddressAttribute* addr =
-  StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
+  auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
   // Port first
   addr->SetPort(kTestMessagePort1);
   addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
   ASSERT_EQ(kTestMessagePort1, addr->port());
   ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
 
-  StunAddressAttribute* addr2 =
-  StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
+  auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
   // IP first
   addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
   addr2->SetPort(kTestMessagePort2);
   ASSERT_EQ(kTestMessagePort2, addr2->port());
   ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
-
-  delete addr;
-  delete addr2;
 }
 
 TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
@@ -881,11 +873,10 @@
                   kStunTransactionIdLength));
   CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
 
-  StunAddressAttribute* addr =
-      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
   addr->SetAddress(test_addr);
-  msg.AddAttribute(addr);
+  msg.AddAttribute(std::move(addr));
 
   CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
 
@@ -911,11 +902,10 @@
                   kStunTransactionIdLength));
   CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
 
-  StunAddressAttribute* addr =
-      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
   addr->SetAddress(test_addr);
-  msg.AddAttribute(addr);
+  msg.AddAttribute(std::move(addr));
 
   CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
 
@@ -941,11 +931,10 @@
                   kStunTransactionIdLength));
   CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
 
-  StunAddressAttribute* addr =
-      StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
+  auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
   rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
   addr->SetAddress(test_addr);
-  msg.AddAttribute(addr);
+  msg.AddAttribute(std::move(addr));
 
   CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
 
@@ -972,11 +961,10 @@
                   kStunTransactionIdLength));
   CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
 
-  StunAddressAttribute* addr =
-      StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
+  auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
   rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
   addr->SetAddress(test_addr);
-  msg.AddAttribute(addr);
+  msg.AddAttribute(std::move(addr));
 
   CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
 
@@ -1073,10 +1061,10 @@
       std::string(reinterpret_cast<const char*>(kTestTransactionId1),
                   kStunTransactionIdLength));
   CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
-  StunErrorCodeAttribute* errorcode = StunAttribute::CreateErrorCode();
+  auto errorcode = StunAttribute::CreateErrorCode();
   errorcode->SetCode(kTestErrorCode);
   errorcode->SetReason(kTestErrorReason);
-  msg.AddAttribute(errorcode);
+  msg.AddAttribute(std::move(errorcode));
   CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
 
   rtc::ByteBufferWriter out;
@@ -1095,11 +1083,11 @@
       std::string(reinterpret_cast<const char*>(kTestTransactionId2),
                   kStunTransactionIdLength));
   CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
-  StunUInt16ListAttribute* list = StunAttribute::CreateUnknownAttributes();
+  auto list = StunAttribute::CreateUnknownAttributes();
   list->AddType(0x1U);
   list->AddType(0x1000U);
   list->AddType(0xAB0CU);
-  msg.AddAttribute(list);
+  msg.AddAttribute(std::move(list));
   CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
 
   rtc::ByteBufferWriter out;
@@ -1118,9 +1106,9 @@
   msg.SetTransactionID(
       std::string(reinterpret_cast<const char*>(kTestTransactionId1),
                   kStunTransactionIdLength));
-  StunByteStringAttribute* origin =
-      new StunByteStringAttribute(STUN_ATTR_ORIGIN, kTestOrigin);
-  msg.AddAttribute(origin);
+  auto origin =
+      rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, kTestOrigin);
+  msg.AddAttribute(std::move(origin));
 
   rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
@@ -1389,29 +1377,27 @@
   EXPECT_EQ(13, addr->port());
   EXPECT_EQ(legacy_ip, addr->ipaddr());
 
-  StunAddressAttribute* addr2 =
-      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   addr2->SetPort(13);
   addr2->SetIP(legacy_ip);
-  msg2.AddAttribute(addr2);
+  msg2.AddAttribute(std::move(addr2));
 
   const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
   ASSERT_TRUE(bytes != NULL);
   EXPECT_EQ(12U, bytes->length());
   EXPECT_EQ("abcdefghijkl", bytes->GetString());
 
-  StunByteStringAttribute* bytes2 =
-  StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
   bytes2->CopyBytes("abcdefghijkl");
-  msg2.AddAttribute(bytes2);
+  msg2.AddAttribute(std::move(bytes2));
 
   const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
   ASSERT_TRUE(uval != NULL);
   EXPECT_EQ(11U, uval->value());
 
-  StunUInt32Attribute* uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
+  auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
   uval2->SetValue(11);
-  msg2.AddAttribute(uval2);
+  msg2.AddAttribute(std::move(uval2));
 
   bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
   ASSERT_TRUE(bytes != NULL);
@@ -1424,7 +1410,7 @@
   bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
   bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
                     sizeof(TURN_MAGIC_COOKIE_VALUE));
-  msg2.AddAttribute(bytes2);
+  msg2.AddAttribute(std::move(bytes2));
 
   uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
   ASSERT_TRUE(uval != NULL);
@@ -1432,7 +1418,7 @@
 
   uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
   uval2->SetValue(6);
-  msg2.AddAttribute(uval2);
+  msg2.AddAttribute(std::move(uval2));
 
   addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
   ASSERT_TRUE(addr != NULL);
@@ -1443,7 +1429,7 @@
   addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
   addr2->SetPort(13);
   addr2->SetIP(legacy_ip);
-  msg2.AddAttribute(addr2);
+  msg2.AddAttribute(std::move(addr2));
 
   addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
   ASSERT_TRUE(addr != NULL);
@@ -1454,7 +1440,7 @@
   addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
   addr2->SetPort(13);
   addr2->SetIP(legacy_ip);
-  msg2.AddAttribute(addr2);
+  msg2.AddAttribute(std::move(addr2));
 
   bytes = msg.GetByteString(STUN_ATTR_DATA);
   ASSERT_TRUE(bytes != NULL);
@@ -1463,7 +1449,7 @@
 
   bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
   bytes2->CopyBytes("abcdefg");
-  msg2.AddAttribute(bytes2);
+  msg2.AddAttribute(std::move(bytes2));
 
   rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
diff --git a/webrtc/p2p/base/stunrequest.cc b/webrtc/p2p/base/stunrequest.cc
index ef2bee8..d3336fa 100644
--- a/webrtc/p2p/base/stunrequest.cc
+++ b/webrtc/p2p/base/stunrequest.cc
@@ -16,6 +16,7 @@
 #include "webrtc/base/checks.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/logging.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/stringencode.h"
 
 namespace cricket {
@@ -189,8 +190,8 @@
 void StunRequest::Construct() {
   if (msg_->type() == 0) {
     if (!origin_.empty()) {
-      msg_->AddAttribute(new StunByteStringAttribute(STUN_ATTR_ORIGIN,
-          origin_));
+      msg_->AddAttribute(
+          rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, origin_));
     }
     Prepare(msg_);
     RTC_DCHECK(msg_->type() != 0);
diff --git a/webrtc/p2p/base/stunserver.cc b/webrtc/p2p/base/stunserver.cc
index bac9fd5..532add7 100644
--- a/webrtc/p2p/base/stunserver.cc
+++ b/webrtc/p2p/base/stunserver.cc
@@ -62,10 +62,10 @@
   err_msg.SetType(GetStunErrorResponseType(msg.type()));
   err_msg.SetTransactionID(msg.transaction_id());
 
-  StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode();
+  auto err_code = StunAttribute::CreateErrorCode();
   err_code->SetCode(error_code);
   err_code->SetReason(error_desc);
-  err_msg.AddAttribute(err_code);
+  err_msg.AddAttribute(std::move(err_code));
 
   SendResponse(err_msg, addr);
 }
@@ -86,14 +86,14 @@
   response->SetTransactionID(request->transaction_id());
 
   // Tell the user the address that we received their request from.
-  StunAddressAttribute* mapped_addr;
+  std::unique_ptr<StunAddressAttribute> mapped_addr;
   if (!request->IsLegacy()) {
     mapped_addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
   } else {
     mapped_addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
   }
   mapped_addr->SetAddress(remote_addr);
-  response->AddAttribute(mapped_addr);
+  response->AddAttribute(std::move(mapped_addr));
 }
 
 }  // namespace cricket
diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc
index 62b7450..9015169 100644
--- a/webrtc/p2p/base/turnport.cc
+++ b/webrtc/p2p/base/turnport.cc
@@ -12,15 +12,16 @@
 
 #include <functional>
 
-#include "webrtc/p2p/base/common.h"
-#include "webrtc/p2p/base/stun.h"
 #include "webrtc/base/asyncpacketsocket.h"
 #include "webrtc/base/byteorder.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/nethelpers.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/socketaddress.h"
 #include "webrtc/base/stringencode.h"
+#include "webrtc/p2p/base/common.h"
+#include "webrtc/p2p/base/stun.h"
 
 namespace cricket {
 
@@ -928,12 +929,12 @@
 void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
   // If we've gotten the necessary data from the server, add it to our request.
   RTC_DCHECK(!hash_.empty());
-  msg->AddAttribute(new StunByteStringAttribute(
+  msg->AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
       STUN_ATTR_USERNAME, credentials_.username));
-  msg->AddAttribute(new StunByteStringAttribute(
-      STUN_ATTR_REALM, realm_));
-  msg->AddAttribute(new StunByteStringAttribute(
-      STUN_ATTR_NONCE, nonce_));
+  msg->AddAttribute(
+      rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
+  msg->AddAttribute(
+      rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_NONCE, nonce_));
   const bool success = msg->AddMessageIntegrity(hash());
   RTC_DCHECK(success);
 }
@@ -1109,10 +1110,10 @@
 void TurnAllocateRequest::Prepare(StunMessage* request) {
   // Create the request as indicated in RFC 5766, Section 6.1.
   request->SetType(TURN_ALLOCATE_REQUEST);
-  StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
-      STUN_ATTR_REQUESTED_TRANSPORT);
+  auto transport_attr =
+      StunAttribute::CreateUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
   transport_attr->SetValue(IPPROTO_UDP << 24);
-  request->AddAttribute(transport_attr);
+  request->AddAttribute(std::move(transport_attr));
   if (!port_->hash().empty()) {
     port_->AddRequestAuthInfo(request);
   }
@@ -1286,8 +1287,8 @@
   // No attributes need to be included.
   request->SetType(TURN_REFRESH_REQUEST);
   if (lifetime_ > -1) {
-    request->AddAttribute(new StunUInt32Attribute(
-        STUN_ATTR_LIFETIME, lifetime_));
+    request->AddAttribute(
+        rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_));
   }
 
   port_->AddRequestAuthInfo(request);
@@ -1356,7 +1357,7 @@
 void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
   // Create the request as indicated in RFC5766, Section 9.1.
   request->SetType(TURN_CREATE_PERMISSION_REQUEST);
-  request->AddAttribute(new StunXorAddressAttribute(
+  request->AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
       STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
   port_->AddRequestAuthInfo(request);
 }
@@ -1417,9 +1418,9 @@
 void TurnChannelBindRequest::Prepare(StunMessage* request) {
   // Create the request as indicated in RFC5766, Section 11.1.
   request->SetType(TURN_CHANNEL_BIND_REQUEST);
-  request->AddAttribute(new StunUInt32Attribute(
+  request->AddAttribute(rtc::MakeUnique<StunUInt32Attribute>(
       STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16));
-  request->AddAttribute(new StunXorAddressAttribute(
+  request->AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
       STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
   port_->AddRequestAuthInfo(request);
 }
@@ -1501,10 +1502,10 @@
     msg.SetType(TURN_SEND_INDICATION);
     msg.SetTransactionID(
         rtc::CreateRandomString(kStunTransactionIdLength));
-    msg.AddAttribute(new StunXorAddressAttribute(
+    msg.AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
         STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
-    msg.AddAttribute(new StunByteStringAttribute(
-        STUN_ATTR_DATA, data, size));
+    msg.AddAttribute(
+        rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
     const bool success = msg.Write(&buf);
     RTC_DCHECK(success);
 
diff --git a/webrtc/p2p/base/turnserver.cc b/webrtc/p2p/base/turnserver.cc
index 26d306d..368bea1 100644
--- a/webrtc/p2p/base/turnserver.cc
+++ b/webrtc/p2p/base/turnserver.cc
@@ -12,19 +12,20 @@
 
 #include <tuple>  // for std::tie
 
-#include "webrtc/p2p/base/asyncstuntcpsocket.h"
-#include "webrtc/p2p/base/common.h"
-#include "webrtc/p2p/base/packetsocketfactory.h"
-#include "webrtc/p2p/base/stun.h"
 #include "webrtc/base/bind.h"
 #include "webrtc/base/bytebuffer.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/messagedigest.h"
+#include "webrtc/base/ptr_util.h"
 #include "webrtc/base/socketadapters.h"
 #include "webrtc/base/stringencode.h"
 #include "webrtc/base/thread.h"
+#include "webrtc/p2p/base/asyncstuntcpsocket.h"
+#include "webrtc/p2p/base/common.h"
+#include "webrtc/p2p/base/packetsocketfactory.h"
+#include "webrtc/p2p/base/stun.h"
 
 namespace cricket {
 
@@ -113,7 +114,7 @@
     return false;
   resp->SetType(resp_type);
   resp->SetTransactionID(req->transaction_id());
-  resp->AddAttribute(new cricket::StunErrorCodeAttribute(
+  resp->AddAttribute(rtc::MakeUnique<cricket::StunErrorCodeAttribute>(
       STUN_ATTR_ERROR_CODE, code, reason));
   return true;
 }
@@ -353,10 +354,9 @@
   InitResponse(req, &response);
 
   // Tell the user the address that we received their request from.
-  StunAddressAttribute* mapped_addr_attr;
-  mapped_addr_attr = new StunXorAddressAttribute(
+  auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
       STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
-  response.AddAttribute(mapped_addr_attr);
+  response.AddAttribute(std::move(mapped_addr_attr));
 
   SendStun(conn, &response);
 }
@@ -470,10 +470,10 @@
     timestamp = ts_for_next_nonce_;
     ts_for_next_nonce_ = 0;
   }
+  resp.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
+      STUN_ATTR_NONCE, GenerateNonce(timestamp)));
   resp.AddAttribute(
-      new StunByteStringAttribute(STUN_ATTR_NONCE, GenerateNonce(timestamp)));
-  resp.AddAttribute(new StunByteStringAttribute(
-      STUN_ATTR_REALM, realm_));
+      rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
   SendStun(conn, &resp);
 }
 
@@ -483,8 +483,8 @@
   TurnMessage resp;
   InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
                     STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
-  resp.AddAttribute(new StunAddressAttribute(
-      STUN_ATTR_ALTERNATE_SERVER, addr));
+  resp.AddAttribute(
+      rtc::MakeUnique<StunAddressAttribute>(STUN_ATTR_ALTERNATE_SERVER, addr));
   SendStun(conn, &resp);
 }
 
@@ -492,8 +492,8 @@
   rtc::ByteBufferWriter buf;
   // Add a SOFTWARE attribute if one is set.
   if (!software_.empty()) {
-    msg->AddAttribute(
-        new StunByteStringAttribute(STUN_ATTR_SOFTWARE, software_));
+    msg->AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
+        STUN_ATTR_SOFTWARE, software_));
   }
   msg->Write(&buf);
   Send(conn, buf);
@@ -651,16 +651,15 @@
   TurnMessage response;
   InitResponse(msg, &response);
 
-  StunAddressAttribute* mapped_addr_attr =
-      new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
-  StunAddressAttribute* relayed_addr_attr =
-      new StunXorAddressAttribute(STUN_ATTR_XOR_RELAYED_ADDRESS,
-          external_socket_->GetLocalAddress());
-  StunUInt32Attribute* lifetime_attr =
-      new StunUInt32Attribute(STUN_ATTR_LIFETIME, lifetime_secs);
-  response.AddAttribute(mapped_addr_attr);
-  response.AddAttribute(relayed_addr_attr);
-  response.AddAttribute(lifetime_attr);
+  auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
+      STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
+  auto relayed_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
+      STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress());
+  auto lifetime_attr =
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
+  response.AddAttribute(std::move(mapped_addr_attr));
+  response.AddAttribute(std::move(relayed_addr_attr));
+  response.AddAttribute(std::move(lifetime_attr));
 
   SendResponse(&response);
 }
@@ -680,9 +679,9 @@
   TurnMessage response;
   InitResponse(msg, &response);
 
-  StunUInt32Attribute* lifetime_attr =
-      new StunUInt32Attribute(STUN_ATTR_LIFETIME, lifetime_secs);
-  response.AddAttribute(lifetime_attr);
+  auto lifetime_attr =
+      rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
+  response.AddAttribute(std::move(lifetime_attr));
 
   SendResponse(&response);
 }
@@ -819,10 +818,10 @@
     msg.SetType(TURN_DATA_INDICATION);
     msg.SetTransactionID(
         rtc::CreateRandomString(kStunTransactionIdLength));
-    msg.AddAttribute(new StunXorAddressAttribute(
+    msg.AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
         STUN_ATTR_XOR_PEER_ADDRESS, addr));
-    msg.AddAttribute(new StunByteStringAttribute(
-        STUN_ATTR_DATA, data, size));
+    msg.AddAttribute(
+        rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
     server_->SendStun(&conn_, &msg);
   } else {
     LOG_J(LS_WARNING, this) << "Received external packet without permission, "