From d10d2cf2d284daa024deb9a512868c55608dfd1c Mon Sep 17 00:00:00 2001
From: "raymes@chromium.org"
 <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Tue, 18 Jun 2013 18:49:47 +0000
Subject: Revert 207040 "Don't send PP_Vars/V8 values with cycles across P..."

> Don't send PP_Vars/V8 values with cycles across PostMessage
>
> This prevents PP_Vars/V8 values with cycles being transmitted across PostMessage. An undefined value will be sent instead and an error will be logged to the console.
>
> BUG=236958
>
> Review URL: https://chromiumcodereview.appspot.com/16140011

TBR=raymes@chromium.org

Review URL: https://codereview.chromium.org/17239007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207043 0039d316-1c4b-4281-b951-d872f2087c98
---
 ppapi/api/ppb_messaging.idl          |  4 +-
 ppapi/api/ppp_messaging.idl          |  7 ++--
 ppapi/c/ppb_messaging.h              |  6 +--
 ppapi/c/ppp_messaging.h              |  9 +++--
 ppapi/cpp/instance.h                 | 24 +++--------
 ppapi/proxy/handle_converter.cc      |  8 +++-
 ppapi/proxy/ppb_instance_proxy.cc    | 10 -----
 ppapi/proxy/raw_var_data.cc          | 77 ++++++++++++------------------------
 ppapi/proxy/raw_var_data.h           |  2 +
 ppapi/proxy/raw_var_data_unittest.cc | 32 +++++++--------
 ppapi/proxy/serialized_var.cc        | 39 ++----------------
 ppapi/proxy/serialized_var.h         | 31 ++-------------
 ppapi/tests/test_post_message.cc     | 48 +++++-----------------
 ppapi/tests/test_post_message.h      |  4 --
 14 files changed, 86 insertions(+), 215 deletions(-)

(limited to 'ppapi')

