| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ppapi/tests/test_flash_message_loop.h" |
| |
| #include "ppapi/c/pp_macros.h" |
| #include "ppapi/c/ppb_var.h" |
| #include "ppapi/cpp/core.h" |
| #include "ppapi/cpp/dev/scriptable_object_deprecated.h" |
| #include "ppapi/cpp/logging.h" |
| #include "ppapi/cpp/module.h" |
| #include "ppapi/cpp/private/flash_message_loop.h" |
| #include "ppapi/tests/testing_instance.h" |
| |
| namespace { |
| |
| const char kDidRunScriptCallback[] = "DidRunScriptCallback"; |
| |
| } // namespace |
| |
| class TestFlashMessageLoop::InstanceSO |
| : public pp::deprecated::ScriptableObject { |
| public: |
| explicit InstanceSO(TestFlashMessageLoop* owner) : owner_(owner) {} |
| |
| ~InstanceSO() override { |
| if (owner_) |
| owner_->clear_instance_so(); |
| } |
| |
| // pp::deprecated::ScriptableObject overrides. |
| bool HasMethod(const pp::Var& name, pp::Var* exception) override { |
| if (!name.is_string()) |
| return false; |
| return name.AsString() == kDidRunScriptCallback; |
| } |
| |
| pp::Var Call(const pp::Var& method_name, |
| const std::vector<pp::Var>& args, |
| pp::Var* exception) override { |
| if (!method_name.is_string()) |
| return false; |
| std::string name = method_name.AsString(); |
| |
| if (name == kDidRunScriptCallback) { |
| if (args.size() != 0) { |
| *exception = pp::Var("Bad argument to DidRunScriptCallback()"); |
| } else if (owner_) { |
| owner_->DidRunScriptCallback(); |
| } |
| } else { |
| *exception = pp::Var("Bad function call"); |
| } |
| |
| return pp::Var(); |
| } |
| |
| void clear_owner() { owner_ = nullptr; } |
| |
| private: |
| TestFlashMessageLoop* owner_; |
| }; |
| |
| REGISTER_TEST_CASE(FlashMessageLoop); |
| |
| TestFlashMessageLoop::TestFlashMessageLoop(TestingInstance* instance) |
| : TestCase(instance), |
| message_loop_(nullptr), |
| instance_so_(nullptr), |
| suspend_script_callback_result_(false), |
| callback_factory_(this) {} |
| |
| TestFlashMessageLoop::~TestFlashMessageLoop() { |
| PP_DCHECK(!message_loop_); |
| |
| ResetTestObject(); |
| if (instance_so_) |
| instance_so_->clear_owner(); |
| } |
| |
| void TestFlashMessageLoop::RunTests(const std::string& filter) { |
| RUN_TEST(Basics, filter); |
| RUN_TEST(RunWithoutQuit, filter); |
| RUN_TEST(SuspendScriptCallbackWhileRunning, filter); |
| } |
| |
| void TestFlashMessageLoop::DidRunScriptCallback() { |
| // Script callbacks are not supposed to run while the Flash message loop is |
| // running. |
| if (message_loop_) |
| suspend_script_callback_result_ = false; |
| } |
| |
| pp::deprecated::ScriptableObject* TestFlashMessageLoop::CreateTestObject() { |
| if (!instance_so_) |
| instance_so_ = new InstanceSO(this); |
| return instance_so_; |
| } |
| |
| std::string TestFlashMessageLoop::TestBasics() { |
| message_loop_ = new pp::flash::MessageLoop(instance_); |
| |
| pp::CompletionCallback callback = callback_factory_.NewCallback( |
| &TestFlashMessageLoop::QuitMessageLoopTask); |
| pp::Module::Get()->core()->CallOnMainThread(0, callback); |
| int32_t result = message_loop_->Run(); |
| |
| ASSERT_TRUE(message_loop_); |
| delete message_loop_; |
| message_loop_ = nullptr; |
| |
| ASSERT_EQ(PP_OK, result); |
| PASS(); |
| } |
| |
| std::string TestFlashMessageLoop::TestRunWithoutQuit() { |
| message_loop_ = new pp::flash::MessageLoop(instance_); |
| |
| pp::CompletionCallback callback = callback_factory_.NewCallback( |
| &TestFlashMessageLoop::DestroyMessageLoopResourceTask); |
| pp::Module::Get()->core()->CallOnMainThread(0, callback); |
| int32_t result = message_loop_->Run(); |
| |
| if (message_loop_) { |
| delete message_loop_; |
| message_loop_ = nullptr; |
| ASSERT_TRUE(false); |
| } |
| |
| ASSERT_EQ(PP_ERROR_ABORTED, result); |
| PASS(); |
| } |
| |
| std::string TestFlashMessageLoop::TestSuspendScriptCallbackWhileRunning() { |
| suspend_script_callback_result_ = true; |
| message_loop_ = new pp::flash::MessageLoop(instance_); |
| |
| pp::CompletionCallback callback = callback_factory_.NewCallback( |
| &TestFlashMessageLoop::TestSuspendScriptCallbackTask); |
| pp::Module::Get()->core()->CallOnMainThread(0, callback); |
| message_loop_->Run(); |
| |
| ASSERT_TRUE(message_loop_); |
| delete message_loop_; |
| message_loop_ = nullptr; |
| |
| ASSERT_TRUE(suspend_script_callback_result_); |
| PASS(); |
| } |
| |
| void TestFlashMessageLoop::TestSuspendScriptCallbackTask(int32_t unused) { |
| pp::Var exception; |
| pp::Var rev = instance_->ExecuteScript( |
| "(function() {" |
| " function delayedHandler() {" |
| " document.getElementById('plugin').DidRunScriptCallback();" |
| " }" |
| " setTimeout(delayedHandler, 1);" |
| "})()", |
| &exception); |
| if (!exception.is_undefined()) |
| suspend_script_callback_result_ = false; |
| |
| pp::CompletionCallback callback = |
| callback_factory_.NewCallback(&TestFlashMessageLoop::QuitMessageLoopTask); |
| pp::Module::Get()->core()->CallOnMainThread(500, callback); |
| } |
| |
| void TestFlashMessageLoop::QuitMessageLoopTask(int32_t unused) { |
| if (message_loop_) |
| message_loop_->Quit(); |
| else |
| PP_NOTREACHED(); |
| } |
| |
| void TestFlashMessageLoop::DestroyMessageLoopResourceTask(int32_t unused) { |
| if (message_loop_) { |
| delete message_loop_; |
| message_loop_ = nullptr; |
| } else { |
| PP_NOTREACHED(); |
| } |
| } |