Use std::unique_ptr<base::Value> in V8ValueConverter.

More ownership with less comments!

BUG=581865

Review-Url: https://codereview.chromium.org/2014323002
Cr-Commit-Position: refs/heads/master@{#396504}
diff --git a/android_webview/renderer/aw_message_port_client.cc b/android_webview/renderer/aw_message_port_client.cc
index 62def3d5..52e6ee7 100644
--- a/android_webview/renderer/aw_message_port_client.cc
+++ b/android_webview/renderer/aw_message_port_client.cc
@@ -4,6 +4,9 @@
 
 #include "android_webview/renderer/aw_message_port_client.h"
 
+#include <memory>
+#include <utility>
+
 #include "android_webview/common/aw_message_port_messages.h"
 #include "content/public/child/v8_value_converter.h"
 #include "content/public/renderer/render_frame.h"
@@ -62,9 +65,9 @@
   converter->SetDateAllowed(true);
   converter->SetRegExpAllowed(true);
   base::ListValue result;
-  base::Value* value = converter->FromV8Value(v8value, context);
+  std::unique_ptr<base::Value> value = converter->FromV8Value(v8value, context);
   if (value) {
-    result.Append(value);
+    result.Append(std::move(value));
   }
 
   Send(new AwMessagePortHostMsg_ConvertedWebToAppMessage(
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc
index 2834540b..c03f63f 100644
--- a/chrome/renderer/extensions/cast_streaming_native_handler.cc
+++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -509,16 +509,14 @@
     return;
 
   std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
-  base::Value* options_value =
-      converter->FromV8Value(args[1], context()->v8_context());
-  base::DictionaryValue* options;
-  if (!options_value || !options_value->GetAsDictionary(&options)) {
-    delete options_value;
+  std::unique_ptr<base::DictionaryValue> options = base::DictionaryValue::From(
+      converter->FromV8Value(args[1], context()->v8_context()));
+  if (!options) {
     args.GetIsolate()->ThrowException(v8::Exception::TypeError(
         v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
     return;
   }
-  transport->SetOptions(base::WrapUnique(options));
+  transport->SetOptions(std::move(options));
 }
 
 void CastStreamingNativeHandler::ToggleLogging(
diff --git a/content/child/v8_value_converter_impl.cc b/content/child/v8_value_converter_impl.cc
index 799d505..d0e084cf 100644
--- a/content/child/v8_value_converter_impl.cc
+++ b/content/child/v8_value_converter_impl.cc
@@ -10,10 +10,12 @@
 #include <cmath>
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "third_party/WebKit/public/web/WebArrayBuffer.h"
 #include "third_party/WebKit/public/web/WebArrayBufferConverter.h"
@@ -26,7 +28,7 @@
 
 bool V8ValueConverter::Strategy::FromV8Object(
     v8::Local<v8::Object> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate,
     const FromV8ValueCallback& callback) const {
   return false;
@@ -34,24 +36,27 @@
 
 bool V8ValueConverter::Strategy::FromV8Array(
     v8::Local<v8::Array> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate,
     const FromV8ValueCallback& callback) const {
   return false;
 }
 
-bool V8ValueConverter::Strategy::FromV8ArrayBuffer(v8::Local<v8::Object> value,
-                                                   base::Value** out,
-                                                   v8::Isolate* isolate) const {
+bool V8ValueConverter::Strategy::FromV8ArrayBuffer(
+    v8::Local<v8::Object> value,
+    std::unique_ptr<base::Value>* out,
+    v8::Isolate* isolate) const {
   return false;
 }
 
-bool V8ValueConverter::Strategy::FromV8Number(v8::Local<v8::Number> value,
-                                              base::Value** out) const {
+bool V8ValueConverter::Strategy::FromV8Number(
+    v8::Local<v8::Number> value,
+    std::unique_ptr<base::Value>* out) const {
   return false;
 }
 
-bool V8ValueConverter::Strategy::FromV8Undefined(base::Value** out) const {
+bool V8ValueConverter::Strategy::FromV8Undefined(
+    std::unique_ptr<base::Value>* out) const {
   return false;
 }
 
@@ -212,7 +217,7 @@
       ToV8ValueImpl(context->GetIsolate(), context->Global(), value));
 }
 
-base::Value* V8ValueConverterImpl::FromV8Value(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Value(
     v8::Local<v8::Value> val,
     v8::Local<v8::Context> context) const {
   v8::Context::Scope context_scope(context);
@@ -341,7 +346,7 @@
       &buffer, creation_context, isolate);
 }
 
-base::Value* V8ValueConverterImpl::FromV8ValueImpl(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ValueImpl(
     FromV8ValueState* state,
     v8::Local<v8::Value> val,
     v8::Isolate* isolate) const {
@@ -349,43 +354,46 @@
 
   FromV8ValueState::Level state_level(state);
   if (state->HasReachedMaxRecursionDepth())
-    return NULL;
+    return nullptr;
 
   if (val->IsNull())
-    return base::Value::CreateNullValue().release();
+    return base::Value::CreateNullValue();
 
   if (val->IsBoolean())
-    return new base::FundamentalValue(val->ToBoolean(isolate)->Value());
+    return base::MakeUnique<base::FundamentalValue>(
+        val->ToBoolean(isolate)->Value());
 
   if (val->IsNumber() && strategy_) {
-    base::Value* out = NULL;
+    std::unique_ptr<base::Value> out;
     if (strategy_->FromV8Number(val.As<v8::Number>(), &out))
       return out;
   }
 
   if (val->IsInt32())
-    return new base::FundamentalValue(val->ToInt32(isolate)->Value());
+    return base::MakeUnique<base::FundamentalValue>(
+        val->ToInt32(isolate)->Value());
 
   if (val->IsNumber()) {
     double val_as_double = val.As<v8::Number>()->Value();
     if (!std::isfinite(val_as_double))
-      return NULL;
-    return new base::FundamentalValue(val_as_double);
+      return nullptr;
+    return base::MakeUnique<base::FundamentalValue>(val_as_double);
   }
 
   if (val->IsString()) {
     v8::String::Utf8Value utf8(val);
-    return new base::StringValue(std::string(*utf8, utf8.length()));
+    return base::MakeUnique<base::StringValue>(
+        std::string(*utf8, utf8.length()));
   }
 
   if (val->IsUndefined()) {
     if (strategy_) {
-      base::Value* out = NULL;
+      std::unique_ptr<base::Value> out;
       if (strategy_->FromV8Undefined(&out))
         return out;
     }
     // JSON.stringify ignores undefined.
-    return NULL;
+    return nullptr;
   }
 
   if (val->IsDate()) {
@@ -394,14 +402,14 @@
       // consistent within this class.
       return FromV8Object(val->ToObject(isolate), state, isolate);
     v8::Date* date = v8::Date::Cast(*val);
-    return new base::FundamentalValue(date->ValueOf() / 1000.0);
+    return base::MakeUnique<base::FundamentalValue>(date->ValueOf() / 1000.0);
   }
 
   if (val->IsRegExp()) {
     if (!reg_exp_allowed_)
       // JSON.stringify converts to an object.
       return FromV8Object(val.As<v8::Object>(), state, isolate);
-    return new base::StringValue(*v8::String::Utf8Value(val));
+    return base::MakeUnique<base::StringValue>(*v8::String::Utf8Value(val));
   }
 
   // v8::Value doesn't have a ToArray() method for some reason.
@@ -411,7 +419,7 @@
   if (val->IsFunction()) {
     if (!function_allowed_)
       // JSON.stringify refuses to convert function(){}.
-      return NULL;
+      return nullptr;
     return FromV8Object(val.As<v8::Object>(), state, isolate);
   }
 
@@ -422,16 +430,16 @@
     return FromV8Object(val.As<v8::Object>(), state, isolate);
 
   LOG(ERROR) << "Unexpected v8 value type encountered.";
-  return NULL;
+  return nullptr;
 }
 
-base::Value* V8ValueConverterImpl::FromV8Array(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Array(
     v8::Local<v8::Array> val,
     FromV8ValueState* state,
     v8::Isolate* isolate) const {
   ScopedUniquenessGuard uniqueness_guard(state, val);
   if (!uniqueness_guard.is_valid())
-    return base::Value::CreateNullValue().release();
+    return base::Value::CreateNullValue();
 
   std::unique_ptr<v8::Context::Scope> scope;
   // If val was created in a different context than our current one, change to
@@ -447,12 +455,12 @@
         base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
                    base::Unretained(this),
                    base::Unretained(state));
-    base::Value* out = NULL;
+    std::unique_ptr<base::Value> out;
     if (strategy_->FromV8Array(val, &out, isolate, callback))
       return out;
   }
 
-  base::ListValue* result = new base::ListValue();
+  std::unique_ptr<base::ListValue> result(new base::ListValue());
 
   // Only fields with integer keys are carried over to the ListValue.
   for (uint32_t i = 0; i < val->Length(); ++i) {
@@ -468,22 +476,23 @@
       continue;
     }
 
-    base::Value* child = FromV8ValueImpl(state, child_v8, isolate);
+    std::unique_ptr<base::Value> child =
+        FromV8ValueImpl(state, child_v8, isolate);
     if (child)
-      result->Append(child);
+      result->Append(std::move(child));
     else
       // JSON.stringify puts null in places where values don't serialize, for
       // example undefined and functions. Emulate that behavior.
       result->Append(base::Value::CreateNullValue());
   }
-  return result;
+  return std::move(result);
 }
 
-base::Value* V8ValueConverterImpl::FromV8ArrayBuffer(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ArrayBuffer(
     v8::Local<v8::Object> val,
     v8::Isolate* isolate) const {
   if (strategy_) {
-    base::Value* out = NULL;
+    std::unique_ptr<base::Value> out;
     if (strategy_->FromV8ArrayBuffer(val, &out, isolate))
       return out;
   }
@@ -506,18 +515,19 @@
   }
 
   if (data)
-    return base::BinaryValue::CreateWithCopiedBuffer(data, length);
+    return base::WrapUnique(
+        base::BinaryValue::CreateWithCopiedBuffer(data, length));
   else
-    return NULL;
+    return nullptr;
 }
 
-base::Value* V8ValueConverterImpl::FromV8Object(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Object(
     v8::Local<v8::Object> val,
     FromV8ValueState* state,
     v8::Isolate* isolate) const {
   ScopedUniquenessGuard uniqueness_guard(state, val);
   if (!uniqueness_guard.is_valid())
-    return base::Value::CreateNullValue().release();
+    return base::Value::CreateNullValue();
 
   std::unique_ptr<v8::Context::Scope> scope;
   // If val was created in a different context than our current one, change to
@@ -533,7 +543,7 @@
         base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
                    base::Unretained(this),
                    base::Unretained(state));
-    base::Value* out = NULL;
+    std::unique_ptr<base::Value> out;
     if (strategy_->FromV8Object(val, &out, isolate, callback))
       return out;
   }
@@ -552,7 +562,7 @@
   // ANOTHER NOTE: returning an empty dictionary here to minimise surprise.
   // See also http://crbug.com/330559.
   if (val->InternalFieldCount())
-    return new base::DictionaryValue();
+    return base::MakeUnique<base::DictionaryValue>();
 
   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
   v8::Local<v8::Array> property_names(val->GetOwnPropertyNames());
@@ -579,8 +589,8 @@
       child_v8 = v8::Null(isolate);
     }
 
-    std::unique_ptr<base::Value> child(
-        FromV8ValueImpl(state, child_v8, isolate));
+    std::unique_ptr<base::Value> child =
+        FromV8ValueImpl(state, child_v8, isolate);
     if (!child)
       // JSON.stringify skips properties whose values don't serialize, for
       // example undefined and functions. Emulate that behavior.
@@ -610,10 +620,10 @@
       continue;
 
     result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
-                                    child.release());
+                                    std::move(child));
   }
 
-  return result.release();
+  return std::move(result);
 }
 
 }  // namespace content
diff --git a/content/child/v8_value_converter_impl.h b/content/child/v8_value_converter_impl.h
index fd23c47a..4b4c00af 100644
--- a/content/child/v8_value_converter_impl.h
+++ b/content/child/v8_value_converter_impl.h
@@ -34,8 +34,9 @@
   v8::Local<v8::Value> ToV8Value(
       const base::Value* value,
       v8::Local<v8::Context> context) const override;
-  base::Value* FromV8Value(v8::Local<v8::Value> value,
-                           v8::Local<v8::Context> context) const override;
+  std::unique_ptr<base::Value> FromV8Value(
+      v8::Local<v8::Value> value,
+      v8::Local<v8::Context> context) const override;
 
  private:
   friend class ScopedAvoidIdentityHashForTesting;
@@ -57,21 +58,21 @@
                                       v8::Local<v8::Object> creation_context,
                                       const base::BinaryValue* value) const;
 
