• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
InvokePostMessageThreadArg__anonf4bbd15d0111::InvokePostMessageThreadArg56   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 
InvokePostMessageThreadFunc(void * user_data)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.
VarsEqual(const pp::Var & expected,const pp::Var & actual,std::map<int64_t,int64_t> * visited_ids)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 
VarsEqual(const pp::Var & expected,const pp::Var & actual)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:
ScopedArrayBufferSizeSetter(const PPB_Testing_Private * interface,PP_Instance instance,uint32_t threshold)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   }
~ScopedArrayBufferSizeSetter()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 
TestPostMessage(TestingInstance * instance)149 TestPostMessage::TestPostMessage(TestingInstance* instance)
150     : TestCase(instance) {
151 }
152 
~TestPostMessage()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 
Init()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 
RunTests(const std::string & filter)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 
HandleMessage(const pp::Var & message_data)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 
AddEchoingListener(const std::string & expression)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 
PostMessageFromJavaScript(const std::string & func)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 
ClearListeners()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 
WaitForMessages()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 
PostAsyncMessageFromJavaScriptAndWait(const std::string & func)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 
CheckMessageProperties(const pp::Var & test_data,const std::vector<std::string> & properties_to_check)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 
TestSendInInit()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 
TestSendingData()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 
TestSendingArrayBuffer()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 
TestSendingArray()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 
TestSendingDictionary()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 
TestSendingResource()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 
TestSendingComplexVar()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 
TestMessageEvent()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 
TestNoHandler()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 
TestExtraParam()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 
TestNonMainThread()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