Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/tests/test_post_message.h" | 5 #include "ppapi/tests/test_post_message.h" |
| 6 | 6 |
| 7 #include <string.h> | |
| 7 #include <algorithm> | 8 #include <algorithm> |
| 8 #include <map> | 9 #include <map> |
| 9 #include <sstream> | 10 #include <sstream> |
| 10 | 11 |
| 11 #include "ppapi/c/dev/ppb_testing_dev.h" | 12 #include "ppapi/c/dev/ppb_testing_dev.h" |
| 12 #include "ppapi/c/pp_var.h" | 13 #include "ppapi/c/pp_var.h" |
| 14 #include "ppapi/c/ppb_file_io.h" | |
| 15 #include "ppapi/cpp/file_io.h" | |
| 16 #include "ppapi/cpp/file_ref.h" | |
| 17 #include "ppapi/cpp/file_system.h" | |
| 13 #include "ppapi/cpp/instance.h" | 18 #include "ppapi/cpp/instance.h" |
| 14 #include "ppapi/cpp/var.h" | 19 #include "ppapi/cpp/var.h" |
| 15 #include "ppapi/cpp/var_array.h" | 20 #include "ppapi/cpp/var_array.h" |
| 16 #include "ppapi/cpp/var_array_buffer.h" | 21 #include "ppapi/cpp/var_array_buffer.h" |
| 17 #include "ppapi/cpp/var_dictionary.h" | 22 #include "ppapi/cpp/var_dictionary.h" |
| 18 #include "ppapi/tests/pp_thread.h" | 23 #include "ppapi/tests/pp_thread.h" |
| 19 #include "ppapi/tests/test_utils.h" | 24 #include "ppapi/tests/test_utils.h" |
| 20 #include "ppapi/tests/testing_instance.h" | 25 #include "ppapi/tests/testing_instance.h" |
| 21 | 26 |
| 22 // Windows defines 'PostMessage', so we have to undef it. | 27 // Windows defines 'PostMessage', so we have to undef it. |
| 23 #ifdef PostMessage | 28 #ifdef PostMessage |
| 24 #undef PostMessage | 29 #undef PostMessage |
| 25 #endif | 30 #endif |
| 26 | 31 |
| 27 REGISTER_TEST_CASE(PostMessage); | 32 REGISTER_TEST_CASE(PostMessage); |
| 28 | 33 |
| 29 namespace { | 34 namespace { |
| 30 | 35 |
| 36 const char kTestFilename[] = "testfile.txt"; | |
| 31 const char kTestString[] = "Hello world!"; | 37 const char kTestString[] = "Hello world!"; |
| 32 const bool kTestBool = true; | 38 const bool kTestBool = true; |
| 33 const int32_t kTestInt = 42; | 39 const int32_t kTestInt = 42; |
| 34 const double kTestDouble = 42.0; | 40 const double kTestDouble = 42.0; |
| 35 | 41 |
| 36 // On Windows XP bots, the NonMainThread test can run very slowly. So we dial | 42 // On Windows XP bots, the NonMainThread test can run very slowly. So we dial |
| 37 // back the number of threads & messages when running on Windows. | 43 // back the number of threads & messages when running on Windows. |
| 38 #ifdef PPAPI_OS_WIN | 44 #ifdef PPAPI_OS_WIN |
| 39 const int32_t kThreadsToRun = 2; | 45 const int32_t kThreadsToRun = 2; |
| 40 const int32_t kMessagesToSendPerThread = 5; | 46 const int32_t kMessagesToSendPerThread = 5; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 js_code += "var plugin = document.getElementById('plugin');" | 160 js_code += "var plugin = document.getElementById('plugin');" |
| 155 "plugin.removeEventListener('message'," | 161 "plugin.removeEventListener('message'," |
| 156 " plugin.wait_for_messages_handler);" | 162 " plugin.wait_for_messages_handler);" |
| 157 "delete plugin.wait_for_messages_handler;"; | 163 "delete plugin.wait_for_messages_handler;"; |
| 158 instance_->EvalScript(js_code); | 164 instance_->EvalScript(js_code); |
| 159 } | 165 } |
| 160 | 166 |
| 161 bool TestPostMessage::Init() { | 167 bool TestPostMessage::Init() { |
| 162 bool success = CheckTestingInterface(); | 168 bool success = CheckTestingInterface(); |
| 163 | 169 |
| 170 core_interface_ = static_cast<const PPB_Core*>( | |
| 171 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); | |
| 172 file_system_interface_ = static_cast<const PPB_FileSystem*>( | |
| 173 pp::Module::Get()->GetBrowserInterface(PPB_FILESYSTEM_INTERFACE)); | |
| 174 var_interface_ = static_cast<const PPB_Var*>( | |
| 175 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); | |
| 176 var_resource_interface_ = static_cast<const PPB_VarResource_Dev*>( | |
| 177 pp::Module::Get()->GetBrowserInterface(PPB_VAR_RESOURCE_DEV_INTERFACE)); | |
| 178 if (!core_interface_ || !file_system_interface_ || !var_interface_ || | |
| 179 !var_resource_interface_) | |
| 180 return false; | |
| 181 | |
| 164 // Set up a special listener that only responds to a FINISHED_WAITING string. | 182 // Set up a special listener that only responds to a FINISHED_WAITING string. |
| 165 // This is for use by WaitForMessages. | 183 // This is for use by WaitForMessages. |
| 166 std::string js_code; | 184 std::string js_code; |
| 167 // Note the following code is dependent on some features of test_case.html. | 185 // Note the following code is dependent on some features of test_case.html. |
| 168 // E.g., it is assumed that the DOM element where the plugin is embedded has | 186 // E.g., it is assumed that the DOM element where the plugin is embedded has |
| 169 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows | 187 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows |
| 170 // us to ignore the messages that are intended for use by the testing | 188 // us to ignore the messages that are intended for use by the testing |
| 171 // framework itself. | 189 // framework itself. |
| 172 js_code += "var plugin = document.getElementById('plugin');" | 190 js_code += "var plugin = document.getElementById('plugin');" |
| 173 "var wait_for_messages_handler = function(message_event) {" | 191 "var wait_for_messages_handler = function(message_event) {" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 194 } | 212 } |
| 195 | 213 |
| 196 void TestPostMessage::RunTests(const std::string& filter) { | 214 void TestPostMessage::RunTests(const std::string& filter) { |
| 197 // Note: SendInInit must be first, because it expects to receive a message | 215 // Note: SendInInit must be first, because it expects to receive a message |
| 198 // that was sent in Init above. | 216 // that was sent in Init above. |
| 199 RUN_TEST(SendInInit, filter); | 217 RUN_TEST(SendInInit, filter); |
| 200 RUN_TEST(SendingData, filter); | 218 RUN_TEST(SendingData, filter); |
| 201 RUN_TEST(SendingArrayBuffer, filter); | 219 RUN_TEST(SendingArrayBuffer, filter); |
| 202 RUN_TEST(SendingArray, filter); | 220 RUN_TEST(SendingArray, filter); |
| 203 RUN_TEST(SendingDictionary, filter); | 221 RUN_TEST(SendingDictionary, filter); |
| 222 RUN_TEST(SendingResource, filter); | |
| 204 RUN_TEST(SendingComplexVar, filter); | 223 RUN_TEST(SendingComplexVar, filter); |
| 205 RUN_TEST(MessageEvent, filter); | 224 RUN_TEST(MessageEvent, filter); |
| 206 RUN_TEST(NoHandler, filter); | 225 RUN_TEST(NoHandler, filter); |
| 207 RUN_TEST(ExtraParam, filter); | 226 RUN_TEST(ExtraParam, filter); |
| 208 if (testing_interface_->IsOutOfProcess()) | 227 if (testing_interface_->IsOutOfProcess()) |
| 209 RUN_TEST(NonMainThread, filter); | 228 RUN_TEST(NonMainThread, filter); |
| 210 } | 229 } |
| 211 | 230 |
| 212 void TestPostMessage::HandleMessage(const pp::Var& message_data) { | 231 void TestPostMessage::HandleMessage(const pp::Var& message_data) { |
| 213 if (message_data.is_string() && | 232 if (message_data.is_string() && |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) { | 265 bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) { |
| 247 std::string js_code; | 266 std::string js_code; |
| 248 js_code += "var plugin = document.getElementById('plugin');" | 267 js_code += "var plugin = document.getElementById('plugin');" |
| 249 "plugin.postMessage("; | 268 "plugin.postMessage("; |
| 250 js_code += func + "()"; | 269 js_code += func + "()"; |
| 251 js_code += " );"; | 270 js_code += " );"; |
| 252 instance_->EvalScript(js_code); | 271 instance_->EvalScript(js_code); |
| 253 return true; | 272 return true; |
| 254 } | 273 } |
| 255 | 274 |
| 275 bool TestPostMessage::PostMessageFromJavaScriptAsync(const std::string& func) { | |
| 276 // After the |func| calls callback, post both the given |message|, as well as | |
| 277 // the special message FINISHED_WAITING_MESSAGE. This ensures that | |
| 278 // WaitForMessagesAsync correctly waits until the callback is called. | |
| 279 std::string js_code; | |
| 280 js_code += "var plugin = document.getElementById('plugin');" | |
| 281 "var callback = function(message) {" | |
| 282 " plugin.postMessage(message);" | |
| 283 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');" | |
| 284 "};"; | |
| 285 js_code += "(" + func + ")(callback);"; | |
| 286 instance_->EvalScript(js_code); | |
| 287 return true; | |
| 288 } | |
| 289 | |
| 256 bool TestPostMessage::ClearListeners() { | 290 bool TestPostMessage::ClearListeners() { |
| 257 std::string js_code; | 291 std::string js_code; |
| 258 js_code += "var plugin = document.getElementById('plugin');" | 292 js_code += "var plugin = document.getElementById('plugin');" |
| 259 "while (plugin.eventListeners.length) {" | 293 "while (plugin.eventListeners.length) {" |
| 260 " plugin.removeEventListener('message'," | 294 " plugin.removeEventListener('message'," |
| 261 " plugin.eventListeners.pop());" | 295 " plugin.eventListeners.pop());" |
| 262 "}"; | 296 "}"; |
| 263 instance_->EvalScript(js_code); | 297 instance_->EvalScript(js_code); |
| 264 return true; | 298 return true; |
| 265 } | 299 } |
| 266 | 300 |
| 267 int TestPostMessage::WaitForMessages() { | 301 int TestPostMessage::WaitForMessages() { |
| 268 size_t message_size_before = message_data_.size(); | 302 size_t message_size_before = message_data_.size(); |
| 269 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to | 303 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to |
| 270 // come back _after_ any other incoming messages that were already pending. | 304 // come back _after_ any other incoming messages that were already pending. |
| 271 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); | 305 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); |
| 272 testing_interface_->RunMessageLoop(instance_->pp_instance()); | 306 testing_interface_->RunMessageLoop(instance_->pp_instance()); |
| 273 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know | 307 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know |
| 274 // that all pending messages have been slurped up. Return the number we | 308 // that all pending messages have been slurped up. Return the number we |
| 275 // received (which may be zero). | 309 // received (which may be zero). |
| 276 return message_data_.size() - message_size_before; | 310 return message_data_.size() - message_size_before; |
| 277 } | 311 } |
| 278 | 312 |
| 313 int TestPostMessage::WaitForMessagesAsync() { | |
|
dmichael (off chromium)
2013/10/23 17:36:02
This function only works right if you've called Po
Matt Giuca
2013/10/24 01:00:11
Done.
| |
| 314 size_t message_size_before = message_data_.size(); | |
| 315 // Unlike WaitForMessages, we do not post FINISHED_WAITING_MESSAGE. This is | |
| 316 // because PostMessageFromJavaScriptAsync will post it for us, when the | |
| 317 // asynchronous operation completes. | |
| 318 testing_interface_->RunMessageLoop(instance_->pp_instance()); | |
| 319 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know | |
| 320 // that all pending messages have been slurped up. Return the number we | |
| 321 // received (which may be zero). | |
| 322 return message_data_.size() - message_size_before; | |
| 323 } | |
| 324 | |
| 279 std::string TestPostMessage::CheckMessageProperties( | 325 std::string TestPostMessage::CheckMessageProperties( |
| 280 const pp::Var& test_data, | 326 const pp::Var& test_data, |
| 281 const std::vector<std::string>& properties_to_check) { | 327 const std::vector<std::string>& properties_to_check) { |
| 282 typedef std::vector<std::string>::const_iterator Iterator; | 328 typedef std::vector<std::string>::const_iterator Iterator; |
| 283 for (Iterator iter = properties_to_check.begin(); | 329 for (Iterator iter = properties_to_check.begin(); |
| 284 iter != properties_to_check.end(); | 330 iter != properties_to_check.end(); |
| 285 ++iter) { | 331 ++iter) { |
| 286 ASSERT_TRUE(AddEchoingListener(*iter)); | 332 ASSERT_TRUE(AddEchoingListener(*iter)); |
| 287 message_data_.clear(); | 333 message_data_.clear(); |
| 288 instance_->PostMessage(test_data); | 334 instance_->PostMessage(test_data); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 ASSERT_EQ(WaitForMessages(), 1); | 572 ASSERT_EQ(WaitForMessages(), 1); |
| 527 ASSERT_TRUE(message_data_.back().is_dictionary()); | 573 ASSERT_TRUE(message_data_.back().is_dictionary()); |
| 528 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); | 574 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); |
| 529 | 575 |
| 530 message_data_.clear(); | 576 message_data_.clear(); |
| 531 ASSERT_TRUE(ClearListeners()); | 577 ASSERT_TRUE(ClearListeners()); |
| 532 | 578 |
| 533 PASS(); | 579 PASS(); |
| 534 } | 580 } |
| 535 | 581 |
| 582 std::string TestPostMessage::TestSendingResource() { | |
| 583 // Clean up after previous tests. This also swallows the message sent by Init | |
| 584 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
| 585 // should start with these. | |
| 586 WaitForMessages(); | |
| 587 message_data_.clear(); | |
| 588 ASSERT_TRUE(ClearListeners()); | |
| 589 | |
| 590 // Test sending a DOMFileSystem from JavaScript to the plugin. | |
| 591 // This opens a real (temporary) file using the HTML5 FileSystem API and | |
| 592 // writes to it. | |
| 593 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
| 594 std::string js_code = | |
| 595 "function(callback) {" | |
| 596 " window.webkitRequestFileSystem(window.TEMPORARY, 1024," | |
| 597 " function(fileSystem) {" | |
| 598 " fileSystem.root.getFile('"; | |
| 599 js_code += kTestFilename; | |
| 600 js_code += "', {create: true}, function(tempFile) {" | |
| 601 " tempFile.createWriter(function(writer) {" | |
| 602 " writer.onerror = function() { callback(null); };" | |
| 603 " writer.onwriteend = function() { callback(fileSystem); };" | |
| 604 " var blob = new Blob(['"; | |
| 605 js_code += kTestString; | |
| 606 js_code += "'], {'type': 'text/plain'});" | |
| 607 " writer.write(blob);" | |
| 608 " });" | |
| 609 " }, function() { callback(null); });" | |
| 610 " }, function() { callback(null); });" | |
| 611 "}"; | |
| 612 PostMessageFromJavaScriptAsync(js_code); | |
| 613 ASSERT_EQ(message_data_.size(), 0); | |
| 614 ASSERT_EQ(WaitForMessagesAsync(), 1); | |
| 615 // TODO(mgiuca): Use the C++ API instead of the C API, when it is available. | |
| 616 PP_Var var = message_data_.back().Detach(); | |
| 617 PP_Resource result = var_resource_interface_->VarToResource(var); | |
| 618 ASSERT_TRUE(file_system_interface_->IsFileSystem(result)); | |
| 619 { | |
| 620 pp::FileSystem file_system(pp::PASS_REF, result); | |
| 621 std::string file_path = "/"; | |
| 622 file_path += kTestFilename; | |
| 623 pp::FileRef file_ref(file_system, file_path.c_str()); | |
| 624 ASSERT_NE(0, file_ref.pp_resource()); | |
| 625 ASSERT_EQ(kTestFilename, file_ref.GetName().AsString()); | |
| 626 pp::FileIO file_io(instance_); | |
| 627 ASSERT_NE(0, file_io.pp_resource()); | |
| 628 | |
| 629 TestCompletionCallback callback_1(instance_->pp_instance(), | |
| 630 callback_type()); | |
| 631 callback_1.WaitForResult( | |
| 632 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, callback_1.GetCallback())); | |
| 633 CHECK_CALLBACK_BEHAVIOR(callback_1); | |
| 634 ASSERT_EQ(PP_OK, callback_1.result()); | |
| 635 | |
| 636 TestCompletionCallback callback_2(instance_->pp_instance(), | |
| 637 callback_type()); | |
|
dmichael (off chromium)
2013/10/23 17:33:21
We usually just reuse the first TestCompletionCall
Matt Giuca
2013/10/24 01:00:11
Done. (I copied the callback_1 style from test_fil
dmichael (off chromium)
2013/10/25 20:13:16
That's necessary when you have 2 operations in par
| |
| 638 int length = strlen(kTestString); | |
| 639 char buffer[length]; // Note: Not null-terminated! | |
| 640 callback_2.WaitForResult( | |
| 641 file_io.Read(0, buffer, length, callback_2.GetCallback())); | |
| 642 CHECK_CALLBACK_BEHAVIOR(callback_2); | |
| 643 ASSERT_EQ(length, callback_2.result()); | |
| 644 ASSERT_EQ(0, memcmp(buffer, kTestString, length)); | |
| 645 } | |
| 646 var_interface_->Release(var); | |
| 647 | |
| 648 WaitForMessages(); | |
| 649 message_data_.clear(); | |
| 650 ASSERT_TRUE(ClearListeners()); | |
| 651 | |
| 652 // TODO(mgiuca): Test roundtrip from plugin to JS and back, when the plugin to | |
| 653 // JS support is available. | |
| 654 | |
| 655 PASS(); | |
| 656 } | |
| 657 | |
| 536 std::string TestPostMessage::TestSendingComplexVar() { | 658 std::string TestPostMessage::TestSendingComplexVar() { |
| 537 // Clean up after previous tests. This also swallows the message sent by Init | 659 // Clean up after previous tests. This also swallows the message sent by Init |
| 538 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | 660 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' |
| 539 // should start with these. | 661 // should start with these. |
| 540 WaitForMessages(); | 662 WaitForMessages(); |
| 541 message_data_.clear(); | 663 message_data_.clear(); |
| 542 ASSERT_TRUE(ClearListeners()); | 664 ASSERT_TRUE(ClearListeners()); |
| 543 | 665 |
| 544 pp::Var string(kTestString); | 666 pp::Var string(kTestString); |
| 545 pp::VarDictionary dictionary; | 667 pp::VarDictionary dictionary; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 756 ASSERT_TRUE(received_value <= kThreadsToRun); | 878 ASSERT_TRUE(received_value <= kThreadsToRun); |
| 757 ++received_counts[received_value]; | 879 ++received_counts[received_value]; |
| 758 } | 880 } |
| 759 ASSERT_EQ(received_counts, expected_counts); | 881 ASSERT_EQ(received_counts, expected_counts); |
| 760 | 882 |
| 761 message_data_.clear(); | 883 message_data_.clear(); |
| 762 ASSERT_TRUE(ClearListeners()); | 884 ASSERT_TRUE(ClearListeners()); |
| 763 | 885 |
| 764 PASS(); | 886 PASS(); |
| 765 } | 887 } |
| OLD | NEW |