-  base::Value* FromV8ValueImpl(FromV8ValueState* state,
-                               v8::Local<v8::Value> value,
-                               v8::Isolate* isolate) const;
-  base::Value* FromV8Array(v8::Local<v8::Array> array,
-                           FromV8ValueState* state,
-                           v8::Isolate* isolate) const;
+  std::unique_ptr<base::Value> FromV8ValueImpl(FromV8ValueState* state,
+                                               v8::Local<v8::Value> value,
+                                               v8::Isolate* isolate) const;
+  std::unique_ptr<base::Value> FromV8Array(v8::Local<v8::Array> array,
+                                           FromV8ValueState* state,
+                                           v8::Isolate* isolate) const;
 
   // This will convert objects of type ArrayBuffer or any of the
   // ArrayBufferView subclasses.
-  base::Value* FromV8ArrayBuffer(v8::Local<v8::Object> val,
-                                 v8::Isolate* isolate) const;
+  std::unique_ptr<base::Value> FromV8ArrayBuffer(v8::Local<v8::Object> val,
+                                                 v8::Isolate* isolate) const;
 
-  base::Value* FromV8Object(v8::Local<v8::Object> object,
-                            FromV8ValueState* state,
-                            v8::Isolate* isolate) const;
+  std::unique_ptr<base::Value> FromV8Object(v8::Local<v8::Object> object,
+                                            FromV8ValueState* state,
+                                            v8::Isolate* isolate) const;
 
   // If true, we will convert Date JavaScript objects to doubles.
   bool date_allowed_;
