Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ppapi/tests/test_post_message.h"
      6 
      7 #include <algorithm>
      8 #include <map>
      9 #include <sstream>
     10 
     11 #include "ppapi/c/dev/ppb_testing_dev.h"
     12 #include "ppapi/c/pp_var.h"
     13 #include "ppapi/cpp/instance.h"
     14 #include "ppapi/cpp/var.h"
     15 #include "ppapi/cpp/var_array.h"
     16 #include "ppapi/cpp/var_array_buffer.h"
     17 #include "ppapi/cpp/var_dictionary.h"
     18 #include "ppapi/tests/pp_thread.h"
     19 #include "ppapi/tests/test_utils.h"
     20 #include "ppapi/tests/testing_instance.h"
     21 
     22 // Windows defines 'PostMessage', so we have to undef it.
     23 #ifdef PostMessage
     24 #undef PostMessage
     25 #endif
     26 
     27 REGISTER_TEST_CASE(PostMessage);
     28 
     29 namespace {
     30 
     31 const char kTestString[] = "Hello world!";
     32 const bool kTestBool = true;
     33 const int32_t kTestInt = 42;
     34 const double kTestDouble = 42.0;
     35 
     36 // On Windows XP bots, the NonMainThread test can run very slowly. So we dial
     37 // back the number of threads & messages when running on Windows.
     38 #ifdef PPAPI_OS_WIN
     39 const int32_t kThreadsToRun = 2;
     40 const int32_t kMessagesToSendPerThread = 5;
     41 #else
     42 const int32_t kThreadsToRun = 4;
     43 const int32_t kMessagesToSendPerThread = 10;
     44 #endif
     45 
     46 // The struct that invoke_post_message_thread_func expects for its argument.
     47 // It includes the instance on which to invoke PostMessage, and the value to
     48 // pass to PostMessage.
     49 struct InvokePostMessageThreadArg {
     50   InvokePostMessageThreadArg(pp::Instance* i, const pp::Var& v)
     51       : instance(i), value_to_send(v) {}
     52   pp::Instance* instance;
     53   pp::Var value_to_send;
     54 };
     55 
     56 void InvokePostMessageThreadFunc(void* user_data) {
     57   InvokePostMessageThreadArg* arg =
     58       static_cast<InvokePostMessageThreadArg*>(user_data);
     59   for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
     60     arg->instance->PostMessage(arg->value_to_send);
     61   delete arg;
     62 }
     63 
     64 // TODO(raymes): Consider putting something like this into pp::Var.
     65 bool VarsEqual(const pp::Var& expected,
     66                const pp::Var& actual,
     67                std::map<int64_t, int64_t>* visited_ids) {
     68   if (expected.pp_var().type != actual.pp_var().type) {
     69     if (!expected.is_number() && !actual.is_number())
     70       return false;
     71   }
     72   // TODO(raymes): Implement a pp::Var::IsRefCounted() function.
     73   if (expected.pp_var().type > PP_VARTYPE_DOUBLE) {
     74     std::map<int64_t, int64_t>::const_iterator it =
     75         visited_ids->find(expected.pp_var().value.as_id);
     76     if (it != visited_ids->end()) {
     77       if (it->second == actual.pp_var().value.as_id)
     78         return true;
     79       return false;
     80     }
     81     (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id;
     82   }
     83 
     84   if (expected.is_number()) {
     85     return fabs(expected.AsDouble() - actual.AsDouble()) < 1.0e-4;
     86   } else if (expected.is_array()) {
     87     pp::VarArray expected_array(expected);
     88     pp::VarArray actual_array(actual);
     89     if (expected_array.GetLength() != actual_array.GetLength())
     90       return false;
     91     for (uint32_t i = 0; i < expected_array.GetLength(); ++i) {
     92       if (!VarsEqual(expected_array.Get(i), actual_array.Get(i), visited_ids))
     93         return false;
     94     }
     95     return true;
     96   } else if (expected.is_dictionary()) {
     97     pp::VarDictionary expected_dict(expected);
     98     pp::VarDictionary actual_dict(actual);
     99     if (expected_dict.GetKeys().GetLength() !=
    100         actual_dict.GetKeys().GetLength()) {
    101       return false;
    102     }
    103     for (uint32_t i = 0; i < expected_dict.GetKeys().GetLength(); ++i) {
    104       pp::Var key = expected_dict.GetKeys().Get(i);
    105       if (!actual_dict.HasKey(key))
    106         return false;
    107       if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids))
    108         return false;
    109     }
    110     return true;
    111   } else {
    112     return expected == actual;
    113   }
    114 }
    115 
    116 bool VarsEqual(const pp::Var& expected,
    117                const pp::Var& actual) {
    118   std::map<int64_t, int64_t> visited_ids;
    119   return VarsEqual(expected, actual, &visited_ids);
    120 }
    121 
    122 class ScopedArrayBufferSizeSetter {
    123  public:
    124   ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface,
    125                               PP_Instance instance,
    126                               uint32_t threshold)
    127      : interface_(interface),
    128        instance_(instance) {
    129     interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold);
    130   }
    131   ~ScopedArrayBufferSizeSetter() {
    132     interface_->SetMinimumArrayBufferSizeForShmem(instance_, 0);
    133   }
    134  private:
    135   const PPB_Testing_Dev* interface_;
    136   PP_Instance instance_;
    137 };
    138 
    139 #define FINISHED_WAITING_MESSAGE "TEST_POST_MESSAGE_FINISHED_WAITING"
    140 
    141 }  // namespace
    142 
    143 TestPostMessage::TestPostMessage(TestingInstance* instance)
    144     : TestCase(instance) {
    145 }
    146 
    147 TestPostMessage::~TestPostMessage() {
    148   instance_->PostMessage(pp::Var("This isn't guaranteed to be received, but "
    149                                  "shouldn't cause a crash."));
    150 
    151   // Remove the special listener that only responds to a FINISHED_WAITING
    152   // string. See Init for where it gets added.
    153   std::string js_code;
    154   js_code += "var plugin = document.getElementById('plugin');"
    155              "plugin.removeEventListener('message',"
    156              "                           plugin.wait_for_messages_handler);"
    157              "delete plugin.wait_for_messages_handler;";
    158   instance_->EvalScript(js_code);
    159 }
    160 
    161 bool TestPostMessage::Init() {
    162   bool success = CheckTestingInterface();
    163 
    164   // Set up a special listener that only responds to a FINISHED_WAITING string.
    165   // This is for use by WaitForMessages.
    166   std::string js_code;
    167   // Note the following code is dependent on some features of test_case.html.
    168   // E.g., it is assumed that the DOM element where the plugin is embedded has
    169   // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
    170   // us to ignore the messages that are intended for use by the testing
    171   // framework itself.
    172   js_code += "var plugin = document.getElementById('plugin');"
    173              "var wait_for_messages_handler = function(message_event) {"
    174              "  if (!IsTestingMessage(message_event.data) &&"
    175              "      message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
    176              "    plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
    177              "  }"
    178              "};"
    179              "plugin.addEventListener('message', wait_for_messages_handler);"
    180              // Stash it on the plugin so we can remove it in the destructor.
    181              "plugin.wait_for_messages_handler = wait_for_messages_handler;";
    182   instance_->EvalScript(js_code);
    183 
    184   // Set up the JavaScript message event listener to echo the data part of the
    185   // message event back to us.
    186   success = success && AddEchoingListener("message_event.data");
    187   message_data_.clear();
    188   // Send a message that the first test will expect to receive. This is to
    189   // verify that we can send messages when the 'Instance::Init' function is on
    190   // the stack.
    191   instance_->PostMessage(pp::Var(kTestString));
    192 
    193   return success;
    194 }
    195 
    196 void TestPostMessage::RunTests(const std::string& filter) {
    197   // Note: SendInInit must be first, because it expects to receive a message
    198   // that was sent in Init above.
    199   RUN_TEST(SendInInit, filter);
    200   RUN_TEST(SendingData, filter);
    201   RUN_TEST(SendingArrayBuffer, filter);
    202   RUN_TEST(SendingArray, filter);
    203   RUN_TEST(SendingDictionary, filter);
    204   RUN_TEST(SendingComplexVar, filter);
    205   RUN_TEST(MessageEvent, filter);
    206   RUN_TEST(NoHandler, filter);
    207   RUN_TEST(ExtraParam, filter);
    208   if (testing_interface_->IsOutOfProcess())
    209     RUN_TEST(NonMainThread, filter);
    210 }
    211 
    212 void TestPostMessage::HandleMessage(const pp::Var& message_data) {
    213   if (message_data.is_string() &&
    214       (message_data.AsString() == FINISHED_WAITING_MESSAGE))
    215     testing_interface_->QuitMessageLoop(instance_->pp_instance());
    216   else
    217     message_data_.push_back(message_data);
    218 }
    219 
    220 bool TestPostMessage::AddEchoingListener(const std::string& expression) {
    221   std::string js_code;
    222   // Note the following code is dependent on some features of test_case.html.
    223   // E.g., it is assumed that the DOM element where the plugin is embedded has
    224   // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
    225   // us to ignore the messages that are intended for use by the testing
    226   // framework itself.
    227   js_code += "var plugin = document.getElementById('plugin');"
    228              "var message_handler = function(message_event) {"
    229              "  if (!IsTestingMessage(message_event.data) &&"
    230              "      !(message_event.data === '" FINISHED_WAITING_MESSAGE "')) {"
    231              "    plugin.postMessage(";
    232   js_code += expression;
    233   js_code += "                      );"
    234              "  }"
    235              "};"
    236              "plugin.addEventListener('message', message_handler);"
    237              // Maintain an array of all event listeners, attached to the
    238              // plugin. This is so that we can easily remove them later (see
    239              // ClearListeners()).
    240              "if (!plugin.eventListeners) plugin.eventListeners = [];"
    241              "plugin.eventListeners.push(message_handler);";
    242   instance_->EvalScript(js_code);
    243   return true;
    244 }
    245 
    246 bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) {
    247   std::string js_code;
    248   js_code += "var plugin = document.getElementById('plugin');"
    249              "plugin.postMessage(";
    250   js_code += func + "()";
    251   js_code += "                      );";
    252   instance_->EvalScript(js_code);
    253   return true;
    254 }
    255 
    256 bool TestPostMessage::ClearListeners() {
    257   std::string js_code;
    258   js_code += "var plugin = document.getElementById('plugin');"
    259              "while (plugin.eventListeners.length) {"
    260              "  plugin.removeEventListener('message',"
    261              "                             plugin.eventListeners.pop());"
    262              "}";
    263   instance_->EvalScript(js_code);
    264   return true;
    265 }
    266 
    267 int TestPostMessage::WaitForMessages() {
    268   size_t message_size_before = message_data_.size();
    269   // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to
    270   // come back _after_ any other incoming messages that were already pending.
    271   instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
    272   testing_interface_->RunMessageLoop(instance_->pp_instance());
    273   // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know
    274   // that all pending messages have been slurped up. Return the number we
    275   // received (which may be zero).
    276   return message_data_.size() - message_size_before;
    277 }
    278 
    279 std::string TestPostMessage::CheckMessageProperties(
    280     const pp::Var& test_data,
    281     const std::vector<std::string>& properties_to_check) {
    282   typedef std::vector<std::string>::const_iterator Iterator;
    283   for (Iterator iter = properties_to_check.begin();
    284        iter != properties_to_check.end();
    285        ++iter) {
    286     ASSERT_TRUE(AddEchoingListener(*iter));
    287     message_data_.clear();
    288     instance_->PostMessage(test_data);
    289     ASSERT_EQ(message_data_.size(), 0);
    290     ASSERT_EQ(WaitForMessages(), 1);
    291     ASSERT_TRUE(message_data_.back().is_bool());
    292     if (!message_data_.back().AsBool())
    293       return std::string("Failed: ") + *iter;
    294     ASSERT_TRUE(message_data_.back().AsBool());
    295     ASSERT_TRUE(ClearListeners());
    296   }
    297   PASS();
    298 }
    299 
    300 std::string TestPostMessage::TestSendInInit() {
    301   ASSERT_EQ(WaitForMessages(), 1);
    302   // This test assumes Init already sent a message.
    303   ASSERT_EQ(message_data_.size(), 1);
    304   ASSERT_TRUE(message_data_.back().is_string());
    305   ASSERT_EQ(message_data_.back().AsString(), kTestString);
    306   message_data_.clear();
    307   PASS();
    308 }
    309 
    310 std::string TestPostMessage::TestSendingData() {
    311   // Clean up after previous tests. This also swallows the message sent by Init
    312   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
    313   // should start with these.
    314   WaitForMessages();
    315   ASSERT_TRUE(ClearListeners());
    316   // Set up the JavaScript message event listener to echo the data part of the
    317   // message event back to us.
    318   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    319 
    320   // Test sending a message to JavaScript for each supported type.  The JS sends
    321   // the data back to us, and we check that they match.
    322   message_data_.clear();
    323   instance_->PostMessage(pp::Var(kTestString));
    324   // PostMessage is asynchronous, so we should not receive a response yet.
    325   ASSERT_EQ(message_data_.size(), 0);
    326   ASSERT_EQ(WaitForMessages(), 1);
    327   ASSERT_TRUE(message_data_.back().is_string());
    328   ASSERT_EQ(message_data_.back().AsString(), kTestString);
    329 
    330   message_data_.clear();
    331   instance_->PostMessage(pp::Var(kTestBool));
    332   ASSERT_EQ(message_data_.size(), 0);
    333   ASSERT_EQ(WaitForMessages(), 1);
    334   ASSERT_TRUE(message_data_.back().is_bool());
    335   ASSERT_EQ(message_data_.back().AsBool(), kTestBool);
    336 
    337   message_data_.clear();
    338   instance_->PostMessage(pp::Var(kTestInt));
    339   ASSERT_EQ(message_data_.size(), 0);
    340   ASSERT_EQ(WaitForMessages(), 1);
    341   ASSERT_TRUE(message_data_.back().is_number());
    342   ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(),
    343                    static_cast<double>(kTestInt));
    344 
    345   message_data_.clear();
    346   instance_->PostMessage(pp::Var(kTestDouble));
    347   ASSERT_EQ(message_data_.size(), 0);
    348   ASSERT_EQ(WaitForMessages(), 1);
    349   ASSERT_TRUE(message_data_.back().is_number());
    350   ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(), kTestDouble);
    351 
    352   message_data_.clear();
    353   instance_->PostMessage(pp::Var());
    354   ASSERT_EQ(message_data_.size(), 0);
    355   ASSERT_EQ(WaitForMessages(), 1);
    356   ASSERT_TRUE(message_data_.back().is_undefined());
    357 
    358   message_data_.clear();
    359   instance_->PostMessage(pp::Var(pp::Var::Null()));
    360   ASSERT_EQ(message_data_.size(), 0);
    361   ASSERT_EQ(WaitForMessages(), 1);
    362   ASSERT_TRUE(message_data_.back().is_null());
    363 
    364   message_data_.clear();
    365   ASSERT_TRUE(ClearListeners());
    366 
    367   PASS();
    368 }
    369 
    370 std::string TestPostMessage::TestSendingArrayBuffer() {
    371   // Clean up after previous tests. This also swallows the message sent by Init
    372   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
    373   // should start with these.
    374   WaitForMessages();
    375   ASSERT_TRUE(ClearListeners());
    376 
    377   // TODO(sehr,dmichael): Add testing of longer array buffers when
    378   // crbug.com/110086 is fixed.
    379   ScopedArrayBufferSizeSetter setter(testing_interface_,
    380                                      instance_->pp_instance(),
    381                                      200);
    382   uint32_t sizes[] = { 0, 100, 1000, 10000 };
    383   for (size_t i = 0; i < sizeof(sizes)/sizeof(sizes[i]); ++i) {
    384     std::ostringstream size_stream;
    385     size_stream << sizes[i];
    386     const std::string kSizeAsString(size_stream.str());
    387 
    388     // Create an appropriately sized array buffer with test_data[i] == i.
    389     pp::VarArrayBuffer test_data(sizes[i]);
    390     if (sizes[i] > 0)
    391       ASSERT_NE(NULL, test_data.Map());
    392     // Make sure we can Unmap/Map successfully (there's not really any way to
    393     // detect if it's unmapped, so we just re-map before getting the pointer to
    394     // the buffer).
    395     test_data.Unmap();
    396     test_data.Map();
    397     ASSERT_EQ(sizes[i], test_data.ByteLength());
    398     unsigned char* buff = static_cast<unsigned char*>(test_data.Map());
    399     const uint32_t kByteLength = test_data.ByteLength();
    400     for (size_t j = 0; j < kByteLength; ++j)
    401       buff[j] = static_cast<uint8_t>(j % 256u);
    402 
    403     // Have the listener test some properties of the ArrayBuffer.
    404     std::vector<std::string> properties_to_check;
    405     properties_to_check.push_back(
    406         "message_event.data.constructor.name === 'ArrayBuffer'");
    407     properties_to_check.push_back(
    408         std::string("message_event.data.byteLength === ") + kSizeAsString);
    409     if (sizes[i] > 0) {
    410       properties_to_check.push_back(
    411           "(new DataView(message_event.data)).getUint8(0) == 0");
    412       // Checks that the last element has the right value: (byteLength-1)%256.
    413       std::string received_byte("(new DataView(message_event.data)).getUint8("
    414                                 "    message_event.data.byteLength-1)");
    415       std::string expected_byte("(message_event.data.byteLength-1)%256");
    416       properties_to_check.push_back(received_byte + " == " + expected_byte);
    417     }
    418     ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(test_data,
    419                                                   properties_to_check));
    420 
    421     // Set up the JavaScript message event listener to echo the data part of the
    422     // message event back to us.
    423     ASSERT_TRUE(AddEchoingListener("message_event.data"));
    424     message_data_.clear();
    425     instance_->PostMessage(test_data);
    426     // PostMessage is asynchronous, so we should not receive a response yet.
    427     ASSERT_EQ(message_data_.size(), 0);
    428     ASSERT_EQ(WaitForMessages(), 1);
    429     ASSERT_TRUE(message_data_.back().is_array_buffer());
    430     pp::VarArrayBuffer received(message_data_.back());
    431     message_data_.clear();
    432     ASSERT_EQ(test_data.ByteLength(), received.ByteLength());
    433     unsigned char* received_buff = static_cast<unsigned char*>(received.Map());
    434     // The buffer should be copied, so this should be a distinct buffer. When
    435     // 'transferrables' are implemented for PPAPI, we'll also want to test that
    436     // we get the _same_ buffer back when it's transferred.
    437     if (sizes[i] > 0)
    438       ASSERT_NE(buff, received_buff);
    439     for (size_t i = 0; i < test_data.ByteLength(); ++i)
    440       ASSERT_EQ(buff[i], received_buff[i]);
    441 
    442     message_data_.clear();
    443     ASSERT_TRUE(ClearListeners());
    444   }
    445 
    446   PASS();
    447 }
    448 
    449 std::string TestPostMessage::TestSendingArray() {
    450   // Clean up after previous tests. This also swallows the message sent by Init
    451   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
    452   // should start with these.
    453   WaitForMessages();
    454   ASSERT_TRUE(ClearListeners());
    455 
    456   pp::VarArray array;
    457   array.Set(0, pp::Var(kTestBool));
    458   array.Set(1, pp::Var(kTestString));
    459   // Purposely leave index 2 empty.
    460   array.Set(3, pp::Var(kTestInt));
    461   array.Set(4, pp::Var(kTestDouble));
    462 
    463   std::stringstream ss;
    464   ss << array.GetLength();
    465   std::string length_as_string(ss.str());
    466 
    467   // Have the listener test some properties of the Array.
    468   std::vector<std::string> properties_to_check;
    469   properties_to_check.push_back(
    470       "message_event.data.constructor.name === 'Array'");
    471   properties_to_check.push_back(
    472       std::string("message_event.data.length === ") + length_as_string);
    473   ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(array, properties_to_check));
    474 
    475   // Set up the JavaScript message event listener to echo the data part of the
    476   // message event back to us.
    477   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    478   message_data_.clear();
    479   instance_->PostMessage(array);
    480   // PostMessage is asynchronous, so we should not receive a response yet.
    481   ASSERT_EQ(message_data_.size(), 0);
    482   ASSERT_EQ(WaitForMessages(), 1);
    483   ASSERT_TRUE(message_data_.back().is_array());
    484   ASSERT_TRUE(VarsEqual(array, message_data_.back()));
    485 
    486   message_data_.clear();
    487   ASSERT_TRUE(ClearListeners());
    488 
    489   PASS();
    490 }
    491 
    492 std::string TestPostMessage::TestSendingDictionary() {
    493   // Clean up after previous tests. This also swallows the message sent by Init
    494   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
    495   // should start with these.
    496   WaitForMessages();
    497   ASSERT_TRUE(ClearListeners());
    498 
    499   pp::VarDictionary dictionary;
    500   dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
    501   dictionary.Set(pp::Var("bar"), pp::Var(kTestString));
    502   dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
    503   dictionary.Set(pp::Var("def"), pp::Var());
    504 
    505   std::stringstream ss;
    506   ss << dictionary.GetKeys().GetLength();
    507   std::string length_as_string(ss.str());
    508 
    509   // Have the listener test some properties of the Dictionary.
    510   std::vector<std::string> properties_to_check;
    511   properties_to_check.push_back(
    512       "message_event.data.constructor.name === 'Object'");
    513   properties_to_check.push_back(
    514       std::string("Object.keys(message_event.data).length === ") +
    515       length_as_string);
    516   ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary,
    517                                                 properties_to_check));
    518 
    519   // Set up the JavaScript message event listener to echo the data part of the
    520   // message event back to us.
    521   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    522   message_data_.clear();
    523   instance_->PostMessage(dictionary);
    524   // PostMessage is asynchronous, so we should not receive a response yet.
    525   ASSERT_EQ(message_data_.size(), 0);
    526   ASSERT_EQ(WaitForMessages(), 1);
    527   ASSERT_TRUE(message_data_.back().is_dictionary());
    528   ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
    529 
    530   message_data_.clear();
    531   ASSERT_TRUE(ClearListeners());
    532 
    533   PASS();
    534 }
    535 
    536 std::string TestPostMessage::TestSendingComplexVar() {
    537   // Clean up after previous tests. This also swallows the message sent by Init
    538   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
    539   // should start with these.
    540   WaitForMessages();
    541   message_data_.clear();
    542   ASSERT_TRUE(ClearListeners());
    543 
    544   pp::Var string(kTestString);
    545   pp::VarDictionary dictionary;
    546   dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
    547   dictionary.Set(pp::Var("bar"), string);
    548   dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
    549   dictionary.Set(pp::Var("def"), pp::Var());
    550 
    551   // Reference to array.
    552   pp::VarArray array;
    553   array.Set(0, pp::Var(kTestBool));
    554   array.Set(1, string);
    555   // Purposely leave index 2 empty (which will place an undefined var there).
    556   array.Set(3, pp::Var(kTestInt));
    557   array.Set(4, pp::Var(kTestDouble));
    558 
    559   dictionary.Set(pp::Var("array-ref1"), array);
    560   dictionary.Set(pp::Var("array-ref2"), array);
    561 
    562   // Set up the JavaScript message event listener to echo the data part of the
    563   // message event back to us.
    564   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    565   instance_->PostMessage(dictionary);
    566   // PostMessage is asynchronous, so we should not receive a response yet.
    567   ASSERT_EQ(message_data_.size(), 0);
    568   ASSERT_EQ(WaitForMessages(), 1);
    569   ASSERT_TRUE(message_data_.back().is_dictionary());
    570   pp::VarDictionary result(message_data_.back());
    571   ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
    572 
    573   WaitForMessages();
    574   message_data_.clear();
    575   ASSERT_TRUE(ClearListeners());
    576 
    577   // Set up a (dictionary -> array -> dictionary) cycle. Cycles shouldn't be
    578   // transmitted.
    579   pp::VarArray array2;
    580   array2.Set(0, dictionary);
    581   dictionary.Set(pp::Var("array2"), array2);
    582 
    583   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    584   instance_->PostMessage(dictionary);
    585   // PostMessage is asynchronous, so we should not receive a response yet.
    586   ASSERT_EQ(message_data_.size(), 0);
    587   ASSERT_EQ(WaitForMessages(), 0);
    588 
    589   // Break the cycles.
    590   dictionary.Delete(pp::Var("array2"));
    591 
    592   WaitForMessages();
    593   message_data_.clear();
    594   ASSERT_TRUE(ClearListeners());
    595 
    596   // Test sending a cycle from JavaScript to the plugin.
    597   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    598   PostMessageFromJavaScript("function() { var x = []; x[0] = x; return x; }");
    599   ASSERT_EQ(message_data_.size(), 0);
    600   ASSERT_EQ(WaitForMessages(), 0);
    601 
    602   WaitForMessages();
    603   message_data_.clear();
    604   ASSERT_TRUE(ClearListeners());
    605 
    606   PASS();
    607 }
    608 
    609 std::string TestPostMessage::TestMessageEvent() {
    610   // Set up the JavaScript message event listener to pass us some values from
    611   // the MessageEvent and make sure they match our expectations.
    612 
    613   WaitForMessages();
    614   ASSERT_TRUE(ClearListeners());
    615   // Have the listener pass back the class name of message_event and make sure
    616   // it's "MessageEvent".
    617   ASSERT_TRUE(AddEchoingListener("message_event.constructor.name"));
    618   message_data_.clear();
    619   instance_->PostMessage(pp::Var(kTestInt));
    620   ASSERT_EQ(message_data_.size(), 0);
    621   ASSERT_EQ(WaitForMessages(), 1);
    622   ASSERT_TRUE(message_data_.back().is_string());
    623   ASSERT_EQ(message_data_.back().AsString(), "MessageEvent");
    624   ASSERT_TRUE(ClearListeners());
    625 
    626   // Make sure all the non-data properties have the expected values.
    627   bool success = AddEchoingListener("((message_event.origin === '')"
    628                                    " && (message_event.lastEventId === '')"
    629                                    " && (message_event.source === null)"
    630                                    " && (message_event.ports.length === 0)"
    631                                    " && (message_event.bubbles === false)"
    632                                    " && (message_event.cancelable === false)"
    633                                    ")");
    634   ASSERT_TRUE(success);
    635   message_data_.clear();
    636   instance_->PostMessage(pp::Var(kTestInt));
    637   ASSERT_EQ(message_data_.size(), 0);
    638   ASSERT_EQ(WaitForMessages(), 1);
    639   ASSERT_TRUE(message_data_.back().is_bool());
    640   ASSERT_TRUE(message_data_.back().AsBool());
    641   ASSERT_TRUE(ClearListeners());
    642 
    643   // Add some event handlers to make sure they receive messages.
    644   ASSERT_TRUE(AddEchoingListener("1"));
    645   ASSERT_TRUE(AddEchoingListener("2"));
    646   ASSERT_TRUE(AddEchoingListener("3"));
    647 
    648   message_data_.clear();
    649   instance_->PostMessage(pp::Var(kTestInt));
    650   // Make sure we don't get a response in a re-entrant fashion.
    651   ASSERT_EQ(message_data_.size(), 0);
    652   // We should get 3 messages.
    653   ASSERT_EQ(WaitForMessages(), 3);
    654   // Copy to a vector of doubles and sort; w3c does not specify the order for
    655   // event listeners. (Copying is easier than writing an operator< for pp::Var.)
    656   //
    657   // See http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html.
    658   VarVector::iterator iter(message_data_.begin()), the_end(message_data_.end());
    659   std::vector<double> double_vec;
    660   for (; iter != the_end; ++iter) {
    661     ASSERT_TRUE(iter->is_number());
    662     double_vec.push_back(iter->AsDouble());
    663   }
    664   std::sort(double_vec.begin(), double_vec.end());
    665   ASSERT_DOUBLE_EQ(double_vec[0], 1.0);
    666   ASSERT_DOUBLE_EQ(double_vec[1], 2.0);
    667   ASSERT_DOUBLE_EQ(double_vec[2], 3.0);
    668 
    669   message_data_.clear();
    670   ASSERT_TRUE(ClearListeners());
    671 
    672   PASS();
    673 }
    674 
    675 std::string TestPostMessage::TestNoHandler() {
    676   // Delete any lingering messages and event listeners.
    677   WaitForMessages();
    678   ASSERT_TRUE(ClearListeners());
    679 
    680   // Now send a message.  We shouldn't get a response.
    681   message_data_.clear();
    682   instance_->PostMessage(pp::Var());
    683   ASSERT_EQ(WaitForMessages(), 0);
    684   ASSERT_TRUE(message_data_.empty());
    685 
    686   PASS();
    687 }
    688 
    689 std::string TestPostMessage::TestExtraParam() {
    690   // Delete any lingering messages and event listeners.
    691   WaitForMessages();
    692   ASSERT_TRUE(ClearListeners());
    693   // Add a listener that will respond with 1 and an empty array (where the
    694   // message port array would appear if it was Worker postMessage).
    695   ASSERT_TRUE(AddEchoingListener("1, []"));
    696 
    697   // Now send a message.  We shouldn't get a response.
    698   message_data_.clear();
    699   instance_->PostMessage(pp::Var());
    700   ASSERT_EQ(WaitForMessages(), 0);
    701   ASSERT_TRUE(message_data_.empty());
    702 
    703   ASSERT_TRUE(ClearListeners());
    704 
    705   PASS();
    706 }
    707 
    708 std::string TestPostMessage::TestNonMainThread() {
    709   WaitForMessages();
    710   ASSERT_TRUE(ClearListeners());
    711   ASSERT_TRUE(AddEchoingListener("message_event.data"));
    712   message_data_.clear();
    713 
    714   // Set up a thread for each integer from 0 to (kThreadsToRun - 1).  Make each
    715   // thread send the number that matches its index kMessagesToSendPerThread
    716   // times.  For good measure, call postMessage from the main thread
    717   // kMessagesToSendPerThread times. At the end, we make sure we got all the
    718   // values we expected.
    719   PP_ThreadType threads[kThreadsToRun];
    720   for (int32_t i = 0; i < kThreadsToRun; ++i) {
    721     // Set up a thread to send a value of i.
    722     void* arg = new InvokePostMessageThreadArg(instance_, pp::Var(i));
    723     PP_CreateThread(&threads[i], &InvokePostMessageThreadFunc, arg);
    724   }
    725   // Invoke PostMessage right now to send a value of (kThreadsToRun).
    726   for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
    727     instance_->PostMessage(pp::Var(kThreadsToRun));
    728 
    729   // Now join all threads.
    730   for (int32_t i = 0; i < kThreadsToRun; ++i)
    731     PP_JoinThread(threads[i]);
    732 
    733   // PostMessage is asynchronous, so we should not receive a response yet.
    734   ASSERT_EQ(message_data_.size(), 0);
    735 
    736   // Make sure we got all values that we expected.  Note that because it's legal
    737   // for the JavaScript engine to treat our integers as floating points, we
    738   // can't just use std::find or equality comparison. So we instead, we convert
    739   // each incoming value to an integer, and count them in received_counts.
    740   int32_t expected_num = (kThreadsToRun + 1) * kMessagesToSendPerThread;
    741   // Count how many we receive per-index.
    742   std::vector<int32_t> expected_counts(kThreadsToRun + 1,
    743                                        kMessagesToSendPerThread);
    744   std::vector<int32_t> received_counts(kThreadsToRun + 1, 0);
    745   ASSERT_EQ(WaitForMessages(), expected_num);
    746   for (int32_t i = 0; i < expected_num; ++i) {
    747     const pp::Var& latest_var(message_data_[i]);
    748     ASSERT_TRUE(latest_var.is_int() || latest_var.is_double());
    749     int32_t received_value = -1;
    750     if (latest_var.is_int()) {
    751       received_value = latest_var.AsInt();
    752     } else if (latest_var.is_double()) {
    753       received_value = static_cast<int32_t>(latest_var.AsDouble() + 0.5);
    754     }
    755     ASSERT_TRUE(received_value >= 0);
    756     ASSERT_TRUE(received_value <= kThreadsToRun);
    757     ++received_counts[received_value];
    758   }
    759   ASSERT_EQ(received_counts, expected_counts);
    760 
    761   message_data_.clear();
    762   ASSERT_TRUE(ClearListeners());
    763 
    764   PASS();
    765 }
    766