| 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> |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 // Created and destroyed on the main thread. All public methods should be called | 37 // Created and destroyed on the main thread. All public methods should be called |
| 38 // on the main thread. Most data members are only accessed on the main thread. | 38 // on the main thread. Most data members are only accessed on the main thread. |
| 39 // (Though it handles messages on the background thread). | 39 // (Though it handles messages on the background thread). |
| 40 class EchoingMessageHandler { | 40 class EchoingMessageHandler { |
| 41 public: | 41 public: |
| 42 explicit EchoingMessageHandler(PP_Instance instance, | 42 explicit EchoingMessageHandler(PP_Instance instance, |
| 43 const pp::MessageLoop& loop) | 43 const pp::MessageLoop& loop) |
| 44 : pp_instance_(instance), | 44 : pp_instance_(instance), |
| 45 message_handler_loop_(loop), | 45 message_handler_loop_(loop), |
| 46 ppb_messaging_if_(static_cast<const PPB_Messaging_1_1*>( | 46 ppb_messaging_if_(static_cast<const PPB_Messaging_1_2*>( |
| 47 pp::Module::Get()->GetBrowserInterface( | 47 pp::Module::Get()->GetBrowserInterface( |
| 48 PPB_MESSAGING_INTERFACE_1_1))), | 48 PPB_MESSAGING_INTERFACE_1_2))), |
| 49 ppp_message_handler_if_(), | 49 ppp_message_handler_if_(), |
| 50 is_registered_(false), | 50 is_registered_(false), |
| 51 test_finished_event_(instance), | 51 test_finished_event_(instance), |
| 52 destroy_event_(instance) { | 52 destroy_event_(instance) { |
| 53 AssertOnMainThread(); | 53 AssertOnMainThread(); |
| 54 ppp_message_handler_if_.HandleMessage = &HandleMessage; | 54 ppp_message_handler_if_.HandleMessage = &HandleMessage; |
| 55 ppp_message_handler_if_.HandleBlockingMessage = &HandleBlockingMessage; | 55 ppp_message_handler_if_.HandleBlockingMessage = &HandleBlockingMessage; |
| 56 ppp_message_handler_if_.Destroy = &Destroy; | 56 ppp_message_handler_if_.Destroy = &Destroy; |
| 57 } | 57 } |
| 58 void Register() { | 58 void Register() { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 } | 107 } |
| 108 void AddError(const std::string& error) { | 108 void AddError(const std::string& error) { |
| 109 if (!error.empty()) { | 109 if (!error.empty()) { |
| 110 if (!errors_.empty()) | 110 if (!errors_.empty()) |
| 111 errors_ += "<p>"; | 111 errors_ += "<p>"; |
| 112 errors_ += error; | 112 errors_ += error; |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 static void HandleMessage(PP_Instance instance, | 115 static void HandleMessage(PP_Instance instance, |
| 116 void* user_data, | 116 void* user_data, |
| 117 struct PP_Var message_data) { | 117 const PP_Var* message_data) { |
| 118 EchoingMessageHandler* thiz = | 118 EchoingMessageHandler* thiz = |
| 119 static_cast<EchoingMessageHandler*>(user_data); | 119 static_cast<EchoingMessageHandler*>(user_data); |
| 120 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) | 120 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) |
| 121 thiz->AddError("HandleMessage was called on the wrong thread!"); | 121 thiz->AddError("HandleMessage was called on the wrong thread!"); |
| 122 if (instance != thiz->pp_instance_) | 122 if (instance != thiz->pp_instance_) |
| 123 thiz->AddError("HandleMessage was passed the wrong instance!"); | 123 thiz->AddError("HandleMessage was passed the wrong instance!"); |
| 124 pp::Var var(message_data); | 124 pp::Var var(*message_data); |
| 125 if (var.is_string() && var.AsString() == "FINISHED_TEST") | 125 if (var.is_string() && var.AsString() == "FINISHED_TEST") |
| 126 thiz->test_finished_event_.Signal(); | 126 thiz->test_finished_event_.Signal(); |
| 127 else | 127 else |
| 128 thiz->ppb_messaging_if_->PostMessage(instance, message_data); | 128 thiz->ppb_messaging_if_->PostMessage(instance, *message_data); |
| 129 } | 129 } |
| 130 | 130 |
| 131 static PP_Var HandleBlockingMessage(PP_Instance instance, | 131 static void HandleBlockingMessage(PP_Instance instance, |
| 132 void* user_data, | 132 void* user_data, |
| 133 struct PP_Var message_data) { | 133 const PP_Var* message_data, |
| 134 PP_Var* result) { |
| 134 EchoingMessageHandler* thiz = | 135 EchoingMessageHandler* thiz = |
| 135 static_cast<EchoingMessageHandler*>(user_data); | 136 static_cast<EchoingMessageHandler*>(user_data); |
| 136 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) | 137 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) |
| 137 thiz->AddError("HandleBlockingMessage was called on the wrong thread!"); | 138 thiz->AddError("HandleBlockingMessage was called on the wrong thread!"); |
| 138 if (instance != thiz->pp_instance_) | 139 if (instance != thiz->pp_instance_) |
| 139 thiz->AddError("HandleBlockingMessage was passed the wrong instance!"); | 140 thiz->AddError("HandleBlockingMessage was passed the wrong instance!"); |
| 140 | 141 |
| 141 // The PP_Var we are passed is an in-parameter, so the browser is not | 142 // The PP_Var we are passed is an in-parameter, so the browser is not |
| 142 // giving us a ref-count. The ref-count it has will be decremented after we | 143 // giving us a ref-count. The ref-count it has will be decremented after we |
| 143 // return. But we need to add a ref when returning a PP_Var, to pass to the | 144 // return. But we need to add a ref when returning a PP_Var, to pass to the |
| 144 // caller. | 145 // caller. |
| 145 pp::Var take_ref(message_data); | 146 pp::Var take_ref(*message_data); |
| 146 take_ref.Detach(); | 147 take_ref.Detach(); |
| 147 return message_data; | 148 *result = *message_data; |
| 148 } | 149 } |
| 149 | 150 |
| 150 static void Destroy(PP_Instance instance, void* user_data) { | 151 static void Destroy(PP_Instance instance, void* user_data) { |
| 151 EchoingMessageHandler* thiz = | 152 EchoingMessageHandler* thiz = |
| 152 static_cast<EchoingMessageHandler*>(user_data); | 153 static_cast<EchoingMessageHandler*>(user_data); |
| 153 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) | 154 if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_) |
| 154 thiz->AddError("Destroy was called on the wrong thread!"); | 155 thiz->AddError("Destroy was called on the wrong thread!"); |
| 155 if (instance != thiz->pp_instance_) | 156 if (instance != thiz->pp_instance_) |
| 156 thiz->AddError("Destroy was passed the wrong instance!"); | 157 thiz->AddError("Destroy was passed the wrong instance!"); |
| 157 thiz->destroy_event_.Signal(); | 158 thiz->destroy_event_.Signal(); |
| 158 } | 159 } |
| 159 | 160 |
| 160 // These data members are initialized on the main thread, but don't change for | 161 // These data members are initialized on the main thread, but don't change for |
| 161 // the life of the object, so are safe to access on the background thread, | 162 // the life of the object, so are safe to access on the background thread, |
| 162 // because there will be a memory barrier before the the MessageHandler calls | 163 // because there will be a memory barrier before the the MessageHandler calls |
| 163 // are invoked. | 164 // are invoked. |
| 164 const PP_Instance pp_instance_; | 165 const PP_Instance pp_instance_; |
| 165 const pp::MessageLoop message_handler_loop_; | 166 const pp::MessageLoop message_handler_loop_; |
| 166 const pp::MessageLoop main_loop_; | 167 const pp::MessageLoop main_loop_; |
| 167 const PPB_Messaging_1_1* const ppb_messaging_if_; | 168 const PPB_Messaging_1_2* const ppb_messaging_if_; |
| 168 // Spiritually, this member is const, but we can't initialize it in C++03, | 169 // Spiritually, this member is const, but we can't initialize it in C++03, |
| 169 // so it has to be non-const to be set in the constructor body. | 170 // so it has to be non-const to be set in the constructor body. |
| 170 PPP_MessageHandler_0_1 ppp_message_handler_if_; | 171 PPP_MessageHandler_0_2 ppp_message_handler_if_; |
| 171 | 172 |
| 172 // is_registered_ is only read/written on the main thread. | 173 // is_registered_ is only read/written on the main thread. |
| 173 bool is_registered_; | 174 bool is_registered_; |
| 174 | 175 |
| 175 // errors_ is written on the MessageHandler thread. When Destroy() is | 176 // errors_ is written on the MessageHandler thread. When Destroy() is |
| 176 // called, we stop writing to errors_ and signal destroy_event_. This causes | 177 // called, we stop writing to errors_ and signal destroy_event_. This causes |
| 177 // a memory barrier, so it's safe to read errors_ after that. | 178 // a memory barrier, so it's safe to read errors_ after that. |
| 178 std::string errors_; | 179 std::string errors_; |
| 179 NestedEvent test_finished_event_; | 180 NestedEvent test_finished_event_; |
| 180 NestedEvent destroy_event_; | 181 NestedEvent destroy_event_; |
| 181 | 182 |
| 182 // Undefined & private to disallow copy and assign. | 183 // Undefined & private to disallow copy and assign. |
| 183 EchoingMessageHandler(const EchoingMessageHandler&); | 184 EchoingMessageHandler(const EchoingMessageHandler&); |
| 184 EchoingMessageHandler& operator=(const EchoingMessageHandler&); | 185 EchoingMessageHandler& operator=(const EchoingMessageHandler&); |
| 185 }; | 186 }; |
| 186 | 187 |
| 187 void FakeHandleMessage(PP_Instance instance, | 188 void FakeHandleMessage(PP_Instance instance, |
| 188 void* user_data, | 189 void* user_data, |
| 189 struct PP_Var message_data) {} | 190 const PP_Var* message_data) {} |
| 190 PP_Var FakeHandleBlockingMessage(PP_Instance instance, | 191 void FakeHandleBlockingMessage(PP_Instance instance, |
| 191 void* user_data, | 192 void* user_data, |
| 192 struct PP_Var message_data) { | 193 const PP_Var* message_data, |
| 193 return PP_MakeUndefined(); | 194 PP_Var* result) {} |
| 194 } | |
| 195 void FakeDestroy(PP_Instance instance, void* user_data) {} | 195 void FakeDestroy(PP_Instance instance, void* user_data) {} |
| 196 | 196 |
| 197 } // namespace | 197 } // namespace |
| 198 | 198 |
| 199 TestMessageHandler::TestMessageHandler(TestingInstance* instance) | 199 TestMessageHandler::TestMessageHandler(TestingInstance* instance) |
| 200 : TestCase(instance), | 200 : TestCase(instance), |
| 201 ppb_messaging_if_(NULL), | 201 ppb_messaging_if_(NULL), |
| 202 handler_thread_(instance) { | 202 handler_thread_(instance) { |
| 203 } | 203 } |
| 204 | 204 |
| 205 TestMessageHandler::~TestMessageHandler() { | 205 TestMessageHandler::~TestMessageHandler() { |
| 206 handler_thread_.Join(); | 206 handler_thread_.Join(); |
| 207 } | 207 } |
| 208 | 208 |
| 209 bool TestMessageHandler::Init() { | 209 bool TestMessageHandler::Init() { |
| 210 ppb_messaging_if_ = static_cast<const PPB_Messaging_1_1*>( | 210 ppb_messaging_if_ = static_cast<const PPB_Messaging_1_2*>( |
| 211 pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_1)); | 211 pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2)); |
| 212 return ppb_messaging_if_ && | 212 return ppb_messaging_if_ && |
| 213 CheckTestingInterface() && | 213 CheckTestingInterface() && |
| 214 handler_thread_.Start(); | 214 handler_thread_.Start(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 void TestMessageHandler::RunTests(const std::string& filter) { | 217 void TestMessageHandler::RunTests(const std::string& filter) { |
| 218 RUN_TEST(RegisterErrorConditions, filter); | 218 RUN_TEST(RegisterErrorConditions, filter); |
| 219 RUN_TEST(PostMessageAndAwaitResponse, filter); | 219 RUN_TEST(PostMessageAndAwaitResponse, filter); |
| 220 } | 220 } |
| 221 | 221 |
| 222 void TestMessageHandler::HandleMessage(const pp::Var& message_data) { | 222 void TestMessageHandler::HandleMessage(const pp::Var& message_data) { |
| 223 // All messages should go to the background thread message handler. | 223 // All messages should go to the background thread message handler. |
| 224 assert(false); | 224 assert(false); |
| 225 } | 225 } |
| 226 | 226 |
| 227 std::string TestMessageHandler::TestRegisterErrorConditions() { | 227 std::string TestMessageHandler::TestRegisterErrorConditions() { |
| 228 { | 228 { |
| 229 // Test registering with the main thread as the message loop. | 229 // Test registering with the main thread as the message loop. |
| 230 PPP_MessageHandler_0_1 fake_ppp_message_handler = { | 230 PPP_MessageHandler_0_2 fake_ppp_message_handler = { |
| 231 &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy | 231 &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy |
| 232 }; | 232 }; |
| 233 pp::MessageLoop main_loop = pp::MessageLoop::GetForMainThread(); | 233 pp::MessageLoop main_loop = pp::MessageLoop::GetForMainThread(); |
| 234 int32_t result = ppb_messaging_if_->RegisterMessageHandler( | 234 int32_t result = ppb_messaging_if_->RegisterMessageHandler( |
| 235 instance()->pp_instance(), | 235 instance()->pp_instance(), |
| 236 reinterpret_cast<void*>(0xdeadbeef), | 236 reinterpret_cast<void*>(0xdeadbeef), |
| 237 &fake_ppp_message_handler, | 237 &fake_ppp_message_handler, |
| 238 main_loop.pp_resource()); | 238 main_loop.pp_resource()); |
| 239 ASSERT_EQ(PP_ERROR_WRONG_THREAD, result); | 239 ASSERT_EQ(PP_ERROR_WRONG_THREAD, result); |
| 240 } | 240 } |
| 241 { | 241 { |
| 242 // Test registering with incomplete PPP_Messaging interface. | 242 // Test registering with incomplete PPP_Messaging interface. |
| 243 PPP_MessageHandler_0_1 bad_ppp_ifs[] = { | 243 PPP_MessageHandler_0_2 bad_ppp_ifs[] = { |
| 244 { NULL, &FakeHandleBlockingMessage, &FakeDestroy }, | 244 { NULL, &FakeHandleBlockingMessage, &FakeDestroy }, |
| 245 { &FakeHandleMessage, NULL, &FakeDestroy }, | 245 { &FakeHandleMessage, NULL, &FakeDestroy }, |
| 246 { &FakeHandleMessage, &FakeHandleBlockingMessage, NULL }}; | 246 { &FakeHandleMessage, &FakeHandleBlockingMessage, NULL }}; |
| 247 for (size_t i = 0; i < sizeof(bad_ppp_ifs)/sizeof(bad_ppp_ifs[0]); ++i) { | 247 for (size_t i = 0; i < sizeof(bad_ppp_ifs)/sizeof(bad_ppp_ifs[0]); ++i) { |
| 248 int32_t result = ppb_messaging_if_->RegisterMessageHandler( | 248 int32_t result = ppb_messaging_if_->RegisterMessageHandler( |
| 249 instance()->pp_instance(), | 249 instance()->pp_instance(), |
| 250 reinterpret_cast<void*>(0xdeadbeef), | 250 reinterpret_cast<void*>(0xdeadbeef), |
| 251 &bad_ppp_ifs[i], | 251 &bad_ppp_ifs[i], |
| 252 handler_thread_.message_loop().pp_resource()); | 252 handler_thread_.message_loop().pp_resource()); |
| 253 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); | 253 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // That should be fixed before this API goes to stable. See crbug.com/384528 | 288 // That should be fixed before this API goes to stable. See crbug.com/384528 |
| 289 js_code += "plugin.postMessage('FINISHED_TEST');\n"; | 289 js_code += "plugin.postMessage('FINISHED_TEST');\n"; |
| 290 instance_->EvalScript(js_code); | 290 instance_->EvalScript(js_code); |
| 291 handler.WaitForTestFinishedMessage(); | 291 handler.WaitForTestFinishedMessage(); |
| 292 handler.Unregister(); | 292 handler.Unregister(); |
| 293 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); | 293 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); |
| 294 | 294 |
| 295 PASS(); | 295 PASS(); |
| 296 } | 296 } |
| 297 | 297 |
| OLD | NEW |