diff --git a/content/child/v8_value_converter_impl_unittest.cc b/content/child/v8_value_converter_impl_unittest.cc
index 82e23d4..43b654df1 100644
--- a/content/child/v8_value_converter_impl_unittest.cc
+++ b/content/child/v8_value_converter_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/test/values_test_util.h"
 #include "base/values.h"
@@ -180,8 +181,7 @@
     v8::Local<v8::Object> object(v8::Object::New(isolate_));
     object->Set(v8::String::NewFromUtf8(isolate_, "test"), val);
     std::unique_ptr<base::DictionaryValue> dictionary(
-        static_cast<base::DictionaryValue*>(
-            converter.FromV8Value(object, context)));
+        base::DictionaryValue::From(converter.FromV8Value(object, context)));
     ASSERT_TRUE(dictionary.get());
 
     if (expected_value) {
@@ -196,7 +196,7 @@
     v8::Local<v8::Array> array(v8::Array::New(isolate_));
     array->Set(0, val);
     std::unique_ptr<base::ListValue> list(
-        static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+        base::ListValue::From(converter.FromV8Value(array, context)));
     ASSERT_TRUE(list.get());
     if (expected_value) {
       base::Value* temp = NULL;
@@ -329,8 +329,7 @@
   // Converting from v8 value should replace the foo property with null.
   V8ValueConverterImpl converter;
   std::unique_ptr<base::DictionaryValue> converted(
-      static_cast<base::DictionaryValue*>(
-          converter.FromV8Value(object, context)));
+      base::DictionaryValue::From(converter.FromV8Value(object, context)));
   EXPECT_TRUE(converted.get());
   // http://code.google.com/p/v8/issues/detail?id=1342
   // EXPECT_EQ(2u, converted->size());
@@ -374,7 +373,7 @@
   // Converting from v8 value should replace the first item with null.
   V8ValueConverterImpl converter;
   std::unique_ptr<base::ListValue> converted(
-      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+      base::ListValue::From(converter.FromV8Value(array, context)));
   ASSERT_TRUE(converted.get());
   // http://code.google.com/p/v8/issues/detail?id=1342
   EXPECT_EQ(2u, converted->GetSize());
@@ -442,8 +441,7 @@
 
   V8ValueConverterImpl converter;
   std::unique_ptr<base::DictionaryValue> result(
-      static_cast<base::DictionaryValue*>(
-          converter.FromV8Value(object, context)));
+      base::DictionaryValue::From(converter.FromV8Value(object, context)));
   ASSERT_TRUE(result.get());
   EXPECT_EQ(0u, result->size());
 }