diff --git a/ppapi/api/ppb_messaging.idl b/ppapi/api/ppb_messaging.idl
index 0f9a3aa..647f7f6 100644
--- a/ppapi/api/ppb_messaging.idl
+++ b/ppapi/api/ppb_messaging.idl
@@ -36,8 +36,8 @@ interface PPB_Messaging {
    * JavaScript.
    *
    * When passing array or dictionary <code>PP_Var</code>s, the entire reference
-   * graph will be converted and transferred. If the reference graph has cycles,
-   * the message will not be sent and an error will be logged to the console.
+   * graph will be converted and transferred, including reference cycles if they
+   * exist.
    *
    * Listeners for message events in JavaScript code will receive an object
    * conforming to the HTML 5 <code>MessageEvent</code> interface.
diff --git a/ppapi/api/ppp_messaging.idl b/ppapi/api/ppp_messaging.idl
index 83c2010..150f771 100644
--- a/ppapi/api/ppp_messaging.idl
+++ b/ppapi/api/ppp_messaging.idl
@@ -36,9 +36,10 @@ interface PPP_Messaging {
    *
    * When converting JavaScript arrays, any object properties whose name
    * is not an array index are ignored. When passing arrays and objects, the
-   * entire reference graph will be converted and transferred. If the reference
-   * graph has cycles, the message will not be sent and an error will be logged
-   * to the console.
+   * entire reference graph will be converted and transferred, including
+   * reference cycles if they exist. Since <code>PP_Var</code>s are ref-counted,
+   * the author of the plugin must take care if they expect to receive vars with
+   * cycles. Cycles must be manually broken to correctly release the vars.
    *
    * The following JavaScript code invokes <code>HandleMessage</code>, passing
    * the module instance on which it was invoked, with <code>message</code>
diff --git a/ppapi/c/ppb_messaging.h b/ppapi/c/ppb_messaging.h
index 06e31205..404a11c 100644
--- a/ppapi/c/ppb_messaging.h
+++ b/ppapi/c/ppb_messaging.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppb_messaging.idl modified Wed Jun  5 10:32:59 2013. */
+/* From ppb_messaging.idl modified Mon May 20 15:31:07 2013. */
 
 #ifndef PPAPI_C_PPB_MESSAGING_H_
 #define PPAPI_C_PPB_MESSAGING_H_
@@ -50,8 +50,8 @@ struct PPB_Messaging_1_0 {
    * JavaScript.
    *
    * When passing array or dictionary <code>PP_Var</code>s, the entire reference
-   * graph will be converted and transferred. If the reference graph has cycles,
-   * the message will not be sent and an error will be logged to the console.
+   * graph will be converted and transferred, including reference cycles if they
+   * exist.
    *
    * Listeners for message events in JavaScript code will receive an object
    * conforming to the HTML 5 <code>MessageEvent</code> interface.
diff --git a/ppapi/c/ppp_messaging.h b/ppapi/c/ppp_messaging.h
index 28d40d6..b2e1f3c 100644
--- a/ppapi/c/ppp_messaging.h
+++ b/ppapi/c/ppp_messaging.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppp_messaging.idl modified Wed Jun  5 10:32:43 2013. */
+/* From ppp_messaging.idl modified Tue May 21 09:01:17 2013. */
 
 #ifndef PPAPI_C_PPP_MESSAGING_H_
 #define PPAPI_C_PPP_MESSAGING_H_
@@ -52,9 +52,10 @@ struct PPP_Messaging_1_0 {
    *
    * When converting JavaScript arrays, any object properties whose name
    * is not an array index are ignored. When passing arrays and objects, the
-   * entire reference graph will be converted and transferred. If the reference
-   * graph has cycles, the message will not be sent and an error will be logged
-   * to the console.
+   * entire reference graph will be converted and transferred, including
+   * reference cycles if they exist. Since <code>PP_Var</code>s are ref-counted,
+   * the author of the plugin must take care if they expect to receive vars with
+   * cycles. Cycles must be manually broken to correctly release the vars.
    *
    * The following JavaScript code invokes <code>HandleMessage</code>, passing
    * the module instance on which it was invoked, with <code>message</code>
diff --git a/ppapi/cpp/instance.h b/ppapi/cpp/instance.h
index 6bf4e83..48bca90 100644
--- a/ppapi/cpp/instance.h
+++ b/ppapi/cpp/instance.h
@@ -244,12 +244,6 @@ class Instance {
   /// JavaScript execution will not be blocked while HandleMessage() is
   /// processing the message.
   ///
-  /// When converting JavaScript arrays, any object properties whose name
-  /// is not an array index are ignored. When passing arrays and objects, the
-  /// entire reference graph will be converted and transferred. If the reference
-  /// graph has cycles, the message will not be sent and an error will be logged
-  /// to the console.
-  ///
   /// <strong>Example:</strong>
   ///
   /// The following JavaScript code invokes <code>HandleMessage</code>, passing
@@ -270,10 +264,9 @@ class Instance {
   ///
   /// Refer to PostMessage() for sending messages to JavaScript.
   ///
-  /// @param[in] message A <code>Var</code> which has been converted from a
-  /// JavaScript value. JavaScript array/object types are supported from Chrome
-  /// M29 onward. All JavaScript values are copied when passing them to the
-  /// plugin.
+  /// @param[in] message A <code>Var</code> containing the data sent from
+  /// JavaScript. Message can have an int32_t, double, bool, or string value
+  /// (objects are not supported).
   virtual void HandleMessage(const Var& message);
 
   /// @}
@@ -460,11 +453,6 @@ class Instance {
   ///
   /// The browser will pop-up an alert saying "Hello world!"
   ///
-  /// When passing array or dictionary <code>PP_Var</code>s, the entire
-  /// reference graph will be converted and transferred. If the reference graph
-  /// has cycles, the message will not be sent and an error will be logged to
-  /// the console.
-  ///
   /// Listeners for message events in JavaScript code will receive an object
   /// conforming to the HTML 5 <code>MessageEvent</code> interface.
   /// Specifically, the value of message will be contained as a property called
@@ -478,9 +466,9 @@ class Instance {
   /// Refer to HandleMessage() for receiving events from JavaScript.
   ///
   /// @param[in] message A <code>Var</code> containing the data to be sent to
-  /// JavaScript. Message can have a numeric, boolean, or string value.
-  /// Array/Dictionary types are supported from Chrome M29 onward.
-  /// All var types are copied when passing them to JavaScript.
+  /// JavaScript. Message can have a numeric, boolean, or string value; arrays
+  /// and dictionaries are not yet supported. Ref-counted var types are copied,
+  /// and are therefore not shared between the instance and the browser.
   void PostMessage(const Var& message);
 
   /// @}
diff --git a/ppapi/proxy/handle_converter.cc b/ppapi/proxy/handle_converter.cc
index d2fc4a9..b77ee49 100644
--- a/ppapi/proxy/handle_converter.cc
+++ b/ppapi/proxy/handle_converter.cc
@@ -54,14 +54,18 @@ void ConvertHandlesInParam(const ppapi::proxy::SerializedVar& var,
                            Handles* handles,
                            IPC::Message* msg,
                            int* handle_index) {
-  std::vector<ppapi::proxy::SerializedHandle*> var_handles = var.GetHandles();
+  if (!var.raw_var_data())
+    return;
+
+  std::vector<ppapi::proxy::SerializedHandle*> var_handles =
+      var.raw_var_data()->GetHandles();
   if (var_handles.empty())
     return;
 
   for (size_t i = 0; i < var_handles.size(); ++i)
     handles->push_back(*var_handles[i]);
   if (msg)
-    var.WriteDataToMessage(msg, base::Bind(&HandleWriter, handle_index));
+    var.raw_var_data()->Write(msg, base::Bind(&HandleWriter, handle_index));
 }
 
 // For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index e3948f06a..4009a19 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -56,10 +56,6 @@ namespace proxy {
 
 namespace {
 
-const char kSerializationError[] = "Failed to convert a PostMessage "
-    "argument from a PP_Var to a Javascript value. It may have cycles or be of "
-    "an unsupported type.";
-
 InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher) {
   return new PPB_Instance_Proxy(dispatcher);
 }
@@ -937,12 +933,6 @@ void PPB_Instance_Proxy::OnHostMsgPostMessage(
     PP_Instance instance,
     SerializedVarReceiveInput message) {
   EnterInstanceNoLock enter(instance);
-  if (!message.is_valid_var()) {
-    PpapiGlobals::Get()->LogWithSource(
-        instance, PP_LOGLEVEL_ERROR, std::string(), kSerializationError);
-    return;
-  }
-
   if (enter.succeeded())
     enter.functions()->PostMessage(instance,
                                    message.GetForInstance(dispatcher(),
diff --git a/ppapi/proxy/raw_var_data.cc b/ppapi/proxy/raw_var_data.cc
index a550c3f..4de51ae 100644
--- a/ppapi/proxy/raw_var_data.cc
+++ b/ppapi/proxy/raw_var_data.cc
@@ -31,27 +31,25 @@ static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
 static uint32 g_minimum_array_buffer_size_for_shmem =
     kMinimumArrayBufferSizeForShmem;
 
-struct StackEntry {
-  StackEntry(PP_Var v, size_t i) : var(v), data_index(i) {}
-  PP_Var var;
-  size_t data_index;
-};
+void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
+  IPC::ParamTraits<SerializedHandle>::Write(m, handle);
+}
 
 // For a given PP_Var, returns the RawVarData associated with it, or creates a
 // new one if there is no existing one. The data is appended to |data| if it
 // is newly created. The index into |data| pointing to the result is returned.
-// |visited_map| keeps track of RawVarDatas that have already been created.
+// |id_map| keeps track of RawVarDatas that have already been created.
 size_t GetOrCreateRawVarData(const PP_Var& var,
-                             base::hash_map<int64_t, size_t>* visited_map,
+                             base::hash_map<int64_t, size_t>* id_map,
                              ScopedVector<RawVarData>* data) {
   if (VarTracker::IsVarTypeRefcounted(var.type)) {
-    base::hash_map<int64_t, size_t>::iterator it = visited_map->find(
+    base::hash_map<int64_t, size_t>::iterator it = id_map->find(
         var.value.as_id);
-    if (it != visited_map->end()) {
+    if (it != id_map->end()) {
       return it->second;
     } else {
       data->push_back(RawVarData::Create(var.type));
-      (*visited_map)[var.value.as_id] = data->size() - 1;
+      (*id_map)[var.value.as_id] = data->size() - 1;
     }
   } else {
     data->push_back(RawVarData::Create(var.type));
@@ -59,10 +57,6 @@ size_t GetOrCreateRawVarData(const PP_Var& var,
   return data->size() - 1;
 }
 
-bool CanHaveChildren(PP_Var var) {
-  return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY;
-}
-
 }  // namespace
 
 // RawVarDataGraph ------------------------------------------------------------
@@ -72,40 +66,27 @@ RawVarDataGraph::RawVarDataGraph() {
 RawVarDataGraph::~RawVarDataGraph() {
 }
 
-// This function uses a stack-based DFS search to traverse the var graph. Each
-// iteration, the top node on the stack examined. If the node has not been
-// visited yet (i.e. !initialized()) then it is added to the list of
-// |parent_ids| which contains all of the nodes on the path from the start node
-// to the current node. Each of that nodes children are examined. If they appear
-// in the list of |parent_ids| it means we have a cycle and we return NULL.
-// Otherwise, if they haven't been visited yet we add them to the stack, If the
-// node at the top of the stack has already been visited, then we pop it off the
-// stack and erase it from |parent_ids|.
 // static
 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
                                                     PP_Instance instance) {
   scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
   // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
-  base::hash_map<int64_t, size_t> visited_map;
-  base::hash_set<int64_t> parent_ids;
+  base::hash_map<int64_t, size_t> id_map;
 
-  std::stack<StackEntry> stack;
-  stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map,
-                                                   &graph->data_)));
+  std::stack<std::pair<PP_Var, size_t> > stack;
+  stack.push(make_pair(var, GetOrCreateRawVarData(var, &id_map,
+                                                  &graph->data_)));
 
+  // Traverse the PP_Var graph with DFS.
   while (!stack.empty()) {
-    PP_Var current_var = stack.top().var;
-    RawVarData* current_var_data = graph->data_[stack.top().data_index];
+    PP_Var current_var = stack.top().first;
+    RawVarData* current_var_data = graph->data_[stack.top().second];
+    stack.pop();
 
-    if (current_var_data->initialized()) {
-      stack.pop();
-      if (CanHaveChildren(current_var))
-        parent_ids.erase(current_var.value.as_id);
+    // If the node is initialized, it means we have visited it.
+    if (current_var_data->initialized())
       continue;
-    }
 
-    if (CanHaveChildren(current_var))
-      parent_ids.insert(current_var.value.as_id);
     if (!current_var_data->Init(current_var, instance)) {
       NOTREACHED();
       return scoped_ptr<RawVarDataGraph>();
@@ -122,16 +103,10 @@ scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
                array_var->elements().begin();
            iter != array_var->elements().end();
            ++iter) {
-        const PP_Var& child = iter->get();
-        // If a child of this node is already in parent_ids, we have a cycle so
-        // we just return null.
-        if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
-          return scoped_ptr<RawVarDataGraph>();
-        size_t child_id = GetOrCreateRawVarData(child, &visited_map,
+        size_t child_id = GetOrCreateRawVarData(iter->get(), &id_map,
                                                 &graph->data_);
         static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
-        if (!graph->data_[child_id]->initialized())
-          stack.push(StackEntry(child, child_id));
+        stack.push(make_pair(iter->get(), child_id));
       }
     } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
       DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
@@ -143,15 +118,11 @@ scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
                dict_var->key_value_map().begin();
            iter != dict_var->key_value_map().end();
            ++iter) {
-        const PP_Var& child = iter->second.get();
-        if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
-          return scoped_ptr<RawVarDataGraph>();
-        size_t child_id = GetOrCreateRawVarData(child, &visited_map,
+        size_t child_id = GetOrCreateRawVarData(iter->second.get(), &id_map,
                                                 &graph->data_);
         static_cast<DictionaryRawVarData*>(
             current_var_data)->AddChild(iter->first, child_id);
-        if (!graph->data_[child_id]->initialized())
-          stack.push(StackEntry(child, child_id));
+        stack.push(make_pair(iter->second.get(), child_id));
       }
     }
   }
@@ -182,6 +153,10 @@ void RawVarDataGraph::Write(IPC::Message* m,
   }
 }
 
+void RawVarDataGraph::Write(IPC::Message* m) {
+  Write(m, base::Bind(&DefaultHandleWriter));
+}
+
 // static
 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Read(const IPC::Message* m,
                                                   PickleIterator* iter) {
diff --git a/ppapi/proxy/raw_var_data.h b/ppapi/proxy/raw_var_data.h
index c7981d3..1e8746f 100644
--- a/ppapi/proxy/raw_var_data.h
+++ b/ppapi/proxy/raw_var_data.h
@@ -65,6 +65,8 @@ class PPAPI_PROXY_EXPORT RawVarDataGraph {
 
   // Write the graph to a message using the given HandleWriter.
   void Write(IPC::Message* m, const HandleWriter& handle_writer);
+  // Write the graph to a message using the default handle writer.
+  void Write(IPC::Message* m);
 
   // Create a RawVarDataGraph from the given message.
   static scoped_ptr<RawVarDataGraph> Read(const IPC::Message* m,
diff --git a/ppapi/proxy/raw_var_data_unittest.cc b/ppapi/proxy/raw_var_data_unittest.cc
index 2ee6914..2b134af 100644
--- a/ppapi/proxy/raw_var_data_unittest.cc
+++ b/ppapi/proxy/raw_var_data_unittest.cc
@@ -26,10 +26,6 @@ namespace proxy {
 
 namespace {
 
-void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
-  IPC::ParamTraits<SerializedHandle>::Write(m, handle);
-}
-
 class RawVarDataTest : public testing::Test {
  public:
   RawVarDataTest() {}
@@ -48,28 +44,21 @@ class RawVarDataTest : public testing::Test {
   TestGlobals globals_;
 };
 
-bool WriteAndRead(const PP_Var& var, PP_Var* result) {
+PP_Var WriteAndRead(const PP_Var& var) {
   PP_Instance dummy_instance = 1234;
   scoped_ptr<RawVarDataGraph> expected_data(RawVarDataGraph::Create(
       var, dummy_instance));
-  if (!expected_data)
-    return false;
   IPC::Message m;
-  expected_data->Write(&m, base::Bind(&DefaultHandleWriter));
+  expected_data->Write(&m);
   PickleIterator iter(m);
   scoped_ptr<RawVarDataGraph> actual_data(RawVarDataGraph::Read(&m, &iter));
-  *result = actual_data->CreatePPVar(dummy_instance);
-  return true;
+  return actual_data->CreatePPVar(dummy_instance);
 }
 
 // Assumes a ref for var.
 bool WriteReadAndCompare(const PP_Var& var) {
   ScopedPPVar expected(ScopedPPVar::PassRef(), var);
-  PP_Var result;
-  bool success = WriteAndRead(expected.get(), &result);
-  if (!success)
-    return false;
-  ScopedPPVar actual(ScopedPPVar::PassRef(), result);
+  ScopedPPVar actual(ScopedPPVar::PassRef(), WriteAndRead(expected.get()));
   return TestEqual(expected.get(), actual.get());
 }
 
@@ -171,18 +160,25 @@ TEST_F(RawVarDataTest, DictionaryArrayTest) {
 
   // Array <-> dictionary cycle.
   dictionary->SetWithStringKey("10", release_array.get());
-  PP_Var result;
-  ASSERT_FALSE(WriteAndRead(release_dictionary.get(), &result));
+  ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(),
+                                   WriteAndRead(release_dictionary.get()));
+  EXPECT_TRUE(TestEqual(release_dictionary.get(), result.get()));
   // Break the cycle.
   // TODO(raymes): We need some better machinery for releasing vars with
   // cycles. Remove the code below once we have that.
   dictionary->DeleteWithStringKey("10");
+  DictionaryVar* result_dictionary = DictionaryVar::FromPPVar(result.get());
+  result_dictionary->DeleteWithStringKey("10");
 
   // Array with self references.
   array->Set(index, release_array.get());
-  ASSERT_FALSE(WriteAndRead(release_array.get(), &result));
+  result = ScopedPPVar(ScopedPPVar::PassRef(),
+                       WriteAndRead(release_array.get()));
+  EXPECT_TRUE(TestEqual(release_array.get(), result.get()));
   // Break the self reference.
   array->Set(index, PP_MakeUndefined());
+  ArrayVar* result_array = ArrayVar::FromPPVar(result.get());
+  result_array->Set(index, PP_MakeUndefined());
 }
 
 }  // namespace proxy
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
index 72e7cc8..1217a83 100644
--- a/ppapi/proxy/serialized_var.cc
+++ b/ppapi/proxy/serialized_var.cc
@@ -18,20 +18,13 @@
 namespace ppapi {
 namespace proxy {
 
-namespace {
-void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
-  IPC::ParamTraits<SerializedHandle>::Write(m, handle);
-}
-}  // namespace
-
 // SerializedVar::Inner --------------------------------------------------------
 
 SerializedVar::Inner::Inner()
     : serialization_rules_(NULL),
       var_(PP_MakeUndefined()),
       instance_(0),
-      cleanup_mode_(CLEANUP_NONE),
-      is_valid_var_(true) {
+      cleanup_mode_(CLEANUP_NONE) {
 #ifndef NDEBUG
   has_been_serialized_ = false;
   has_been_deserialized_ = false;
@@ -114,24 +107,7 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
   DCHECK(!has_been_serialized_);
   has_been_serialized_ = true;
 #endif
-  scoped_ptr<RawVarDataGraph> data = RawVarDataGraph::Create(var_, instance_);
-  if (data) {
-    m->WriteBool(true);  // Success.
-    data->Write(m, base::Bind(&DefaultHandleWriter));
-  } else {
-    m->WriteBool(false);  // Failure.
-  }
-}
-
-void SerializedVar::Inner::WriteDataToMessage(
-    IPC::Message* m,
-    const HandleWriter& handle_writer) const {
-  if (raw_var_data_) {
-    m->WriteBool(true);  // Success.
-    raw_var_data_->Write(m, handle_writer);
-  } else {
-    m->WriteBool(false);  // Failure.
-  }
+  RawVarDataGraph::Create(var_, instance_)->Write(m);
 }
 
 bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
@@ -149,15 +125,8 @@ bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
 #endif
   // When reading, the dispatcher should be set when we get a Deserialize
   // call (which will supply a dispatcher).
-  if (!m->ReadBool(iter, &is_valid_var_))
-      return false;
-  if (is_valid_var_) {
-    raw_var_data_ = RawVarDataGraph::Read(m, iter);
-    if (!raw_var_data_)
-      return false;
-  }
-
-  return true;
+  raw_var_data_ = RawVarDataGraph::Read(m, iter);
+  return raw_var_data_.get() != NULL;
 }
 
 void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h
index 0b8e796..98cafa0 100644
--- a/ppapi/proxy/serialized_var.h
+++ b/ppapi/proxy/serialized_var.h
@@ -80,24 +80,12 @@ class PPAPI_PROXY_EXPORT SerializedVar {
   void WriteToMessage(IPC::Message* m) const {
     inner_->WriteToMessage(m);
   }
-  // If ReadFromMessage has been called, WriteDataToMessage will write the var
-  // that has been read from ReadFromMessage back to a message. This is used
-  // when converting handles for use in NaCl.
-  void WriteDataToMessage(IPC::Message* m,
-                          const HandleWriter& handle_writer) const {
-    inner_->WriteDataToMessage(m, handle_writer);
-  }
   bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter) {
     return inner_->ReadFromMessage(m, iter);
   }
 
-  bool is_valid_var() const {
-    return inner_->is_valid_var();
-  }
-
-  // Returns the shared memory handles associated with this SerializedVar.
-  std::vector<SerializedHandle*> GetHandles() const {
-    return inner_->GetHandles();
+  RawVarDataGraph* raw_var_data() const {
+    return inner_->raw_var_data();
   }
 
  protected:
@@ -122,13 +110,8 @@ class PPAPI_PROXY_EXPORT SerializedVar {
       serialization_rules_ = serialization_rules;
     }
 
-    bool is_valid_var() const {
-      return is_valid_var_;
-    }
-
-    std::vector<SerializedHandle*> GetHandles() {
-      return (raw_var_data_ ? raw_var_data_->GetHandles() :
-          std::vector<SerializedHandle*>());
+    RawVarDataGraph* raw_var_data() {
+      return raw_var_data_.get();
     }
 
     // See outer class's declarations above.
@@ -141,8 +124,6 @@ class PPAPI_PROXY_EXPORT SerializedVar {
     void ForceSetVarValueForTest(PP_Var value);
 
     void WriteToMessage(IPC::Message* m) const;
-    void WriteDataToMessage(IPC::Message* m,
-                            const HandleWriter& handle_writer) const;
     bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter);
 
     // Sets the cleanup mode. See the CleanupMode enum below.
@@ -181,9 +162,6 @@ class PPAPI_PROXY_EXPORT SerializedVar {
 
     CleanupMode cleanup_mode_;
 
-    // If the var is not properly serialized, this will be false.
-    bool is_valid_var_;
-
 #ifndef NDEBUG
     // When being sent or received over IPC, we should only be serialized or
     // deserialized once. These flags help us assert this is true.
@@ -364,7 +342,6 @@ class PPAPI_PROXY_EXPORT SerializedVarReceiveInput {
 
   PP_Var Get(Dispatcher* dispatcher);
   PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
-  bool is_valid_var() { return serialized_.is_valid_var(); }
 
  private:
   const SerializedVar& serialized_;
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
index 944b5614..8c67ee5 100644
--- a/ppapi/tests/test_post_message.cc
+++ b/ppapi/tests/test_post_message.cc
@@ -238,16 +238,6 @@ bool TestPostMessage::AddEchoingListener(const std::string& expression) {
   return true;
 }
 
-bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) {
-  std::string js_code;
-  js_code += "var plugin = document.getElementById('plugin');"
-             "plugin.postMessage(";
-  js_code += func + "()";
-  js_code += "                      );";
-  instance_->EvalScript(js_code);
-  return true;
-}
-
 bool TestPostMessage::ClearListeners() {
   std::string js_code;
   js_code += "var plugin = document.getElementById('plugin');"
@@ -533,7 +523,6 @@ std::string TestPostMessage::TestSendingComplexVar() {
   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
   // should start with these.
   WaitForMessages();
-  message_data_.clear();
   ASSERT_TRUE(ClearListeners());
 
   pp::Var string(kTestString);
@@ -542,6 +531,7 @@ std::string TestPostMessage::TestSendingComplexVar() {
   dictionary.Set(pp::Var("bar"), string);
   dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
   dictionary.Set(pp::Var("def"), pp::Var());
+  dictionary.Set(pp::Var("dictionary"), dictionary);  // Self-reference.
 
   // Reference to array.
   pp::VarArray_Dev array;
@@ -554,9 +544,15 @@ std::string TestPostMessage::TestSendingComplexVar() {
   dictionary.Set(pp::Var("array-ref1"), array);
   dictionary.Set(pp::Var("array-ref2"), array);
 
+  // Set up a (dictionary -> array -> dictionary) cycle.
+  pp::VarArray_Dev array2;
+  array2.Set(0, dictionary);
+  dictionary.Set(pp::Var("array2"), array2);
+
   // Set up the JavaScript message event listener to echo the data part of the
   // message event back to us.
   ASSERT_TRUE(AddEchoingListener("message_event.data"));
+  message_data_.clear();
   instance_->PostMessage(dictionary);
   // PostMessage is asynchronous, so we should not receive a response yet.
   ASSERT_EQ(message_data_.size(), 0);
@@ -565,36 +561,12 @@ std::string TestPostMessage::TestSendingComplexVar() {
   pp::VarDictionary_Dev result(message_data_.back());
   ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
 
-  WaitForMessages();
-  message_data_.clear();
-  ASSERT_TRUE(ClearListeners());
-
-  // Set up a (dictionary -> array -> dictionary) cycle. Cycles shouldn't be
-  // transmitted.
-  pp::VarArray_Dev array2;
-  array2.Set(0, dictionary);
-  dictionary.Set(pp::Var("array2"), array2);
-
-  ASSERT_TRUE(AddEchoingListener("message_event.data"));
-  instance_->PostMessage(dictionary);
-  // PostMessage is asynchronous, so we should not receive a response yet.
-  ASSERT_EQ(message_data_.size(), 0);
-  ASSERT_EQ(WaitForMessages(), 0);
-
   // Break the cycles.
+  dictionary.Delete(pp::Var("dictionary"));
   dictionary.Delete(pp::Var("array2"));
+  result.Delete(pp::Var("dictionary"));
+  result.Delete(pp::Var("array2"));
 
-  WaitForMessages();
-  message_data_.clear();
-  ASSERT_TRUE(ClearListeners());
-
-  // Test sending a cycle from JavaScript to the plugin.
-  ASSERT_TRUE(AddEchoingListener("message_event.data"));
-  PostMessageFromJavaScript("function() { var x = []; x[0] = x; return x; }");
-  ASSERT_EQ(message_data_.size(), 0);
-  ASSERT_EQ(WaitForMessages(), 0);
-
-  WaitForMessages();
   message_data_.clear();
   ASSERT_TRUE(ClearListeners());
 
diff --git a/ppapi/tests/test_post_message.h b/ppapi/tests/test_post_message.h
index 2f2f628..3ea69e8 100644
--- a/ppapi/tests/test_post_message.h
+++ b/ppapi/tests/test_post_message.h
@@ -34,10 +34,6 @@ class TestPostMessage : public TestCase {
   // Returns true on success, false on failure.
   bool AddEchoingListener(const std::string& expression);
 
-  // Posts a message from JavaScript to the plugin. |func| should be a
-  // JavaScript function which returns the variable to post.
-  bool PostMessageFromJavaScript(const std::string& func);
-
   // Clear any listeners that have been added using AddEchoingListener by
   // calling removeEventListener for each.
   // Returns true on success, false on failure.
-- 
cgit v1.1