diff --git a/ppapi/proxy/callback_tracker.cc b/ppapi/proxy/callback_tracker.cc
new file mode 100644
index 0000000000000000000000000000000000000000..98064970f3ae90d6872e986dd16d993faa9b22c4
--- /dev/null
+++ b/ppapi/proxy/callback_tracker.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2010 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/proxy/callback_tracker.h"
+
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+struct CallbackData {
+  CallbackTracker* tracker;
+  uint32_t callback_id;
+};
+
+void CallbackProxy(void* user_data, int32_t result) {
+  CallbackData* data = static_cast<CallbackData*>(user_data);
+  data->tracker->SendExecuteSerializedCallback(data->callback_id, result);
+  delete data;
+}
+
+}  // namespace
+
+CallbackTracker::CallbackTracker(Dispatcher* dispatcher)
+    : dispatcher_(dispatcher),
+      next_callback_id_(1) {
+}
+
+CallbackTracker::~CallbackTracker() {
+}
+
+uint32_t CallbackTracker::SendCallback(PP_CompletionCallback callback) {
+  // Find the next callback ID we can use (being careful about wraparound).
+  while (callback_map_.find(next_callback_id_) != callback_map_.end())
+    next_callback_id_++;
+  callback_map_[next_callback_id_] = callback;
+  return next_callback_id_++;
+}
+
+PP_CompletionCallback CallbackTracker::ReceiveCallback(
+    uint32_t serialized_callback) {
+  CallbackData* data = new CallbackData;
+  data->tracker = this;
+  data->callback_id = serialized_callback;
+  return PP_MakeCompletionCallback(&CallbackProxy, data);
+}
+
+void CallbackTracker::SendExecuteSerializedCallback(
+    uint32_t serialized_callback,
+    int32_t param) {
+  dispatcher_->Send(new PpapiMsg_ExecuteCallback(serialized_callback, param));
+}
+
+void CallbackTracker::ReceiveExecuteSerializedCallback(
+    uint32_t serialized_callback,
+    int32_t param) {
+  CallbackMap::iterator found = callback_map_.find(serialized_callback);
+  if (found == callback_map_.end()) {
+    NOTREACHED();
+    return;
+  }
+
+  PP_RunCompletionCallback(&found->second, param);
+  callback_map_.erase(found);
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/callback_tracker.h b/ppapi/proxy/callback_tracker.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f8233c1df5bf4ac78c7e153a1a01446569a585b
--- /dev/null
+++ b/ppapi/proxy/callback_tracker.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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_PROXY_CALLBACK_TRACKER_H_
+#define PPAPI_PROXY_CALLBACK_TRACKER_H_
+
+#include <map>
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_stdint.h"
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+// This object tracks cross-process callbacks. When the plugin sends a callback
+// object to the renderer, we save the information and pass an identifier
+// instead.
+//
+// On the renderer side, this identifier is converted to a new callback in that
+// process. When executed, this new callback sends an IPC message containing the
+// previous identifier back to the plugin.
+//
+// When we receive that message, ExecuteSerializedCallback converts the
+// identifier back to the original callback information and runs the callback.
+class CallbackTracker {
+ public:
+  CallbackTracker(Dispatcher* dispatcher);
+  ~CallbackTracker();
+
+  // Converts the given callback in the context of the plugin to a serialized
+  // ID. This will be passed to ReceiveCallback on the renderer side.
+  uint32_t SendCallback(PP_CompletionCallback callback);
+
+  // Converts the given serialized callback ID to a new completion callback in
+  // the context of the current process. This callback actually will represent
+  // a proxy that will execute the callback in the plugin process.
+  PP_CompletionCallback ReceiveCallback(uint32_t serialized_callback);
+
+  // Sends a request to the remote process to execute the given callback.
+  void SendExecuteSerializedCallback(uint32_t serialized_callback,
+                                     int32_t param);
+
+  // Executes the given callback ID with the given result in the current
+  // process. This will also destroy the information associated with the
+  // callback and the serialized ID won't be valid any more.
+  void ReceiveExecuteSerializedCallback(uint32_t serialized_callback,
+                                        int32_t param);
+
+ private:
+  // Pointer to the dispatcher that owns us.
+  Dispatcher* dispatcher_;
+
+  int32_t next_callback_id_;
+
+  // Maps callback IDs to the actual callback objects in the plugin process.
+  typedef std::map<int32_t, PP_CompletionCallback> CallbackMap;
+  CallbackMap callback_map_;
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_CALLBACK_TRACKER_H_
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e2c6f1ec4150ac50a0b1275c15808109f77b3a7e
--- /dev/null
+++ b/ppapi/proxy/dispatcher.cc
@@ -0,0 +1,215 @@
+// Copyright (c) 2010 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/proxy/dispatcher.h"
+
+#include <string.h>  // For memset.
+
+#include <map>
+
+#include "base/logging.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/ppb_core_proxy.h"
+#include "ppapi/proxy/ppb_graphics_2d_proxy.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/ppb_instance_proxy.h"
+#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/ppp_instance_proxy.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+Dispatcher::Dispatcher(GetInterfaceFunc local_get_interface)
+    : pp_module_(0),
+      disallow_trusted_interfaces_(true),
+      local_get_interface_(local_get_interface),
+      declared_supported_remote_interfaces_(false),
+      callback_tracker_(this) {
+  memset(id_to_proxy_, 0,
+         static_cast<int>(INTERFACE_ID_COUNT) * sizeof(InterfaceProxy*));
+}
+
+Dispatcher::~Dispatcher() {
+}
+
+bool Dispatcher::InitWithChannel(MessageLoop* ipc_message_loop,
+                                 const std::string& channel_name,
+                                 bool is_client,
+                                 base::WaitableEvent* shutdown_event) {
+  IPC::Channel::Mode mode = is_client ? IPC::Channel::MODE_CLIENT
+                                      : IPC::Channel::MODE_SERVER;
+  channel_.reset(new IPC::SyncChannel(channel_name, mode, this, NULL,
+                                      ipc_message_loop, false, shutdown_event));
+  return true;
+}
+
+void Dispatcher::OnMessageReceived(const IPC::Message& msg) {
+  // Control messages.
+  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+    IPC_BEGIN_MESSAGE_MAP(Dispatcher, msg)
+      IPC_MESSAGE_HANDLER(PpapiMsg_DeclareInterfaces,
+                          OnMsgDeclareInterfaces)
+      IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
+      IPC_MESSAGE_FORWARD(PpapiMsg_ExecuteCallback, &callback_tracker_,
+                          CallbackTracker::ReceiveExecuteSerializedCallback)
+    IPC_END_MESSAGE_MAP()
+    return;
+  }
+
+  // Interface-specific messages.
+  if (msg.routing_id() > 0 && msg.routing_id() < INTERFACE_ID_COUNT) {
+    InterfaceProxy* proxy = id_to_proxy_[msg.routing_id()];
+    if (proxy)
+      proxy->OnMessageReceived(msg);
+    else
+      NOTREACHED();
+    // TODO(brettw): kill the plugin if it starts sending invalid messages?
+  }
+}
+
+void Dispatcher::SetSerializationRules(
+    VarSerializationRules* var_serialization_rules) {
+  serialization_rules_.reset(var_serialization_rules);
+}
+
+void Dispatcher::InjectProxy(InterfaceID id,
+                             const std::string& name,
+                             InterfaceProxy* proxy) {
+  proxies_[name] = linked_ptr<InterfaceProxy>(proxy);
+  id_to_proxy_[id] = proxy;
+}
+
+const void* Dispatcher::GetLocalInterface(const char* interface) {
+  return local_get_interface_(interface);
+}
+
+const void* Dispatcher::GetProxiedInterface(const std::string& interface) {
+  // See if we already know about this interface and have created a host.
+  ProxyMap::const_iterator found = proxies_.find(interface);
+  if (found != proxies_.end())
+    return found->second->GetSourceInterface();
+
+  // When the remote side has sent us a declared list of all interfaces it
+  // supports and we don't have it in our list, we know the requested interface
+  // doesn't exist and we can return failure.
+  if (declared_supported_remote_interfaces_)
+    return NULL;
+
+  if (!RemoteSupportsTargetInterface(interface))
+    return NULL;
+
+  linked_ptr<InterfaceProxy> proxy(CreateProxyForInterface(interface, NULL));
+  if (!proxy.get())
+    return NULL;  // Don't know how to proxy this interface.
+
+  // Save our proxy.
+  proxies_[interface] = proxy;
+  id_to_proxy_[proxy->GetInterfaceId()] = proxy.get();
+  return proxy->GetSourceInterface();
+}
+
+bool Dispatcher::Send(IPC::Message* msg) {
+  return channel_->Send(msg);
+}
+
+bool Dispatcher::RemoteSupportsTargetInterface(const std::string& interface) {
+  bool result = false;
+  Send(new PpapiMsg_SupportsInterface(interface, &result));
+  return result;
+}
+
+bool Dispatcher::IsInterfaceTrusted(const std::string& interface) {
+  // FIXME(brettw)
+  (void)interface;
+  return false;
+}
+
+bool Dispatcher::SetupProxyForTargetInterface(const std::string& interface) {
+  // If we already have a proxy that knows about the locally-implemented
+  // interface, we know it's supported and don't need to re-query.
+  ProxyMap::const_iterator found = proxies_.find(interface);
+  if (found != proxies_.end())
+    return true;
+
+  if (disallow_trusted_interfaces_ && IsInterfaceTrusted(interface))
+    return false;
+
+  // Create the proxy if it doesn't exist and set the local interface on it.
+  // This also handles the case where possibly an interface could be supported
+  // by both the local and remote side.
+  const void* interface_functions = local_get_interface_(interface.c_str());
+  if (!interface_functions)
+    return false;
+  InterfaceProxy* proxy = CreateProxyForInterface(interface,
+                                                  interface_functions);
+  if (!proxy)
+    return false;
+
+  proxies_[interface] = linked_ptr<InterfaceProxy>(proxy);
+  id_to_proxy_[proxy->GetInterfaceId()] = proxy;
+  return true;
+}
+
+void Dispatcher::OnMsgSupportsInterface(const std::string& interface_name,
+                                        bool* result) {
+  *result = SetupProxyForTargetInterface(interface_name);
+}
+
+void Dispatcher::OnMsgDeclareInterfaces(
+    const std::vector<std::string>& interfaces) {
+  // Make proxies for all the interfaces it supports that we also support.
+  for (size_t i = 0; i < interfaces.size(); i++) {
+    // Possibly the plugin could request an interface before the "declare"
+    // message is received, so we could already have an entry for this
+    // interface. In this case, we can just skip to the next one.
+    if (proxies_.find(interfaces[i]) != proxies_.end())
+      continue;
+
+    linked_ptr<InterfaceProxy> proxy(CreateProxyForInterface(interfaces[i],
+                                                             NULL));
+    if (!proxy.get()) {
+      // Since only the browser declares supported interfaces, we should never
+      // get one we don't support.
+      //NOTREACHED() << "Remote side declaring an unsupported proxy.";
+      continue;
+    }
+    proxies_[interfaces[i]] = proxy;
+    id_to_proxy_[proxy->GetInterfaceId()] = proxy.get();
+  }
+}
+
+InterfaceProxy* Dispatcher::CreateProxyForInterface(
+    const std::string& interface_name,
+    const void* interface_functions) {
+  if (interface_name == PPB_CORE_INTERFACE)
+    return new PPB_Core_Proxy(this, interface_functions);
+  if (interface_name == PPB_GRAPHICS_2D_INTERFACE)
+    return new PPB_Graphics2D_Proxy(this, interface_functions);
+  if (interface_name == PPB_IMAGEDATA_INTERFACE)
+    return new PPB_ImageData_Proxy(this, interface_functions);
+  if (interface_name == PPB_INSTANCE_INTERFACE)
+    return new PPB_Instance_Proxy(this, interface_functions);
+  if (interface_name == PPB_VAR_DEPRECATED_INTERFACE)
+    return new PPB_Var_Deprecated_Proxy(this, interface_functions);
+  if (interface_name == PPP_INSTANCE_INTERFACE)
+    return new PPP_Instance_Proxy(this, interface_functions);
+
+  return NULL;
+}
+
+}  // namespace proxy
+}  // namespace pp
+
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..412b2d8f11fc92f0cdaee65bb0a88453fce7504f
--- /dev/null
+++ b/ppapi/proxy/dispatcher.h
@@ -0,0 +1,187 @@
+// Copyright (c) 2010 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_PROXY_DISPATCHER_H_
+#define PPAPI_PROXY_DISPATCHER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/linked_ptr.h"
+#include "base/scoped_ptr.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/callback_tracker.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+class MessageLoop;
+struct PPB_Var_Deprecated;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace IPC {
+class SyncChannel;
+}
+
+namespace pp {
+namespace proxy {
+
+class InterfaceProxy;
+class VarSerializationRules;
+
+// An interface proxy can represent either end of a cross-process interface
+// call. The "source" side is where the call is invoked, and the "target" side
+// is where the call ends up being executed.
+//
+// Plugin side                          | Browser side
+// -------------------------------------|--------------------------------------
+//                                      |
+//    "Source"                          |    "Target"
+//    InterfaceProxy ----------------------> InterfaceProxy
+//                                      |
+//                                      |
+//    "Target"                          |    "Source"
+//    InterfaceProxy <---------------------- InterfaceProxy
+//                                      |
+class Dispatcher : public IPC::Channel::Listener,
+                   public IPC::Message::Sender {
+ public:
+  typedef const void* (*GetInterfaceFunc)(const char*);
+  typedef const int32_t (*InitModuleFunc)(PP_Module, GetInterfaceFunc);
+  typedef const void (*ShutdownModuleFunc)();
+
+  ~Dispatcher();
+
+  bool InitWithChannel(MessageLoop* ipc_message_loop,
+                       const std::string& channel_name,
+                       bool is_client,
+                       base::WaitableEvent* shutdown_event);
+
+  // Returns true if the dispatcher is on the plugin side, or false if it's the
+  // browser side.
+  virtual bool IsPlugin() const = 0;
+
+  VarSerializationRules* serialization_rules() const {
+    return serialization_rules_.get();
+  }
+  PP_Module pp_module() const {
+    return pp_module_;
+  }
+
+  // Wrapper for calling the local GetInterface function.
+  const void* GetLocalInterface(const char* interface);
+
+  // Implements PPP_GetInterface and PPB_GetInterface on the "source" side. It
+  // will check if the remote side supports this interface as a target, and
+  // create a proxy if it does. A local implementation of that interface backed
+  // by the proxy will be returned on success. If the interface is unproxyable
+  // or not supported by the remote side, returns NULL.
+  const void* GetProxiedInterface(const std::string& interface);
+
+  // Called if the remote side is declaring to us which interfaces it supports
+  // so we don't have to query for each one. We'll pre-create proxies for
+  // each of the given interfaces.
+
+  // IPC::Message::Sender implementation.
+  virtual bool Send(IPC::Message* msg);
+
+  // IPC::Channel::Listener implementation.
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+  IPC::SyncChannel* channel() const {
+    return channel_.get();
+  }
+
+  CallbackTracker& callback_tracker() {
+    return callback_tracker_;
+  }
+
+ protected:
+  Dispatcher(GetInterfaceFunc local_get_interface);
+
+  // Setter for the derived classes to set the appropriate var serialization.
+  // Takes ownership of the given pointer, which must be on the heap.
+  void SetSerializationRules(VarSerializationRules* var_serialization_rules);
+
+  void set_pp_module(PP_Module module) {
+    pp_module_ = module;
+  }
+
+  // Allows the PluginDispatcher to add a magic proxy for PPP_Class, bypassing
+  // the normal "do you support this proxy" stuff and the big lookup of
+  // name to proxy object. Takes ownership of the pointer.
+  void InjectProxy(InterfaceID id,
+                   const std::string& name,
+                   InterfaceProxy* proxy);
+
+ private:
+  typedef std::map< std::string, linked_ptr<InterfaceProxy> > ProxyMap;
+
+  // Message handlers
+  void OnMsgSupportsInterface(const std::string& interface_name, bool* result);
+  void OnMsgDeclareInterfaces(const std::vector<std::string>& interfaces);
+
+  // Allocates a new proxy on the heap corresponding to the given interface
+  // name, or returns NULL if that interface name isn't known proxyable. The
+  // caller owns the returned pointer.
+  //
+  // The interface_functions gives the pointer to the local interfece when this
+  // is a target proxy. When creating a source proxy, set this to NULL.
+  InterfaceProxy* CreateProxyForInterface(
+      const std::string& interface_name,
+      const void* interface_functions);
+
+  // Returns true if the remote side supports the given interface as the
+  // target of an IPC call.
+  bool RemoteSupportsTargetInterface(const std::string& interface);
+
+  // Sets up a proxy as the target for the given interface, if it is supported.
+  // Returns true if this process implements the given interface and it is
+  // proxyable.
+  bool SetupProxyForTargetInterface(const std::string& interface);
+
+  bool IsInterfaceTrusted(const std::string& interface);
+
+  // Set by the derived classed to indicate the module ID corresponding to
+  // this dispatcher.
+  PP_Module pp_module_;
+
+  scoped_ptr<IPC::SyncChannel> channel_;
+
+  bool disallow_trusted_interfaces_;
+
+  GetInterfaceFunc local_get_interface_;
+
+  ProxyMap proxies_;
+  InterfaceProxy* id_to_proxy_[INTERFACE_ID_COUNT];
+
+  // True if the remote side has declared which interfaces it supports in
+  // advance. When set, it means if we don't already have a source proxy for
+  // the requested interface, that the remote side doesn't support it and
+  // we don't need to query.
+  //
+  // This is just an optimization. The browser has a fixed set of interfaces
+  // it supports, and the many plugins will end up querying many of them. By
+  // having the browser just send all of those interfaces in one message, we
+  // can avoid a bunch of IPC chatter to set up each interface.
+  bool declared_supported_remote_interfaces_;
+
+  CallbackTracker callback_tracker_;
+
+  scoped_ptr<VarSerializationRules> serialization_rules_;
+
+  DISALLOW_COPY_AND_ASSIGN(Dispatcher);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_DISPATCHER_H_
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bb7079690c1f819c89b812b92f9fd06bf6fbcf30
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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/proxy/host_dispatcher.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ppapi/proxy/host_var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+typedef std::map<PP_Instance, HostDispatcher*> InstanceToDispatcherMap;
+InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
+
+}  // namespace
+
+HostDispatcher::HostDispatcher(const PPB_Var_Deprecated* var_interface,
+                               PP_Module module,
+                               GetInterfaceFunc local_get_interface)
+    : Dispatcher(local_get_interface) {
+  SetSerializationRules(new HostVarSerializationRules(var_interface, module));
+}
+
+HostDispatcher::~HostDispatcher() {
+}
+
+// static
+HostDispatcher* HostDispatcher::GetForInstance(PP_Instance instance) {
+  if (!g_instance_to_dispatcher)
+    return NULL;
+  InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+      instance);
+  if (found == g_instance_to_dispatcher->end())
+    return NULL;
+  return found->second;
+}
+
+// static
+void HostDispatcher::SetForInstance(PP_Instance instance,
+                                    HostDispatcher* dispatcher) {
+  if (!g_instance_to_dispatcher)
+    g_instance_to_dispatcher = new InstanceToDispatcherMap;
+  (*g_instance_to_dispatcher)[instance] = dispatcher;
+}
+
+// static
+void HostDispatcher::RemoveForInstance(PP_Instance instance) {
+  if (!g_instance_to_dispatcher)
+    return;
+  InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+      instance);
+  if (found != g_instance_to_dispatcher->end())
+    g_instance_to_dispatcher->erase(found);
+}
+
+}  // namespace proxy
+}  // namespace pp
+
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..94d45d2deaa88f0a30e87418e5a485a0d6db31ef
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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_PROXY_HOST_DISPATCHER_H_
+#define PPAPI_PROXY_HOST_DISPATCHER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+struct PPB_Var_Deprecated;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace IPC {
+class SyncChannel;
+}
+
+namespace pp {
+namespace proxy {
+
+class InterfaceProxy;
+class VarSerialization;
+
+class HostDispatcher : public Dispatcher {
+ public:
+  // Constructor for the renderer side.
+  //
+  // You must call Dispatcher::InitWithChannel after the constructor.
+  HostDispatcher(const PPB_Var_Deprecated* var_interface,
+                 PP_Module module,
+                 GetInterfaceFunc local_get_interface);
+  ~HostDispatcher();
+
+  // The host side maintains a mapping from PP_Instance to Dispatcher so
+  // that we can send the messages to the right channel.
+  static HostDispatcher* GetForInstance(PP_Instance instance);
+  static void SetForInstance(PP_Instance instance,
+                             HostDispatcher* dispatcher);
+  static void RemoveForInstance(PP_Instance instance);
+
+  // Dispatcher overrides.
+  virtual bool IsPlugin() const { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HostDispatcher);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_HOST_DISPATCHER_H_
diff --git a/ppapi/proxy/interface_id.h b/ppapi/proxy/interface_id.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f5ad9bcb390e2c7921facfb98b8c29c19447ac5
--- /dev/null
+++ b/ppapi/proxy/interface_id.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 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_PROXY_INTERFACE_ID_H_
+#define PPAPI_PROXY_INTERFACE_ID_H_
+
+namespace pp {
+namespace proxy {
+
+// These numbers must be all small integers. They are used in a lookup table
+// to route messages to the appropriate message handler.
+enum InterfaceID {
+  // Zero is reserved for control messages.
+  INTERFACE_ID_PPB_CORE = 1,
+  INTERFACE_ID_PPB_GRAPHICS_2D,
+  INTERFACE_ID_PPB_IMAGE_DATA,
+  INTERFACE_ID_PPB_INSTANCE,
+  INTERFACE_ID_PPB_URL_LOADER,
+  INTERFACE_ID_PPB_VAR,
+  INTERFACE_ID_PPB_VAR_DEPRECATED,
+
+  INTERFACE_ID_PPP_CLASS,
+  INTERFACE_ID_PPP_INSTANCE,
+
+  // Must be last to indicate the number of interface IDs.
+  INTERFACE_ID_COUNT
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_INTERFACE_ID_H_
diff --git a/ppapi/proxy/interface_proxy.cc b/ppapi/proxy/interface_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7561d5ecd2402e9f6650ad1fe04ed358369684f4
--- /dev/null
+++ b/ppapi/proxy/interface_proxy.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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/proxy/interface_proxy.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/dispatcher.h"
+
+namespace pp {
+namespace proxy {
+
+InterfaceProxy::InterfaceProxy(Dispatcher* dispatcher,
+                               const void* target_interface)
+    : dispatcher_(dispatcher),
+      target_interface_(target_interface) {
+}
+
+InterfaceProxy::~InterfaceProxy() {
+}
+
+bool InterfaceProxy::Send(IPC::Message* msg) {
+  return dispatcher_->Send(msg);
+}
+
+uint32 InterfaceProxy::SendCallback(PP_CompletionCallback callback) {
+  return dispatcher_->callback_tracker().SendCallback(callback);
+}
+
+PP_CompletionCallback InterfaceProxy::ReceiveCallback(
+    uint32 serialized_callback) {
+  return dispatcher_->callback_tracker().ReceiveCallback(serialized_callback);
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/interface_proxy.h b/ppapi/proxy/interface_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..538ebf5f7b03ff703497d3e5cf925605ab69d1ae
--- /dev/null
+++ b/ppapi/proxy/interface_proxy.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2010 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_PROXY_INTERFACE_PROXY_H_
+#define PPAPI_PROXY_INTERFACE_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_id.h"
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+class InterfaceProxy : public IPC::Channel::Listener,
+                       public IPC::Message::Sender {
+ public:
+  // Creates the given interface associated with the given dispatcher. The
+  // dispatcher manages our lifetime.
+  //
+  // The target interface pointer, when non-NULL, indicates that this is a
+  // target proxy (see dispatcher.h for a definition).  In this case, the proxy
+  // will interpret this pointer to the actual implementation of the interface
+  // in the local process.
+  //
+  // If the target interface is NULL, this proxy will be a "source" interface.
+  InterfaceProxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~InterfaceProxy();
+
+  // See dispatcher.h for definitions of source and target.
+  bool is_source_proxy() const { return !target_interface_; }
+  bool is_target_proxy() const { return !!target_interface_; }
+
+  // When this proxy is the "target" of the IPC communication (see
+  // dispatcher.h), this target_interface pointer will indicate the local
+  // side's interface pointer. This contains the functions that actually
+  // implement the proxied interface.
+  //
+  // This will be NULL when this proxy is a source proxy.
+  const void* target_interface() const { return target_interface_; }
+
+  Dispatcher* dispatcher() { return dispatcher_; }
+
+  // IPC::Message::Sender implementation.
+  virtual bool Send(IPC::Message* msg);
+
+  // Returns the local implementation of the interface that will proxy it to
+  // the remote side. This is used on the source side only (see dispatcher.h).
+  virtual const void* GetSourceInterface() const = 0;
+
+  // Returns the interface ID associated with this proxy. Implemented by each
+  // derived class to identify itself.
+  virtual InterfaceID GetInterfaceId() const = 0;
+
+  // Sub-classes must implement IPC::Channel::Listener which contains this:
+  //virtual void OnMessageReceived(const IPC::Message& msg);
+
+ protected:
+  uint32 SendCallback(PP_CompletionCallback callback);
+  PP_CompletionCallback ReceiveCallback(uint32 serialized_callback);
+
+ private:
+  Dispatcher* dispatcher_;
+  const void* target_interface_;
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_INTERFACE_PROXY_H_
+
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1997dc43eec5f5578d82e230be689ebd24b99ea4
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 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/proxy/plugin_dispatcher.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_var_serialization_rules.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PluginDispatcher* g_dispatcher = NULL;
+
+const void* GetInterfaceFromDispatcher(const char* interface) {
+  // TODO(brettw) need some kind of lock for multi-thread access.
+  return pp::proxy::PluginDispatcher::Get()->GetProxiedInterface(interface);
+}
+
+}  // namespace
+
+PluginDispatcher::PluginDispatcher(GetInterfaceFunc get_interface,
+                                   InitModuleFunc init_module,
+                                   ShutdownModuleFunc shutdown_module)
+    : Dispatcher(get_interface),
+      init_module_(init_module),
+      shutdown_module_(shutdown_module),
+      plugin_resource_tracker_(new PluginResourceTracker(this)),
+      plugin_var_tracker_(new PluginVarTracker(this)) {
+  SetSerializationRules(
+      new PluginVarSerializationRules(plugin_var_tracker_.get()));
+
+  // As a plugin, we always support the PPP_Class interface. There's no
+  // GetInterface call or name for it, so we insert it into our table now.
+  InjectProxy(INTERFACE_ID_PPP_CLASS, "$Internal_PPP_Class",
+              new PPP_Class_Proxy(this));
+}
+
+PluginDispatcher::~PluginDispatcher() {
+  if (shutdown_module_)
+    shutdown_module_();
+}
+
+// static
+PluginDispatcher* PluginDispatcher::Get() {
+  return g_dispatcher;
+}
+
+// static
+void PluginDispatcher::SetGlobal(PluginDispatcher* dispatcher) {
+  DCHECK(!dispatcher || !g_dispatcher);
+  g_dispatcher = dispatcher;
+}
+
+void PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
+  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+    // Handle some plugin-specific control messages.
+    IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
+      IPC_MESSAGE_HANDLER(PpapiMsg_InitializeModule, OnInitializeModule)
+
+      // Forward all other control messages to the superclass.
+      IPC_MESSAGE_UNHANDLED(Dispatcher::OnMessageReceived(msg))
+    IPC_END_MESSAGE_MAP()
+    return;
+  }
+
+  // All non-control messages get handled by the superclass.
+  Dispatcher::OnMessageReceived(msg);
+}
+
+void PluginDispatcher::OnInitializeModule(PP_Module pp_module, bool* result) {
+  set_pp_module(pp_module);
+  *result = init_module_(pp_module, &GetInterfaceFromDispatcher) == PP_OK;
+}
+
+}  // namespace proxy
+}  // namespace pp
+
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a9796517ef5e0c9a66d4b724899001ab0c418d0
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2010 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_PROXY_PLUGIN_DISPATCHER_H_
+#define PPAPI_PROXY_PLUGIN_DISPATCHER_H_
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "ppapi/proxy/callback_tracker.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+class MessageLoop;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher : public Dispatcher {
+ public:
+  // Constructor for the plugin side. The init and shutdown functions will be
+  // will be automatically called when requested by the renderer side. The
+  // module ID will be set upon receipt of the InitializeModule message.
+  //
+  // You must call Dispatcher::InitWithChannel after the constructor.
+  PluginDispatcher(GetInterfaceFunc get_interface,
+                   InitModuleFunc init_module,
+                   ShutdownModuleFunc shutdown_module);
+  ~PluginDispatcher();
+
+  // The plugin maintains a global Dispatcher pointer. There is only one since
+  // there is only one connection to the browser. Don't call this on the
+  // browser side, see GetForInstnace.
+  static PluginDispatcher* Get();
+  static void SetGlobal(PluginDispatcher* dispatcher);
+
+  // Dispatcher overrides.
+  virtual bool IsPlugin() const { return true; }
+
+  // IPC::Channel::Listener implementation.
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+  // Returns the resource tracker for the plugin. In the browser process this
+  // will return NULL.
+  PluginResourceTracker* plugin_resource_tracker() {
+    return plugin_resource_tracker_.get();
+  }
+
+  // Returns the var tracker for the plugin. In the browser process this
+  // will return NULL.
+  PluginVarTracker* plugin_var_tracker() {
+    return plugin_var_tracker_.get();
+  }
+
+ private:
+  void OnInitializeModule(PP_Module pp_module, bool* result);
+
+  InitModuleFunc init_module_;
+  ShutdownModuleFunc shutdown_module_;
+
+  scoped_ptr<PluginResourceTracker> plugin_resource_tracker_;
+  scoped_ptr<PluginVarTracker> plugin_var_tracker_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginDispatcher);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PLUGIN_DISPATCHER_H_
diff --git a/ppapi/proxy/plugin_resource.cc b/ppapi/proxy/plugin_resource.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b1a579ea0a078187e330b56a9161a4333a1e76a6
--- /dev/null
+++ b/ppapi/proxy/plugin_resource.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2010 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/proxy/plugin_resource.h"
+
+namespace pp {
+namespace proxy {
+
+PluginResource::PluginResource() {
+}
+
+PluginResource::~PluginResource() {
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a7026688cdf013049daf2211cbb8864b3594935
--- /dev/null
+++ b/ppapi/proxy/plugin_resource.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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_PROXY_PLUGIN_RESOURCE_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+
+// If you inherit from resource, make sure you add the class name here.
+#define FOR_ALL_RESOURCES(F) \
+  F(Graphics2D) \
+  F(ImageData) \
+  F(URLLoader)
+
+namespace pp {
+namespace proxy {
+
+// Forward declaration of Resource classes.
+#define DECLARE_RESOURCE_CLASS(RESOURCE) class RESOURCE;
+FOR_ALL_RESOURCES(DECLARE_RESOURCE_CLASS)
+#undef DECLARE_RESOURCE_CLASS
+
+class PluginResource {
+ public:
+  PluginResource();
+  virtual ~PluginResource();
+
+  // Returns NULL if the resource is invalid or is a different type.
+  template<typename T> static T* GetAs(PP_Resource res) {
+    PluginResource* resource =
+        PluginDispatcher::Get()->plugin_resource_tracker()->GetResourceObject(
+            res);
+    return resource ? resource->Cast<T>() : NULL;
+  }
+
+  template <typename T> T* Cast() { return NULL; }
+
+ private:
+  // Type-specific getters for individual resource types. These will return
+  // NULL if the resource does not match the specified type. Used by the Cast()
+  // function.
+  #define DEFINE_TYPE_GETTER(RESOURCE)  \
+      virtual RESOURCE* As##RESOURCE() { return NULL; }
+  FOR_ALL_RESOURCES(DEFINE_TYPE_GETTER)
+  #undef DEFINE_TYPE_GETTER
+
+  DISALLOW_COPY_AND_ASSIGN(PluginResource);
+};
+
+// Cast() specializations.
+#define DEFINE_RESOURCE_CAST(Type)                   \
+  template <> inline Type* PluginResource::Cast<Type>() {  \
+      return As##Type();                             \
+  }
+FOR_ALL_RESOURCES(DEFINE_RESOURCE_CAST)
+#undef DEFINE_RESOURCE_CAST
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PLUGIN_RESOURCE_H_
diff --git a/ppapi/proxy/plugin_resource_tracker.cc b/ppapi/proxy/plugin_resource_tracker.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a285311d97e18e413ffaa0aa7926a614da94c64d
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2010 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/proxy/plugin_resource_tracker.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+PluginResourceTracker::ResourceInfo::ResourceInfo() : ref_count(0) {
+}
+
+PluginResourceTracker::ResourceInfo::ResourceInfo(int rc,
+                                                  linked_ptr<PluginResource> r)
+    : ref_count(rc),
+      resource(r) {
+}
+
+PluginResourceTracker::ResourceInfo::ResourceInfo(const ResourceInfo& other)
+    : ref_count(other.ref_count),
+      resource(other.resource) {
+}
+
+PluginResourceTracker::ResourceInfo::~ResourceInfo() {
+}
+
+PluginResourceTracker::ResourceInfo&
+PluginResourceTracker::ResourceInfo::operator=(
+    const ResourceInfo& other) {
+  ref_count = other.ref_count;
+  resource = other.resource;
+  return *this;
+}
+
+PluginResourceTracker::PluginResourceTracker(PluginDispatcher* dispatcher)
+    : dispatcher_(dispatcher) {
+}
+
+PluginResourceTracker::~PluginResourceTracker() {
+}
+
+PluginResource* PluginResourceTracker::GetResourceObject(
+    PP_Resource pp_resource) {
+  ResourceMap::iterator found = resource_map_.find(pp_resource);
+  if (found == resource_map_.end())
+    return NULL;
+  return found->second.resource.get();
+}
+
+void PluginResourceTracker::AddResource(PP_Resource pp_resource,
+                                        linked_ptr<PluginResource> object) {
+  DCHECK(resource_map_.find(pp_resource) == resource_map_.end());
+  resource_map_[pp_resource] = ResourceInfo(1, object);
+}
+
+void PluginResourceTracker::AddRefResource(PP_Resource resource) {
+  resource_map_[resource].ref_count++;
+}
+
+void PluginResourceTracker::ReleaseResource(PP_Resource resource) {
+  ReleasePluginResourceRef(resource, true);
+}
+
+void PluginResourceTracker::ReleasePluginResourceRef(
+    const PP_Resource& resource,
+    bool notify_browser_on_release) {
+  ResourceMap::iterator found = resource_map_.find(resource);
+  if (found == resource_map_.end())
+    return;
+  found->second.ref_count--;
+  if (found->second.ref_count == 0) {
+    if (notify_browser_on_release) {
+      dispatcher_->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
+          INTERFACE_ID_PPB_CORE, resource));
+    }
+    resource_map_.erase(found);
+  }
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/plugin_resource_tracker.h b/ppapi/proxy/plugin_resource_tracker.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9ea9631729f9086eaa9437128e4affe0f8b5d85
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 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_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+
+#include <map>
+
+#include "base/linked_ptr.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher;
+class PluginResource;
+
+class PluginResourceTracker {
+ public:
+  PluginResourceTracker(PluginDispatcher* dispatcher);
+  ~PluginResourceTracker();
+
+  // Returns the object associated with the given resource ID, or NULL if
+  // there isn't one.
+  PluginResource* GetResourceObject(PP_Resource pp_resource);
+
+  void AddResource(PP_Resource pp_resource, linked_ptr<PluginResource> object);
+
+  void AddRefResource(PP_Resource resource);
+  void ReleaseResource(PP_Resource resource);
+
+ private:
+  struct ResourceInfo {
+    ResourceInfo();
+    ResourceInfo(int ref_count, linked_ptr<PluginResource> r);
+    ResourceInfo(const ResourceInfo& other);
+    ~ResourceInfo();
+
+    ResourceInfo& operator=(const ResourceInfo& other);
+
+    int ref_count;
+    linked_ptr<PluginResource> resource;  // May be NULL.
+  };
+
+  void ReleasePluginResourceRef(const PP_Resource& var,
+                                bool notify_browser_on_release);
+
+  // Pointer to the dispatcher that owns us.
+  PluginDispatcher* dispatcher_;
+
+  typedef std::map<PP_Resource, ResourceInfo> ResourceMap;
+  ResourceMap resource_map_;
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
diff --git a/ppapi/proxy/ppapi_messages.cc b/ppapi/proxy/ppapi_messages.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1cc617bd5033b0ad5ff05ba165d83c376d457b66
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2010 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/proxy/ppapi_messages.h"
+
+#include "base/file_path.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ppapi/c/ppb_var.h"
+
+// This actually defines the implementations of all the IPC message functions.
+#define MESSAGES_INTERNAL_IMPL_FILE "ppapi/proxy/ppapi_messages_internal.h"
+#include "ipc/ipc_message_impl_macros.h"
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
new file mode 100644
index 0000000000000000000000000000000000000000..89ba4e9e4b50aba41d6ef57940ef813b2914f489
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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_PROXY_PPAPI_MESSAGES_H_
+#define PPAPI_PROXY_PPAPI_MESSAGES_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+
+#define MESSAGES_INTERNAL_FILE "ppapi/proxy/ppapi_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif  // PPAPI_PROXY_PPAPI_MESSAGES_H_
diff --git a/ppapi/proxy/ppapi_messages_internal.h b/ppapi/proxy/ppapi_messages_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..f99f4cc4cd2d33fbe7b29738728467c0b4e88e1a
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages_internal.h
@@ -0,0 +1,321 @@
+// Copyright (c) 2010 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.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard. It is included by backing_store_messages_internal.h
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+// This file needs to be included again, even though we're actually included
+// from it via utility_messages.h.
+#include "ipc/ipc_message_macros.h"
+
+// These are from the plugin to the renderer
+IPC_BEGIN_MESSAGES(Ppapi)
+  // Loads the given plugin.
+  IPC_MESSAGE_CONTROL2(PpapiMsg_LoadPlugin,
+                       FilePath /* path */,
+                       int /* renderer_id */)
+
+  IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_InitializeModule,
+                              PP_Module /* module_id */,
+                              bool /* result */)
+
+  // Sent in both directions to see if the other side supports the given
+  // interface.
+  IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_SupportsInterface,
+                              std::string /* interface_name */,
+                              bool /* result */)
+
+  // Way for the renderer to list all interfaces that is supports in advance to
+  // avoid extra IPC traffic.
+  IPC_MESSAGE_CONTROL1(PpapiMsg_DeclareInterfaces,
+                       std::vector<std::string> /* interfaces */)
+
+  IPC_MESSAGE_CONTROL2(PpapiMsg_ExecuteCallback,
+                       uint32 /* serialized_callback */,
+                       int32 /* param */)
+
+  // PPP_Class.
+  IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasProperty,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             pp::proxy::SerializedVar /* property */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasMethod,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             pp::proxy::SerializedVar /* method */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_GetProperty,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             pp::proxy::SerializedVar /* property */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiMsg_PPPClass_EnumerateProperties,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             std::vector<pp::proxy::SerializedVar> /* props */,
+                             pp::proxy::SerializedVar /* out_exception */)
+  IPC_SYNC_MESSAGE_ROUTED4_1(PpapiMsg_PPPClass_SetProperty,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             pp::proxy::SerializedVar /* name */,
+                             pp::proxy::SerializedVar /* value */,
+                             pp::proxy::SerializedVar /* out_exception */)
+  IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPClass_RemoveProperty,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             pp::proxy::SerializedVar /* property */,
+                             pp::proxy::SerializedVar /* out_exception */)
+  IPC_SYNC_MESSAGE_ROUTED4_2(PpapiMsg_PPPClass_Call,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             pp::proxy::SerializedVar /* method_name */,
+                             std::vector<pp::proxy::SerializedVar> /* args */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_Construct,
+                             int64 /* ppp_class */,
+                             int64 /* object */,
+                             std::vector<pp::proxy::SerializedVar> /* args */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_MESSAGE_ROUTED2(PpapiMsg_PPPClass_Deallocate,
+                      int64 /* ppp_class */,
+                      int64 /* object */)
+
+  // PPP_Instance.
+  IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPInstance_DidCreate,
+                             PP_Instance /* instance */,
+                             std::vector<std::string> /* argn */,
+                             std::vector<std::string> /* argv */,
+                             bool /* result */)
+  IPC_MESSAGE_ROUTED1(PpapiMsg_PPPInstance_DidDestroy,
+                      PP_Instance /* instance */)
+  IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_DidChangeView,
+                      PP_Instance /* instance */,
+                      PP_Rect /* position */,
+                      PP_Rect /* clip */)
+  IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInstance_DidChangeFocus,
+                      PP_Instance /* instance */,
+                      bool /* has_focus */)
+  IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleInputEvent,
+                             PP_Instance /* instance */,
+                             PP_InputEvent /* event */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleDocumentLoad,
+                             PP_Instance /* instance */,
+                             PP_Resource /* url_loader */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstance_GetInstanceObject,
+                             PP_Instance /* instance */,
+                             pp::proxy::SerializedVar /* result */)
+
+
+  // PPB_URLLoader
+  // (Messages from browser to plugin to notify it of changes in state.)
+  IPC_MESSAGE_ROUTED5(PpapiMsg_PPBURLLoader_UpdateProgress,
+                      PP_Resource /* resource */,
+                      int64 /* bytes_sent */,
+                      int64 /* total_bytes_to_be_sent */,
+                      int64 /* bytes_received */,
+                      int64 /* total_bytes_to_be_received */)
+IPC_END_MESSAGES(Ppapi)
+
+// -----------------------------------------------------------------------------
+// These are from the plugin to the renderer.
+IPC_BEGIN_MESSAGES(PpapiHost)
+  // Reply to PpapiMsg_LoadPlugin.
+  IPC_MESSAGE_CONTROL1(PpapiHostMsg_PluginLoaded,
+                       IPC::ChannelHandle /* handle */)
+
+  // PPB_Core.
+  IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_AddRefResource, PP_Resource)
+  IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource, PP_Resource)
+  IPC_SYNC_MESSAGE_ROUTED0_1(PpapiHostMsg_PPBCore_GetTime,
+                             double /* return value -> time */)
+  IPC_SYNC_MESSAGE_ROUTED0_1(PpapiHostMsg_PPBCore_GetTimeTicks,
+                             double /* return value -> time */)
+  IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBCore_CallOnMainThread,
+                      int /* delay_in_msec */,
+                      uint32_t /* serialized_callback */,
+                      int32_t /* result */)
+
+  // PPB_Graphics2D.
+  IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics2D_Create,
+                             PP_Module /* module */,
+                             PP_Size /* size */,
+                             bool /* is_always_opaque */,
+                             PP_Resource /* result */)
+  IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBGraphics2D_PaintImageData,
+                      PP_Resource /* graphics_2d */,
+                      PP_Resource /* image_data */,
+                      PP_Point /* top_left */,
+                      bool /* src_rect_specified */,
+                      PP_Rect /* src_rect */)
+  IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBGraphics2D_Scroll,
+                      PP_Resource /* graphics_2d */,
+                      bool /* clip_specified */,
+                      PP_Rect /* clip */,
+                      PP_Point /* amount */)
+  IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBGraphics2D_ReplaceContents,
+                      PP_Resource /* graphics_2d */,
+                      PP_Resource /* image_data */)
+  IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBGraphics2D_Flush,
+                             PP_Resource /* graphics_2d */,
+                             uint32_t /* serialized_callback */,
+                             int32_t /* result */)
+
+  // PPB_ImageData.
+  IPC_SYNC_MESSAGE_ROUTED0_1(
+      PpapiHostMsg_PPBImageData_GetNativeImageDataFormat,
+      int32 /* result_format */)
+  IPC_SYNC_MESSAGE_ROUTED1_1(
+      PpapiHostMsg_PPBImageData_IsImageDataFormatSupported,
+      int32 /* format */,
+      bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_PPBImageData_Create,
+                             PP_Module /* module */,
+                             int32 /* format */,
+                             PP_Size /* size */,
+                             bool /* init_to_zero */,
+                             PP_Resource /* result_resource */,
+                             std::string /* image_data_desc */,
+                             uint64_t /* result_shm_handle */)
+
+  // PPB_Instance.
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetWindowObject,
+                             PP_Instance /* instance */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+                             PP_Instance /* instance */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_BindGraphics,
+                             PP_Instance /* instance */,
+                             PP_Resource /* device */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_IsFullFrame,
+                             PP_Instance /* instance */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBInstance_ExecuteScript,
+                             PP_Instance /* instance */,
+                             pp::proxy::SerializedVar /* script */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+
+  // PPB_URLLoader.
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_Create,
+                             PP_Instance /* instance */,
+                             PP_Resource /* result */)
+  IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLLoader_Open,
+                      PP_Resource /* loader */,
+                      PP_Resource /*request_info */,
+                      uint32_t /* serialized_callback */)
+  IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FollowRedirect,
+                      PP_Resource /* loader */,
+                      uint32_t /* serialized_callback */)
+  IPC_SYNC_MESSAGE_ROUTED1_3(PpapiHostMsg_PPBURLLoader_GetUploadProgress,
+                             PP_Resource /* loader */,
+                             int64 /* bytes_sent */,
+                             int64 /* total_bytes_to_be_sent */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED1_3(PpapiHostMsg_PPBURLLoader_GetDownloadProgress,
+                             PP_Resource /* loader */,
+                             int64 /* bytes_received */,
+                             int64 /* total_bytes_to_be_received */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_GetResponseInfo,
+                             PP_Resource /* loader */,
+                             PP_Resource /* response_info_out */)
+  IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLLoader_ReadResponseBody,
+                      PP_Resource /* loader */,
+                      int32_t /* bytes_to_read */,
+                      uint32_t /* serialized_callback */)
+  IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile,
+                      PP_Resource /* loader */,
+                      uint32_t /* serialized_callback */)
+  IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_Close,
+                      PP_Resource /* loader */)
+
+  // PPB_Var.
+  IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVar_AddRefObject,
+                      int64 /* object_id */)
+  IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVar_ReleaseObject,
+                      int64 /* object_id */)
+  IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_ConvertType,
+                             PP_Instance /* instance */,
+                             pp::proxy::SerializedVar /* var */,
+                             int /* new_type */,
+                             pp::proxy::SerializedVar /* exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBVar_DefineProperty,
+                      pp::proxy::SerializedVar /* object */,
+                      PP_ObjectProperty /* property */,
+                      pp::proxy::SerializedVar /* out_exception */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasProperty,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* property */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* method */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_GetProperty,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* property */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_DeleteProperty,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* property */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBVar_EnumerateProperties,
+                             pp::proxy::SerializedVar /* object */,
+                             std::vector<pp::proxy::SerializedVar> /* props */,
+                             pp::proxy::SerializedVar /* out_exception */)
+  IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* name */,
+                             pp::proxy::SerializedVar /* value */,
+                             pp::proxy::SerializedVar /* out_exception */)
+  IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBVar_IsCallable,
+                             pp::proxy::SerializedVar /* object */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED4_2(PpapiHostMsg_PPBVar_Call,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* this_object */,
+                             pp::proxy::SerializedVar /* method_name */,
+                             std::vector<pp::proxy::SerializedVar> /* args */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_CallDeprecated,
+                             pp::proxy::SerializedVar /* object */,
+                             pp::proxy::SerializedVar /* method_name */,
+                             std::vector<pp::proxy::SerializedVar> /* args */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_Construct,
+                             pp::proxy::SerializedVar /* object */,
+                             std::vector<pp::proxy::SerializedVar> /* args */,
+                             pp::proxy::SerializedVar /* out_exception */,
+                             pp::proxy::SerializedVar /* result */)
+  IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+                             pp::proxy::SerializedVar /* var */,
+                             int64 /* object_class */,
+                             int64 /* object-data */,
+                             bool /* result */)
+  IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
+                             PP_Module /* module */,
+                             int64 /* object_class */,
+                             int64 /* object_data */,
+                             pp::proxy::SerializedVar /* result */)
+
+IPC_END_MESSAGES(PpapiHost)
+
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4bfe23cbf38ad7028e6b15ba8decc9cadac4630e
--- /dev/null
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -0,0 +1,190 @@
+// Copyright (c) 2010 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/proxy/ppapi_param_traits.h"
+
+#include <string.h>  // For memcpy
+
+#include "ppapi/proxy/serialized_var.h"
+
+namespace IPC {
+
+// static
+void ParamTraits<PP_InputEvent>::Write(Message* m, const param_type& p) {
+  // PP_InputEvent is just POD so we can just memcpy it.
+  m->WriteData(reinterpret_cast<const char*>(&p), sizeof(PP_InputEvent));
+}
+
+// static
+bool ParamTraits<PP_InputEvent>::Read(const Message* m,
+                                      void** iter,
+                                      param_type* r) {
+  const char* data;
+  int data_size;
+  if (!m->ReadData(iter, &data, &data_size))
+    return false;
+  memcpy(r, data, sizeof(PP_InputEvent));
+  return true;
+}
+
+// static
+void ParamTraits<PP_InputEvent>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_ObjectProperty -----------------------------------------------------------
+
+// static
+void ParamTraits<PP_ObjectProperty>::Write(Message* m, const param_type& p) {
+  // FIXME(brettw);
+}
+
+// static
+bool ParamTraits<PP_ObjectProperty>::Read(const Message* m,
+                                          void** iter,
+                                          param_type* r) {
+  // FIXME(brettw);
+  return true;
+}
+
+// static
+void ParamTraits<PP_ObjectProperty>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Point --------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Point>::Write(Message* m, const param_type& p) {
+  m->WriteInt(p.x);
+  m->WriteInt(p.y);
+}
+
+// static
+bool ParamTraits<PP_Point>::Read(const Message* m, void** iter, param_type* r) {
+  return m->ReadInt(iter, &r->x) && !m->ReadInt(iter, &r->y);
+}
+
+// static
+void ParamTraits<PP_Point>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Rect ---------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Rect>::Write(Message* m, const param_type& p) {
+  m->WriteInt(p.point.x);
+  m->WriteInt(p.point.y);
+  m->WriteInt(p.size.width);
+  m->WriteInt(p.size.height);
+}
+
+// static
+bool ParamTraits<PP_Rect>::Read(const Message* m,
+                                void** iter,
+                                param_type* r) {
+  if (!m->ReadInt(iter, &r->point.x) ||
+      !m->ReadInt(iter, &r->point.y) ||
+      !m->ReadInt(iter, &r->size.width) ||
+      !m->ReadInt(iter, &r->size.height))
+    return false;
+  return true;
+}
+
+// static
+void ParamTraits<PP_Rect>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Size ---------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Size>::Write(Message* m, const param_type& p) {
+  m->WriteInt(p.width);
+  m->WriteInt(p.height);
+}
+
+// static
+bool ParamTraits<PP_Size>::Read(const Message* m, void** iter, param_type* r) {
+  return m->ReadInt(iter, &r->width) && m->ReadInt(iter, &r->height);
+}
+
+// static
+void ParamTraits<PP_Size>::Log(const param_type& p, std::string* l) {
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::SerializedVar>::Write(Message* m,
+                                                  const param_type& p) {
+  p.WriteToMessage(m);
+}
+
+// static
+bool ParamTraits<pp::proxy::SerializedVar>::Read(const Message* m,
+                                                 void** iter,
+                                                 param_type* r) {
+  return r->ReadFromMessage(m, iter);
+}
+
+// static
+void ParamTraits<pp::proxy::SerializedVar>::Log(const param_type& p,
+                                                std::string* l) {
+}
+
+// std::vector<SerializedVar> --------------------------------------------------
+
+void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Write(
+    Message* m,
+    const param_type& p) {
+  WriteParam(m, static_cast<int>(p.size()));
+  for (size_t i = 0; i < p.size(); i++)
+    WriteParam(m, p[i]);
+}
+
+// static
+bool ParamTraits< std::vector<pp::proxy::SerializedVar> >::Read(
+    const Message* m,
+    void** iter,
+    param_type* r) {
+  // This part is just a copy of the the default ParamTraits vector Read().
+  int size;
+  // ReadLength() checks for < 0 itself.
+  if (!m->ReadLength(iter, &size))
+    return false;
+  // Resizing beforehand is not safe, see BUG 1006367 for details.
+  if (INT_MAX / sizeof(pp::proxy::SerializedVar) <= static_cast<size_t>(size))
+    return false;
+
+  // The default vector deserializer does resize here and then we deserialize
+  // into those allocated slots. However, the implementation of vector (at
+  // least in GCC's implementation), creates a new empty object using the
+  // default constructor, and then sets the rest of the items to that empty
+  // one using the copy constructor.
+  //
+  // Since we allocate the inner class when you call the default constructor
+  // and transfer the inner class when you do operator=, the entire vector
+  // will end up referring to the same inner class. Deserializing into this
+  // will just end up overwriting the same item over and over, since all the
+  // SerializedVars will refer to the same thing.
+  //
+  // The solution is to make a new SerializedVar for each deserialized item,
+  // and then add it to the vector one at a time. Our copies are efficient so
+  // this is no big deal.
+  r->reserve(size);
+  for (int i = 0; i < size; i++) {
+    pp::proxy::SerializedVar var;
+    if (!ReadParam(m, iter, &var))
+      return false;
+    r->push_back(var);
+  }
+  return true;
+}
+
+// static
+void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Log(
+    const param_type& p,
+    std::string* l) {
+}
+
+
+}  // namespace IPC
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8c17d83e2bacdc45ca468baf9f25f34159bde27
--- /dev/null
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2010 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_PROXY_PPAPI_PARAM_TRAITS_H_
+#define PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
+
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_input_event.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/serialized_var.h" // TODO(brettw) eraseme.
+
+class PP_ObjectProperty;
+
+namespace pp {
+namespace proxy {
+class SerializedVar;
+}
+}
+
+namespace IPC {
+
+template<>
+struct ParamTraits<PP_InputEvent> {
+  typedef PP_InputEvent param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_ObjectProperty> {
+  typedef PP_ObjectProperty param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_Point> {
+  typedef PP_Point param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_Rect> {
+  typedef PP_Rect param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_Size> {
+  typedef PP_Size param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<pp::proxy::SerializedVar> {
+  typedef pp::proxy::SerializedVar param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+// We need a special implementation of sending a vector of SerializedVars
+// because the behavior of vector doesn't always play nicely with our
+// weird SerializedVar implementation (see "Read" in the .cc file).
+template<>
+struct ParamTraits< std::vector<pp::proxy::SerializedVar> > {
+  typedef std::vector<pp::proxy::SerializedVar> param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+}  // namespace IPC
+
+#endif  // PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a76f2196b8bd1552e211a00c071a4edb746f08ed
--- /dev/null
+++ b/ppapi/proxy/serialized_var.cc
@@ -0,0 +1,457 @@
+// Copyright (c) 2010 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/proxy/serialized_var.h"
+
+#include "base/logging.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+// SerializedVar::Inner --------------------------------------------------------
+
+SerializedVar::Inner::Inner()
+    : serialization_rules_(NULL),
+      var_(PP_MakeUndefined()),
+      cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+  has_been_serialized_ = false;
+  has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
+    : serialization_rules_(serialization_rules),
+      var_(PP_MakeUndefined()),
+      cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+  has_been_serialized_ = false;
+  has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules,
+                            const PP_Var& var)
+    : serialization_rules_(serialization_rules),
+      var_(var),
+      cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+  has_been_serialized_ = false;
+  has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::~Inner() {
+  switch (cleanup_mode_) {
+    case END_SEND_PASS_REF:
+      serialization_rules_->EndSendPassRef(var_);
+      break;
+    case END_RECEIVE_CALLER_OWNED:
+      serialization_rules_->EndReceiveCallerOwned(var_);
+      break;
+    default:
+      break;
+  }
+}
+
+PP_Var SerializedVar::Inner::GetVar() const {
+  DCHECK(serialization_rules_);
+
+  // If we're a string var, we should have already converted the string value
+  // to a var ID.
+  DCHECK(var_.type != PP_VARTYPE_STRING || var_.value.as_id != 0);
+  return var_;
+}
+
+PP_Var SerializedVar::Inner::GetIncompleteVar() const {
+  DCHECK(serialization_rules_);
+  return var_;
+}
+
+void SerializedVar::Inner::SetVar(PP_Var var) {
+  // Sanity check, when updating the var we should have received a
+  // serialization rules pointer already.
+  DCHECK(serialization_rules_);
+  var_ = var;
+}
+
+const std::string& SerializedVar::Inner::GetString() const {
+  DCHECK(serialization_rules_);
+  return string_value_;
+}
+
+std::string* SerializedVar::Inner::GetStringPtr() {
+  DCHECK(serialization_rules_);
+  return &string_value_;
+}
+
+void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
+  // When writing to the IPC messages, a serization rules handler should
+  // always have been set.
+  //
+  // When sending a message, it should be difficult to trigger this if you're
+  // using the SerializedVarSendInput class and giving a non-NULL dispatcher.
+  // Make sure you're using the proper "Send" helper class.
+  //
+  // It should be more common to see this when handling an incoming message
+  // that returns a var. This means the message handler didn't write to the
+  // output parameter, or possibly you used the wrong helper class
+  // (normally SerializedVarReturnValue).
+  DCHECK(serialization_rules_);
+
+#ifndef NDEBUG
+  // We should only be serializing something once.
+  DCHECK(!has_been_serialized_);
+  has_been_serialized_ = true;
+#endif
+
+  // If the var is not a string type, we should not have ended up with any
+  // string data.
+  DCHECK(var_.type == PP_VARTYPE_STRING || string_value_.empty());
+
+  m->WriteInt(static_cast<int>(var_.type));
+  switch (var_.type) {
+    case PP_VARTYPE_UNDEFINED:
+    case PP_VARTYPE_NULL:
+      // These don't need any data associated with them other than the type we
+      // just serialized.
+      break;
+    case PP_VARTYPE_BOOL:
+      m->WriteBool(var_.value.as_bool);
+      break;
+    case PP_VARTYPE_INT32:
+      m->WriteInt(var_.value.as_int);
+      break;
+    case PP_VARTYPE_DOUBLE:
+      IPC::ParamTraits<double>::Write(m, var_.value.as_double);
+      break;
+    case PP_VARTYPE_STRING:
+      // TODO(brettw) in the case of an invalid string ID, it would be nice
+      // to send something to the other side such that a 0 ID would be
+      // generated there. Then the function implementing the interface can
+      // handle the invalid string as if it was in process rather than seeing
+      // what looks like a valid empty string.
+      m->WriteString(string_value_);
+      break;
+    case PP_VARTYPE_OBJECT:
+      m->WriteInt64(var_.value.as_id);
+      break;
+  }
+}
+
+bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m, void** iter) {
+#ifndef NDEBUG
+  // We should only deserialize something once or will end up with leaked
+  // references.
+  //
+  // One place this has happened in the past is using
+  // std::vector<SerializedVar>.resize(). If you're doing this manually instead
+  // of using the helper classes for handling in/out vectors of vars, be
+  // sure you use the same pattern as the SerializedVarVector classes.
+  DCHECK(!has_been_deserialized_);
+  has_been_deserialized_ = true;
+#endif
+
+  // When reading, the dispatcher should be set when we get a Deserialize
+  // call (which will supply a dispatcher).
+  int type;
+  if (!m->ReadInt(iter, &type))
+    return false;
+
+  bool success = false;
+  switch (type) {
+    case PP_VARTYPE_UNDEFINED:
+    case PP_VARTYPE_NULL:
+      // These don't have any data associated with them other than the type we
+      // just serialized.
+      success = true;
+      break;
+    case PP_VARTYPE_BOOL:
+      success = m->ReadBool(iter, &var_.value.as_bool);
+      break;
+    case PP_VARTYPE_INT32:
+      success = m->ReadInt(iter, &var_.value.as_int);
+      break;
+    case PP_VARTYPE_DOUBLE:
+      success = IPC::ParamTraits<double>::Read(m, iter, &var_.value.as_double);
+      break;
+    case PP_VARTYPE_STRING:
+      success = m->ReadString(iter, &string_value_);
+      var_.value.as_id = 0;
+      break;
+    case PP_VARTYPE_OBJECT:
+      success = m->ReadInt64(iter, &var_.value.as_id);
+      break;
+    default:
+      // Leave success as false.
+      break;
+  }
+
+  // All success cases get here. We avoid writing the type above so that the
+  // output param is untouched (defaults to VARTYPE_UNDEFINED) even in the
+  // failure case.
+  if (success)
+    var_.type = static_cast<PP_VarType>(type);
+  return success;
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+SerializedVar::SerializedVar() : inner_(new Inner) {
+}
+
+SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
+    : inner_(new Inner(serialization_rules)) {
+}
+
+SerializedVar::SerializedVar(VarSerializationRules* serialization_rules,
+                             const PP_Var& var)
+    : inner_(new Inner(serialization_rules, var)) {
+}
+
+SerializedVar::~SerializedVar() {
+}
+
+// SerializedVarSendInput ------------------------------------------------------
+
+SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
+                                               const PP_Var& var)
+    : SerializedVar(dispatcher->serialization_rules(), var) {
+  dispatcher->serialization_rules()->SendCallerOwned(var, GetStringPtr());
+}
+
+// static
+void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
+                                           const PP_Var* input,
+                                           size_t input_count,
+                                           std::vector<SerializedVar>* output) {
+  output->resize(input_count);
+  for (size_t i = 0; i < input_count; i++) {
+    (*output)[i] = SerializedVar(dispatcher->serialization_rules(), input[i]);
+    dispatcher->serialization_rules()->SendCallerOwned(input[i],
+                                                 (*output)[i].GetStringPtr());
+  }
+}
+
+// ReceiveSerializedVarReturnValue ---------------------------------------------
+
+ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
+}
+
+PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
+  set_serialization_rules(dispatcher->serialization_rules());
+  SetVar(serialization_rules()->ReceivePassRef(GetIncompleteVar(),
+                                               GetString()));
+  return GetVar();
+}
+
+// ReceiveSerializedException --------------------------------------------------
+
+ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
+                                                       PP_Var* exception)
+    : SerializedVar(dispatcher->serialization_rules()),
+      exception_(exception) {
+}
+
+ReceiveSerializedException::~ReceiveSerializedException() {
+  if (exception_) {
+    // When an output exception is specified, it will take ownership of the
+    // reference.
+    SetVar(serialization_rules()->ReceivePassRef(GetIncompleteVar(),
+                                                 GetString()));
+    *exception_ = GetVar();
+  } else {
+    // When no output exception is specified, the browser thinks we have a ref
+    // to an object that we don't want (this will happen only in the plugin
+    // since the browser will always specify an out exception for the plugin to
+    // write into).
+    //
+    // Strings don't need this handling since we can just avoid creating a
+    // Var from the std::string in the first place.
+    if (GetVar().type == PP_VARTYPE_OBJECT)
+      serialization_rules()->ReleaseObjectRef(GetVar());
+  }
+}
+
+bool ReceiveSerializedException::IsThrown() const {
+  return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
+}
+
+// ReceiveSerializedVarVectorOutParam ------------------------------------------
+
+ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
+    Dispatcher* dispatcher,
+    uint32_t* output_count,
+    PP_Var** output)
+    : dispatcher_(dispatcher),
+      output_count_(output_count),
+      output_(output) {
+}
+
+ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
+  *output_count_ = static_cast<uint32_t>(vector_.size());
+  if (!vector_.size()) {
+    *output_ = NULL;
+    return;
+  }
+
+  *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
+  for (size_t i = 0; i < vector_.size(); i++) {
+    // Here we just mimic what happens when returning a value.
+    ReceiveSerializedVarReturnValue converted;
+    SerializedVar* serialized = &converted;
+    *serialized = vector_[i];
+    (*output_)[i] = converted.Return(dispatcher_);
+  }
+}
+
+std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
+  return &vector_;
+}
+
+// SerializedVarReceiveInput ---------------------------------------------------
+
+SerializedVarReceiveInput::SerializedVarReceiveInput(
+    const SerializedVar& serialized)
+    : serialized_(serialized),
+      dispatcher_(NULL),
+      var_(PP_MakeUndefined()) {
+}
+
+SerializedVarReceiveInput::~SerializedVarReceiveInput() {
+}
+
+PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
+  serialized_.set_serialization_rules(dispatcher->serialization_rules());
+
+  // Ensure that when the serialized var goes out of scope it cleans up the
+  // stuff we're making in BeginReceiveCallerOwned.
+  serialized_.set_cleanup_mode(SerializedVar::END_RECEIVE_CALLER_OWNED);
+
+  serialized_.SetVar(
+      serialized_.serialization_rules()->BeginReceiveCallerOwned(
+          serialized_.GetIncompleteVar(), serialized_.GetStringPtr()));
+  return serialized_.GetVar();
+}
+
+// SerializedVarVectorReceiveInput ---------------------------------------------
+
+SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
+    const std::vector<SerializedVar>& serialized)
+    : serialized_(serialized) {
+}
+
+SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
+  for (size_t i = 0; i < deserialized_.size(); i++) {
+    serialized_[i].serialization_rules()->EndReceiveCallerOwned(
+        deserialized_[i]);
+  }
+}
+
+PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
+                                             uint32_t* array_size) {
+  deserialized_.resize(serialized_.size());
+  for (size_t i = 0; i < serialized_.size(); i++) {
+    // The vector must be able to clean themselves up after this call is
+    // torn down.
+    serialized_[i].set_serialization_rules(dispatcher->serialization_rules());
+
+    serialized_[i].SetVar(
+        serialized_[i].serialization_rules()->BeginReceiveCallerOwned(
+            serialized_[i].GetIncompleteVar(), serialized_[i].GetStringPtr()));
+    deserialized_[i] = serialized_[i].GetVar();
+  }
+
+  *array_size = static_cast<uint32_t>(serialized_.size());
+  return deserialized_.size() > 0 ? &deserialized_[0] : NULL;
+}
+
+// SerializedVarReturnValue ----------------------------------------------------
+
+SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
+    : serialized_(serialized) {
+}
+
+void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
+                                      const PP_Var& var) {
+  serialized_->set_serialization_rules(dispatcher->serialization_rules());
+  serialized_->SetVar(var);
+
+  // Var must clean up after our BeginSendPassRef call.
+  serialized_->set_cleanup_mode(SerializedVar::END_SEND_PASS_REF);
+
+  dispatcher->serialization_rules()->BeginSendPassRef(
+      serialized_->GetIncompleteVar(), serialized_->GetStringPtr());
+}
+
+// SerializedVarOutParam -------------------------------------------------------
+
+SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
+    : serialized_(serialized),
+      writable_var_(PP_MakeUndefined()) {
+}
+
+SerializedVarOutParam::~SerializedVarOutParam() {
+  if (serialized_->serialization_rules()) {
+    // When unset, OutParam wasn't called. We'll just leave the var untouched
+    // in that case.
+    serialized_->SetVar(writable_var_);
+    serialized_->serialization_rules()->BeginSendPassRef(
+        writable_var_, serialized_->GetStringPtr());
+
+    // Normally the current object will be created on the stack to wrap a
+    // SerializedVar and won't have a scope around the actual IPC send. So we
+    // need to tell the SerializedVar to do the begin/end send pass ref calls.
+    serialized_->set_cleanup_mode(SerializedVar::END_SEND_PASS_REF);
+  }
+}
+
+PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
+  serialized_->set_serialization_rules(dispatcher->serialization_rules());
+  return &writable_var_;
+}
+
+// SerializedVarVectorOutParam -------------------------------------------------
+
+SerializedVarVectorOutParam::SerializedVarVectorOutParam(
+    std::vector<SerializedVar>* serialized)
+    : dispatcher_(NULL),
+      serialized_(serialized),
+      count_(0),
+      array_(NULL) {
+}
+
+SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
+  DCHECK(dispatcher_);
+
+  // Convert the array written by the pepper code to the serialized structure.
+  // Note we can't use resize here, we have to allocate a new SerializedVar
+  // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
+  serialized_->reserve(count_);
+  for (uint32_t i = 0; i < count_; i++) {
+    // Just mimic what we do for regular OutParams.
+    SerializedVar var;
+    SerializedVarOutParam out(&var);
+    *out.OutParam(dispatcher_) = array_[i];
+    serialized_->push_back(var);
+  }
+
+  // When returning arrays, the pepper code expects the caller to take
+  // ownership of the array.
+  free(array_);
+}
+
+PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
+  DCHECK(!dispatcher_);  // Should only be called once.
+  dispatcher_ = dispatcher;
+  return &array_;
+}
+
+}  // namespace proxy
+}  // namespace pp
+