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