| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_message_handler.h" | 5 #include "ppapi/tests/test_message_handler.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <sstream> | 10 #include <sstream> |
| 11 | 11 |
| 12 #include "ppapi/c/pp_var.h" | 12 #include "ppapi/c/pp_var.h" |
| 13 #include "ppapi/c/ppb_file_io.h" | 13 #include "ppapi/c/ppb_file_io.h" |
| 14 #include "ppapi/c/ppb_messaging.h" | 14 #include "ppapi/c/ppb_messaging.h" |
| 15 #include "ppapi/c/ppp_message_handler.h" | 15 #include "ppapi/c/ppp_message_handler.h" |
| 16 #include "ppapi/cpp/file_io.h" | 16 #include "ppapi/cpp/file_io.h" |
| 17 #include "ppapi/cpp/file_ref.h" | 17 #include "ppapi/cpp/file_ref.h" |
| 18 #include "ppapi/cpp/file_system.h" | 18 #include "ppapi/cpp/file_system.h" |
| 19 #include "ppapi/cpp/instance.h" | 19 #include "ppapi/cpp/instance.h" |
| 20 #include "ppapi/cpp/message_handler.h" |
| 20 #include "ppapi/cpp/module_impl.h" | 21 #include "ppapi/cpp/module_impl.h" |
| 21 #include "ppapi/cpp/var.h" | 22 #include "ppapi/cpp/var.h" |
| 22 #include "ppapi/cpp/var_array.h" | 23 #include "ppapi/cpp/var_array.h" |
| 23 #include "ppapi/cpp/var_array_buffer.h" | 24 #include "ppapi/cpp/var_array_buffer.h" |
| 24 #include "ppapi/cpp/var_dictionary.h" | 25 #include "ppapi/cpp/var_dictionary.h" |
| 25 #include "ppapi/tests/pp_thread.h" | 26 #include "ppapi/tests/pp_thread.h" |
| 26 #include "ppapi/tests/test_utils.h" | 27 #include "ppapi/tests/test_utils.h" |
| 27 #include "ppapi/tests/testing_instance.h" | 28 #include "ppapi/tests/testing_instance.h" |
| 28 | 29 |
| 29 // Windows defines 'PostMessage', so we have to undef it. | 30 // Windows defines 'PostMessage', so we have to undef it. |
| 30 #ifdef PostMessage | 31 #ifdef PostMessage |
| 31 #undef PostMessage | 32 #undef PostMessage |
| 32 #endif | 33 #endif |
| 33 | 34 |
| 34 REGISTER_TEST_CASE(MessageHandler); | 35 REGISTER_TEST_CASE(MessageHandler); |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 | 38 |
| 38 // Created and destroyed on the main thread. All public methods should be called | 39 // Created and destroyed on the main thread. All public methods should be called |
| 39 // on the main thread. Most data members are only accessed on the main thread. | 40 // on the main thread. Most data members are only accessed on the main thread. |
| 40 // (Though it handles messages on the background thread). | 41 // (Though it handles messages on the background thread). |
| 41 class EchoingMessageHandler { | 42 class EchoingMessageHandler : public pp::MessageHandler { |
| 42 public: | 43 public: |
| 43 explicit EchoingMessageHandler(PP_Instance instance, | 44 explicit EchoingMessageHandler(TestingInstance* instance, |
| 44 const pp::MessageLoop& loop) | 45 const pp::MessageLoop& loop) |
| 45 : pp_instance_(instance), | 46 : testing_instance_(instance), |
| 46 message_handler_loop_(loop), | 47 message_handler_loop_(loop), |
| 47 ppb_messaging_if_(static_cast<const PPB_Messaging_1_2*>( | |
| 48 pp::Module::Get()->GetBrowserInterface( | |
| 49 PPB_MESSAGING_INTERFACE_1_2))), | |
| 50 ppp_message_handler_if_(), | |
| 51 is_registered_(false), | 48 is_registered_(false), |
| 52 test_finished_event_(instance), | 49 test_finished_event_(instance->pp_instance()), |
| 53 destroy_event_(instance) { | 50 destroy_event_(instance->pp_instance()) { |
| 54 AssertOnMainThread(); | 51 AssertOnMainThread(); |
| 55 ppp_message_handler_if_.HandleMessage = &HandleMessage; | |
| 56 ppp_message_handler_if_.HandleBlockingMessage = &HandleBlockingMessage; | |
| 57 ppp_message_handler_if_.Destroy = &Destroy; | |
| 58 } | 52 } |
| 59 void Register() { | 53 void Register() { |
| 60 AssertOnMainThread(); | 54 AssertOnMainThread(); |
| 61 assert(!is_registered_); | 55 assert(!is_registered_); |
| 62 int32_t result = ppb_messaging_if_->RegisterMessageHandler( | 56 int32_t result = |
| 63 pp_instance_, | 57 testing_instance_->RegisterMessageHandler(this, message_handler_loop_); |
| 64 this, | |
| 65 &ppp_message_handler_if_, | |
| 66 message_handler_loop_.pp_resource()); | |
| 67 if (result == PP_OK) { | 58 if (result == PP_OK) { |
| 68 is_registered_ = true; | 59 is_registered_ = true; |
| 69 } else { | 60 } else { |
| 70 std::ostringstream stream; | 61 std::ostringstream stream; |
| 71 stream << "Failed to register message handler; got error " << result; | 62 stream << "Failed to register message handler; got error " << result; |
| 72 AddError(stream.str()); | 63 AddError(stream.str()); |
| 73 test_finished_event_.Signal(); | 64 test_finished_event_.Signal(); |
| 74 } | 65 } |
| 75 // Note, at this point, we can't safely read or write errors_ until we wait | 66 // Note, at this point, we can't safely read or write errors_ until we wait |
| 76 // on destroy_event_. | 67 // on destroy_event_. |
| 77 } | 68 } |
| 78 void Unregister() { | 69 void Unregister() { |
| 79 AssertOnMainThread(); | 70 AssertOnMainThread(); |
| 80 assert(is_registered_); | 71 assert(is_registered_); |
| 81 ppb_messaging_if_->UnregisterMessageHandler(pp_instance_); | 72 testing_instance_->UnregisterMessageHandler(); |
| 82 is_registered_ = false; | 73 is_registered_ = false; |
| 83 } | 74 } |
| 84 void WaitForTestFinishedMessage() { | 75 void WaitForTestFinishedMessage() { |
| 85 test_finished_event_.Wait(); | 76 test_finished_event_.Wait(); |
| 86 test_finished_event_.Reset(); | 77 test_finished_event_.Reset(); |
| 87 } | 78 } |
| 88 // Wait for Destroy() to be called on the MessageHandler thread. When it's | 79 // Wait for Destroy() to be called on the MessageHandler thread. When it's |
| 89 // done, return any errors that occurred during the time the MessageHandler | 80 // done, return any errors that occurred during the time the MessageHandler |
| 90 // was getting messages. | 81 // was getting messages. |
| 91 std::string WaitForDestroy() { | 82 std::string WaitForDestroy() { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 106 assert(pp::MessageLoop::GetForMainThread() == | 97 assert(pp::MessageLoop::GetForMainThread() == |
| 107 pp::MessageLoop::GetCurrent()); | 98 pp::MessageLoop::GetCurrent()); |
| 108 } | 99 } |
| 109 void AddError(const std::string& error) { | 100 void AddError(const std::string& error) { |
| 110 if (!error.empty()) { | 101 if (!error.empty()) { |
| 111 if (!errors_.empty()) | 102 if (!errors_.empty()) |
| 112 errors_ += "<p>"; | 103 errors_ += "<p>"; |
| 113 errors_ += error; | 104 errors_ += error; |
| 114 } | 105 } |
| 115 } | 106 } |
| 116 static void HandleMessage(PP_Instance instance, | 107 virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) { |
| 117 void* user_data, | 108 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) |
| 118 const PP_Var* message_data) { | 109 AddError("HandleMessage was called on the wrong thread!"); |
| 119 EchoingMessageHandler* thiz = | 110 if (instance.pp_instance() != testing_instance_->pp_instance()) |
| 120 static_cast<EchoingMessageHandler*>(user_data); | 111 AddError("HandleMessage was passed the wrong instance!"); |
| 121 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) | |
| 122 thiz->AddError("HandleMessage was called on the wrong thread!"); | |
| 123 if (instance != thiz->pp_instance_) | |
| 124 thiz->AddError("HandleMessage was passed the wrong instance!"); | |
| 125 pp::Var var(*message_data); | |
| 126 if (var.is_string() && var.AsString() == "FINISHED_TEST") | 112 if (var.is_string() && var.AsString() == "FINISHED_TEST") |
| 127 thiz->test_finished_event_.Signal(); | 113 test_finished_event_.Signal(); |
| 128 else | 114 else |
| 129 thiz->ppb_messaging_if_->PostMessage(instance, *message_data); | 115 testing_instance_->PostMessage(var); |
| 130 } | 116 } |
| 131 | 117 |
| 132 static void HandleBlockingMessage(PP_Instance instance, | 118 virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance, |
| 133 void* user_data, | 119 const pp::Var& var) { |
| 134 const PP_Var* message_data, | 120 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) |
| 135 PP_Var* result) { | 121 AddError("HandleBlockingMessage was called on the wrong thread!"); |
| 136 EchoingMessageHandler* thiz = | 122 if (instance.pp_instance() != testing_instance_->pp_instance()) |
| 137 static_cast<EchoingMessageHandler*>(user_data); | 123 AddError("HandleBlockingMessage was passed the wrong instance!"); |
| 138 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) | |
| 139 thiz->AddError("HandleBlockingMessage was called on the wrong thread!"); | |
| 140 if (instance != thiz->pp_instance_) | |
| 141 thiz->AddError("HandleBlockingMessage was passed the wrong instance!"); | |
| 142 | 124 |
| 143 // The PP_Var we are passed is an in-parameter, so the browser is not | 125 return var; |
| 144 // giving us a ref-count. The ref-count it has will be decremented after we | |
| 145 // return. But we need to add a ref when returning a PP_Var, to pass to the | |
| 146 // caller. | |
| 147 pp::Var take_ref(*message_data); | |
| 148 take_ref.Detach(); | |
| 149 *result = *message_data; | |
| 150 } | 126 } |
| 151 | 127 |
| 152 static void Destroy(PP_Instance instance, void* user_data) { | 128 virtual void WasUnregistered(pp::InstanceHandle instance) { |
| 153 EchoingMessageHandler* thiz = | 129 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) |
| 154 static_cast<EchoingMessageHandler*>(user_data); | 130 AddError("Destroy was called on the wrong thread!"); |
| 155 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) | 131 if (instance.pp_instance() != testing_instance_->pp_instance()) |
| 156 thiz->AddError("Destroy was called on the wrong thread!"); | 132 AddError("Destroy was passed the wrong instance!"); |
| 157 if (instance != thiz->pp_instance_) | 133 destroy_event_.Signal(); |
| 158 thiz->AddError("Destroy was passed the wrong instance!"); | |
| 159 thiz->destroy_event_.Signal(); | |
| 160 } | 134 } |
| 161 | 135 |
| 162 // These data members are initialized on the main thread, but don't change for | 136 // These data members are initialized on the main thread, but don't change for |
| 163 // the life of the object, so are safe to access on the background thread, | 137 // the life of the object, so are safe to access on the background thread, |
| 164 // because there will be a memory barrier before the the MessageHandler calls | 138 // because there will be a memory barrier before the the MessageHandler calls |
| 165 // are invoked. | 139 // are invoked. |
| 166 const PP_Instance pp_instance_; | 140 TestingInstance* const testing_instance_; |
| 167 const pp::MessageLoop message_handler_loop_; | 141 const pp::MessageLoop message_handler_loop_; |
| 168 const pp::MessageLoop main_loop_; | 142 const pp::MessageLoop main_loop_; |
| 169 const PPB_Messaging_1_2* const ppb_messaging_if_; | |
| 170 // Spiritually, this member is const, but we can't initialize it in C++03, | |
| 171 // so it has to be non-const to be set in the constructor body. | |
| 172 PPP_MessageHandler_0_2 ppp_message_handler_if_; | |
| 173 | 143 |
| 174 // is_registered_ is only read/written on the main thread. | 144 // is_registered_ is only read/written on the main thread. |
| 175 bool is_registered_; | 145 bool is_registered_; |
| 176 | 146 |
| 177 // errors_ is written on the MessageHandler thread. When Destroy() is | 147 // errors_ is written on the MessageHandler thread. When Destroy() is |
| 178 // called, we stop writing to errors_ and signal destroy_event_. This causes | 148 // called, we stop writing to errors_ and signal destroy_event_. This causes |
| 179 // a memory barrier, so it's safe to read errors_ after that. | 149 // a memory barrier, so it's safe to read errors_ after that. |
| 180 std::string errors_; | 150 std::string errors_; |
| 181 NestedEvent test_finished_event_; | 151 NestedEvent test_finished_event_; |
| 182 NestedEvent destroy_event_; | 152 NestedEvent destroy_event_; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 reinterpret_cast<void*>(0xdeadbeef), | 221 reinterpret_cast<void*>(0xdeadbeef), |
| 252 &bad_ppp_ifs[i], | 222 &bad_ppp_ifs[i], |
| 253 handler_thread_.message_loop().pp_resource()); | 223 handler_thread_.message_loop().pp_resource()); |
| 254 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); | 224 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 255 } | 225 } |
| 256 } | 226 } |
| 257 PASS(); | 227 PASS(); |
| 258 } | 228 } |
| 259 | 229 |
| 260 std::string TestMessageHandler::TestPostMessageAndAwaitResponse() { | 230 std::string TestMessageHandler::TestPostMessageAndAwaitResponse() { |
| 261 EchoingMessageHandler handler(instance()->pp_instance(), | 231 EchoingMessageHandler handler(instance(), |
| 262 handler_thread_.message_loop()); | 232 handler_thread_.message_loop()); |
| 263 handler.Register(); | 233 handler.Register(); |
| 264 std::string js_code("var plugin = document.getElementById('plugin');\n"); | 234 std::string js_code("var plugin = document.getElementById('plugin');\n"); |
| 265 js_code += "var result = undefined;\n"; | 235 js_code += "var result = undefined;\n"; |
| 266 const char* const values_to_test[] = { | 236 const char* const values_to_test[] = { |
| 267 "5", | 237 "5", |
| 268 "undefined", | 238 "undefined", |
| 269 "1.5", | 239 "1.5", |
| 270 "'hello'", | 240 "'hello'", |
| 271 "{'key': 'value', 'array_key': [1, 2, 3, 4, 5]}", | 241 "{'key': 'value', 'array_key': [1, 2, 3, 4, 5]}", |
| (...skipping 17 matching lines...) Expand all Loading... |
| 289 // That should be fixed before this API goes to stable. See crbug.com/384528 | 259 // That should be fixed before this API goes to stable. See crbug.com/384528 |
| 290 js_code += "plugin.postMessage('FINISHED_TEST');\n"; | 260 js_code += "plugin.postMessage('FINISHED_TEST');\n"; |
| 291 instance_->EvalScript(js_code); | 261 instance_->EvalScript(js_code); |
| 292 handler.WaitForTestFinishedMessage(); | 262 handler.WaitForTestFinishedMessage(); |
| 293 handler.Unregister(); | 263 handler.Unregister(); |
| 294 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); | 264 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); |
| 295 | 265 |
| 296 PASS(); | 266 PASS(); |
| 297 } | 267 } |
| 298 | 268 |
| OLD | NEW |