@@ -609,8 +607,7 @@
   converter.SetStripNullFromObjects(true);
 
   std::unique_ptr<base::DictionaryValue> result(
-      static_cast<base::DictionaryValue*>(
-          converter.FromV8Value(object, context)));
+      base::DictionaryValue::From(converter.FromV8Value(object, context)));
   ASSERT_TRUE(result.get());
   EXPECT_EQ(0u, result->size());
 }
@@ -630,8 +627,7 @@
   object->Set(v8::String::NewFromUtf8(isolate_, "obj"), object);
 
   std::unique_ptr<base::DictionaryValue> object_result(
-      static_cast<base::DictionaryValue*>(
-          converter.FromV8Value(object, context)));
+      base::DictionaryValue::From(converter.FromV8Value(object, context)));
   ASSERT_TRUE(object_result.get());
   EXPECT_EQ(2u, object_result->size());
   EXPECT_TRUE(IsNull(object_result.get(), "obj"));
@@ -642,7 +638,7 @@
   array->Set(1, array);
 
   std::unique_ptr<base::ListValue> list_result(
-      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+      base::ListValue::From(converter.FromV8Value(array, context)));
   ASSERT_TRUE(list_result.get());
   EXPECT_EQ(2u, list_result->GetSize());
   EXPECT_TRUE(IsNull(list_result.get(), 1));
