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