PPAPI: Make PPP_MessageHandler work in PNaCl

The PNaCl ABI does not work in general with passing structs by-value.
Rather than add more complication to the shim, this changes
HandleBlockingMessage's parameter to a const-pointer param, and the return
to an out-param by pointer.

Note I wanted to pass PP_Var by const-pointer, while its "default" is
by value. So I added a new "constptr_in" param style.
(Maybe I should invert that and add a byvalue instead?)

Verified backwards compat with manual testing.

BUG=384539
[email protected], [email protected], [email protected]

Review URL: https://codereview.chromium.org/564573002

Cr-Commit-Position: refs/heads/master@{#295341}
diff --git a/ppapi/api/ppb_messaging.idl b/ppapi/api/ppb_messaging.idl
index 5100f5f5..b6da9e8 100644
--- a/ppapi/api/ppb_messaging.idl
+++ b/ppapi/api/ppb_messaging.idl
@@ -9,11 +9,9 @@
  * specific module instance.
  */
 
-[generate_thunk]
-
 label Chrome {
   M14 = 1.0,
-  [channel=dev] M37 = 1.1
+  [channel=dev] M39 = 1.2
 };
 
 /**
@@ -120,7 +118,7 @@
    * PPP_MessageHandler functions should be invoked.
    * @return PP_OK on success, or an error from pp_errors.h.
    */
-  [version=1.1]
+  [version=1.2]
   int32_t RegisterMessageHandler([in] PP_Instance instance,
                                  [inout] mem_t user_data,
                                  [in] PPP_MessageHandler handler,
@@ -140,7 +138,7 @@
    * @param[in] instance A <code>PP_Instance</code> identifying one instance
    * of a module.
    */
-  [version=1.1]
+  [version=1.2]
   void UnregisterMessageHandler([in] PP_Instance instance);
 };
 
diff --git a/ppapi/api/ppp_message_handler.idl b/ppapi/api/ppp_message_handler.idl
index 675b1a3..e898f0b 100644
--- a/ppapi/api/ppp_message_handler.idl
+++ b/ppapi/api/ppp_message_handler.idl
@@ -11,7 +11,7 @@
  */
 
 label Chrome {
-  [channel=none] M37 = 0.1
+  [channel=dev] M39 = 0.2
 };
 
 /**
@@ -38,7 +38,7 @@
    */
   void HandleMessage([in] PP_Instance instance,
                      [inout] mem_t user_data,
-                     [in] PP_Var message);
+                     [constptr_in] PP_Var message);
   /**
    * Invoked as a result of JavaScript invoking postMessageAndAwaitResponse()
    * on the plugin's DOM element.
@@ -49,12 +49,14 @@
    * RegisterMessageHandler.
    * @param[in] message is a copy of the parameter that JavaScript provided
    * to postMessageAndAwaitResponse.
-   * @return will be copied to a JavaScript object which is returned as
-   * the result of postMessageAndAwaitResponse to the invoking JavaScript.
+   * @param[out] response will be copied to a JavaScript object which is
+   * returned as the result of postMessageAndAwaitResponse to the invoking
+     JavaScript.
    */
-  PP_Var HandleBlockingMessage([in] PP_Instance instance,
-                               [inout] mem_t user_data,
-                               [in] PP_Var message);
+  void HandleBlockingMessage([in] PP_Instance instance,
+                             [inout] mem_t user_data,
+                             [constptr_in] PP_Var message,
+                             [out] PP_Var response);
   /**
    * Invoked when the handler object is no longer needed. After this, no more
    * calls will be made which pass this same value for <code>instance</code>
diff --git a/ppapi/c/dev/ppb_messaging_deprecated.h b/ppapi/c/dev/ppb_messaging_deprecated.h
new file mode 100644
index 0000000..045c9d9
--- /dev/null
+++ b/ppapi/c/dev/ppb_messaging_deprecated.h
@@ -0,0 +1,47 @@
+/* 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_C_DEV_IMPL_PPB_MESSAGING_DEPRECATED_H_
+#define PPAPI_C_DEV_IMPL_PPB_MESSAGING_DEPRECATED_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+
+/* dev, deprecated */
+#define PPB_MESSAGING_INTERFACE_1_1_DEPRECATED "PPB_Messaging;1.1"
+
+/**
+ * This file defines a dev-channel-only API, PPB_Messaging;1.1 that is
+ * deprecated, but which still should provide ABI compatibility for a little
+ * bit longer to give time to transition off of it. The header is *not* provided
+ * in ppapi/c/ppb_messaging.h, in order to push clients to the new API,
+ * version 1.2.
+ * TODO(dmichael): Delete this API altogether when all uses are gone.
+ *                 crbug.com/414398
+ */
+struct PPP_MessageHandler_0_1_Deprecated { /* dev */
+  void (*HandleMessage)(PP_Instance instance,
+                        void* user_data,
+                        struct PP_Var message);
+  struct PP_Var (*HandleBlockingMessage)(PP_Instance instance,
+                                void* user_data,
+                                struct PP_Var message);
+  void (*Destroy)(PP_Instance instance, void* user_data);
+};
+
+struct PPB_Messaging_1_1_Deprecated { /* dev */
+  void (*PostMessage)(PP_Instance instance, struct PP_Var message);
+  int32_t (*RegisterMessageHandler)(
+      PP_Instance instance,
+      void* user_data,
+      const struct PPP_MessageHandler_0_1_Deprecated* handler,
+      PP_Resource message_loop);
+  void (*UnregisterMessageHandler)(PP_Instance instance);
+};
+
+#endif  /* PPAPI_C_DEV_IMPL_PPB_MESSAGING_DEPRECATED_H_ */
+
diff --git a/ppapi/c/ppb_messaging.h b/ppapi/c/ppb_messaging.h
index c361d148..73ec4a6 100644
--- a/ppapi/c/ppb_messaging.h
+++ b/ppapi/c/ppb_messaging.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppb_messaging.idl modified Fri Jun 13 15:28:26 2014. */
+/* From ppb_messaging.idl modified Wed Sep 10 15:41:14 2014. */
 
 #ifndef PPAPI_C_PPB_MESSAGING_H_
 #define PPAPI_C_PPB_MESSAGING_H_