@@ -709,7 +705,7 @@
 
   V8ValueConverterImpl converter;
   std::unique_ptr<base::ListValue> result(
-      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+      base::ListValue::From(converter.FromV8Value(array, context)));
   ASSERT_TRUE(result.get());
   EXPECT_EQ(2u, result->GetSize());
 }
@@ -873,8 +869,7 @@
 
     // The actual result.
     std::unique_ptr<base::DictionaryValue> result(
-        static_cast<base::DictionaryValue*>(
-            converter.FromV8Value(object, context)));
+        base::DictionaryValue::From(converter.FromV8Value(object, context)));
     ASSERT_TRUE(result.get());
     EXPECT_EQ(2u, result->size());
 
@@ -906,7 +901,7 @@
 
     // The actual result.
     std::unique_ptr<base::ListValue> list_result(
-        static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+        base::ListValue::From(converter.FromV8Value(array, context)));
     ASSERT_TRUE(list_result.get());
     ASSERT_EQ(2u, list_result->GetSize());
     for (size_t i = 0; i < list_result->GetSize(); ++i) {
@@ -963,39 +958,39 @@
   V8ValueConverterOverridingStrategyForTesting()
       : reference_value_(NewReferenceValue()) {}
   bool FromV8Object(v8::Local<v8::Object> value,
-                    base::Value** out,
+                    std::unique_ptr<base::Value>* out,
                     v8::Isolate* isolate,
                     const FromV8ValueCallback& callback) const override {
     *out = NewReferenceValue();
     return true;
   }
   bool FromV8Array(v8::Local<v8::Array> value,
-                   base::Value** out,
+                   std::unique_ptr<base::Value>* out,
                    v8::Isolate* isolate,
                    const FromV8ValueCallback& callback) const override {
     *out = NewReferenceValue();
     return true;
   }
   bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
-                         base::Value** out,
+                         std::unique_ptr<base::Value>* out,
                          v8::Isolate* isolate) const override {
     *out = NewReferenceValue();
     return true;
   }
   bool FromV8Number(v8::Local<v8::Number> value,
-                    base::Value** out) const override {
+                    std::unique_ptr<base::Value>* out) const override {
     *out = NewReferenceValue();
     return true;
   }
-  bool FromV8Undefined(base::Value** out) const override {
+  bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override {
     *out = NewReferenceValue();
     return true;
   }
   base::Value* reference_value() const { return reference_value_.get(); }
 
  private:
-  static base::Value* NewReferenceValue() {
-    return new base::StringValue("strategy");
+  static std::unique_ptr<base::Value> NewReferenceValue() {
+    return base::MakeUnique<base::StringValue>("strategy");
   }
   std::unique_ptr<base::Value> reference_value_;
 };
@@ -1058,27 +1053,29 @@
     : public V8ValueConverter::Strategy {
  public:
   bool FromV8Object(v8::Local<v8::Object> value,
-                    base::Value** out,
+                    std::unique_ptr<base::Value>* out,
                     v8::Isolate* isolate,
                     const FromV8ValueCallback& callback) const override {
     return false;
   }
   bool FromV8Array(v8::Local<v8::Array> value,
-                   base::Value** out,
+                   std::unique_ptr<base::Value>* out,
                    v8::Isolate* isolate,
                    const FromV8ValueCallback& callback) const override {
     return false;
   }
   bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
-                         base::Value** out,
+                         std::unique_ptr<base::Value>* out,
                          v8::Isolate* isolate) const override {
     return false;
   }
   bool FromV8Number(v8::Local<v8::Number> value,
-                    base::Value** out) const override {
+                    std::unique_ptr<base::Value>* out) const override {
     return false;
   }
-  bool FromV8Undefined(base::Value** out) const override { return false; }
+  bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override {
+    return false;
+  }
 };
 
 // Verify that having a strategy that fallbacks to default behaviour
