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