summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authordmichael <dmichael@chromium.org>2014-09-18 11:00:29 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-18 18:00:46 +0000
commitb8737917043275c52ae682cddc6604c495d2e73f (patch)
treee9e333fe6377a717160e4cf52b15393c85e07db6 /ppapi
parent54f98657d48d67fdb4d0097e7a9f906cc52f9378 (diff)
downloadchromium_src-b8737917043275c52ae682cddc6604c495d2e73f.zip
chromium_src-b8737917043275c52ae682cddc6604c495d2e73f.tar.gz
chromium_src-b8737917043275c52ae682cddc6604c495d2e73f.tar.bz2
PPAPI: Add C++ wrapper for MessageHandler stuff.
BUG=367896 Review URL: https://codereview.chromium.org/318763003 Cr-Commit-Position: refs/heads/master@{#295495}
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/api/ppp_message_handler.idl13
-rw-r--r--ppapi/c/ppp_message_handler.h15
-rw-r--r--ppapi/cpp/instance.cc61
-rw-r--r--ppapi/cpp/instance.h51
-rw-r--r--ppapi/cpp/message_handler.h57
-rw-r--r--ppapi/ppapi_sources.gypi1
-rw-r--r--ppapi/tests/test_message_handler.cc92
7 files changed, 217 insertions, 73 deletions
diff --git a/ppapi/api/ppp_message_handler.idl b/ppapi/api/ppp_message_handler.idl
index e898f0b..7d76040 100644
--- a/ppapi/api/ppp_message_handler.idl
+++ b/ppapi/api/ppp_message_handler.idl
@@ -32,7 +32,7 @@ interface PPP_MessageHandler {
* @param[in] instance A <code>PP_Instance</code> identifying one instance
* of a module.
* @param[in] user_data is the same pointer which was provided by a call to
- * RegisterMessageHandler.
+ * RegisterMessageHandler().
* @param[in] message A copy of the parameter that JavaScript provided to
* postMessage().
*/
@@ -43,14 +43,19 @@ interface PPP_MessageHandler {
* Invoked as a result of JavaScript invoking postMessageAndAwaitResponse()
* on the plugin's DOM element.
*
+ * NOTE: JavaScript execution is blocked during the duration of this call.
+ * Hence, the plugin should respond as quickly as possible. For this reason,
+ * blocking completion callbacks are disallowed while handling a blocking
+ * message.
+ *
* @param[in] instance A <code>PP_Instance</code> identifying one instance
* of a module.
* @param[in] user_data is the same pointer which was provided by a call to
- * RegisterMessageHandler.
+ * RegisterMessageHandler().
* @param[in] message is a copy of the parameter that JavaScript provided
- * to postMessageAndAwaitResponse.
+ * to postMessageAndAwaitResponse().
* @param[out] response will be copied to a JavaScript object which is
- * returned as the result of postMessageAndAwaitResponse to the invoking
+ * returned as the result of postMessageAndAwaitResponse() to the invoking
JavaScript.
*/
void HandleBlockingMessage([in] PP_Instance instance,
diff --git a/ppapi/c/ppp_message_handler.h b/ppapi/c/ppp_message_handler.h
index 2b1a0db..b73ecb7 100644
--- a/ppapi/c/ppp_message_handler.h
+++ b/ppapi/c/ppp_message_handler.h
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-/* From ppp_message_handler.idl modified Wed Sep 10 17:04:21 2014. */
+/* From ppp_message_handler.idl modified Wed Sep 17 16:54:35 2014. */
#ifndef PPAPI_C_PPP_MESSAGE_HANDLER_H_
#define PPAPI_C_PPP_MESSAGE_HANDLER_H_
@@ -44,7 +44,7 @@ struct PPP_MessageHandler_0_2 { /* dev */
* @param[in] instance A <code>PP_Instance</code> identifying one instance
* of a module.
* @param[in] user_data is the same pointer which was provided by a call to
- * RegisterMessageHandler.
+ * RegisterMessageHandler().
* @param[in] message A copy of the parameter that JavaScript provided to
* postMessage().
*/
@@ -55,14 +55,19 @@ struct PPP_MessageHandler_0_2 { /* dev */
* Invoked as a result of JavaScript invoking postMessageAndAwaitResponse()
* on the plugin's DOM element.
*
+ * NOTE: JavaScript execution is blocked during the duration of this call.
+ * Hence, the plugin should respond as quickly as possible. For this reason,
+ * blocking completion callbacks are disallowed while handling a blocking
+ * message.
+ *
* @param[in] instance A <code>PP_Instance</code> identifying one instance
* of a module.
* @param[in] user_data is the same pointer which was provided by a call to
- * RegisterMessageHandler.
+ * RegisterMessageHandler().
* @param[in] message is a copy of the parameter that JavaScript provided
- * to postMessageAndAwaitResponse.
+ * to postMessageAndAwaitResponse().
* @param[out] response will be copied to a JavaScript object which is
- * returned as the result of postMessageAndAwaitResponse to the invoking
+ * returned as the result of postMessageAndAwaitResponse() to the invoking
*
*/
void (*HandleBlockingMessage)(PP_Instance instance,
diff --git a/ppapi/cpp/instance.cc b/ppapi/cpp/instance.cc
index a5be2b9..74b9321 100644
--- a/ppapi/cpp/instance.cc
+++ b/ppapi/cpp/instance.cc
@@ -9,12 +9,15 @@
#include "ppapi/c/ppb_input_event.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_messaging.h"
+#include "ppapi/c/ppp_message_handler.h"
#include "ppapi/cpp/compositor.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/graphics_3d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance_handle.h"
#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/message_handler.h"
+#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/point.h"
@@ -42,6 +45,38 @@ template <> const char* interface_name<PPB_Messaging_1_0>() {
return PPB_MESSAGING_INTERFACE_1_0;
}
+template <> const char* interface_name<PPB_Messaging_1_2>() {
+ return PPB_MESSAGING_INTERFACE_1_2;
+}
+
+// PPP_MessageHandler implementation -------------------------------------------
+void HandleMessage(PP_Instance pp_instance,
+ void* user_data,
+ const PP_Var* var) {
+ MessageHandler* message_handler = static_cast<MessageHandler*>(user_data);
+ message_handler->HandleMessage(InstanceHandle(pp_instance), Var(*var));
+}
+
+void HandleBlockingMessage(PP_Instance pp_instance,
+ void* user_data,
+ const PP_Var* var,
+ PP_Var* result) {
+ MessageHandler* message_handler = static_cast<MessageHandler*>(user_data);
+ pp::Var result_var =
+ message_handler->HandleBlockingMessage(InstanceHandle(pp_instance),
+ Var(*var));
+ *result = result_var.Detach();
+}
+
+void Destroy(PP_Instance pp_instance, void* user_data) {
+ MessageHandler* message_handler = static_cast<MessageHandler*>(user_data);
+ message_handler->WasUnregistered(InstanceHandle(pp_instance));
+}
+
+static PPP_MessageHandler_0_2 message_handler_if = {
+ &HandleMessage, &HandleBlockingMessage, &Destroy
+};
+
} // namespace
Instance::Instance(PP_Instance instance) : pp_instance_(instance) {
@@ -130,10 +165,30 @@ void Instance::ClearInputEventRequest(uint32_t event_classes) {
}
void Instance::PostMessage(const Var& message) {
- if (!has_interface<PPB_Messaging_1_0>())
+ if (has_interface<PPB_Messaging_1_2>()) {
+ get_interface<PPB_Messaging_1_2>()->PostMessage(pp_instance(),
+ message.pp_var());
+ } else if (has_interface<PPB_Messaging_1_0>()) {
+ get_interface<PPB_Messaging_1_0>()->PostMessage(pp_instance(),
+ message.pp_var());
+ }
+}
+
+int32_t Instance::RegisterMessageHandler(MessageHandler* message_handler,
+ const MessageLoop& message_loop) {
+ if (!has_interface<PPB_Messaging_1_2>())
+ return PP_ERROR_NOTSUPPORTED;
+ return get_interface<PPB_Messaging_1_2>()->RegisterMessageHandler(
+ pp_instance(),
+ message_handler,
+ &message_handler_if,
+ message_loop.pp_resource());
+}
+
+void Instance::UnregisterMessageHandler() {
+ if (!has_interface<PPB_Messaging_1_2>())
return;
- get_interface<PPB_Messaging_1_0>()->PostMessage(pp_instance(),
- message.pp_var());
+ get_interface<PPB_Messaging_1_2>()->UnregisterMessageHandler(pp_instance());
}
void Instance::LogToConsole(PP_LogLevel level, const Var& value) {
diff --git a/ppapi/cpp/instance.h b/ppapi/cpp/instance.h
index af024db..9bc16fb 100644
--- a/ppapi/cpp/instance.h
+++ b/ppapi/cpp/instance.h
@@ -33,6 +33,8 @@ class Graphics2D;
class Graphics3D;
class InputEvent;
class InstanceHandle;
+class MessageHandler;
+class MessageLoop;
class Rect;
class URLLoader;
class Var;
@@ -495,6 +497,55 @@ class Instance {
/// All var types are copied when passing them to JavaScript.
void PostMessage(const Var& message);
+ /// Dev-Channel Only
+ ///
+ /// Registers a handler for receiving messages from JavaScript. If a handler
+ /// is registered this way, it will replace the Instance's HandleMessage
+ /// method, and all messages sent from JavaScript via postMessage and
+ /// postMessageAndAwaitResponse will be dispatched to
+ /// <code>message_handler</code>.
+ ///
+ /// The function calls will be dispatched via <code>message_loop</code>. This
+ /// means that the functions will be invoked on the thread to which
+ /// <code>message_loop</code> is attached, when <code>message_loop</code> is
+ /// run. It is illegal to pass the main thread message loop;
+ /// RegisterMessageHandler will return PP_ERROR_WRONG_THREAD in that case.
+ /// If you quit <code>message_loop</code> before calling Unregister(),
+ /// the browser will not be able to call functions in the plugin's message
+ /// handler any more. That could mean missing some messages or could cause a
+ /// leak if you depend on Destroy() to free hander data. So you should,
+ /// whenever possible, Unregister() the handler prior to quitting its event
+ /// loop.
+ ///
+ /// Attempting to register a message handler when one is already registered
+ /// will cause the current MessageHandler to be unregistered and replaced. In
+ /// that case, no messages will be sent to the "default" message handler
+ /// (pp::Instance::HandleMessage()). Messages will stop arriving at the prior
+ /// message handler and will begin to be dispatched at the new message
+ /// handler.
+ ///
+ /// @param[in] message_handler The plugin-provided object for handling
+ /// messages. The instance does not take ownership of the pointer; it is up
+ /// to the plugin to ensure that |message_handler| lives until its
+ /// WasUnregistered() function is invoked.
+ /// @param[in] message_loop Represents the message loop on which
+ /// MessageHandler's functions should be invoked.
+ /// @return PP_OK on success, or an error from pp_errors.h.
+ int32_t RegisterMessageHandler(MessageHandler* message_handler,
+ const MessageLoop& message_loop);
+
+ /// Unregisters the current message handler for this instance if one is
+ /// registered. After this call, the message handler (if one was
+ /// registered) will have "WasUnregistered" called on it and will receive no
+ /// further messages. After that point, all messages sent from JavaScript
+ /// using postMessage() will be dispatched to pp::Instance::HandleMessage()
+ /// on the main thread. Attempts to call postMessageAndAwaitResponse() from
+ /// JavaScript after that point will fail.
+ ///
+ /// Attempting to unregister a message handler when none is registered has no
+ /// effect.
+ void UnregisterMessageHandler();
+
/// @}
/// @{
diff --git a/ppapi/cpp/message_handler.h b/ppapi/cpp/message_handler.h
new file mode 100644
index 0000000..0bb6ad8
--- /dev/null
+++ b/ppapi/cpp/message_handler.h
@@ -0,0 +1,57 @@
+// Copyright 2014 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.
+
+#ifndef PPAPI_CPP_MESSAGE_HANDLER_H_
+#define PPAPI_CPP_MESSAGE_HANDLER_H_
+
+namespace pp {
+
+/// <code>MessageHandler</code> is an abstract base class that the plugin may
+/// implement if it wants to receive messages from JavaScript on a background
+/// thread when JavaScript invokes postMessage() or
+/// postMessageAndAwaitResponse(). See pp::Instance::RegisterMessageHandler()
+/// for usage.
+class MessageHandler {
+ public:
+ virtual ~MessageHandler() {};
+
+ /// Invoked as a result of JavaScript invoking postMessage() on the plugin's
+ /// DOM element.
+ ///
+ /// @param[in] instance An <code>InstanceHandle</code> identifying one
+ /// instance of a module.
+ /// @param[in] message_data A copy of the parameter that JavaScript provided
+ /// to postMessage().
+ virtual void HandleMessage(pp::InstanceHandle instance,
+ const Var& message_data) = 0;
+
+ /// Invoked as a result of JavaScript invoking postMessageAndAwaitResponse()
+ /// on the plugin's DOM element.
+ ///
+ /// NOTE: JavaScript execution is blocked during the duration of this call.
+ /// Hence, the plugin should respond as quickly as possible. For this reason,
+ /// blocking completion callbacks are disallowed while handling a blocking
+ /// message.
+ ///
+ /// @param[in] instance An <code>InstanceHandle</code> identifying one
+ /// instance of a module.
+ /// @param[in] message_data A copy of the parameter that JavaScript provided
+ /// to postMessage().
+ /// @return Returns a pp::Var that is then copied to a JavaScript object
+ /// which is returned as the result of JavaScript's call of
+ /// postMessageAndAwaitResponse().
+ virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance,
+ const Var& message_data) = 0;
+
+ /// Invoked when this MessageHandler is no longer needed. After this, no more
+ /// calls will be made to this object.
+ ///
+ /// @param[in] instance An <code>InstanceHandle</code> identifying one
+ /// instance of a module.
+ virtual void WasUnregistered(pp::InstanceHandle instance) = 0;
+};
+
+} // namespace pp
+
+#endif // PPAPI_CPP_MESSAGE_HANDLER_H_
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 10f2d16..105ae4f 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -197,6 +197,7 @@
'cpp/media_stream_audio_track.h',
'cpp/media_stream_video_track.cc',
'cpp/media_stream_video_track.h',
+ 'cpp/message_handler.h',
'cpp/message_loop.cc',
'cpp/message_loop.h',
'cpp/module.cc',
diff --git a/ppapi/tests/test_message_handler.cc b/ppapi/tests/test_message_handler.cc
index 5b59f7d..c5c8354 100644
--- a/ppapi/tests/test_message_handler.cc
+++ b/ppapi/tests/test_message_handler.cc
@@ -17,6 +17,7 @@
#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/file_system.h"
#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/message_handler.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array.h"
@@ -38,32 +39,22 @@ namespace {
// Created and destroyed on the main thread. All public methods should be called
// on the main thread. Most data members are only accessed on the main thread.
// (Though it handles messages on the background thread).
-class EchoingMessageHandler {
+class EchoingMessageHandler : public pp::MessageHandler {
public:
- explicit EchoingMessageHandler(PP_Instance instance,
+ explicit EchoingMessageHandler(TestingInstance* instance,
const pp::MessageLoop& loop)
- : pp_instance_(instance),
+ : testing_instance_(instance),
message_handler_loop_(loop),
- ppb_messaging_if_(static_cast<const PPB_Messaging_1_2*>(
- pp::Module::Get()->GetBrowserInterface(
- PPB_MESSAGING_INTERFACE_1_2))),
- ppp_message_handler_if_(),
is_registered_(false),
- test_finished_event_(instance),
- destroy_event_(instance) {
+ test_finished_event_(instance->pp_instance()),
+ destroy_event_(instance->pp_instance()) {
AssertOnMainThread();
- ppp_message_handler_if_.HandleMessage = &HandleMessage;
- ppp_message_handler_if_.HandleBlockingMessage = &HandleBlockingMessage;
- ppp_message_handler_if_.Destroy = &Destroy;
}
void Register() {
AssertOnMainThread();
assert(!is_registered_);
- int32_t result = ppb_messaging_if_->RegisterMessageHandler(
- pp_instance_,
- this,
- &ppp_message_handler_if_,
- message_handler_loop_.pp_resource());
+ int32_t result =
+ testing_instance_->RegisterMessageHandler(this, message_handler_loop_);
if (result == PP_OK) {
is_registered_ = true;
} else {
@@ -78,7 +69,7 @@ class EchoingMessageHandler {
void Unregister() {
AssertOnMainThread();
assert(is_registered_);
- ppb_messaging_if_->UnregisterMessageHandler(pp_instance_);
+ testing_instance_->UnregisterMessageHandler();
is_registered_ = false;
}
void WaitForTestFinishedMessage() {
@@ -113,63 +104,42 @@ class EchoingMessageHandler {
errors_ += error;
}
}
- static void HandleMessage(PP_Instance instance,
- void* user_data,
- const PP_Var* message_data) {
- EchoingMessageHandler* thiz =
- static_cast<EchoingMessageHandler*>(user_data);
- if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_)
- thiz->AddError("HandleMessage was called on the wrong thread!");
- if (instance != thiz->pp_instance_)
- thiz->AddError("HandleMessage was passed the wrong instance!");
- pp::Var var(*message_data);
+ virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) {
+ if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
+ AddError("HandleMessage was called on the wrong thread!");
+ if (instance.pp_instance() != testing_instance_->pp_instance())
+ AddError("HandleMessage was passed the wrong instance!");
if (var.is_string() && var.AsString() == "FINISHED_TEST")
- thiz->test_finished_event_.Signal();
+ test_finished_event_.Signal();
else
- thiz->ppb_messaging_if_->PostMessage(instance, *message_data);
+ testing_instance_->PostMessage(var);
}
- static void HandleBlockingMessage(PP_Instance instance,
- void* user_data,
- const PP_Var* message_data,
- PP_Var* result) {
- EchoingMessageHandler* thiz =
- static_cast<EchoingMessageHandler*>(user_data);
- if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_)
- thiz->AddError("HandleBlockingMessage was called on the wrong thread!");
- if (instance != thiz->pp_instance_)
- thiz->AddError("HandleBlockingMessage was passed the wrong instance!");
+ virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance,
+ const pp::Var& var) {
+ if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
+ AddError("HandleBlockingMessage was called on the wrong thread!");
+ if (instance.pp_instance() != testing_instance_->pp_instance())
+ AddError("HandleBlockingMessage was passed the wrong instance!");
- // The PP_Var we are passed is an in-parameter, so the browser is not
- // giving us a ref-count. The ref-count it has will be decremented after we
- // return. But we need to add a ref when returning a PP_Var, to pass to the
- // caller.
- pp::Var take_ref(*message_data);
- take_ref.Detach();
- *result = *message_data;
+ return var;
}
- static void Destroy(PP_Instance instance, void* user_data) {
- EchoingMessageHandler* thiz =
- static_cast<EchoingMessageHandler*>(user_data);
- if (pp::MessageLoop::GetCurrent() != thiz->message_handler_loop_)
- thiz->AddError("Destroy was called on the wrong thread!");
- if (instance != thiz->pp_instance_)
- thiz->AddError("Destroy was passed the wrong instance!");
- thiz->destroy_event_.Signal();
+ virtual void WasUnregistered(pp::InstanceHandle instance) {
+ if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
+ AddError("Destroy was called on the wrong thread!");
+ if (instance.pp_instance() != testing_instance_->pp_instance())
+ AddError("Destroy was passed the wrong instance!");
+ destroy_event_.Signal();
}
// These data members are initialized on the main thread, but don't change for
// the life of the object, so are safe to access on the background thread,
// because there will be a memory barrier before the the MessageHandler calls
// are invoked.
- const PP_Instance pp_instance_;
+ TestingInstance* const testing_instance_;
const pp::MessageLoop message_handler_loop_;
const pp::MessageLoop main_loop_;
- const PPB_Messaging_1_2* const ppb_messaging_if_;
- // Spiritually, this member is const, but we can't initialize it in C++03,
- // so it has to be non-const to be set in the constructor body.
- PPP_MessageHandler_0_2 ppp_message_handler_if_;
// is_registered_ is only read/written on the main thread.
bool is_registered_;
@@ -258,7 +228,7 @@ std::string TestMessageHandler::TestRegisterErrorConditions() {
}
std::string TestMessageHandler::TestPostMessageAndAwaitResponse() {
- EchoingMessageHandler handler(instance()->pp_instance(),
+ EchoingMessageHandler handler(instance(),
handler_thread_.message_loop());
handler.Register();
std::string js_code("var plugin = document.getElementById('plugin');\n");