15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_proxy_test.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/serialized_var.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var MakeObjectVar(int64_t object_id) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var ret;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ret.type = PP_VARTYPE_OBJECT;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ret.value.as_id = object_id;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SerializedVarTest : public PluginProxyTest {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SerializedVarTest() {}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests output arguments in the plugin. This is when the host calls into the
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// plugin and the plugin returns something via an out param, like an exception.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginSerializedVarInOutParam) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var host_object = MakeObjectVar(0x31337);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var plugin_object;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the object param, we should be tracking it with no refcount, and
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // no messages sent.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input(host_object);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarReceiveInput receive_input(input);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_object = receive_input.Get(plugin_dispatcher());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVar sv;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The "OutParam" does its work in its destructor, it will write the
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // information to the SerializedVar we passed in the constructor.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SerializedVarOutParam out_param(&sv);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // An out-param needs to pass a reference to the caller, so it's the
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // responsibility of the plugin to bump the ref-count on an input
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // parameter.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var_tracker().AddRefVar(plugin_object);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We should have informed the host that a reference was taken.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(1u, sink().message_count());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out_param.OutParam(plugin_dispatcher()) = plugin_object;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The object should have transformed the plugin object back to the host
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // object ID. Nothing in the var tracker should have changed yet, and no
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // messages should have been sent.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestReader reader(sv);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(host_object.value.as_id, reader.GetVar().value.as_id);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, sink().message_count());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The out param should have done an "end receive caller owned" on the plugin
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // var serialization rules, which should have released the "track-with-no-
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference" count in the var tracker as well as the 1 reference we passed
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back to the host, so the object should no longer be in the tracker. The
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference we added has been removed, so another message should be sent to
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the host to tell it we're done with the object.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, sink().message_count());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests output strings in the plugin. This is when the host calls into the
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// plugin with a string and the plugin returns it via an out param.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginSerializedStringVarInOutParam) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var plugin_string;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTestString("elite");
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the string param. We should track it with 1 refcount.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input(kTestString);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarReceiveInput receive_input(input);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_string = receive_input.Get(plugin_dispatcher());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_string));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVar sv;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The "OutParam" does its work in its destructor, it will write the
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // information to the SerializedVar we passed in the constructor.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SerializedVarOutParam out_param(&sv);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // An out-param needs to pass a reference to the caller, so it's the
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // responsibility of the plugin to bump the ref-count of an input
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // parameter.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var_tracker().AddRefVar(plugin_string);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0u, sink().message_count());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out_param.OutParam(plugin_dispatcher()) = plugin_string;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The SerializedVar should have set the string value internally. Nothing in
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the var tracker should have changed yet, and no messages should have been
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sent.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestReader reader(sv);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //EXPECT_EQ(kTestString, *reader.GetTrackerStringPtr());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The reference the string had initially should be gone, and the reference we
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // passed to the host should also be gone, so the string should be removed.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_string));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, sink().message_count());
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests receiving an argument and passing it back to the browser as an output
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameter.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginSerializedVarOutParam) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var host_object = MakeObjectVar(0x31337);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start tracking this object in the plugin.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var plugin_object = var_tracker().ReceiveObjectPassRef(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_object, plugin_dispatcher());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVar sv;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The "OutParam" does its work in its destructor, it will write the
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // information to the SerializedVar we passed in the constructor.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SerializedVarOutParam out_param(&sv);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out_param.OutParam(plugin_dispatcher()) = plugin_object;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The object should have transformed the plugin object back to the host
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // object ID. Nothing in the var tracker should have changed yet, and no
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // messages should have been sent.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestReader reader(sv);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(host_object.value.as_id, reader.GetVar().value.as_id);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The out param should have done an "end send pass ref" on the plugin
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // var serialization rules, which should have in turn released the reference
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the var tracker. Since we only had one reference, this should have sent
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a release to the browser.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, sink().message_count());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't bother validating that message since it's nontrivial and the
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PluginVarTracker test has cases that cover that this message is correct.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the case that the plugin receives the same var twice as an input
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameter (not passing ownership).
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginReceiveInput) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var host_object = MakeObjectVar(0x31337);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var plugin_object;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the first param, we should be tracking it with no refcount, and
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // no messages sent.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input1(host_object);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarReceiveInput receive_input(input1);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_object = receive_input.Get(plugin_dispatcher());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the second param, it should be resolved to the same plugin
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // object and there should still be no refcount.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input2(host_object);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarReceiveInput receive_input2(input2);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var plugin_object2 = receive_input2.Get(plugin_dispatcher());
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Take a reference to the object, as if the plugin was using it, and then
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // release it, we should still be tracking the object since the
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ReceiveInputs keep the "track_with_no_reference_count" alive until
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // they're destroyed.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_tracker().AddRefVar(plugin_object);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_tracker().ReleaseVar(plugin_object);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2u, sink().message_count());
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we didn't keep any refs to the objects, it should have freed the
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the case that the plugin receives the same vars twice as an input
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameter (not passing ownership) within a vector.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginVectorReceiveInput) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var host_object = MakeObjectVar(0x31337);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PP_Var> plugin_objects;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PP_Var> plugin_objects2;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the params. The object should be tracked with no refcount and
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // no messages sent. The string should is plugin-side only and should have
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a reference-count of 1.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SerializedVar> input1;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input1.push_back(SerializedVarTestConstructor(host_object));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input1.push_back(SerializedVarTestConstructor("elite"));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarVectorReceiveInput receive_input(input1);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t array_size = 0;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var* plugin_objects_array =
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        receive_input.Get(plugin_dispatcher(), &array_size);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_objects.insert(plugin_objects.begin(), plugin_objects_array,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          plugin_objects_array + array_size);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(2u, array_size);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0]));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[1]));
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the second param, it should be resolved to the same plugin
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // object and there should still be no refcount.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SerializedVar> input2;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input2.push_back(SerializedVarTestConstructor(host_object));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input2.push_back(SerializedVarTestConstructor("elite"));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarVectorReceiveInput receive_input2(input2);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t array_size2 = 0;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var* plugin_objects_array2 =
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        receive_input2.Get(plugin_dispatcher(), &array_size2);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_objects2.insert(plugin_objects2.begin(), plugin_objects_array2,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           plugin_objects_array2 + array_size2);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(2u, array_size2);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(plugin_objects[0].value.as_id, plugin_objects2[0].value.as_id);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0]));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings get re-created with a new ID. We don't try to reuse strings in
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the tracker, so the string should get a new ID.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(plugin_objects[1].value.as_id, plugin_objects2[1].value.as_id);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects2[1]));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Take a reference to the object, as if the plugin was using it, and then
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // release it, we should still be tracking the object since the
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ReceiveInputs keep the "track_with_no_reference_count" alive until
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // they're destroyed.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_tracker().AddRefVar(plugin_objects[0]);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[0]));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_tracker().ReleaseVar(plugin_objects[0]);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0]));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2u, sink().message_count());
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Take a reference to a string and then release it. Make sure no messages
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // are sent.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t old_message_count = sink().message_count();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_tracker().AddRefVar(plugin_objects[1]);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_objects[1]));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_tracker().ReleaseVar(plugin_objects[1]);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[1]));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(old_message_count, sink().message_count());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we didn't keep any refs to the objects or strings, so they should
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have been freed.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects[0]));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects[1]));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects2[1]));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the plugin receiving a var as a return value from the browser
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// two different times (passing ownership).
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginReceiveReturn) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var host_object = MakeObjectVar(0x31337);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var plugin_object;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the first param, we should be tracking it with a refcount of 1.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input1(host_object);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReceiveSerializedVarReturnValue receive_input(input1);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_object = receive_input.Return(plugin_dispatcher());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the second param, it should be resolved to the same plugin
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // object and there should be a plugin refcount of 2. There should have
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // been an IPC message sent that released the duplicated ref in the browser
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (so both of our refs are represented by one in the browser).
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input2(host_object);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReceiveSerializedVarReturnValue receive_input2(input2);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var plugin_object2 = receive_input2.Return(plugin_dispatcher());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_object));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, sink().message_count());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ReceiveSerializedVarReturnValue destructor shouldn't have affected
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the refcount or sent any messages.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_object));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, sink().message_count());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Manually release one refcount, it shouldn't have sent any more messages.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_tracker().ReleaseVar(plugin_object);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, sink().message_count());
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Manually release the last refcount, it should have freed it and sent a
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // release message to the browser.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_tracker().ReleaseVar(plugin_object);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, sink().message_count());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a value from the browser to the plugin, then return that one ref
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// back to the browser.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SerializedVarTest, PluginReturnValue) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var host_object = MakeObjectVar(0x31337);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var plugin_object;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Receive the param in the plugin.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarTestConstructor input1(host_object);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReceiveSerializedVarReturnValue receive_input(input1);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_object = receive_input.Return(plugin_dispatcher());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, sink().message_count());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now return to the browser.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVar output;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedVarReturnValue return_output(&output);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return_output.Return(plugin_dispatcher(), plugin_object);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The ref in the plugin should be alive until the ReturnValue goes out of
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // scope, since the release needs to be after the browser processes the
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // message.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the ReturnValue object goes out of scope, it should have sent a
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // release message to the browser.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, sink().message_count());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
355