1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/tests/test_message_handler.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <algorithm> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <map> 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sstream> 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/c/pp_var.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/c/ppb_file_io.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ppapi/c/ppb_messaging.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/c/ppp_message_handler.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ppapi/cpp/completion_callback.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/file_io.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/file_ref.h" 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/file_system.h" 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/instance.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ppapi/cpp/message_handler.h" 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/module_impl.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ppapi/cpp/network_list.h" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ppapi/cpp/network_monitor.h" 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/var.h" 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/var_array.h" 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/var_array_buffer.h" 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/var_dictionary.h" 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/tests/pp_thread.h" 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/tests/test_utils.h" 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/tests/testing_instance.h" 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Windows defines 'PostMessage', so we have to undef it. 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef PostMessage 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#undef PostMessage 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)REGISTER_TEST_CASE(MessageHandler); 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Created and destroyed on the main thread. All public methods should be called 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// on the main thread. Most data members are only accessed on the main thread. 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// (Though it handles messages on the background thread). 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass EchoingMessageHandler : public pp::MessageHandler { 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci explicit EchoingMessageHandler(TestingInstance* instance, 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const pp::MessageLoop& loop) 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : testing_instance_(instance), 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) message_handler_loop_(loop), 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) is_registered_(false), 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci test_finished_event_(instance->pp_instance()), 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci destroy_event_(instance->pp_instance()) { 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AssertOnMainThread(); 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void Register() { 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AssertOnMainThread(); 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assert(!is_registered_); 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32_t result = 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci testing_instance_->RegisterMessageHandler(this, message_handler_loop_); 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result == PP_OK) { 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) is_registered_ = true; 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::ostringstream stream; 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stream << "Failed to register message handler; got error " << result; 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AddError(stream.str()); 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) test_finished_event_.Signal(); 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Note, at this point, we can't safely read or write errors_ until we wait 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // on destroy_event_. 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void Unregister() { 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AssertOnMainThread(); 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assert(is_registered_); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci testing_instance_->UnregisterMessageHandler(); 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) is_registered_ = false; 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void WaitForTestFinishedMessage() { 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) test_finished_event_.Wait(); 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) test_finished_event_.Reset(); 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Wait for Destroy() to be called on the MessageHandler thread. When it's 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // done, return any errors that occurred during the time the MessageHandler 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // was getting messages. 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string WaitForDestroy() { 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AssertOnMainThread(); 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If we haven't called Unregister, we'll be waiting forever. 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assert(!is_registered_); 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) destroy_event_.Wait(); 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) destroy_event_.Reset(); 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Now that we know Destroy() has been called, we know errors_ isn't being 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // written on the MessageHandler thread anymore. So we can safely read it 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // here on the main thread (since destroy_event_ gave us a memory barrier). 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string temp_errors; 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) errors_.swap(temp_errors); 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return temp_errors; 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static void AssertOnMainThread() { 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assert(pp::MessageLoop::GetForMainThread() == 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pp::MessageLoop::GetCurrent()); 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void AddError(const std::string& error) { 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!error.empty()) { 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!errors_.empty()) 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) errors_ += "<p>"; 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) errors_ += error; 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) { 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("HandleMessage was called on the wrong thread!"); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (instance.pp_instance() != testing_instance_->pp_instance()) 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("HandleMessage was passed the wrong instance!"); 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (var.is_string() && var.AsString() == "FINISHED_TEST") 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci test_finished_event_.Signal(); 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci testing_instance_->PostMessage(var); 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance, 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const pp::Var& var) { 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("HandleBlockingMessage was called on the wrong thread!"); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (instance.pp_instance() != testing_instance_->pp_instance()) 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("HandleBlockingMessage was passed the wrong instance!"); 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Attempt a blocking operation; make sure it's disallowed. 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::NetworkMonitor monitor(instance); 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_Resource out_param = 0; 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::CompletionCallbackWithOutput<pp::NetworkList> blocking_callback( 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &out_param); 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32_t error = monitor.UpdateNetworkList(blocking_callback); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (error != PP_ERROR_WOULD_BLOCK_THREAD) { 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("HandleBlockingMessage was allowed to do a blocking call!"); 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::Module::Get()->core()->ReleaseResource(out_param); 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return var; 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void WasUnregistered(pp::InstanceHandle instance) { 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("Destroy was called on the wrong thread!"); 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (instance.pp_instance() != testing_instance_->pp_instance()) 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddError("Destroy was passed the wrong instance!"); 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci destroy_event_.Signal(); 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // These data members are initialized on the main thread, but don't change for 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // the life of the object, so are safe to access on the background thread, 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // because there will be a memory barrier before the the MessageHandler calls 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // are invoked. 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TestingInstance* const testing_instance_; 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const pp::MessageLoop message_handler_loop_; 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const pp::MessageLoop main_loop_; 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // is_registered_ is only read/written on the main thread. 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool is_registered_; 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // errors_ is written on the MessageHandler thread. When Destroy() is 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // called, we stop writing to errors_ and signal destroy_event_. This causes 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // a memory barrier, so it's safe to read errors_ after that. 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string errors_; 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NestedEvent test_finished_event_; 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NestedEvent destroy_event_; 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Undefined & private to disallow copy and assign. 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EchoingMessageHandler(const EchoingMessageHandler&); 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EchoingMessageHandler& operator=(const EchoingMessageHandler&); 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FakeHandleMessage(PP_Instance instance, 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* user_data, 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const PP_Var* message_data) {} 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid FakeHandleBlockingMessage(PP_Instance instance, 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void* user_data, 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const PP_Var* message_data, 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_Var* result) {} 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FakeDestroy(PP_Instance instance, void* user_data) {} 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TestMessageHandler::TestMessageHandler(TestingInstance* instance) 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : TestCase(instance), 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ppb_messaging_if_(NULL), 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handler_thread_(instance), 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_received_(instance->pp_instance()) { 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TestMessageHandler::~TestMessageHandler() { 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler_thread_.Join(); 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool TestMessageHandler::Init() { 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ppb_messaging_if_ = static_cast<const PPB_Messaging_1_2*>( 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2)); 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ppb_messaging_if_ && 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CheckTestingInterface() && 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler_thread_.Start(); 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void TestMessageHandler::RunTests(const std::string& filter) { 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RUN_TEST(RegisterErrorConditions, filter); 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RUN_TEST(PostMessageAndAwaitResponse, filter); 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RUN_TEST(Exceptions, filter); 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void TestMessageHandler::HandleMessage(const pp::Var& message_data) { 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (instance()->current_test_name() == "Exceptions") { 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // For TestPostMessageAndAwaitResponse(), all messages should go to the 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // background thread message handler. 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci assert(false); 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (message_data.is_string()) { 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci last_message_ = message_data.AsString(); 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci last_message_ = "message_data was not a string!"; 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_received_.Signal(); 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)std::string TestMessageHandler::TestRegisterErrorConditions() { 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Test registering with the main thread as the message loop. 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PPP_MessageHandler_0_2 fake_ppp_message_handler = { 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pp::MessageLoop main_loop = pp::MessageLoop::GetForMainThread(); 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int32_t result = ppb_messaging_if_->RegisterMessageHandler( 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) instance()->pp_instance(), 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<void*>(0xdeadbeef), 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &fake_ppp_message_handler, 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) main_loop.pp_resource()); 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(PP_ERROR_WRONG_THREAD, result); 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Test registering with incomplete PPP_Messaging interface. 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PPP_MessageHandler_0_2 bad_ppp_ifs[] = { 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { NULL, &FakeHandleBlockingMessage, &FakeDestroy }, 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { &FakeHandleMessage, NULL, &FakeDestroy }, 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { &FakeHandleMessage, &FakeHandleBlockingMessage, NULL }}; 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < sizeof(bad_ppp_ifs)/sizeof(bad_ppp_ifs[0]); ++i) { 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int32_t result = ppb_messaging_if_->RegisterMessageHandler( 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) instance()->pp_instance(), 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<void*>(0xdeadbeef), 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &bad_ppp_ifs[i], 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler_thread_.message_loop().pp_resource()); 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(PP_ERROR_BADARGUMENT, result); 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PASS(); 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)std::string TestMessageHandler::TestPostMessageAndAwaitResponse() { 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EchoingMessageHandler handler(instance(), 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler_thread_.message_loop()); 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Test doing a sync call before the handler is registered. 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler.Register(); 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string js_code("var plugin = document.getElementById('plugin');\n"); 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += "var result = undefined;\n"; 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* const values_to_test[] = { 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "5", 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "undefined", 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "1.5", 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "'hello'", 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "{'key': 'value', 'array_key': [1, 2, 3, 4, 5]}", 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NULL 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; values_to_test[i]; ++i) { 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += "result = plugin.postMessageAndAwaitResponse("; 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += values_to_test[i]; 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += ");\n"; 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += "if (!deepCompare(result, "; 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += values_to_test[i]; 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += "))\n"; 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += " InternalError(\" Failed postMessageAndAwaitResponse for: "; 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += values_to_test[i]; 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) js_code += " result: \" + result);\n"; 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) instance_->EvalScript(js_code); 28334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) instance_->EvalScript("plugin.postMessage('FINISHED_TEST');\n"); 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler.WaitForTestFinishedMessage(); 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler.Unregister(); 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PASS(); 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string TestMessageHandler::TestExceptions() { 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EchoingMessageHandler handler(instance(), 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handler_thread_.message_loop()); 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // First, try sending a blocking message when there is no handler 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // registered. It should throw an exception. 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string js_code( 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "var plugin = document.getElementById('plugin');\n" 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "var caught_exception = false;\n" 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "try {\n" 3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " plugin.postMessageAndAwaitResponse('Hello!');\n" 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "} catch (err) {\n" 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " caught_exception = true;\n" 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "}\n" 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"); 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci instance_->EvalScript(js_code); 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_received_.Wait(); 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_EQ("SUCCESS", last_message_); 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handler.Register(); 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Now that a handler is registered, try requesting and sending a 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // FileSystem. It should throw an exception. The file system is opened 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // asynchronously. What *should* happen is that it opens successfully, then 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // we try to send it via postMessageAndAwaitResponse, which fails with an 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // exception. The test could fail either because the filesystem doesn't 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // open or because postMessageAndAwaitResponse doesn't throw an exception. 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string js_code( 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "var plugin = document.getElementById('plugin');\n" 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "function gotFileSystem(fs) {\n" 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " var caught_exception = false;\n" 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " try {\n" 3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " plugin.postMessageAndAwaitResponse(fs);\n" 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " } catch (err) {\n" 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " caught_exception = true;\n" 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " }\n" 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n" 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "}\n" 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "function fileSystemError() {\n" 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " plugin.postMessage('Failed to open filesystem');\n" 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "}\n" 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "window.webkitRequestFileSystem(\n" 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci " window.Temporary, 1024, gotFileSystem, fileSystemError)\n"); 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci instance_->EvalScript(js_code); 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_received_.Wait(); 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_EQ("SUCCESS", last_message_); 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handler.Unregister(); 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PASS(); 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 344