@@ -17,7 +17,7 @@
 #include "ppapi/c/ppp_message_handler.h"
 
 #define PPB_MESSAGING_INTERFACE_1_0 "PPB_Messaging;1.0"
-#define PPB_MESSAGING_INTERFACE_1_1 "PPB_Messaging;1.1" /* dev */
+#define PPB_MESSAGING_INTERFACE_1_2 "PPB_Messaging;1.2" /* dev */
 #define PPB_MESSAGING_INTERFACE PPB_MESSAGING_INTERFACE_1_0
 
 /**
@@ -37,7 +37,7 @@
  * and is related to sending messages to JavaScript message event listeners on
  * the DOM element associated with specific module instance.
  */
-struct PPB_Messaging_1_1 { /* dev */
+struct PPB_Messaging_1_2 { /* dev */
   /**
    * PostMessage() asynchronously invokes any listeners for message events on
    * the DOM element for the given module instance. A call to PostMessage()
@@ -137,7 +137,7 @@
   int32_t (*RegisterMessageHandler)(
       PP_Instance instance,
       void* user_data,
-      const struct PPP_MessageHandler_0_1* handler,
+      const struct PPP_MessageHandler_0_2* handler,
       PP_Resource message_loop);
   /**
    * Unregisters the current message handler for <code>instance</code> if one
diff --git a/ppapi/c/ppp_message_handler.h b/ppapi/c/ppp_message_handler.h
index 8032378..2b1a0db 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 Tue Jun  3 16:50:26 2014. */
+/* From ppp_message_handler.idl modified Wed Sep 10 17:04:21 2014. */
 
 #ifndef PPAPI_C_PPP_MESSAGE_HANDLER_H_
 #define PPAPI_C_PPP_MESSAGE_HANDLER_H_
@@ -36,7 +36,7 @@
  * This interface struct should not be returned by PPP_GetInterface; instead it
  * must be passed as a parameter to PPB_Messaging::RegisterMessageHandler.
  */
-struct PPP_MessageHandler_0_1 {
+struct PPP_MessageHandler_0_2 { /* dev */
   /**
    * Invoked as a result of JavaScript invoking postMessage() on the plugin's
    * DOM element.
@@ -50,7 +50,7 @@
    */
   void (*HandleMessage)(PP_Instance instance,
                         void* user_data,
-                        struct PP_Var message);
+                        const struct PP_Var* message);
   /**
    * Invoked as a result of JavaScript invoking postMessageAndAwaitResponse()
    * on the plugin's DOM element.
@@ -61,12 +61,14 @@
    * RegisterMessageHandler.
    * @param[in] message is a copy of the parameter that JavaScript provided
    * to postMessageAndAwaitResponse.
-   * @return will be copied to a JavaScript object which is returned as
-   * the result of postMessageAndAwaitResponse to the invoking JavaScript.
+   * @param[out] response will be copied to a JavaScript object which is
+   * returned as the result of postMessageAndAwaitResponse to the invoking
+   *
    */
-  struct PP_Var (*HandleBlockingMessage)(PP_Instance instance,
-                                         void* user_data,
-                                         struct PP_Var message);
+  void (*HandleBlockingMessage)(PP_Instance instance,
+                                void* user_data,
+                                const struct PP_Var* message,
+                                struct PP_Var* response);
   /**
    * Invoked when the handler object is no longer needed. After this, no more
    * calls will be made which pass this same value for <code>instance</code>
diff --git a/ppapi/generators/idl_c_proto.py b/ppapi/generators/idl_c_proto.py
index bc569ad..d6b9ebc 100755
--- a/ppapi/generators/idl_c_proto.py
+++ b/ppapi/generators/idl_c_proto.py
@@ -148,6 +148,7 @@
     },
     'TypeValue': {
       'in': '%s',
+      'constptr_in': 'const %s*',  # So we can use const* for PP_Var sometimes.
       'inout': '%s*',
       'out': '%s*',
       'return': '%s',
@@ -382,6 +383,7 @@
     if node.GetProperty('in'): return 'in'
     if node.GetProperty('out'): return 'out'
     if node.GetProperty('inout'): return 'inout'
+    if node.GetProperty('constptr_in'): return 'constptr_in'
     return 'return'
 
   #
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
index 12d73b5e4..ee1219b 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -124,7 +124,7 @@
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_1_0;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_MessageLoop_1_0;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Messaging_1_0;
-static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Messaging_1_1;
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Messaging_1_2;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_MouseLock_1_0;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_NetAddress_1_0;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_NetworkList_1_0;
@@ -1329,24 +1329,24 @@
 
 /* End wrapper methods for PPB_Messaging_1_0 */
 
-/* Begin wrapper methods for PPB_Messaging_1_1 */
+/* Begin wrapper methods for PPB_Messaging_1_2 */
 
-static void Pnacl_M37_PPB_Messaging_PostMessage(PP_Instance instance, struct PP_Var* message) {
-  const struct PPB_Messaging_1_1 *iface = Pnacl_WrapperInfo_PPB_Messaging_1_1.real_iface;
+static void Pnacl_M39_PPB_Messaging_PostMessage(PP_Instance instance, struct PP_Var* message) {
+  const struct PPB_Messaging_1_2 *iface = Pnacl_WrapperInfo_PPB_Messaging_1_2.real_iface;
   iface->PostMessage(instance, *message);
 }
 
-static int32_t Pnacl_M37_PPB_Messaging_RegisterMessageHandler(PP_Instance instance, void* user_data, const struct PPP_MessageHandler_0_1* handler, PP_Resource message_loop) {
-  const struct PPB_Messaging_1_1 *iface = Pnacl_WrapperInfo_PPB_Messaging_1_1.real_iface;
+static int32_t Pnacl_M39_PPB_Messaging_RegisterMessageHandler(PP_Instance instance, void* user_data, const struct PPP_MessageHandler_0_2* handler, PP_Resource message_loop) {
+  const struct PPB_Messaging_1_2 *iface = Pnacl_WrapperInfo_PPB_Messaging_1_2.real_iface;
   return iface->RegisterMessageHandler(instance, user_data, handler, message_loop);
 }
 
-static void Pnacl_M37_PPB_Messaging_UnregisterMessageHandler(PP_Instance instance) {
-  const struct PPB_Messaging_1_1 *iface = Pnacl_WrapperInfo_PPB_Messaging_1_1.real_iface;
+static void Pnacl_M39_PPB_Messaging_UnregisterMessageHandler(PP_Instance instance) {
+  const struct PPB_Messaging_1_2 *iface = Pnacl_WrapperInfo_PPB_Messaging_1_2.real_iface;
   iface->UnregisterMessageHandler(instance);
 }
 
-/* End wrapper methods for PPB_Messaging_1_1 */
+/* End wrapper methods for PPB_Messaging_1_2 */
 
 /* Not generating wrapper methods for PPB_MouseCursor_1_0 */
 
@@ -2121,7 +2121,7 @@
 
 /* Not generating wrapper methods for PPP_Instance_1_1 */
 
-/* Not generating wrapper methods for PPP_MessageHandler_0_1 */
+/* Not generating wrapper methods for PPP_MessageHandler_0_2 */
 
 /* Begin wrapper methods for PPP_Messaging_1_0 */
 
@@ -4819,10 +4819,10 @@
     .PostMessage = (void (*)(PP_Instance instance, struct PP_Var message))&Pnacl_M14_PPB_Messaging_PostMessage
 };
 
-static const struct PPB_Messaging_1_1 Pnacl_Wrappers_PPB_Messaging_1_1 = {
-    .PostMessage = (void (*)(PP_Instance instance, struct PP_Var message))&Pnacl_M37_PPB_Messaging_PostMessage,
-    .RegisterMessageHandler = (int32_t (*)(PP_Instance instance, void* user_data, const struct PPP_MessageHandler_0_1* handler, PP_Resource message_loop))&Pnacl_M37_PPB_Messaging_RegisterMessageHandler,
-    .UnregisterMessageHandler = (void (*)(PP_Instance instance))&Pnacl_M37_PPB_Messaging_UnregisterMessageHandler
+static const struct PPB_Messaging_1_2 Pnacl_Wrappers_PPB_Messaging_1_2 = {
+    .PostMessage = (void (*)(PP_Instance instance, struct PP_Var message))&Pnacl_M39_PPB_Messaging_PostMessage,
+    .RegisterMessageHandler = (int32_t (*)(PP_Instance instance, void* user_data, const struct PPP_MessageHandler_0_2* handler, PP_Resource message_loop))&Pnacl_M39_PPB_Messaging_RegisterMessageHandler,
+    .UnregisterMessageHandler = (void (*)(PP_Instance instance))&Pnacl_M39_PPB_Messaging_UnregisterMessageHandler
 };
 
 /* Not generating wrapper interface for PPB_MouseCursor_1_0 */
@@ -5053,7 +5053,7 @@
 
 /* Not generating wrapper interface for PPP_Instance_1_1 */
 
-/* Not generating wrapper interface for PPP_MessageHandler_0_1 */
+/* Not generating wrapper interface for PPP_MessageHandler_0_2 */
 
 static const struct PPP_Messaging_1_0 Pnacl_Wrappers_PPP_Messaging_1_0 = {
     .HandleMessage = &Pnacl_M14_PPP_Messaging_HandleMessage
@@ -5896,9 +5896,9 @@
   .real_iface = NULL
 };
 
-static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Messaging_1_1 = {
-  .iface_macro = PPB_MESSAGING_INTERFACE_1_1,
-  .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_Messaging_1_1,
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Messaging_1_2 = {
+  .iface_macro = PPB_MESSAGING_INTERFACE_1_2,
+  .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_Messaging_1_2,
   .real_iface = NULL
 };
 
@@ -6411,7 +6411,7 @@
   &Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_1_0,
   &Pnacl_WrapperInfo_PPB_MessageLoop_1_0,
   &Pnacl_WrapperInfo_PPB_Messaging_1_0,
-  &Pnacl_WrapperInfo_PPB_Messaging_1_1,
+  &Pnacl_WrapperInfo_PPB_Messaging_1_2,
   &Pnacl_WrapperInfo_PPB_MouseLock_1_0,
   &Pnacl_WrapperInfo_PPB_NetAddress_1_0,
   &Pnacl_WrapperInfo_PPB_NetworkList_1_0,
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index 295069e7..3e9003f 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -17,6 +17,7 @@
 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
 #include "ppapi/c/dev/ppb_ime_input_event_dev.h"
 #include "ppapi/c/dev/ppb_memory_dev.h"
+#include "ppapi/c/dev/ppb_messaging_deprecated.h"
 #include "ppapi/c/dev/ppb_opengles2ext_dev.h"
 #include "ppapi/c/dev/ppb_printing_dev.h"
 #include "ppapi/c/dev/ppb_scrollbar_dev.h"
diff --git a/ppapi/proxy/message_handler.cc b/ppapi/proxy/message_handler.cc
index fff8788..e095dd76 100644
--- a/ppapi/proxy/message_handler.cc
+++ b/ppapi/proxy/message_handler.cc
@@ -16,14 +16,18 @@
 namespace proxy {
 namespace {
 
-typedef void (*HandleMessageFunc)(PP_Instance, void*, PP_Var);
-typedef PP_Var (*HandleBlockingMessageFunc)(PP_Instance, void*, PP_Var);
+typedef void (*HandleMessageFunc)(PP_Instance, void*, const PP_Var*);
+typedef void (*HandleBlockingMessageFunc)(
+    PP_Instance, void*, const PP_Var*, PP_Var*);
+typedef void (*HandleMessageFunc_0_1)(PP_Instance, void*, PP_Var);
+typedef PP_Var (*HandleBlockingMessageFunc_0_1)(PP_Instance, void*, PP_Var);
 
 void HandleMessageWrapper(HandleMessageFunc function,
                           PP_Instance instance,
                           void* user_data,
                           ScopedPPVar message_data) {
-  CallWhileUnlocked(function, instance, user_data, message_data.get());
+  CallWhileUnlocked(function, instance, user_data,
+                    &message_data.get());
 }
 
 void HandleBlockingMessageWrapper(HandleBlockingMessageFunc function,
@@ -34,6 +38,32 @@
   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
   if (!dispatcher)
     return;
+  PP_Var result = PP_MakeUndefined();
+  CallWhileUnlocked(
+      function, instance, user_data, &message_data.get(), &result);
+  PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams(
+      reply_msg.get(),
+      SerializedVarReturnValue::Convert(dispatcher, result),
+      true /* was_handled */);
+  dispatcher->Send(reply_msg.release());
+}
+
+// TODO(dmichael): Remove the 0_1 verions; crbug.com/414398
+void HandleMessageWrapper_0_1(HandleMessageFunc_0_1 function,
+                              PP_Instance instance,
+                              void* user_data,
+                              ScopedPPVar message_data) {
+  CallWhileUnlocked(function, instance, user_data, message_data.get());
+}
+
+void HandleBlockingMessageWrapper_0_1(HandleBlockingMessageFunc_0_1 function,
+                                      PP_Instance instance,
+                                      void* user_data,
+                                      ScopedPPVar message_data,
+                                      scoped_ptr<IPC::Message> reply_msg) {
+  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+  if (!dispatcher)
+    return;
   PP_Var return_value = CallWhileUnlocked(function,
                                           instance,
                                           user_data,
@@ -50,7 +80,45 @@
 // static
 scoped_ptr<MessageHandler> MessageHandler::Create(
       PP_Instance instance,
-      const PPP_MessageHandler_0_1* handler_if,
+      const PPP_MessageHandler_0_2* handler_if,
+      void* user_data,
+      PP_Resource message_loop,
+      int32_t* error) {
+  scoped_ptr<MessageHandler> result;
+  // The interface and all function pointers must be valid.
+  if (!handler_if ||
+      !handler_if->HandleMessage ||
+      !handler_if->HandleBlockingMessage ||
+      !handler_if->Destroy) {
+    *error = PP_ERROR_BADARGUMENT;
+    return result.Pass();
+  }
+  thunk::EnterResourceNoLock<thunk::PPB_MessageLoop_API>
+      enter_loop(message_loop, true);
+  if (enter_loop.failed()) {
+    *error = PP_ERROR_BADRESOURCE;
+    return result.Pass();
+  }
+  scoped_refptr<MessageLoopResource> message_loop_resource(
+      static_cast<MessageLoopResource*>(enter_loop.object()));
+  if (message_loop_resource->is_main_thread_loop()) {
+    *error = PP_ERROR_WRONG_THREAD;
+    return result.Pass();
+  }
+
+  result.reset(new MessageHandler(
+      instance, handler_if, user_data, message_loop_resource));
+  *error = PP_OK;
+  return result.Pass();
+}
+
+// CreateDeprecated is a near-exact copy of Create, but we'll just delete it
+// when 0.1 is deprecated, so need to get fancy to avoid code duplication.
+// TODO(dmichael) crbug.com/414398
+// static
+scoped_ptr<MessageHandler> MessageHandler::CreateDeprecated(
+      PP_Instance instance,
+      const PPP_MessageHandler_0_1_Deprecated* handler_if,
       void* user_data,
       PP_Resource message_loop,
       int32_t* error) {
@@ -88,6 +156,13 @@
   if (message_loop_->message_loop_proxy().get()) {
     // The posted task won't have the proxy lock, but that's OK, it doesn't
     // touch any internal state; it's a direct call on the plugin's function.
+    if (handler_if_0_1_) {
+      message_loop_->message_loop_proxy()->PostTask(FROM_HERE,
+          base::Bind(handler_if_0_1_->Destroy,
+                     instance_,
+                     user_data_));
+      return;
+    }
     message_loop_->message_loop_proxy()->PostTask(FROM_HERE,
         base::Bind(handler_if_->Destroy,
                    instance_,
@@ -100,6 +175,16 @@
 }
 
 void MessageHandler::HandleMessage(ScopedPPVar var) {
+  if (handler_if_0_1_) {
+    // TODO(dmichael): Remove this code path. crbug.com/414398
+    message_loop_->message_loop_proxy()->PostTask(FROM_HERE,
+        RunWhileLocked(base::Bind(&HandleMessageWrapper_0_1,
+                                  handler_if_0_1_->HandleMessage,
+                                  instance_,
+                                  user_data_,
+                                  var)));
+    return;
+  }
   message_loop_->message_loop_proxy()->PostTask(FROM_HERE,
       RunWhileLocked(base::Bind(&HandleMessageWrapper,
                                 handler_if_->HandleMessage,
@@ -110,6 +195,17 @@
 
 void MessageHandler::HandleBlockingMessage(ScopedPPVar var,
                                            scoped_ptr<IPC::Message> reply_msg) {
+  if (handler_if_0_1_) {
+    // TODO(dmichael): Remove this code path. crbug.com/414398
+    message_loop_->message_loop_proxy()->PostTask(FROM_HERE,
+        RunWhileLocked(base::Bind(&HandleBlockingMessageWrapper_0_1,
+                                  handler_if_0_1_->HandleBlockingMessage,
+                                  instance_,
+                                  user_data_,
+                                  var,
+                                  base::Passed(reply_msg.Pass()))));
+    return;
+  }
   message_loop_->message_loop_proxy()->PostTask(FROM_HERE,
       RunWhileLocked(base::Bind(&HandleBlockingMessageWrapper,
                                 handler_if_->HandleBlockingMessage,
@@ -121,11 +217,24 @@
 
 MessageHandler::MessageHandler(
     PP_Instance instance,
-    const PPP_MessageHandler_0_1* handler_if,
+    const PPP_MessageHandler_0_2* handler_if,
     void* user_data,
     scoped_refptr<MessageLoopResource> message_loop)
     : instance_(instance),
       handler_if_(handler_if),
+      handler_if_0_1_(NULL),
+      user_data_(user_data),
+      message_loop_(message_loop) {
+}
+
+MessageHandler::MessageHandler(
+    PP_Instance instance,
+    const PPP_MessageHandler_0_1_Deprecated* handler_if,
+    void* user_data,
+    scoped_refptr<MessageLoopResource> message_loop)
+    : instance_(instance),
+      handler_if_(NULL),
+      handler_if_0_1_(handler_if),
       user_data_(user_data),
       message_loop_(message_loop) {
 }
diff --git a/ppapi/proxy/message_handler.h b/ppapi/proxy/message_handler.h
index 61ee639..1d047bb3 100644
--- a/ppapi/proxy/message_handler.h
+++ b/ppapi/proxy/message_handler.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "ppapi/c/dev/ppb_messaging_deprecated.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/c/ppp_message_handler.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
@@ -43,7 +44,16 @@
   // |error| is an out-param that will be set on failure.
   static scoped_ptr<MessageHandler> Create(
       PP_Instance instance,
-      const PPP_MessageHandler_0_1* handler_if,
+      const PPP_MessageHandler_0_2* handler_if,
+      void* user_data,
+      PP_Resource message_loop,
+      int32_t* error);
+  // Provide temporary backwards compatibility. TODO(dmichael): Remove all
+  // references to PPB_Messaging_1_1 and PPP_MessageHandler_0_1.
+  // crbug.com/414398
+  static scoped_ptr<MessageHandler> CreateDeprecated(
+      PP_Instance instance,
+      const PPP_MessageHandler_0_1_Deprecated* handler_if,
       void* user_data,
       PP_Resource message_loop,
       int32_t* error);
@@ -57,12 +67,18 @@
 
  private:
   MessageHandler(PP_Instance instance,
-                 const PPP_MessageHandler_0_1* handler_if,
+                 const PPP_MessageHandler_0_2* handler_if,
+                 void* user_data,
+                 scoped_refptr<MessageLoopResource> message_loop);
+  MessageHandler(PP_Instance instance,
+                 const PPP_MessageHandler_0_1_Deprecated* handler_if,
                  void* user_data,
                  scoped_refptr<MessageLoopResource> message_loop);
 
+
   PP_Instance instance_;
-  const PPP_MessageHandler_0_1* handler_if_;
+  const PPP_MessageHandler_0_2* handler_if_;
+  const PPP_MessageHandler_0_1_Deprecated* handler_if_0_1_;
   void* user_data_;
   scoped_refptr<MessageLoopResource> message_loop_;
 
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index e93a219..1dfb897 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -838,7 +838,7 @@
 int32_t PPB_Instance_Proxy::RegisterMessageHandler(
     PP_Instance instance,
     void* user_data,
-    const PPP_MessageHandler_0_1* handler,
+    const PPP_MessageHandler_0_2* handler,
     PP_Resource message_loop) {
   InstanceData* data =
       static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
@@ -853,6 +853,25 @@
   return result;
 }
 
+// TODO(dmichael): Remove this. crbug.com/414398
+int32_t PPB_Instance_Proxy::RegisterMessageHandler_1_1_Deprecated(
+    PP_Instance instance,
+    void* user_data,
+    const PPP_MessageHandler_0_1_Deprecated* handler,
+    PP_Resource message_loop) {
+  InstanceData* data =
+      static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
+  if (!data)
+    return PP_ERROR_BADARGUMENT;
+
+  int32_t result = PP_ERROR_FAILED;
+  scoped_ptr<MessageHandler> message_handler = MessageHandler::CreateDeprecated(
+      instance, handler, user_data, message_loop, &result);
+  if (message_handler)
+    data->message_handler = message_handler.Pass();
+  return result;
+}
+
 void PPB_Instance_Proxy::UnregisterMessageHandler(PP_Instance instance) {
   InstanceData* data =
       static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h
index 83a0e993..56d4a12 100644
--- a/ppapi/proxy/ppb_instance_proxy.h
+++ b/ppapi/proxy/ppb_instance_proxy.h
@@ -89,8 +89,13 @@
   virtual void PostMessage(PP_Instance instance, PP_Var message) OVERRIDE;
   virtual int32_t RegisterMessageHandler(PP_Instance instance,
                                          void* user_data,
-                                         const PPP_MessageHandler_0_1* handler,
+                                         const PPP_MessageHandler_0_2* handler,
                                          PP_Resource message_loop) OVERRIDE;
+  virtual int32_t RegisterMessageHandler_1_1_Deprecated(
+      PP_Instance instance,
+      void* user_data,
+      const PPP_MessageHandler_0_1_Deprecated* handler,
+      PP_Resource message_loop) OVERRIDE;
   virtual void UnregisterMessageHandler(PP_Instance instance) OVERRIDE;
   virtual PP_Bool SetCursor(PP_Instance instance,
                             PP_MouseCursor_Type type,
diff --git a/ppapi/tests/test_message_handler.cc b/ppapi/tests/test_message_handler.cc
index 54474f7..5b59f7d 100644
--- a/ppapi/tests/test_message_handler.cc
+++ b/ppapi/tests/test_message_handler.cc
@@ -11,6 +11,7 @@
 
 #include "ppapi/c/pp_var.h"
 #include "ppapi/c/ppb_file_io.h"
+#include "ppapi/c/ppb_messaging.h"
 #include "ppapi/c/ppp_message_handler.h"
 #include "ppapi/cpp/file_io.h"
 #include "ppapi/cpp/file_ref.h"
@@ -43,9 +44,9 @@
                                  const pp::MessageLoop& loop)
       : pp_instance_(instance),
         message_handler_loop_(loop),
-        ppb_messaging_if_(static_cast<const PPB_Messaging_1_1*>(
+        ppb_messaging_if_(static_cast<const PPB_Messaging_1_2*>(
             pp::Module::Get()->GetBrowserInterface(
-                PPB_MESSAGING_INTERFACE_1_1))),
+                PPB_MESSAGING_INTERFACE_1_2))),
         ppp_message_handler_if_(),
         is_registered_(false),
         test_finished_event_(instance),
@@ -114,23 +115,24 @@
   }
   static void HandleMessage(PP_Instance instance,
                             void* user_data,
-                            struct PP_Var message_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);
+    pp::Var var(*message_data);
     if (var.is_string() && var.AsString() == "FINISHED_TEST")
       thiz->test_finished_event_.Signal();
     else
-      thiz->ppb_messaging_if_->PostMessage(instance, message_data);
+      thiz->ppb_messaging_if_->PostMessage(instance, *message_data);
   }
 
-  static PP_Var HandleBlockingMessage(PP_Instance instance,
-                                      void* user_data,
-                                      struct PP_Var message_data) {
+  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_)
@@ -142,9 +144,9 @@
     // 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);
+    pp::Var take_ref(*message_data);
     take_ref.Detach();
-    return message_data;
+    *result = *message_data;
   }
 
   static void Destroy(PP_Instance instance, void* user_data) {
@@ -164,10 +166,10 @@
   const PP_Instance pp_instance_;
   const pp::MessageLoop message_handler_loop_;
   const pp::MessageLoop main_loop_;
-  const PPB_Messaging_1_1* const ppb_messaging_if_;
+  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_1 ppp_message_handler_if_;
+  PPP_MessageHandler_0_2 ppp_message_handler_if_;
 
   // is_registered_ is only read/written on the main thread.
   bool is_registered_;
@@ -186,12 +188,11 @@
 
 void FakeHandleMessage(PP_Instance instance,
                        void* user_data,
-                       struct PP_Var message_data) {}
-PP_Var FakeHandleBlockingMessage(PP_Instance instance,
-                                 void* user_data,
-                                 struct PP_Var message_data) {
-  return PP_MakeUndefined();
-}
+                       const PP_Var* message_data) {}
+void FakeHandleBlockingMessage(PP_Instance instance,
+                               void* user_data,
+                               const PP_Var* message_data,
+                               PP_Var* result) {}
 void FakeDestroy(PP_Instance instance, void* user_data) {}
 
 }  // namespace
@@ -207,8 +208,8 @@
 }
 
 bool TestMessageHandler::Init() {
-  ppb_messaging_if_ = static_cast<const PPB_Messaging_1_1*>(
-      pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_1));
+  ppb_messaging_if_ = static_cast<const PPB_Messaging_1_2*>(
+      pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2));
   return ppb_messaging_if_ &&
          CheckTestingInterface() &&
          handler_thread_.Start();
@@ -227,7 +228,7 @@
 std::string TestMessageHandler::TestRegisterErrorConditions() {
   {
     // Test registering with the main thread as the message loop.
-    PPP_MessageHandler_0_1 fake_ppp_message_handler = {
+    PPP_MessageHandler_0_2 fake_ppp_message_handler = {
       &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy
     };
     pp::MessageLoop main_loop = pp::MessageLoop::GetForMainThread();
@@ -240,7 +241,7 @@
   }
   {
     // Test registering with incomplete PPP_Messaging interface.
-    PPP_MessageHandler_0_1 bad_ppp_ifs[] = {
+    PPP_MessageHandler_0_2 bad_ppp_ifs[] = {
         { NULL, &FakeHandleBlockingMessage, &FakeDestroy },
         { &FakeHandleMessage, NULL, &FakeDestroy },
         { &FakeHandleMessage, &FakeHandleBlockingMessage, NULL }};
diff --git a/ppapi/tests/test_message_handler.h b/ppapi/tests/test_message_handler.h
index 560a1ff..70e6a2f 100644
--- a/ppapi/tests/test_message_handler.h
+++ b/ppapi/tests/test_message_handler.h
@@ -26,7 +26,7 @@
   std::string TestRegisterErrorConditions();
   std::string TestPostMessageAndAwaitResponse();
 
-  const PPB_Messaging_1_1* ppb_messaging_if_;
+  const PPB_Messaging_1_2* ppb_messaging_if_;
   pp::SimpleThread handler_thread_;
 };
 
diff --git a/ppapi/thunk/interfaces_ppb_public_dev_channel.h b/ppapi/thunk/interfaces_ppb_public_dev_channel.h
index a4f0e596..8512f37 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev_channel.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev_channel.h
@@ -11,7 +11,9 @@
 PROXIED_IFACE(PPB_COMPOSITOR_INTERFACE_0_1, PPB_Compositor_0_1)
 PROXIED_IFACE(PPB_COMPOSITORLAYER_INTERFACE_0_1, PPB_CompositorLayer_0_1)
 PROXIED_IFACE(PPB_FILEMAPPING_INTERFACE_0_1, PPB_FileMapping_0_1)
-PROXIED_IFACE(PPB_MESSAGING_INTERFACE_1_1, PPB_Messaging_1_1)
+PROXIED_IFACE(PPB_MESSAGING_INTERFACE_1_1_DEPRECATED,
+              PPB_Messaging_1_1_Deprecated)
+PROXIED_IFACE(PPB_MESSAGING_INTERFACE_1_2, PPB_Messaging_1_2)
 PROXIED_IFACE(PPB_VIDEODECODER_INTERFACE_0_1, PPB_VideoDecoder_0_1)
 
 // Note, PPB_TraceEvent is special. We don't want to actually make it stable,
diff --git a/ppapi/thunk/ppb_instance_api.h b/ppapi/thunk/ppb_instance_api.h
index 1f0e2a5..997c32e4 100644
--- a/ppapi/thunk/ppb_instance_api.h
+++ b/ppapi/thunk/ppb_instance_api.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "ppapi/c/dev/ppb_messaging_deprecated.h"
 #include "ppapi/c/dev/ppb_url_util_dev.h"
 #include "ppapi/c/pp_bool.h"
 #include "ppapi/c/pp_completion_callback.h"
@@ -31,7 +32,7 @@
 
 struct PP_DecryptedBlockInfo;
 struct PP_DecryptedFrameInfo;
-struct PPP_MessageHandler_0_1;
+struct PPP_MessageHandler_0_2;
 
 namespace ppapi {
 
@@ -118,8 +119,13 @@
   virtual void PostMessage(PP_Instance instance, PP_Var message) = 0;
   virtual int32_t RegisterMessageHandler(PP_Instance instance,
                                          void* user_data,
-                                         const PPP_MessageHandler_0_1* handler,
+                                         const PPP_MessageHandler_0_2* handler,
                                          PP_Resource message_loop) = 0;
+  virtual int32_t RegisterMessageHandler_1_1_Deprecated(
+      PP_Instance instance,
+      void* user_data,
+      const PPP_MessageHandler_0_1_Deprecated* handler,
+      PP_Resource message_loop) = 0;
   virtual void UnregisterMessageHandler(PP_Instance instance) = 0;
 
   // Mouse cursor.
diff --git a/ppapi/thunk/ppb_messaging_thunk.cc b/ppapi/thunk/ppb_messaging_thunk.cc
index c351233..1d5d041 100644
--- a/ppapi/thunk/ppb_messaging_thunk.cc
+++ b/ppapi/thunk/ppb_messaging_thunk.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_messaging.idl modified Thu May 29 15:54:46 2014.
+// From ppb_messaging.idl modified Wed Sep 10 15:41:14 2014.
 
+#include "ppapi/c/dev/ppb_messaging_deprecated.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_messaging.h"
 #include "ppapi/shared_impl/tracked_callback.h"
@@ -23,10 +24,25 @@
   enter.functions()->PostMessage(instance, message);
 }
 
-int32_t RegisterMessageHandler(PP_Instance instance,
-                               void* user_data,
-                               const struct PPP_MessageHandler_0_1* handler,
-                               PP_Resource message_loop) {
+int32_t RegisterMessageHandler_1_1_Deprecated(
+    PP_Instance instance,
+    void* user_data,
+    const struct PPP_MessageHandler_0_1_Deprecated* handler,
+    PP_Resource message_loop) {
+  VLOG(4) << "PPB_Messaging::RegisterMessageHandler_1_1()";
+  EnterInstance enter(instance);
+  if (enter.failed())
+    return enter.retval();
+  return enter.functions()->RegisterMessageHandler_1_1_Deprecated(instance,
+                                                                  user_data,
+                                                                  handler,
+                                                                  message_loop);
+}
+
+int32_t RegisterMessageHandler_1_2(PP_Instance instance,
+                                   void* user_data,
+                                   const struct PPP_MessageHandler_0_2* handler,
+                                   PP_Resource message_loop) {
   VLOG(4) << "PPB_Messaging::RegisterMessageHandler()";
   EnterInstance enter(instance);
   if (enter.failed())
@@ -49,9 +65,15 @@
   &PostMessage
 };
 
-const PPB_Messaging_1_1 g_ppb_messaging_thunk_1_1 = {
+const PPB_Messaging_1_1_Deprecated g_ppb_messaging_thunk_1_1_deprecated = {
   &PostMessage,
-  &RegisterMessageHandler,
+  &RegisterMessageHandler_1_1_Deprecated,
+  &UnregisterMessageHandler
+};
+
+const PPB_Messaging_1_2 g_ppb_messaging_thunk_1_2 = {
+  &PostMessage,
+  &RegisterMessageHandler_1_2,
   &UnregisterMessageHandler
 };
 
@@ -61,8 +83,13 @@
   return &g_ppb_messaging_thunk_1_0;
 }
 
-PPAPI_THUNK_EXPORT const PPB_Messaging_1_1* GetPPB_Messaging_1_1_Thunk() {
-  return &g_ppb_messaging_thunk_1_1;
+PPAPI_THUNK_EXPORT
+const PPB_Messaging_1_1_Deprecated* GetPPB_Messaging_1_1_Deprecated_Thunk() {
+  return &g_ppb_messaging_thunk_1_1_deprecated;
+}
+
+PPAPI_THUNK_EXPORT const PPB_Messaging_1_2* GetPPB_Messaging_1_2_Thunk() {
+  return &g_ppb_messaging_thunk_1_2;
 }
 
 }  // namespace thunk