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