diff --git a/content/public/child/v8_value_converter.h b/content/public/child/v8_value_converter.h
index 67e3025f..aeb38c9 100644
--- a/content/public/child/v8_value_converter.h
+++ b/content/public/child/v8_value_converter.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_PUBLIC_CHILD_V8_VALUE_CONVERTER_H_
 #define CONTENT_PUBLIC_CHILD_V8_VALUE_CONVERTER_H_
 
+#include <memory>
+
 #include "base/callback.h"
 #include "content/common/content_export.h"
 #include "v8/include/v8.h"
@@ -28,8 +30,9 @@
   // Extends the default behaviour of V8ValueConverter.
   class CONTENT_EXPORT Strategy {
    public:
-    typedef base::Callback<base::Value*(
-        v8::Local<v8::Value>, v8::Isolate* isolate)> FromV8ValueCallback;
+    typedef base::Callback<std::unique_ptr<base::Value>(v8::Local<v8::Value>,
+                                                        v8::Isolate* isolate)>
+        FromV8ValueCallback;
 
     virtual ~Strategy() {}
 
@@ -38,7 +41,7 @@
     // Use |callback| to convert any child values, as this will retain
     // the ValueConverter's internal checks for depth and cycles.
     virtual bool FromV8Object(v8::Local<v8::Object> value,
-                              base::Value** out,
+                              std::unique_ptr<base::Value>* out,
                               v8::Isolate* isolate,
                               const FromV8ValueCallback& callback) const;
 
@@ -47,7 +50,7 @@
     // Use |callback| to convert any child values, as this will retain
     // the ValueConverter's internal checks for depth and cycles.
     virtual bool FromV8Array(v8::Local<v8::Array> value,
-                             base::Value** out,
+                             std::unique_ptr<base::Value>* out,
                              v8::Isolate* isolate,
                              const FromV8ValueCallback& callback) const;
 
@@ -55,18 +58,18 @@
     // behavior. v8::Object is passed as ArrayBuffer and ArrayBufferView
     // classes are siblings.
     virtual bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
-                                   base::Value** out,
+                                   std::unique_ptr<base::Value>* out,
                                    v8::Isolate* isolate) const;
 
     // If false is returned, V8ValueConverter proceeds with the default
     // behavior. This allows to intercept "non-finite" values and do something
     // with them.
     virtual bool FromV8Number(v8::Local<v8::Number> value,
-                              base::Value** out) const;
+                              std::unique_ptr<base::Value>* out) const;
 
     // If false is returned, V8ValueConverter proceeds with the default
     // behavior.
-    virtual bool FromV8Undefined(base::Value** out) const;
+    virtual bool FromV8Undefined(std::unique_ptr<base::Value>* out) const;
   };
 
   static V8ValueConverter* create();
@@ -119,9 +122,9 @@
   // Likewise, if an object throws while converting a property it will not be
   // converted, whereas if an array throws while converting an item it will be
   // converted to Value(TYPE_NULL).
-  // TODO(dcheng): This should return a unique_ptr.
-  virtual base::Value* FromV8Value(v8::Local<v8::Value> value,
-                                   v8::Local<v8::Context> context) const = 0;
+  virtual std::unique_ptr<base::Value> FromV8Value(
+      v8::Local<v8::Value> value,
+      v8::Local<v8::Context> context) const = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/dom_automation_controller.cc b/content/renderer/dom_automation_controller.cc
index 3f119b6..91b456a3 100644
--- a/content/renderer/dom_automation_controller.cc
+++ b/content/renderer/dom_automation_controller.cc
@@ -102,8 +102,8 @@
       (args.PeekNext()->IsString() || args.PeekNext()->IsBoolean() ||
        args.PeekNext()->IsNumber())) {
     V8ValueConverterImpl conv;
-    value.reset(
-        conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext()));
+    value =
+        conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext());
   } else {
     return false;
   }
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc
index 8fe5bae..42f6995 100644
--- a/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -910,7 +910,7 @@
       base::WrapUnique(V8ValueConverter::create());
   v8::Local<v8::Context> v8_context = callback_and_context->GetContext();
   std::unique_ptr<base::Value> value =
