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