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.
5 #include "ppapi/tests/test_post_message.h"
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"
26 // Windows defines 'PostMessage', so we have to undef it.
31 REGISTER_TEST_CASE(PostMessage);
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;
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.
44 const int32_t kThreadsToRun = 2;
45 const int32_t kMessagesToSendPerThread = 5;
47 const int32_t kThreadsToRun = 4;
48 const int32_t kMessagesToSendPerThread = 10;
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;
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);
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())
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)
86 (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id;
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())
96 for (uint32_t i = 0; i < expected_array.GetLength(); ++i) {
97 if (!VarsEqual(expected_array.Get(i), actual_array.Get(i), visited_ids))
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()) {
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))
112 if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids))
117 return expected == actual;
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);
127 class ScopedArrayBufferSizeSetter {
129 ScopedArrayBufferSizeSetter(const PPB_Testing_Private* interface,
130 PP_Instance instance,
132 : interface_(interface),
133 instance_(instance) {
134 interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold);
136 ~ScopedArrayBufferSizeSetter() {
137 interface_->SetMinimumArrayBufferSizeForShmem(instance_, 0);
140 const PPB_Testing_Private* interface_;
141 PP_Instance instance_;
144 #define FINISHED_WAITING_MESSAGE "TEST_POST_MESSAGE_FINISHED_WAITING"
148 TestPostMessage::TestPostMessage(TestingInstance* instance)
149 : TestCase(instance) {
152 TestPostMessage::~TestPostMessage() {
153 instance_->PostMessage(pp::Var("This isn't guaranteed to be received, but "
154 "shouldn't cause a crash."));
156 // Remove the special listener that only responds to a FINISHED_WAITING
157 // string. See Init for where it gets added.
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);
166 bool TestPostMessage::Init() {
167 bool success = CheckTestingInterface();
169 // Set up a special listener that only responds to a FINISHED_WAITING string.
170 // This is for use by WaitForMessages.
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
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 "');"
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);
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
196 instance_->PostMessage(pp::Var(kTestString));
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);
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());
223 message_data_.push_back(message_data);
226 bool TestPostMessage::AddEchoingListener(const std::string& expression) {
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
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;
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);
252 bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) {
254 js_code += "var plugin = document.getElementById('plugin');"
255 "plugin.postMessage(";
256 js_code += func + "()";
258 instance_->EvalScript(js_code);
262 bool TestPostMessage::ClearListeners() {
264 js_code += "var plugin = document.getElementById('plugin');"
265 "while (plugin.eventListeners.length) {"
266 " plugin.removeEventListener('message',"
267 " plugin.eventListeners.pop());"
269 instance_->EvalScript(js_code);
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;
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.
291 js_code += "var plugin = document.getElementById('plugin');"
292 "var callback = function(message) {"
293 " plugin.postMessage(message);"
294 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
296 js_code += "(" + func + ")(callback);";
297 instance_->EvalScript(js_code);
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;
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();
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());
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();
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.
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"));
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);
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);
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());
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);
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());
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());
395 message_data_.clear();
396 ASSERT_TRUE(ClearListeners());
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.
406 ASSERT_TRUE(ClearListeners());
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(),
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());
419 // Create an appropriately sized array buffer with test_data[i] == i.
420 pp::VarArrayBuffer test_data(sizes[i]);
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
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);
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);
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);
449 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(test_data,
450 properties_to_check));
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.
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]);
473 message_data_.clear();
474 ASSERT_TRUE(ClearListeners());
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.
485 ASSERT_TRUE(ClearListeners());
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));
494 std::stringstream ss;
495 ss << array.GetLength();
496 std::string length_as_string(ss.str());
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));
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()));
517 message_data_.clear();
518 ASSERT_TRUE(ClearListeners());
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.
528 ASSERT_TRUE(ClearListeners());
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());
536 std::stringstream ss;
537 ss << dictionary.GetKeys().GetLength();
538 std::string length_as_string(ss.str());
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 === ") +
547 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary,
548 properties_to_check));
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()));
561 message_data_.clear();
562 ASSERT_TRUE(ClearListeners());
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.
572 message_data_.clear();
573 ASSERT_TRUE(ClearListeners());
575 // Test sending a DOMFileSystem from JavaScript to the plugin.
576 // This opens a real (temporary) file using the HTML5 FileSystem API and
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);"
595 " }, function() { callback(null); });"
596 " }, function() { callback(null); });"
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));
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());
610 // Ensure that the file can be queried.
611 TestCompletionCallbackWithOutput<PP_FileInfo> cc(instance_->pp_instance(),
613 cc.WaitForResult(file_ref.Query(cc.GetCallback()));
614 CHECK_CALLBACK_BEHAVIOR(cc);
615 ASSERT_EQ(PP_OK, cc.result());
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(),
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());
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));
638 message_data_.clear();
639 ASSERT_TRUE(ClearListeners());
641 // TODO(mgiuca): Test roundtrip from plugin to JS and back, when the plugin to
642 // JS support is available.
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.
652 message_data_.clear();
653 ASSERT_TRUE(ClearListeners());
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());
662 // Reference to 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));
670 dictionary.Set(pp::Var("array-ref1"), array);
671 dictionary.Set(pp::Var("array-ref2"), array);
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()));
685 message_data_.clear();
686 ASSERT_TRUE(ClearListeners());
688 // Set up a (dictionary -> array -> dictionary) cycle. Cycles shouldn't be
691 array2.Set(0, dictionary);
692 dictionary.Set(pp::Var("array2"), array2);
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);
701 dictionary.Delete(pp::Var("array2"));
704 message_data_.clear();
705 ASSERT_TRUE(ClearListeners());
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);
714 message_data_.clear();
715 ASSERT_TRUE(ClearListeners());
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.
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());
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)"
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());
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"));
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.)
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());
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);
780 message_data_.clear();
781 ASSERT_TRUE(ClearListeners());
786 std::string TestPostMessage::TestNoHandler() {
787 // Delete any lingering messages and event listeners.
789 ASSERT_TRUE(ClearListeners());
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());
800 std::string TestPostMessage::TestExtraParam() {
801 // Delete any lingering messages and event listeners.
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, []"));
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());
814 ASSERT_TRUE(ClearListeners());
819 std::string TestPostMessage::TestNonMainThread() {
821 ASSERT_TRUE(ClearListeners());
822 ASSERT_TRUE(AddEchoingListener("message_event.data"));
823 message_data_.clear();
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);
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));
840 // Now join all threads.
841 for (int32_t i = 0; i < kThreadsToRun; ++i)
842 PP_JoinThread(threads[i]);
844 // PostMessage is asynchronous, so we should not receive a response yet.
845 ASSERT_EQ(0, message_data_.size());
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);
866 ASSERT_TRUE(received_value >= 0);
867 ASSERT_TRUE(received_value <= kThreadsToRun);
868 ++received_counts[received_value];
870 ASSERT_EQ(expected_counts, received_counts);
872 message_data_.clear();
873 ASSERT_TRUE(ClearListeners());