-      base::WrapUnique(converter->FromV8Value(arguments, v8_context));
+      converter->FromV8Value(arguments, v8_context);
 
   return context.compositor()->ScheduleMicroBenchmark(
       name, std::move(value),
@@ -930,7 +930,7 @@
   v8::Local<v8::Context> v8_context =
       context.web_frame()->mainWorldScriptContext();
   std::unique_ptr<base::Value> value =
-      base::WrapUnique(converter->FromV8Value(message, v8_context));
+      converter->FromV8Value(message, v8_context);
 
   return context.compositor()->SendMessageToMicroBenchmark(id,
                                                            std::move(value));
diff --git a/content/renderer/java/gin_java_bridge_value_converter.cc b/content/renderer/java/gin_java_bridge_value_converter.cc
index 527b541c..309d77d 100644
--- a/content/renderer/java/gin_java_bridge_value_converter.cc
+++ b/content/renderer/java/gin_java_bridge_value_converter.cc
@@ -38,20 +38,19 @@
 std::unique_ptr<base::Value> GinJavaBridgeValueConverter::FromV8Value(
     v8::Local<v8::Value> value,
     v8::Local<v8::Context> context) const {
-  return base::WrapUnique(converter_->FromV8Value(value, context));
+  return converter_->FromV8Value(value, context);
 }
 
 bool GinJavaBridgeValueConverter::FromV8Object(
     v8::Local<v8::Object> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate,
     const FromV8ValueCallback& callback) const {
   GinJavaBridgeObject* unwrapped;
   if (!gin::ConvertFromV8(isolate, value, &unwrapped)) {
     return false;
   }
-  *out =
-      GinJavaBridgeValue::CreateObjectIDValue(unwrapped->object_id()).release();
+  *out = GinJavaBridgeValue::CreateObjectIDValue(unwrapped->object_id());
   return true;
 }
 
@@ -124,10 +123,10 @@
 
 bool GinJavaBridgeValueConverter::FromV8ArrayBuffer(
     v8::Local<v8::Object> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate) const {
   if (!value->IsTypedArray()) {
-    *out = GinJavaBridgeValue::CreateUndefinedValue().release();
+    *out = GinJavaBridgeValue::CreateUndefinedValue();
     return true;
   }
 
@@ -139,29 +138,31 @@
     data_length = view.num_bytes();
   }
   if (!data) {
-    *out = GinJavaBridgeValue::CreateUndefinedValue().release();
+    *out = GinJavaBridgeValue::CreateUndefinedValue();
     return true;
   }
 
-  base::ListValue* result = new base::ListValue();
-  *out = result;
+  std::unique_ptr<base::ListValue> result(new base::ListValue);
   std::unique_ptr<TypedArraySerializer> serializer(
       TypedArraySerializer::Create(value.As<v8::TypedArray>()));
-  serializer->serializeTo(data, data_length, result);
+  serializer->serializeTo(data, data_length, result.get());
+  *out = std::move(result);
   return true;
 }
 
-bool GinJavaBridgeValueConverter::FromV8Number(v8::Local<v8::Number> value,
-                                               base::Value** out) const {
+bool GinJavaBridgeValueConverter::FromV8Number(
+    v8::Local<v8::Number> value,
+    std::unique_ptr<base::Value>* out) const {
   double double_value = value->Value();
   if (std::isfinite(double_value))
     return false;
-  *out = GinJavaBridgeValue::CreateNonFiniteValue(double_value).release();
+  *out = GinJavaBridgeValue::CreateNonFiniteValue(double_value);
   return true;
 }
 
-bool GinJavaBridgeValueConverter::FromV8Undefined(base::Value** out) const {
-  *out = GinJavaBridgeValue::CreateUndefinedValue().release();
+bool GinJavaBridgeValueConverter::FromV8Undefined(
+    std::unique_ptr<base::Value>* out) const {
+  *out = GinJavaBridgeValue::CreateUndefinedValue();
   return true;
 }
 
diff --git a/content/renderer/java/gin_java_bridge_value_converter.h b/content/renderer/java/gin_java_bridge_value_converter.h
index 2e48f19..9ab3849a3 100644
--- a/content/renderer/java/gin_java_bridge_value_converter.h
+++ b/content/renderer/java/gin_java_bridge_value_converter.h
@@ -27,15 +27,15 @@
 
   // content::V8ValueConverter::Strategy
   bool FromV8Object(v8::Local<v8::Object> value,
-                    base::Value** out,
+                    std::unique_ptr<base::Value>* out,
                     v8::Isolate* isolate,
                     const FromV8ValueCallback& callback) const override;
   bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
-                         base::Value** out,
+                         std::unique_ptr<base::Value>* out,
                          v8::Isolate* isolate) const override;
   bool FromV8Number(v8::Local<v8::Number> value,
-                    base::Value** out) const override;
-  bool FromV8Undefined(base::Value** out) const override;
+                    std::unique_ptr<base::Value>* out) const override;
+  bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override;
 
  private:
   std::unique_ptr<V8ValueConverter> converter_;
