Expose Value::GetList and Value(ListStorage) on ListValue

This change exposes the API introduced in r465517 also on the ListValue
class directly. This is for convenience, as it simplifies deprecating
the old raw pointer based APIs which eventually will lead to the
complete inlining of the ListValue class into Value.

R=brettw@chromium.org
BUG=646113

Review-Url: https://codereview.chromium.org/2843783003
Cr-Commit-Position: refs/heads/master@{#467384}
diff --git a/base/values.cc b/base/values.cc
index 1aab924..aa3407f 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -1059,6 +1059,11 @@
 
 ListValue::ListValue() : Value(Type::LIST) {}
 
+ListValue::ListValue(const ListStorage& in_list) : Value(in_list) {}
+
+ListValue::ListValue(ListStorage&& in_list) noexcept
+    : Value(std::move(in_list)) {}
+
 void ListValue::Clear() {
   list_->clear();
 }
diff --git a/base/values.h b/base/values.h
index cfef664..920c0a3 100644
--- a/base/values.h
+++ b/base/values.h
@@ -383,6 +383,8 @@
   static std::unique_ptr<ListValue> From(std::unique_ptr<Value> value);
 
   ListValue();
+  explicit ListValue(const ListStorage& in_list);
+  explicit ListValue(ListStorage&& in_list) noexcept;
 
   // Clears the contents of this ListValue
   void Clear();
@@ -428,6 +430,8 @@
   bool GetBinary(size_t index, Value** out_value);
   bool GetDictionary(size_t index, const DictionaryValue** out_value) const;
   bool GetDictionary(size_t index, DictionaryValue** out_value);
+
+  using Value::GetList;
   bool GetList(size_t index, const ListValue** out_value) const;
   bool GetList(size_t index, ListValue** out_value);
 
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index a781dc4..da4d267 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -35,6 +35,9 @@
       "IsNothrowMoveConstructibleFromList");
   static_assert(std::is_nothrow_move_assignable<Value>::value,
                 "IsNothrowMoveAssignable");
+  static_assert(
+      std::is_nothrow_constructible<ListValue, Value::ListStorage&&>::value,
+      "ListIsNothrowMoveConstructibleFromList");
 }
 
 // Group of tests for the value constructors.
@@ -119,6 +122,28 @@
   EXPECT_EQ(Value::Type::LIST, value.type());
 }
 
+TEST(ValuesTest, ConstructListFromStorage) {
+  Value::ListStorage storage;
+  storage.emplace_back("foo");
+
+  {
+    ListValue value(storage);
+    EXPECT_EQ(Value::Type::LIST, value.type());
+    EXPECT_EQ(1u, value.GetList().size());
+    EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
+    EXPECT_EQ("foo", value.GetList()[0].GetString());
+  }
+
+  storage.back() = base::Value("bar");
+  {
+    ListValue value(std::move(storage));
+    EXPECT_EQ(Value::Type::LIST, value.type());
+    EXPECT_EQ(1u, value.GetList().size());
+    EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
+    EXPECT_EQ("bar", value.GetList()[0].GetString());
+  }
+}
+
 // Group of tests for the copy constructors and copy-assigmnent. For equality
 // checks comparisons of the interesting fields are done instead of relying on
 // Equals being correct.