diff --git a/content/renderer/web_ui_extension.cc b/content/renderer/web_ui_extension.cc
index 0751e6ee..a793b4e2 100644
--- a/content/renderer/web_ui_extension.cc
+++ b/content/renderer/web_ui_extension.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/web_ui_extension.h"
 
 #include <memory>
+#include <utility>
 
 #include "base/values.h"
 #include "content/common/view_messages.h"
@@ -108,13 +109,9 @@
     }
 
     std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
-
-    base::Value* value =
-        converter->FromV8Value(obj, frame->mainWorldScriptContext());
-    base::ListValue* list = NULL;
-    value->GetAsList(&list);
-    DCHECK(list);
-    content.reset(list);
+    content = base::ListValue::From(
+        converter->FromV8Value(obj, frame->mainWorldScriptContext()));
+    DCHECK(content);
   }
 
   // Send the message up to the browser.
diff --git a/extensions/renderer/activity_log_converter_strategy.cc b/extensions/renderer/activity_log_converter_strategy.cc
index 301f2e2c..1be41aa 100644
--- a/extensions/renderer/activity_log_converter_strategy.cc
+++ b/extensions/renderer/activity_log_converter_strategy.cc
@@ -55,7 +55,7 @@
 
 bool ActivityLogConverterStrategy::FromV8Object(
     v8::Local<v8::Object> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate,
     const FromV8ValueCallback& callback) const {
   return FromV8Internal(value, out, isolate, callback);
@@ -63,7 +63,7 @@
 
 bool ActivityLogConverterStrategy::FromV8Array(
     v8::Local<v8::Array> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate,
     const FromV8ValueCallback& callback) const {
   return FromV8Internal(value, out, isolate, callback);
@@ -71,12 +71,10 @@
 
 bool ActivityLogConverterStrategy::FromV8Internal(
     v8::Local<v8::Object> value,
-    base::Value** out,
+    std::unique_ptr<base::Value>* out,
     v8::Isolate* isolate,
     const FromV8ValueCallback& callback) const {
-  std::unique_ptr<base::Value> parsed_value;
-  parsed_value = SummarizeV8Value(isolate, value);
-  *out = parsed_value.release();
+  *out = SummarizeV8Value(isolate, value);
 
   return true;
 }
diff --git a/extensions/renderer/activity_log_converter_strategy.h b/extensions/renderer/activity_log_converter_strategy.h
index fd7a1d2..b699d21 100644
--- a/extensions/renderer/activity_log_converter_strategy.h
+++ b/extensions/renderer/activity_log_converter_strategy.h
@@ -28,17 +28,17 @@
 
   // content::V8ValueConverter::Strategy implementation.
   bool FromV8Object(v8::Local<v8::Object> value,
-                    base::Value** out,
+                    std::unique_ptr<base::Value>* out,
                     v8::Isolate* isolate,
                     const FromV8ValueCallback& callback) const override;
   bool FromV8Array(v8::Local<v8::Array> value,
-                   base::Value** out,
+                   std::unique_ptr<base::Value>* out,
                    v8::Isolate* isolate,
                    const FromV8ValueCallback& callback) const override;
 
  private:
   bool FromV8Internal(v8::Local<v8::Object> value,
-                      base::Value** out,
+                      std::unique_ptr<base::Value>* out,
                       v8::Isolate* isolate,
                       const FromV8ValueCallback& callback) const;
 
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc
index 8933f66..f867800 100644
--- a/extensions/renderer/script_injection.cc
+++ b/extensions/renderer/script_injection.cc
@@ -292,7 +292,7 @@
       // when encountered.
       v8::Local<v8::Context> context =
           render_frame_->GetWebFrame()->mainWorldScriptContext();
-      execution_result_.reset(v8_converter->FromV8Value(results[0], context));
+      execution_result_ = v8_converter->FromV8Value(results[0], context);
     }
     if (!execution_result_.get())
       execution_result_ = base::Value::CreateNullValue();