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/host_var_serialization_rules.cc b/ppapi/proxy/host_var_serialization_rules.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9ca6a1512a56c8b88675fe52de51b0cfb7072f0b
--- /dev/null
+++ b/ppapi/proxy/host_var_serialization_rules.cc
@@ -0,0 +1,91 @@
+// 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_var_serialization_rules.h"
+
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+
+namespace pp {
+namespace proxy {
+
+HostVarSerializationRules::HostVarSerializationRules(
+    const PPB_Var_Deprecated* var_interface,
+    PP_Module pp_module)
+    : var_interface_(var_interface),
+      pp_module_(pp_module) {
+}
+
+HostVarSerializationRules::~HostVarSerializationRules() {
+}
+
+void HostVarSerializationRules::SendCallerOwned(const PP_Var& var,
+                                                std::string* str_val) {
+  if (var.type == PP_VARTYPE_STRING)
+    VarToString(var, str_val);
+}
+
+PP_Var HostVarSerializationRules::BeginReceiveCallerOwned(
+    const PP_Var& var,
+    const std::string* str_val) {
+  if (var.type == PP_VARTYPE_STRING) {
+    // Convert the string to the context of the current process.
+    return var_interface_->VarFromUtf8(pp_module_, str_val->c_str(),
+                                       static_cast<uint32_t>(str_val->size()));
+  }
+  return var;
+}
+
+void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
+  if (var.type == PP_VARTYPE_STRING) {
+    // Destroy the string BeginReceiveCallerOwned created above.
+    var_interface_->Release(var);
+  }
+}
+
+PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var,
+                                                 const std::string& str_val) {
+  if (var.type == PP_VARTYPE_STRING) {
+    // Convert the string to the context of the current process.
+    return var_interface_->VarFromUtf8(pp_module_, str_val.c_str(),
+                                       static_cast<uint32_t>(str_val.size()));
+  }
+
+  // See PluginVarSerialization::BeginSendPassRef for an example.
+  if (var.type == PP_VARTYPE_OBJECT)
+    var_interface_->AddRef(var);
+  return var;
+}
+
+void HostVarSerializationRules::BeginSendPassRef(const PP_Var& var,
+                                                 std::string* str_val) {
+  // See PluginVarSerialization::ReceivePassRef for an example. We don't need
+  // to do anything here other than convert the string.
+  if (var.type == PP_VARTYPE_STRING)
+    VarToString(var, str_val);
+}
+
+void HostVarSerializationRules::EndSendPassRef(const PP_Var& var) {
+  // See PluginVarSerialization::ReceivePassRef for an example. We don't need
+  // to do anything here.
+}
+
+void HostVarSerializationRules::VarToString(const PP_Var& var,
+                                            std::string* str) {
+  DCHECK(var.type == PP_VARTYPE_STRING);
+
+  // This could be optimized to avoid an extra string copy by going to a lower
+  // level of the browser's implementation of strings where we already have
+  // a std::string.
+  uint32_t len = 0;
+  const char* data = var_interface_->VarToUtf8(var, &len);
+  str->assign(data, len);
+}
+
+void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+  var_interface_->Release(var);
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/host_var_serialization_rules.h b/ppapi/proxy/host_var_serialization_rules.h
new file mode 100644
index 0000000000000000000000000000000000000000..92e294f786f26719e8933541753deb594017b634
--- /dev/null
+++ b/ppapi/proxy/host_var_serialization_rules.h
@@ -0,0 +1,51 @@
+// 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_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+struct PPB_Var_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class VarTracker;
+
+// Implementation of the VarSerializationRules interface for the host side.
+class HostVarSerializationRules : public VarSerializationRules {
+ public:
+  HostVarSerializationRules(const PPB_Var_Deprecated* var_interface,
+                            PP_Module pp_module);
+  ~HostVarSerializationRules();
+
+  // VarSerialization implementation.
+  virtual void SendCallerOwned(const PP_Var& var, std::string* str_val);
+  virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
+                                         const std::string* str_val);
+  virtual void EndReceiveCallerOwned(const PP_Var& var);
+  virtual PP_Var ReceivePassRef(const PP_Var& var,
+                                const std::string& str_val);
+  virtual void BeginSendPassRef(const PP_Var& var, std::string* str_val);
+  virtual void EndSendPassRef(const PP_Var& var);
+  virtual void ReleaseObjectRef(const PP_Var& var);
+
+ private:
+  // Converts the given var (which must be a VARTYPE_STRING) to the given
+  // string object.
+  void VarToString(const PP_Var& var, std::string* str);
+
+  const PPB_Var_Deprecated* var_interface_;
+  PP_Module pp_module_;
+
+  DISALLOW_COPY_AND_ASSIGN(HostVarSerializationRules);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_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/plugin_var_serialization_rules.cc b/ppapi/proxy/plugin_var_serialization_rules.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d01f8d5cfd173318636afbed42375fcd2809c1d8
--- /dev/null
+++ b/ppapi/proxy/plugin_var_serialization_rules.cc
@@ -0,0 +1,112 @@
+// 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_var_serialization_rules.h"
+
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+namespace pp {
+namespace proxy {
+
+PluginVarSerializationRules::PluginVarSerializationRules(
+    PluginVarTracker* var_tracker)
+    : var_tracker_(var_tracker) {
+}
+
+PluginVarSerializationRules::~PluginVarSerializationRules() {
+}
+
+void PluginVarSerializationRules::SendCallerOwned(const PP_Var& var,
+                                                  std::string* str_val) {
+  // Nothing to do since we manage the refcount, other than retrieve the string
+  // to use for IPC.
+  if (var.type == PP_VARTYPE_STRING)
+    *str_val = var_tracker_->GetString(var);
+}
+
+PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned(
+    const PP_Var& var,
+    const std::string* str_val) {
+  if (var.type == PP_VARTYPE_STRING) {
+    // Convert the string to the context of the current process.
+    PP_Var ret;
+    ret.type = PP_VARTYPE_STRING;
+    ret.value.as_id = var_tracker_->MakeString(*str_val);
+    return ret;
+  }
+
+  return var;
+}
+
+void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
+  if (var.type == PP_VARTYPE_STRING) {
+    // Destroy the string BeginReceiveCallerOwned created above.
+    var_tracker_->Release(var);
+  }
+}
+
+PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var,
+                                                   const std::string& str_val) {
+  if (var.type == PP_VARTYPE_STRING) {
+    // Convert the string to the context of the current process.
+    PP_Var ret;
+    ret.type = PP_VARTYPE_STRING;
+    ret.value.as_id = var_tracker_->MakeString(str_val);
+    return ret;
+  }
+
+  // Overview of sending an object with "pass ref" from the browser to the
+  // plugin:
+  //                                  Example 1             Example 2
+  //                               Plugin   Browser      Plugin   Browser
+  // Before send                      3        2            0        1
+  // Browser calls BeginSendPassRef   3        2            0        1
+  // Plugin calls ReceivePassRef      4        1            1        1
+  // Browser calls EndSendPassRef     4        1            1        1
+  //
+  // In example 1 before the send, the plugin has 3 refs which are represented
+  // as one ref in the browser (since the plugin only tells the browser when
+  // it's refcount goes from 1 -> 0). The initial state is that the browser
+  // plugin code started to return a value, which means it gets another ref
+  // on behalf of the caller. This needs to be transferred to the plugin and
+  // folded in to its set of refs it maintains (with one ref representing all
+  // fo them in the browser).
+  if (var.type == PP_VARTYPE_OBJECT)
+    var_tracker_->ReceiveObjectPassRef(var);
+  return var;
+}
+
+void PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var,
+                                                   std::string* str_val) {
+  // Overview of sending an object with "pass ref" from the plugin to the
+  // browser:
+  //                                  Example 1             Example 2
+  //                               Plugin   Browser      Plugin   Browser
+  // Before send                      3        1            1        1
+  // Plugin calls BeginSendPassRef    3        1            1        1
+  // Browser calls ReceivePassRef     3        2            1        2
+  // Plugin calls EndSendPassRef      2        2            0        1
+  //
+  // The plugin maintains one ref count in the browser on behalf of the
+  // entire ref count in the plugin. When the plugin refcount goes to 0, it
+  // will call the browser to deref the object. This is why in example 2
+  // transferring the object ref to the browser involves no net change in the
+  // browser's refcount.
+
+  if (var.type == PP_VARTYPE_STRING)
+    *str_val = var_tracker_->GetString(var);
+}
+
+void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var) {
+  // See BeginSendPassRef for an example of why we release our ref here.
+  if (var.type == PP_VARTYPE_OBJECT)
+    var_tracker_->Release(var);
+}
+
+void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+  var_tracker_->Release(var);
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/plugin_var_serialization_rules.h b/ppapi/proxy/plugin_var_serialization_rules.h
new file mode 100644
index 0000000000000000000000000000000000000000..f2d8224f06bb16de230894495a7549b5c9d82cc1
--- /dev/null
+++ b/ppapi/proxy/plugin_var_serialization_rules.h
@@ -0,0 +1,44 @@
+// 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_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
+
+#include "base/basictypes.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+class PluginVarTracker;
+
+// Implementation of the VarSerialization interface for the plugin.
+class PluginVarSerializationRules : public VarSerializationRules {
+ public:
+  // This class with use the given non-owning pointer to the var tracker to
+  // handle object refcounting and string conversion.
+  PluginVarSerializationRules(PluginVarTracker* tracker);
+  ~PluginVarSerializationRules();
+
+  // VarSerialization implementation.
+  virtual void SendCallerOwned(const PP_Var& var, std::string* str_val);
+  virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
+                                         const std::string* str_val);
+  virtual void EndReceiveCallerOwned(const PP_Var& var);
+  virtual PP_Var ReceivePassRef(const PP_Var& var,
+                                const std::string& str_val);
+  virtual void BeginSendPassRef(const PP_Var& var, std::string* str_val);
+  virtual void EndSendPassRef(const PP_Var& var);
+  virtual void ReleaseObjectRef(const PP_Var& var);
+
+ private:
+  PluginVarTracker* var_tracker_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginVarSerializationRules);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b28fc385d9c432f19a276abf793aafe1004fbc04
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker.cc
@@ -0,0 +1,134 @@
+// 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_var_tracker.h"
+
+#include "base/ref_counted.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+class RefCountedString : public base::RefCounted<RefCountedString> {
+ public:
+  RefCountedString() {
+  }
+  RefCountedString(const std::string& str) : value_(str) {
+  }
+  RefCountedString(const char* data, size_t len)
+      : value_(data, len) {
+  }
+
+  const std::string& value() const { return value_; }
+
+ private:
+  std::string value_;
+};
+
+// When running in the plugin, this will convert the string ID to the object
+// using casting. No validity checking is done.
+RefCountedString* PluginStringFromID(int64 id) {
+  return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id));
+}
+
+}  // namespace
+
+PluginVarTracker::PluginVarTracker(PluginDispatcher* dispatcher)
+    : dispatcher_(dispatcher),
+      browser_var_interface_(NULL) {
+}
+
+void PluginVarTracker::Init() {
+  browser_var_interface_ = reinterpret_cast<const PPB_Var*>(
+      dispatcher_->GetLocalInterface(PPB_VAR_INTERFACE));
+}
+
+int64 PluginVarTracker::MakeString(const std::string& str) {
+  RefCountedString* out = new RefCountedString(str);
+  out->AddRef();
+  return static_cast<int64>(reinterpret_cast<intptr_t>(out));
+}
+
+std::string PluginVarTracker::GetString(const PP_Var& var) const {
+  return PluginStringFromID(var.value.as_id)->value();
+}
+
+const std::string* PluginVarTracker::GetExistingString(
+    const PP_Var& var) const {
+  if (var.type != PP_VARTYPE_STRING)
+    return NULL;
+  RefCountedString* str = PluginStringFromID(var.value.as_id);
+  return &str->value();
+}
+
+void PluginVarTracker::AddRef(const PP_Var& var) {
+  if (var.type == PP_VARTYPE_STRING) {
+    PluginStringFromID(var.value.as_id)->AddRef();
+  } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) {
+    int& ref_count = object_ref_count_[var.value.as_id];
+    ref_count++;
+    if (ref_count == 1) {
+      // We must handle the case where we got requested to AddRef an object
+      // that we've never seen before. This should tell the browser we've
+      // taken a ref. This comes up when the browser passes an object as an
+      // input param and holds a ref for us. We may not have seen that object
+      // and the plugin handler may want to AddRef and release it internally.
+      SendAddRefObjectMsg(var.value.as_id);
+    }
+  }
+}
+
+void PluginVarTracker::Release(const PP_Var& var) {
+  if (var.type == PP_VARTYPE_STRING) {
+    PluginStringFromID(var.value.as_id)->Release();
+  } else if (var.type == PP_VARTYPE_OBJECT) {
+    ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id);
+    if (found == object_ref_count_.end())
+      return;  // Invalid object.
+    found->second--;
+
+    if (found->second == 0) {
+      // Plugin has released all of its refs, tell the browser.
+      object_ref_count_.erase(found);
+      SendReleaseObjectMsg(var.value.as_id);
+    }
+  }
+}
+
+void PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var) {
+  // We're the plugin and the renderer just sent us a ref. The renderer has
+  // addrefed the var in its tracker for us since it's returning it.
+  //
+  // - If We don't have a reference to this already, then we just add it to
+  //   our tracker and use that one ref.
+  //
+  // - If we do already have a reference to it, that means the renderer now
+  //   has two references on our behalf. We want to transfer that extra
+  //   reference to our list. This means we addref in the plugin, and release
+  //   the extra one in the renderer.
+  ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id);
+  if (found == object_ref_count_.end()) {
+    object_ref_count_[var.value.as_id] = 1;
+  } else {
+    SendReleaseObjectMsg(var.value.as_id);
+    found->second++;
+  }
+}
+
+void PluginVarTracker::SendAddRefObjectMsg(int64_t id) {
+  dispatcher_->Send(new PpapiHostMsg_PPBVar_AddRefObject(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, id));
+}
+
+void PluginVarTracker::SendReleaseObjectMsg(int64_t id) {
+  dispatcher_->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, id));
+}
+
+}  // namesace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h
new file mode 100644
index 0000000000000000000000000000000000000000..b519ee67c1ab867a9e8fbd868d2fd37815473b6a
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker.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_VAR_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
+
+#include <map>
+#include <string>
+
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+
+struct PPB_Var;
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher;
+
+// Tracks live strings and objects in the plugin process. We maintain our own
+// reference count for these objects. In the case of JS objects, we maintain
+// a single ref in the browser process whenever we have a nonzero refcount
+// in the plugin process. This allows AddRef and Release to not initiate too
+// much IPC chat.
+class PluginVarTracker {
+ public:
+  // You must call Init() after creation to set up the correct interfaces. We
+  // do this to avoid having to depend on the dispatcher in the constructor,
+  // which is probably just being created from our constructor.
+  PluginVarTracker(PluginDispatcher* dispatcher);
+
+  // Must be called after construction.
+  void Init();
+
+  // Allocates a string and returns the ID of it. The refcount will be 1.
+  int64_t MakeString(const std::string& str);
+
+  // Returns the string associated with the given string var. The var must be
+  // of type string and must be valid or this function will crash.
+  std::string GetString(const PP_Var& var) const;
+
+  // Returns a pointer to the given string if it exists, or NULL if the var
+  // isn't a string var.
+  const std::string* GetExistingString(const PP_Var& var) const;
+
+  void AddRef(const PP_Var& var);
+  void Release(const PP_Var& var);
+
+  // Manages tracking for receiving a VARTYPE_OBJECT from the remote side
+  // (either the plugin or the renderer) that has already had its reference
+  // count incremented on behalf of the caller.
+  void ReceiveObjectPassRef(const PP_Var& var);
+
+ private:
+  // Sends an addref or release message to the browser for the given object ID.
+  void SendAddRefObjectMsg(int64_t id);
+  void SendReleaseObjectMsg(int64_t id);
+
+  PluginDispatcher* dispatcher_;
+
+  // When !is_plugin_ (we're in the renderer) this points to the actual var
+  // interface implementation which is how we create strings and manage
+  // refcounts.
+  const PPB_Var* browser_var_interface_;
+
+  // Tracks object references to the reference count of that object on the
+  // plugin side.
+  typedef std::map<int64_t, int> ObjectRefCount;
+  ObjectRefCount object_ref_count_;
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PLUGIN_VAR_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/ppb_core_proxy.cc b/ppapi/proxy/ppb_core_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a956f7ad38f717ad44a75ba6de41e4bc6e1cbec0
--- /dev/null
+++ b/ppapi/proxy/ppb_core_proxy.cc
@@ -0,0 +1,129 @@
+// 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/ppb_core_proxy.h"
+
+#include <stdlib.h>  // For malloc
+
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+void AddRefResource(PP_Resource resource) {
+  PluginDispatcher::Get()->plugin_resource_tracker()->AddRefResource(resource);
+}
+
+void ReleaseResource(PP_Resource resource) {
+  PluginDispatcher::Get()->plugin_resource_tracker()->ReleaseResource(resource);
+}
+
+void* MemAlloc(size_t num_bytes) {
+  return malloc(num_bytes);
+}
+
+void MemFree(void* ptr) {
+  free(ptr);
+}
+
+double GetTime() {
+  double result;
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBCore_GetTime(
+      INTERFACE_ID_PPB_CORE, &result));
+  return result;
+}
+
+double GetTimeTicks() {
+  double result;
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBCore_GetTimeTicks(
+      INTERFACE_ID_PPB_CORE, &result));
+  return result;
+}
+
+void CallOnMainThread(int delay_in_msec,
+                      PP_CompletionCallback callback,
+                      int32_t result) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  dispatcher->Send(new PpapiHostMsg_PPBCore_CallOnMainThread(
+      INTERFACE_ID_PPB_CORE, delay_in_msec,
+      dispatcher->callback_tracker().SendCallback(callback),
+      result));
+}
+
+bool IsMainThread() {
+  NOTIMPLEMENTED();
+  return true;
+}
+
+const PPB_Core core_interface = {
+  &AddRefResource,
+  &ReleaseResource,
+  &MemAlloc,
+  &MemFree,
+  &GetTime,
+  &GetTimeTicks,
+  &CallOnMainThread,
+  &IsMainThread
+};
+
+}  // namespace
+
+PPB_Core_Proxy::PPB_Core_Proxy(Dispatcher* dispatcher,
+                               const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Core_Proxy::~PPB_Core_Proxy() {
+}
+
+const void* PPB_Core_Proxy::GetSourceInterface() const {
+  return &core_interface;
+}
+
+InterfaceID PPB_Core_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_CORE;
+}
+
+void PPB_Core_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_Core_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_AddRefResource, OnMsgAddRefResource)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_ReleaseResource, OnMsgReleaseResource)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_GetTime, OnMsgGetTime)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_CallOnMainThread,
+                        OnMsgCallOnMainThread)
+  IPC_END_MESSAGE_MAP()
+  // FIXME(brettw) handle bad messages!
+}
+
+void PPB_Core_Proxy::OnMsgAddRefResource(PP_Resource resource) {
+  ppb_core_target()->AddRefResource(resource);
+}
+
+void PPB_Core_Proxy::OnMsgReleaseResource(PP_Resource resource) {
+  ppb_core_target()->ReleaseResource(resource);
+}
+
+void PPB_Core_Proxy::OnMsgGetTime(double* result) {
+  *result = 0.0;  // FIXME(brettw);
+}
+
+void PPB_Core_Proxy::OnMsgCallOnMainThread(int delay_in_msec,
+                                           uint32_t serialized_callback,
+                                           int32_t result) {
+  // TODO(brettw) this doesn't need to go to the other process, we should be
+  // able to post this to our own message loop and get better performance.
+  ppb_core_target()->CallOnMainThread(delay_in_msec,
+                                      ReceiveCallback(serialized_callback),
+                                      result);
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_core_proxy.h b/ppapi/proxy/ppb_core_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7dfa9019a24ce52e81c789d81f6ae267733eb2d
--- /dev/null
+++ b/ppapi/proxy/ppb_core_proxy.h
@@ -0,0 +1,45 @@
+// 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_PPB_CORE_PROXY_H_
+#define PPAPI_PPB_CORE_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Core;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Core_Proxy : public InterfaceProxy {
+ public:
+  PPB_Core_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPB_Core_Proxy();
+
+  const PPB_Core* ppb_core_target() const {
+    return reinterpret_cast<const PPB_Core*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgAddRefResource(PP_Resource resource);
+  void OnMsgReleaseResource(PP_Resource resource);
+  void OnMsgGetTime(double* result);
+  void OnMsgCallOnMainThread(int delay_in_msec,
+                             uint32_t serialized_callback,
+                             int32_t result);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PPB_CORE_PROXY_H_
diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.cc b/ppapi/proxy/ppb_graphics_2d_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ec0fb09cc88120b8581bdf69f50b84c8ed3ed812
--- /dev/null
+++ b/ppapi/proxy/ppb_graphics_2d_proxy.cc
@@ -0,0 +1,202 @@
+// 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/ppb_graphics_2d_proxy.h"
+
+#include <string.h>  // For memcpy
+
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+class Graphics2D : public PluginResource {
+ public:
+  Graphics2D(const PP_Size& size, bool is_always_opaque)
+      : size_(size), is_always_opaque_(is_always_opaque) {
+  }
+
+  // Resource overrides.
+  virtual Graphics2D* AsGraphics2D() { return this; }
+
+  const PP_Size& size() const { return size_; }
+  bool is_always_opaque() const { return is_always_opaque_; }
+
+ private:
+  PP_Size size_;
+  bool is_always_opaque_;
+
+  DISALLOW_COPY_AND_ASSIGN(Graphics2D);
+};
+
+namespace {
+
+PP_Resource Create(PP_Module module_id,
+                   const PP_Size* size,
+                   bool is_always_opaque) {
+  PluginDispatcher* dispatcher = PluginDispatcher::Get();
+  PP_Resource result = 0;
+  dispatcher->Send(new PpapiHostMsg_PPBGraphics2D_Create(
+      INTERFACE_ID_PPB_GRAPHICS_2D, module_id, *size, is_always_opaque,
+      &result));
+  if (result) {
+    linked_ptr<Graphics2D> graphics_2d(new Graphics2D(*size, is_always_opaque));
+    dispatcher->plugin_resource_tracker()->AddResource(result, graphics_2d);
+  }
+  return result;
+}
+
+bool IsGraphics2D(PP_Resource resource) {
+  Graphics2D* object = PluginResource::GetAs<Graphics2D>(resource);
+  return !!object;
+}
+
+bool Describe(PP_Resource graphics_2d,
+              PP_Size* size,
+              bool* is_always_opaque) {
+  Graphics2D* object = PluginResource::GetAs<Graphics2D>(graphics_2d);
+  if (!object) {
+    size->width = 0;
+    size->height = 0;
+    *is_always_opaque = false;
+    return false;
+  }
+
+  *size = object->size();
+  *is_always_opaque = object->is_always_opaque();
+  return true;
+}
+
+void PaintImageData(PP_Resource graphics_2d,
+                    PP_Resource image_data,
+                    const PP_Point* top_left,
+                    const PP_Rect* src_rect) {
+  PP_Rect dummy;
+  memset(&dummy, 0, sizeof(PP_Rect));
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_PaintImageData(
+      INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, image_data, *top_left,
+      !!src_rect, src_rect ? *src_rect : dummy));
+}
+
+void Scroll(PP_Resource graphics_2d,
+            const PP_Rect* clip_rect,
+            const PP_Point* amount) {
+  PP_Rect dummy;
+  memset(&dummy, 0, sizeof(PP_Rect));
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_Scroll(
+      INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, !!clip_rect,
+      clip_rect ? *clip_rect : dummy, *amount));
+}
+
+void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) {
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_ReplaceContents(
+      INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, image_data));
+}
+
+int32_t Flush(PP_Resource graphics_2d,
+              PP_CompletionCallback callback) {
+  PluginDispatcher* dispatcher = PluginDispatcher::Get();
+  int32_t result = PP_ERROR_FAILED;
+  dispatcher->Send(new PpapiHostMsg_PPBGraphics2D_Flush(
+      INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d,
+      dispatcher->callback_tracker().SendCallback(callback),
+      &result));
+  return result;
+}
+
+const PPB_Graphics2D ppb_graphics_2d = {
+  &Create,
+  &IsGraphics2D,
+  &Describe,
+  &PaintImageData,
+  &Scroll,
+  &ReplaceContents,
+  &Flush
+};
+
+}  // namespace
+
+PPB_Graphics2D_Proxy::PPB_Graphics2D_Proxy(Dispatcher* dispatcher,
+                                           const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Graphics2D_Proxy::~PPB_Graphics2D_Proxy() {
+}
+
+const void* PPB_Graphics2D_Proxy::GetSourceInterface() const {
+  return &ppb_graphics_2d;
+}
+
+InterfaceID PPB_Graphics2D_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_GRAPHICS_2D;
+}
+
+void PPB_Graphics2D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_Graphics2D_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Create,
+                        OnMsgCreate)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_PaintImageData,
+                        OnMsgPaintImageData)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Scroll,
+                        OnMsgScroll)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_ReplaceContents,
+                        OnMsgReplaceContents)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Flush,
+                        OnMsgFlush)
+  IPC_END_MESSAGE_MAP()
+  // FIXME(brettw) handle bad messages!
+}
+
+void PPB_Graphics2D_Proxy::OnMsgCreate(PP_Module module,
+                                       const PP_Size& size,
+                                       bool is_always_opaque,
+                                       PP_Resource* result) {
+  *result = ppb_graphics_2d_target()->Create(
+      module, &size, is_always_opaque);
+}
+
+void PPB_Graphics2D_Proxy::OnMsgPaintImageData(PP_Resource graphics_2d,
+                                               PP_Resource image_data,
+                                               const PP_Point& top_left,
+                                               bool src_rect_specified,
+                                               const PP_Rect& src_rect) {
+  ppb_graphics_2d_target()->PaintImageData(
+      graphics_2d, image_data, &top_left,
+      src_rect_specified ? &src_rect : NULL);
+}
+
+void PPB_Graphics2D_Proxy::OnMsgScroll(PP_Resource graphics_2d,
+                                       bool clip_specified,
+                                       const PP_Rect& clip,
+                                       const PP_Point& amount) {
+  ppb_graphics_2d_target()->Scroll(
+      graphics_2d,
+      clip_specified ? &clip : NULL, &amount);
+}
+
+void PPB_Graphics2D_Proxy::OnMsgReplaceContents(PP_Resource graphics_2d,
+                                                PP_Resource image_data) {
+  ppb_graphics_2d_target()->ReplaceContents(graphics_2d, image_data);
+}
+
+void PPB_Graphics2D_Proxy::OnMsgFlush(PP_Resource graphics_2d,
+                                      uint32_t serialized_callback,
+                                      int32_t* result) {
+  // TODO(brettw) this should be a non-sync function. Ideally it would call
+  // the callback with a failure code from here if you weren't allowed to
+  // call Flush there.
+  *result = ppb_graphics_2d_target()->Flush(
+      graphics_2d, ReceiveCallback(serialized_callback));
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.h b/ppapi/proxy/ppb_graphics_2d_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..80c698134910fda188d525de25c9ab0230292cc1
--- /dev/null
+++ b/ppapi/proxy/ppb_graphics_2d_proxy.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_PPB_GRAPHICS_2D_PROXY_H_
+#define PPAPI_PPB_GRAPHICS_2D_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Graphics2D;
+struct PP_Point;
+struct PP_Rect;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Graphics2D_Proxy : public InterfaceProxy {
+ public:
+  PPB_Graphics2D_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPB_Graphics2D_Proxy();
+
+  const PPB_Graphics2D* ppb_graphics_2d_target() const {
+    return reinterpret_cast<const PPB_Graphics2D*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgCreate(PP_Module module,
+                   const PP_Size& size,
+                   bool is_always_opaque,
+                   PP_Resource* result);
+  void OnMsgPaintImageData(PP_Resource graphics_2d,
+                           PP_Resource image_data,
+                           const PP_Point& top_left,
+                           bool src_rect_specified,
+                           const PP_Rect& src_rect);
+  void OnMsgScroll(PP_Resource graphics_2d,
+                   bool clip_specified,
+                   const PP_Rect& clip,
+                   const PP_Point& amount);
+  void OnMsgReplaceContents(PP_Resource graphics_2d,
+                            PP_Resource image_data);
+  void OnMsgFlush(PP_Resource graphics_2d,
+                  uint32_t serialized_callback,
+                  int32_t* result);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PPB_GRAPHICS_2D_PROXY_H_
diff --git a/ppapi/proxy/ppb_image_data_proxy.cc b/ppapi/proxy/ppb_image_data_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..19d0932da02080f51c1f1b034314128c7af3ca8e
--- /dev/null
+++ b/ppapi/proxy/ppb_image_data_proxy.cc
@@ -0,0 +1,234 @@
+// 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/ppb_image_data_proxy.h"
+
+#include <string.h>  // For memcpy
+
+#include <vector>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/trusted/ppb_image_data_trusted.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+#if defined(OS_LINUX)
+#include <sys/shm.h>
+#endif
+
+namespace pp {
+namespace proxy {
+
+class ImageData : public PluginResource {
+ public:
+  ImageData(const PP_ImageDataDesc& desc, uint64_t memory_handle);
+  virtual ~ImageData();
+
+  // Resource overrides.
+  virtual ImageData* AsImageData() { return this; }
+
+  void* Map();
+  void Unmap();
+
+  const PP_ImageDataDesc& desc() const { return desc_; }
+
+ private:
+  PP_ImageDataDesc desc_;
+  uint64_t memory_handle_;
+
+  void* mapped_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageData);
+};
+
+ImageData::ImageData(const PP_ImageDataDesc& desc,
+                     uint64_t memory_handle)
+    : desc_(desc),
+      memory_handle_(memory_handle),
+      mapped_data_(NULL) {
+}
+
+ImageData::~ImageData() {
+  Unmap();
+}
+
+void* ImageData::Map() {
+#if defined(OS_LINUX)
+  // On linux, the memory handle is a SysV shared memory segment.
+  int shmkey = static_cast<int>(memory_handle_);
+  void* address = shmat(shmkey, NULL, 0);
+  // Mark for deletion in case we crash so the kernel will clean it up.
+  shmctl(shmkey, IPC_RMID, 0);
+  if (address == (void*)-1)
+    return NULL;
+  mapped_data_ = address;
+  return address;
+#else
+  #error write this
+#endif
+}
+
+void ImageData::Unmap() {
+#if defined(OS_LINUX)
+  if (mapped_data_)
+    shmdt(mapped_data_);
+#else
+  #error write this
+#endif
+  mapped_data_ = NULL;
+}
+
+namespace {
+
+PP_ImageDataFormat GetNativeImageDataFormat() {
+  int32 format = 0;
+  PluginDispatcher::Get()->Send(
+      new PpapiHostMsg_PPBImageData_GetNativeImageDataFormat(
+          INTERFACE_ID_PPB_IMAGE_DATA, &format));
+  return static_cast<PP_ImageDataFormat>(format);
+}
+
+bool IsImageDataFormatSupported(PP_ImageDataFormat format) {
+  bool supported = false;
+  PluginDispatcher::Get()->Send(
+      new PpapiHostMsg_PPBImageData_IsImageDataFormatSupported(
+          INTERFACE_ID_PPB_IMAGE_DATA, static_cast<int32_t>(format),
+          &supported));
+  return supported;
+}
+
+PP_Resource Create(PP_Module module_id,
+                   PP_ImageDataFormat format,
+                   const PP_Size* size,
+                   bool init_to_zero) {
+  PP_Resource result = 0;
+  std::string image_data_desc;
+  uint64_t shm_handle = -1;
+  PluginDispatcher::Get()->Send(
+      new PpapiHostMsg_PPBImageData_Create(
+          INTERFACE_ID_PPB_IMAGE_DATA, module_id, format, *size, init_to_zero,
+          &result, &image_data_desc, &shm_handle));
+
+  if (result && image_data_desc.size() == sizeof(PP_ImageDataDesc)) {
+    // We serialize the PP_ImageDataDesc just by copying to a string.
+    PP_ImageDataDesc desc;
+    memcpy(&desc, image_data_desc.data(), sizeof(PP_ImageDataDesc));
+
+    linked_ptr<ImageData> object(
+        new ImageData(desc, shm_handle));
+    PluginDispatcher::Get()->plugin_resource_tracker()->AddResource(
+        result, object);
+  }
+  return result;
+}
+
+bool IsImageData(PP_Resource resource) {
+  ImageData* object = PluginResource::GetAs<ImageData>(resource);
+  return !!object;
+}
+
+bool Describe(PP_Resource resource, PP_ImageDataDesc* desc) {
+  ImageData* object = PluginResource::GetAs<ImageData>(resource);
+  if (!object)
+    return false;
+  memcpy(desc, &object->desc(), sizeof(PP_ImageDataDesc));
+  return true;
+}
+
+void* Map(PP_Resource resource) {
+  ImageData* object = PluginResource::GetAs<ImageData>(resource);
+  if (!object)
+    return NULL;
+  return object->Map();
+}
+
+void Unmap(PP_Resource resource) {
+  ImageData* object = PluginResource::GetAs<ImageData>(resource);
+  if (object)
+    object->Unmap();
+}
+
+const PPB_ImageData ppb_imagedata = {
+  &GetNativeImageDataFormat,
+  &IsImageDataFormatSupported,
+  &Create,
+  &IsImageData,
+  &Describe,
+  &Map,
+  &Unmap,
+};
+
+}  // namespace
+
+PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher,
+                                         const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_ImageData_Proxy::~PPB_ImageData_Proxy() {
+}
+
+const void* PPB_ImageData_Proxy::GetSourceInterface() const {
+  return &ppb_imagedata;
+}
+
+InterfaceID PPB_ImageData_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_IMAGE_DATA;
+}
+
+void PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_GetNativeImageDataFormat,
+                        OnMsgGetNativeImageDataFormat)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_IsImageDataFormatSupported,
+                        OnMsgIsImageDataFormatSupported)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_Create, OnMsgCreate)
+  IPC_END_MESSAGE_MAP()
+  // FIXME(brettw) handle bad messages!
+}
+
+void PPB_ImageData_Proxy::OnMsgGetNativeImageDataFormat(int32* result) {
+  *result = ppb_image_data_target()->GetNativeImageDataFormat();
+}
+
+void PPB_ImageData_Proxy::OnMsgIsImageDataFormatSupported(int32 format,
+                                                          bool* result) {
+  *result = ppb_image_data_target()->IsImageDataFormatSupported(
+      static_cast<PP_ImageDataFormat>(format));
+}
+
+void PPB_ImageData_Proxy::OnMsgCreate(PP_Module module,
+                                      int32_t format,
+                                      const PP_Size& size,
+                                      bool init_to_zero,
+                                      PP_Resource* result,
+                                      std::string* image_data_desc,
+                                      uint64_t* result_shm_handle) {
+  *result = ppb_image_data_target()->Create(
+      module, static_cast<PP_ImageDataFormat>(format), &size, init_to_zero);
+  *result_shm_handle = 0;
+  if (*result) {
+    // The ImageDesc is just serialized as a string.
+    PP_ImageDataDesc desc;
+    if (ppb_image_data_target()->Describe(*result, &desc)) {
+      image_data_desc->resize(sizeof(PP_ImageDataDesc));
+      memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
+    }
+
+    // Get the shared memory handle.
+    const PPB_ImageDataTrusted* trusted =
+        reinterpret_cast<const PPB_ImageDataTrusted*>(
+            dispatcher()->GetLocalInterface(PPB_IMAGEDATA_TRUSTED_INTERFACE));
+    if (trusted)
+      *result_shm_handle = trusted->GetNativeMemoryHandle(*result);
+  }
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_image_data_proxy.h b/ppapi/proxy/ppb_image_data_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..39e8ad6473530a728d5b3ceaf4969548015a7580
--- /dev/null
+++ b/ppapi/proxy/ppb_image_data_proxy.h
@@ -0,0 +1,50 @@
+// 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_PPB_IMAGE_DATA_PROXY_H_
+#define PPAPI_PPB_IMAGE_DATA_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_ImageData;
+
+namespace pp {
+namespace proxy {
+
+class PPB_ImageData_Proxy : public InterfaceProxy {
+ public:
+  PPB_ImageData_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPB_ImageData_Proxy();
+
+  const PPB_ImageData* ppb_image_data_target() const {
+    return reinterpret_cast<const PPB_ImageData*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgGetNativeImageDataFormat(int32* result);
+  void OnMsgIsImageDataFormatSupported(int32 format, bool* result);
+  void OnMsgCreate(PP_Module module,
+                   int32_t format,
+                   const PP_Size& size,
+                   bool init_to_zero,
+                   PP_Resource* result,
+                   std::string* image_data_desc,
+                   uint64_t* result_shm_handle);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PPB_IMAGE_DATA_PROXY_H_
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c81562a13ed3293dce56e1cbbe426df4816e6782
--- /dev/null
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -0,0 +1,139 @@
+// 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/ppb_instance_proxy.h"
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_message_helpers.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Var GetWindowObject(PP_Instance instance) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedVarReturnValue result;
+  dispatcher->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
+      INTERFACE_ID_PPB_INSTANCE, instance, &result));
+  return result.Return(dispatcher);
+}
+
+PP_Var GetOwnerElementObject(PP_Instance instance) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedVarReturnValue result;
+  dispatcher->Send(new PpapiHostMsg_PPBInstance_GetOwnerElementObject(
+          INTERFACE_ID_PPB_INSTANCE, instance, &result));
+  return result.Return(dispatcher);
+}
+
+bool BindGraphics(PP_Instance instance, PP_Resource device) {
+  bool result;
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
+      INTERFACE_ID_PPB_INSTANCE, instance, device, &result));
+  return result;
+}
+
+bool IsFullFrame(PP_Instance instance) {
+  bool result;
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame(
+      INTERFACE_ID_PPB_INSTANCE, instance, &result));
+  return result;
+}
+
+PP_Var ExecuteScript(PP_Instance instance, PP_Var script, PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  if (se.IsThrown())
+    return PP_MakeUndefined();
+
+  ReceiveSerializedVarReturnValue result;
+  dispatcher->Send(new PpapiHostMsg_PPBInstance_ExecuteScript(
+      INTERFACE_ID_PPB_INSTANCE, instance,
+      SerializedVarSendInput(dispatcher, script), &se, &result));
+  return result.Return(dispatcher);
+}
+
+const PPB_Instance instance_interface = {
+  &GetWindowObject,
+  &GetOwnerElementObject,
+  &BindGraphics,
+  &IsFullFrame,
+  &ExecuteScript
+};
+
+}  // namespace
+
+PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher,
+                                       const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Instance_Proxy::~PPB_Instance_Proxy() {
+}
+
+const void* PPB_Instance_Proxy::GetSourceInterface() const {
+  return &instance_interface;
+}
+
+InterfaceID PPB_Instance_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_INSTANCE;
+}
+
+void PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject,
+                        OnMsgGetWindowObject)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+                        OnMsgGetOwnerElementObject)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics,
+                        OnMsgBindGraphics)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame,
+                        OnMsgIsFullFrame)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript,
+                        OnMsgExecuteScript)
+  IPC_END_MESSAGE_MAP()
+}
+
+void PPB_Instance_Proxy::OnMsgGetWindowObject(
+    PP_Instance instance,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(),
+                ppb_instance_target()->GetWindowObject(instance));
+}
+
+void PPB_Instance_Proxy::OnMsgGetOwnerElementObject(
+    PP_Instance instance,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(),
+                ppb_instance_target()->GetOwnerElementObject(instance));
+}
+
+void PPB_Instance_Proxy::OnMsgBindGraphics(PP_Instance instance,
+                                           PP_Resource device,
+                                           bool* result) {
+  *result = ppb_instance_target()->BindGraphics(instance, device);
+}
+
+void PPB_Instance_Proxy::OnMsgIsFullFrame(PP_Instance instance, bool* result) {
+  *result = ppb_instance_target()->IsFullFrame(instance);
+}
+
+void PPB_Instance_Proxy::OnMsgExecuteScript(
+    PP_Instance instance,
+    SerializedVarReceiveInput script,
+    SerializedVarOutParam out_exception,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(), ppb_instance_target()->ExecuteScript(
+      instance,
+      script.Get(dispatcher()),
+      out_exception.OutParam(dispatcher())));
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..64b2b2d4e2430d68d6d0d0a965467d2f16601919
--- /dev/null
+++ b/ppapi/proxy/ppb_instance_proxy.h
@@ -0,0 +1,55 @@
+// 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_PPB_INSTANCE_PROXY_H_
+#define PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Instance;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Instance_Proxy : public InterfaceProxy {
+ public:
+  PPB_Instance_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPB_Instance_Proxy();
+
+  const PPB_Instance* ppb_instance_target() const {
+    return reinterpret_cast<const PPB_Instance*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgGetWindowObject(PP_Instance instance,
+                            SerializedVarReturnValue result);
+  void OnMsgGetOwnerElementObject(PP_Instance instance,
+                                  SerializedVarReturnValue result);
+  void OnMsgBindGraphics(PP_Instance instance,
+                         PP_Resource device,
+                         bool* result);
+  void OnMsgIsFullFrame(PP_Instance instance, bool* result);
+  void OnMsgExecuteScript(PP_Instance instance,
+                          SerializedVarReceiveInput script,
+                          SerializedVarOutParam out_exception,
+                          SerializedVarReturnValue result);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
diff --git a/ppapi/proxy/ppb_url_loader_proxy.cc b/ppapi/proxy/ppb_url_loader_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0ff46e487ce5d0b6eed4b8b9ea7db653adc5257d
--- /dev/null
+++ b/ppapi/proxy/ppb_url_loader_proxy.cc
@@ -0,0 +1,301 @@
+// 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/ppb_url_loader_proxy.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/dev/ppb_url_loader_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+#if defined(OS_LINUX)
+#include <sys/shm.h>
+#endif
+
+namespace pp {
+namespace proxy {
+
+class URLLoader : public PluginResource {
+ public:
+  URLLoader();
+  virtual ~URLLoader();
+
+  // Resource overrides.
+  virtual URLLoader* AsURLLoader() { return this; }
+
+  int64_t bytes_sent_;
+  int64_t total_bytes_to_be_sent_;
+  int64_t bytes_received_;
+  int64_t total_bytes_to_be_received_;
+
+ private:
+
+  DISALLOW_COPY_AND_ASSIGN(URLLoader);
+};
+
+URLLoader::URLLoader()
+    : bytes_sent_(0),
+      total_bytes_to_be_sent_(0),
+      bytes_received_(0),
+      total_bytes_to_be_received_(0) {
+}
+
+URLLoader::~URLLoader() {
+}
+
+namespace {
+
+PP_Resource Create(PP_Instance instance_id) {
+  PluginDispatcher* dispatcher = PluginDispatcher::Get();
+  PP_Resource result = 0;
+  dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Create(
+      INTERFACE_ID_PPB_URL_LOADER, instance_id, &result));
+  if (result) {
+    linked_ptr<URLLoader> object(new URLLoader);
+    dispatcher->plugin_resource_tracker()->AddResource(result, object);
+  }
+  return result;
+}
+
+bool IsURLLoader(PP_Resource resource) {
+  URLLoader* object = PluginResource::GetAs<URLLoader>(resource);
+  return !!object;
+}
+
+int32_t Open(PP_Resource loader_id,
+             PP_Resource request_id,
+             PP_CompletionCallback callback) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Open(
+      INTERFACE_ID_PPB_URL_LOADER, loader_id, request_id,
+      dispatcher->callback_tracker().SendCallback(callback)));
+  return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t FollowRedirect(PP_Resource loader_id,
+                       PP_CompletionCallback callback) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect(
+      INTERFACE_ID_PPB_URL_LOADER, loader_id,
+      dispatcher->callback_tracker().SendCallback(callback)));
+  return PP_ERROR_WOULDBLOCK;
+}
+
+bool GetUploadProgress(PP_Resource loader_id,
+                       int64_t* bytes_sent,
+                       int64_t* total_bytes_to_be_sent) {
+  // TODO(brettw) implement this as a non-blocking call where we get notified
+  // of updates and just send the local copy.
+  bool result = false;
+  PluginDispatcher::Get()->Send(
+      new PpapiHostMsg_PPBURLLoader_GetUploadProgress(
+          INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_sent,
+          total_bytes_to_be_sent, &result));
+  return result;
+}
+
+bool GetDownloadProgress(PP_Resource loader_id,
+                         int64_t* bytes_received,
+                         int64_t* total_bytes_to_be_received) {
+  // TODO(brettw) implement this as a non-blocking call where we get notified
+  // of updates and just send the local copy.
+  bool result = false;
+  PluginDispatcher::Get()->Send(
+      new PpapiHostMsg_PPBURLLoader_GetDownloadProgress(
+        INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_received,
+        total_bytes_to_be_received, &result));
+  return result;
+}
+
+PP_Resource GetResponseInfo(PP_Resource loader_id) {
+  // TODO(brettw) this needs to have proper refcounting handling for the
+  // result!
+  /*
+  PP_Resource result;
+  Dispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo(
+      INTERFACE_ID_PPB_URL_LOADER, loader_id, &result));
+  */
+  return 0;
+}
+
+int32_t ReadResponseBody(PP_Resource loader_id,
+                         char* buffer,
+                         int32_t bytes_to_read,
+                         PP_CompletionCallback callback) {
+                         /* TODO
+  Dispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
+      INTERFACE_ID_PPB_URL_LOADER, loader_id, ));
+      */
+  return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t FinishStreamingToFile(PP_Resource loader_id,
+                              PP_CompletionCallback callback) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile(
+      INTERFACE_ID_PPB_URL_LOADER, loader_id,
+      dispatcher->callback_tracker().SendCallback(callback)));
+  return PP_ERROR_WOULDBLOCK;
+}
+
+void Close(PP_Resource loader_id) {
+  PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_Close(
+      INTERFACE_ID_PPB_URL_LOADER, loader_id));
+}
+
+const PPB_URLLoader_Dev ppb_urlloader = {
+  &Create,
+  &IsURLLoader,
+  &Open,
+  &FollowRedirect,
+  &GetUploadProgress,
+  &GetDownloadProgress,
+  &GetResponseInfo,
+  &ReadResponseBody,
+  &FinishStreamingToFile,
+  &Close
+};
+
+}  // namespace
+
+PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher,
+                                         const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() {
+}
+
+const void* PPB_URLLoader_Proxy::GetSourceInterface() const {
+  return &ppb_urlloader;
+}
+
+InterfaceID PPB_URLLoader_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_URL_LOADER;
+}
+
+void PPB_URLLoader_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_URLLoader_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Create,
+                        OnMsgCreate)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Open,
+                        OnMsgOpen)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FollowRedirect,
+                        OnMsgFollowRedirect)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetUploadProgress,
+                        OnMsgGetUploadProgress)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetDownloadProgress,
+                        OnMsgGetDownloadProgress)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetResponseInfo,
+                        OnMsgGetResponseInfo)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_ReadResponseBody,
+                        OnMsgReadResponseBody)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile,
+                        OnMsgFinishStreamingToFile)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Close,
+                        OnMsgClose)
+
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_UpdateProgress,
+                        OnMsgUpdateProgress)
+  IPC_END_MESSAGE_MAP()
+  // TODO(brettw) handle bad messages!
+}
+
+void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance,
+                                      PP_Resource* result) {
+  *result = ppb_url_loader_target()->Create(instance);
+}
+
+void PPB_URLLoader_Proxy::OnMsgOpen(PP_Resource loader,
+                                    PP_Resource request_info,
+                                    uint32_t serialized_callback) {
+  // TODO(brettw): need to notify in case the result is not "would block".
+  ppb_url_loader_target()->Open(loader, request_info,
+                                ReceiveCallback(serialized_callback));
+}
+
+void PPB_URLLoader_Proxy::OnMsgFollowRedirect(
+    PP_Resource loader,
+    uint32_t serialized_callback) {
+  // TODO(brettw): need to notify in case the result is not "would block".
+  ppb_url_loader_target()->FollowRedirect(loader,
+                                          ReceiveCallback(serialized_callback));
+}
+
+void PPB_URLLoader_Proxy::OnMsgGetUploadProgress(
+    PP_Resource loader,
+    int64* bytes_sent,
+    int64* total_bytes_to_be_sent,
+    bool* result) {
+  *result = ppb_url_loader_target()->GetUploadProgress(
+      loader, bytes_sent, total_bytes_to_be_sent);
+}
+
+void PPB_URLLoader_Proxy::OnMsgGetDownloadProgress(
+    PP_Resource loader,
+    int64* bytes_received,
+    int64* total_bytes_to_be_received,
+    bool* result) {
+  *result = ppb_url_loader_target()->GetDownloadProgress(
+      loader, bytes_received, total_bytes_to_be_received);
+}
+
+void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(PP_Resource loader,
+                                               PP_Resource* result) {
+  /* TODO(brettw) this will depend on the plugin-side FIXME above.
+  *result = ppb_url_loader_target()->GetResponseInfo(loader);
+  */
+}
+
+void PPB_URLLoader_Proxy::OnMsgReadResponseBody(
+    PP_Resource loader,
+    int32_t bytes_to_read,
+    uint32_t serialized_callback) {
+  // TODO(brettw): need to notify in case the result is not "would block".
+  /* TODO(brettw) figure out how to share data.
+  ppb_url_loader_target()->ReadRseponseBody(loader, bytes_to_read,
+      ReceiveCallback(serialized_callback));
+  */
+}
+
+void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile(
+    PP_Resource loader,
+    uint32_t serialized_callback) {
+  // TODO(brettw): need to notify in case the result is not "would block".
+  ppb_url_loader_target()->FinishStreamingToFile(loader,
+      ReceiveCallback(serialized_callback));
+}
+
+void PPB_URLLoader_Proxy::OnMsgClose(PP_Resource loader) {
+  ppb_url_loader_target()->Close(loader);
+}
+
+// TODO(brettw) nobody calls this function. We should have some way to register
+// for these updates so when WebKit tells the pepper url loader code that
+// something changed, we'll get a callback.
+void PPB_URLLoader_Proxy::OnMsgUpdateProgress(
+    PP_Resource resource,
+    int64_t bytes_sent,
+    int64_t total_bytes_to_be_sent,
+    int64_t bytes_received,
+    int64_t total_bytes_to_be_received) {
+  URLLoader* object = PluginResource::GetAs<URLLoader>(resource);
+  if (!object)
+    return;
+
+  object->bytes_sent_ = bytes_sent;
+  object->total_bytes_to_be_sent_ = total_bytes_to_be_sent;
+  object->bytes_received_ = bytes_received;
+  object->total_bytes_to_be_received_ = total_bytes_to_be_received;
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..6978f888d38a6977133780c33c9a7ce086087f60
--- /dev/null
+++ b/ppapi/proxy/ppb_url_loader_proxy.h
@@ -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.
+
+#ifndef PPAPI_PPB_URL_LOADER_PROXY_H_
+#define PPAPI_PPB_URL_LOADER_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_URLLoader_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_URLLoader_Proxy : public InterfaceProxy {
+ public:
+  PPB_URLLoader_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPB_URLLoader_Proxy();
+
+  const PPB_URLLoader_Dev* ppb_url_loader_target() const {
+    return reinterpret_cast<const PPB_URLLoader_Dev*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Plugin->renderer message handlers.
+  void OnMsgCreate(PP_Instance instance,
+                   PP_Resource* result);
+  void OnMsgOpen(PP_Resource loader,
+                 PP_Resource request_info,
+                 uint32_t serialized_callback);
+  void OnMsgFollowRedirect(PP_Resource loader,
+                           uint32_t serialized_callback);
+  void OnMsgGetUploadProgress(PP_Resource loader,
+                              int64* bytes_sent,
+                              int64* total_bytes_to_be_sent,
+                              bool* result);
+  void OnMsgGetDownloadProgress(PP_Resource loader,
+                                int64* bytes_received,
+                                int64* total_bytes_to_be_received,
+                                bool* result);
+  void OnMsgGetResponseInfo(PP_Resource loader,
+                            PP_Resource* result);
+  void OnMsgReadResponseBody(PP_Resource loader,
+                             int32_t bytes_to_read,
+                             uint32_t serialized_callback);
+  void OnMsgFinishStreamingToFile(PP_Resource loader,
+                                  uint32_t serialized_callback);
+  void OnMsgClose(PP_Resource loader);
+
+  // Renderer->plugin message handlers.
+  void OnMsgUpdateProgress(PP_Resource resource,
+                           int64_t bytes_sent,
+                           int64_t total_bytes_to_be_sent,
+                           int64_t bytes_received,
+                           int64_t total_bytes_to_be_received);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PPB_URL_LOADER_PROXY_H_
diff --git a/ppapi/proxy/ppb_var_deprecated_proxy.cc b/ppapi/proxy/ppb_var_deprecated_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e8ba7308af875c5c3b3a447f1171aea4279a6149
--- /dev/null
+++ b/ppapi/proxy/ppb_var_deprecated_proxy.cc
@@ -0,0 +1,376 @@
+// 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/ppb_var_deprecated_proxy.h"
+
+#include <stdlib.h>  // For malloc
+
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_message_helpers.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// PPP_Var_Deprecated plugin ---------------------------------------------------
+
+void AddRefVar(PP_Var var) {
+  PluginDispatcher::Get()->plugin_var_tracker()->AddRef(var);
+}
+
+void ReleaseVar(PP_Var var) {
+  PluginDispatcher::Get()->plugin_var_tracker()->Release(var);
+}
+
+PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) {
+  PP_Var ret;
+  ret.type = PP_VARTYPE_STRING;
+  // TODO(brettw) avoid this extra copy.
+  ret.value.as_id = PluginDispatcher::Get()->plugin_var_tracker()->MakeString(
+      std::string(data, len));
+  return ret;
+}
+
+const char* VarToUtf8(PP_Var var, uint32_t* len) {
+  const std::string* str =
+      PluginDispatcher::Get()->plugin_var_tracker()->GetExistingString(var);
+  if (str) {
+    *len = static_cast<uint32_t>(str->size());
+    return str->c_str();
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+bool HasProperty(PP_Var var,
+                 PP_Var name,
+                 PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_HasProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result;
+}
+
+bool HasMethod(PP_Var var,
+               PP_Var name,
+               PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_HasMethodDeprecated(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result;
+}
+
+PP_Var GetProperty(PP_Var var,
+                   PP_Var name,
+                   PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  ReceiveSerializedVarReturnValue result;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_GetProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result.Return(dispatcher);
+}
+
+void EnumerateProperties(PP_Var var,
+                         uint32_t* property_count,
+                         PP_Var** properties,
+                         PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+
+  ReceiveSerializedVarVectorOutParam out_vector(dispatcher,
+                                                property_count, properties);
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_EnumerateProperties(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        out_vector.OutParam(), &se));
+  }
+}
+
+void SetProperty(PP_Var var,
+                 PP_Var name,
+                 PP_Var value,
+                 PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name),
+        SerializedVarSendInput(dispatcher, value), &se));
+  }
+}
+
+void RemoveProperty(PP_Var var,
+                    PP_Var name,
+                    PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+}
+
+PP_Var Call(PP_Var object,
+            PP_Var method_name,
+            uint32_t argc,
+            PP_Var* argv,
+            PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedVarReturnValue result;
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    std::vector<SerializedVar> argv_vect;
+    SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+    dispatcher->Send(new PpapiHostMsg_PPBVar_CallDeprecated(
+        INTERFACE_ID_PPB_VAR_DEPRECATED,
+        SerializedVarSendInput(dispatcher, object),
+        SerializedVarSendInput(dispatcher, method_name), argv_vect,
+        &se, &result));
+  }
+  return result.Return(dispatcher);
+}
+
+PP_Var Construct(PP_Var object,
+                 uint32_t argc,
+                 PP_Var* argv,
+                 PP_Var* exception) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedVarReturnValue result;
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    std::vector<SerializedVar> argv_vect;
+    SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+    dispatcher->Send(new PpapiHostMsg_PPBVar_Construct(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, object),
+        argv_vect, &se, &result));
+  }
+  return result.Return(dispatcher);
+}
+
+bool IsInstanceOf(PP_Var var,
+                  const PPP_Class_Deprecated* ppp_class,
+                  void** ppp_class_data) {
+  bool result = false;
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
+  int64 class_data_int = 0;
+  dispatcher->Send(new PpapiHostMsg_PPBVar_IsInstanceOfDeprecated(
+      INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+      class_int, &class_data_int, &result));
+  *ppp_class_data =
+      reinterpret_cast<void*>(static_cast<intptr_t>(class_data_int));
+  return result;
+}
+
+PP_Var CreateObject(PP_Module module_id,
+                    const PPP_Class_Deprecated* ppp_class,
+                    void* ppp_class_data) {
+  Dispatcher* dispatcher = PluginDispatcher::Get();
+  ReceiveSerializedVarReturnValue result;
+  int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
+  int64 data_int =
+      static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class_data));
+  dispatcher->Send(new PpapiHostMsg_PPBVar_CreateObjectDeprecated(
+      INTERFACE_ID_PPB_VAR_DEPRECATED, module_id, class_int, data_int, &result));
+  return result.Return(dispatcher);
+}
+
+const PPB_Var_Deprecated var_deprecated_interface = {
+  &AddRefVar,
+  &ReleaseVar,
+  &VarFromUtf8,
+  &VarToUtf8,
+  &HasProperty,
+  &HasMethod,
+  &GetProperty,
+  &EnumerateProperties,
+  &SetProperty,
+  &RemoveProperty,
+  &Call,
+  &Construct,
+  &IsInstanceOf,
+  &CreateObject
+};
+
+}  // namespace
+
+PPB_Var_Deprecated_Proxy::PPB_Var_Deprecated_Proxy(Dispatcher* dispatcher,
+                                                  const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Var_Deprecated_Proxy::~PPB_Var_Deprecated_Proxy() {
+}
+
+const void* PPB_Var_Deprecated_Proxy::GetSourceInterface() const {
+  return &var_deprecated_interface;
+}
+
+InterfaceID PPB_Var_Deprecated_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_VAR_DEPRECATED;
+}
+
+void PPB_Var_Deprecated_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_Var_Deprecated_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasProperty,
+                        OnMsgHasProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+                        OnMsgHasMethodDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_GetProperty,
+                        OnMsgGetProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DeleteProperty,
+                        OnMsgDeleteProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_EnumerateProperties,
+                        OnMsgEnumerateProperties)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+                        OnMsgSetPropertyDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CallDeprecated,
+                        OnMsgCallDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Construct,
+                        OnMsgConstruct)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+                        OnMsgIsInstanceOfDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
+                        OnMsgCreateObjectDeprecated)
+  IPC_END_MESSAGE_MAP()
+  // FIXME(brettw) handle bad messages!
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgHasProperty(
+    SerializedVarReceiveInput var,
+    SerializedVarReceiveInput name,
+    SerializedVarOutParam exception,
+    bool* result) {
+  *result = ppb_var_target()->HasProperty(var.Get(dispatcher()),
+                                          name.Get(dispatcher()),
+                                          exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgHasMethodDeprecated(
+    SerializedVarReceiveInput var,
+    SerializedVarReceiveInput name,
+    SerializedVarOutParam exception,
+    bool* result) {
+  *result = ppb_var_target()->HasMethod(var.Get(dispatcher()),
+                                        name.Get(dispatcher()),
+                                        exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgGetProperty(
+    SerializedVarReceiveInput var,
+    SerializedVarReceiveInput name,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(), ppb_var_target()->GetProperty(
+      var.Get(dispatcher()), name.Get(dispatcher()),
+      exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgEnumerateProperties(
+    SerializedVarReceiveInput var,
+    SerializedVarVectorOutParam props,
+    SerializedVarOutParam exception) {
+  ppb_var_target()->GetAllPropertyNames(var.Get(dispatcher()),
+      props.CountOutParam(), props.ArrayOutParam(dispatcher()),
+      exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgSetPropertyDeprecated(
+    SerializedVarReceiveInput var,
+    SerializedVarReceiveInput name,
+    SerializedVarReceiveInput value,
+    SerializedVarOutParam exception) {
+  ppb_var_target()->SetProperty(var.Get(dispatcher()),
+                                name.Get(dispatcher()),
+                                value.Get(dispatcher()),
+                                exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgDeleteProperty(
+    SerializedVarReceiveInput var,
+    SerializedVarReceiveInput name,
+    SerializedVarOutParam exception,
+    bool* result) {
+  ppb_var_target()->RemoveProperty(var.Get(dispatcher()),
+                                   name.Get(dispatcher()),
+                                   exception.OutParam(dispatcher()));
+  // This deprecated function doesn't actually return a value, but we re-use
+  // the message from the non-deprecated interface with the return value.
+  *result = true;
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgCallDeprecated(
+    SerializedVarReceiveInput object,
+    SerializedVarReceiveInput method_name,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  uint32_t arg_count = 0;
+  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+  result.Return(dispatcher(), ppb_var_target()->Call(
+      object.Get(dispatcher()),
+      method_name.Get(dispatcher()),
+      arg_count, args,
+      exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgConstruct(
+    SerializedVarReceiveInput var,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  uint32_t arg_count = 0;
+  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+  result.Return(dispatcher(), ppb_var_target()->Construct(
+      var.Get(dispatcher()), arg_count, args,
+      exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgIsInstanceOfDeprecated(
+    pp::proxy::SerializedVarReceiveInput var,
+    int64 ppp_class,
+    int64* ppp_class_data,
+    bool* result) {
+  // TODO(brettw) write this.
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgCreateObjectDeprecated(
+    PP_Module module_id,
+    int64 ppp_class,
+    int64 class_data,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(), PPP_Class_Proxy::CreateProxiedObject(
+      ppb_var_target(), dispatcher(), module_id, ppp_class, class_data));
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_var_deprecated_proxy.h b/ppapi/proxy/ppb_var_deprecated_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fe123a0fb89001d0721ecc066105255c1b2d10f
--- /dev/null
+++ b/ppapi/proxy/ppb_var_deprecated_proxy.h
@@ -0,0 +1,95 @@
+// 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_PPB_VAR_PROXY_H_
+#define PPAPI_PPB_VAR_PROXY_H_
+
+#include <vector>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVar;
+class SerializedVarReceiveInput;
+class SerializedVarVectorOutParam;
+class SerializedVarVectorReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Var_Deprecated_Proxy : public InterfaceProxy {
+ public:
+  PPB_Var_Deprecated_Proxy(Dispatcher* dispatcher,
+                           const void* target_interface);
+  virtual ~PPB_Var_Deprecated_Proxy();
+
+  const PPB_Var_Deprecated* ppb_var_target() const {
+    return reinterpret_cast<const PPB_Var_Deprecated*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgHasProperty(SerializedVarReceiveInput var,
+                        SerializedVarReceiveInput name,
+                        SerializedVarOutParam exception,
+                        bool* result);
+  void OnMsgHasMethodDeprecated(SerializedVarReceiveInput var,
+                                SerializedVarReceiveInput name,
+                                SerializedVarOutParam exception,
+                                bool* result);
+  void OnMsgGetProperty(SerializedVarReceiveInput var,
+                        SerializedVarReceiveInput name,
+                        SerializedVarOutParam exception,
+                        SerializedVarReturnValue result);
+  void OnMsgEnumerateProperties(
+      SerializedVarReceiveInput var,
+      SerializedVarVectorOutParam props,
+      SerializedVarOutParam exception);
+  void OnMsgSetPropertyDeprecated(SerializedVarReceiveInput var,
+                                  SerializedVarReceiveInput name,
+                                  SerializedVarReceiveInput value,
+                                  SerializedVarOutParam exception);
+  void OnMsgDeleteProperty(SerializedVarReceiveInput var,
+                           SerializedVarReceiveInput name,
+                           SerializedVarOutParam exception,
+                           bool* result);
+  void OnMsgCall(SerializedVarReceiveInput object,
+                 SerializedVarReceiveInput this_object,
+                 SerializedVarReceiveInput method_name,
+                 SerializedVarVectorReceiveInput arg_vector,
+                 SerializedVarOutParam exception,
+                 SerializedVarReturnValue result);
+  void OnMsgCallDeprecated(SerializedVarReceiveInput object,
+                           SerializedVarReceiveInput method_name,
+                           SerializedVarVectorReceiveInput arg_vector,
+                           SerializedVarOutParam exception,
+                           SerializedVarReturnValue result);
+  void OnMsgConstruct(SerializedVarReceiveInput var,
+                      SerializedVarVectorReceiveInput arg_vector,
+                      SerializedVarOutParam exception,
+                      SerializedVarReturnValue result);
+  void OnMsgIsInstanceOfDeprecated(pp::proxy::SerializedVarReceiveInput var,
+                                   int64 ppp_class,
+                                   int64* ppp_class_data,
+                                   bool* result);
+  void OnMsgCreateObjectDeprecated(PP_Module module_id,
+                                   int64 ppp_class,
+                                   int64 ppp_class_data,
+                                   SerializedVarReturnValue result);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PPB_VAR_PROXY_H_
diff --git a/ppapi/proxy/ppb_var_proxy.cc b/ppapi/proxy/ppb_var_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..117eb6fddcf4b0685416b999f56ae08b1585206f
--- /dev/null
+++ b/ppapi/proxy/ppb_var_proxy.cc
@@ -0,0 +1,478 @@
+// 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/ppb_var_proxy.h"
+
+#include <stdlib.h>  // For malloc
+
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/ppapi_message_helpers.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+void AddRefVar(PP_Var var) {
+  Dispatcher::Get()->plugin_var_tracker()->AddRef(var);
+}
+
+void ReleaseVar(PP_Var var) {
+  Dispatcher::Get()->plugin_var_tracker()->Release(var);
+}
+
+PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) {
+  PP_Var ret;
+  ret.type = PP_VARTYPE_STRING;
+  // TODO(brettw) avoid this extra copy.
+  ret.value.as_id = Dispatcher::Get()->plugin_var_tracker()->MakeString(
+      std::string(data, len));
+  return ret;
+}
+
+const char* VarToUtf8(PP_Var var, uint32_t* len) {
+  const std::string* str =
+      Dispatcher::Get()->plugin_var_tracker()->GetExistingString(var);
+  if (str) {
+    *len = static_cast<uint32_t>(str->size());
+    return str->c_str();
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+PP_Var ConvertType(PP_Instance instance,
+                   PP_Var var,
+                   PP_VarType new_type,
+                   PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  ReceiveSerializedVarReturnValue result(dispatcher);
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_ConvertType(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, instance,
+        SerializedVarSendInput(dispatcher, var),
+        static_cast<int>(new_type), &se, &result));
+  }
+  return result.Return();
+}
+
+bool HasProperty(PP_Var var,
+                 PP_Var name,
+                 PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_HasProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result;
+}
+
+bool HasMethodDeprecated(PP_Var var,
+                         PP_Var name,
+                         PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_HasMethodDeprecated(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result;
+}
+
+PP_Var GetProperty(PP_Var var,
+                   PP_Var name,
+                   PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  ReceiveSerializedVarReturnValue result(dispatcher);
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_GetProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result.Return();
+}
+
+void EnumerateProperties(PP_Var var,
+                         uint32_t* property_count,
+                         PP_Var** properties,
+                         PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+
+  std::vector<SerializedVar> props;
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_EnumerateProperties(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        &props, &se));
+  }
+
+  // TODO(brettw) factor this out so it can be used by ScriptableObject.
+  /*
+  *property_count = static_cast<uint32_t>(props.size());
+  if (property_count) {
+    *properties = static_cast<PP_Var*>(
+        malloc(*property_count * sizeof(PP_Var*)));
+    for (size_t i = 0; i < props.size(); i++) {
+      ReceiveSerializedVarReturnValue converted(dispatcher);
+      SerializedVar* converted_sv = &convered;
+
+      *static_cast<SerializedVar*>(&converted) = props[i];
+      (*properties)[i] = converted.Return();
+    }
+  } else {
+    *properties = NULL;
+  }
+  */
+}
+
+void SetPropertyDeprecated(PP_Var var,
+                           PP_Var name,
+                           PP_Var value,
+                           PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name),
+        SerializedVarSendInput(dispatcher, value), &se));
+  }
+}
+
+bool DeleteProperty(PP_Var var,
+                    PP_Var name,
+                    PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+  return result;
+}
+
+void RemovePropertyDeprecated(PP_Var var,
+                              PP_Var name,
+                              PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedException se(dispatcher, exception);
+  bool result = false;
+  if (!se.IsThrown()) {
+    dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+        SerializedVarSendInput(dispatcher, name), &se, &result));
+  }
+}
+
+
+PP_Var Call(PP_Var object,
+            PP_Var this_object,
+            PP_Var method_name,
+            uint32_t argc,
+            PP_Var* argv,
+            PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedVarReturnValue result(dispatcher);
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    std::vector<SerializedVar> argv_vect;
+    SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+    dispatcher->Send(new PpapiHostMsg_PPBVar_Call(
+        INTERFACE_ID_PPB_VAR_DEPRECATED,
+        SerializedVarSendInput(dispatcher, object),
+        SerializedVarSendInput(dispatcher, this_object),
+        SerializedVarSendInput(dispatcher, method_name), argv_vect,
+        &se, &result));
+  }
+  return result.Return();
+}
+
+PP_Var CallDeprecated(PP_Var object,
+                      PP_Var method_name,
+                      uint32_t argc,
+                      PP_Var* argv,
+                      PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedVarReturnValue result(dispatcher);
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    std::vector<SerializedVar> argv_vect;
+    SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+    dispatcher->Send(new PpapiHostMsg_PPBVar_CallDeprecated(
+        INTERFACE_ID_PPB_VAR_DEPRECATED,
+        SerializedVarSendInput(dispatcher, object),
+        SerializedVarSendInput(dispatcher, method_name), argv_vect,
+        &se, &result));
+  }
+  return result.Return();
+}
+
+PP_Var Construct(PP_Var object,
+                 uint32_t argc,
+                 PP_Var* argv,
+                 PP_Var* exception) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedVarReturnValue result(dispatcher);
+  ReceiveSerializedException se(dispatcher, exception);
+  if (!se.IsThrown()) {
+    std::vector<SerializedVar> argv_vect;
+    SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+    dispatcher->Send(new PpapiHostMsg_PPBVar_Construct(
+        INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, object),
+        argv_vect, &se, &result));
+  }
+  return result.Return();
+}
+
+bool IsInstanceOfDeprecated(PP_Var var,
+                            const PPP_Class_Deprecated* ppp_class,
+                            void** ppp_class_data) {
+  bool result = false;
+  Dispatcher* dispatcher = Dispatcher::Get();
+  int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
+  int64 class_data_int = 0;
+  dispatcher->Send(new PpapiHostMsg_PPBVar_IsInstanceOfDeprecated(
+      INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+      class_int, &class_data_int, &result));
+  *ppp_class_data =
+      reinterpret_cast<void*>(static_cast<intptr_t>(class_data_int));
+  return result;
+}
+
+PP_Var CreateObjectDeprecated(PP_Module module_id,
+                              const PPP_Class_Deprecated* ppp_class,
+                              void* ppp_class_data) {
+  Dispatcher* dispatcher = Dispatcher::Get();
+  ReceiveSerializedVarReturnValue result(dispatcher);
+  int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
+  int64 data_int =
+      static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class_data));
+  dispatcher->Send(new PpapiHostMsg_PPBVar_CreateObjectDeprecated(
+      INTERFACE_ID_PPB_VAR_DEPRECATED, module_id, class_int, data_int, &result));
+  return result.Return();
+}
+
+const PPB_Var var_interface = {
+  &AddRefVar,
+  &ReleaseVar,
+  &VarFromUtf8,
+  &VarToUtf8,
+  &ConvertType,
+};
+
+
+const PPB_Var_Deprecated var_deprecated_interface = {
+  &AddRefVar,
+  &ReleaseVar,
+  &VarFromUtf8,
+  &VarToUtf8,
+  &HasProperty,
+  &HasMethodDeprecated,
+  &GetProperty,
+  &EnumerateProperties,
+  &SetPropertyDeprecated,
+  &RemovePropertyDeprecated,
+  &CallDeprecated,
+  &Construct,
+  &IsInstanceOfDeprecated,
+  &CreateObjectDeprecated
+};
+
+}  // namespace
+
+PPB_Var_Proxy::PPB_Var_Proxy(Dispatcher* dispatcher,
+                               const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Var_Proxy::~PPB_Var_Proxy() {
+}
+
+const void* PPB_Var_Proxy::GetSourceInterface() const {
+  return &var_deprecated_interface;
+}
+
+InterfaceID PPB_Var_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPB_VAR_DEPRECATED;
+}
+
+void PPB_Var_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPB_Var_Proxy, msg)
+    // AddRef /Release here
+    //IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DefineProperty,
+    //                    OnMsgDefineProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_ConvertType,
+                        OnMsgConvertType)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasProperty,
+                        OnMsgHasProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+                        OnMsgHasMethodDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_GetProperty,
+                        OnMsgGetProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DeleteProperty,
+                        OnMsgDeleteProperty)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_EnumerateProperties,
+                        OnMsgEnumerateProperties)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+                        OnMsgSetPropertyDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsCallable,
+                        OnMsgIsCallable)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Call,
+                        OnMsgCall)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CallDeprecated,
+                        OnMsgCallDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Construct,
+                        OnMsgConstruct)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+                        OnMsgIsInstanceOfDeprecated)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
+                        OnMsgCreateObjectDeprecated)
+  IPC_END_MESSAGE_MAP()
+  // FIXME(brettw) handle bad messages!
+}
+
+void PPB_Var_Proxy::OnMsgConvertType(PP_Instance instance,
+                                     SerializedVarReceiveInput var,
+                                     int new_type,
+                                     SerializedVarOutParam exception,
+                                     SerializedVarReturnValue result) {
+  // FIXME(brettw) write this.
+}
+
+void PPB_Var_Proxy::OnMsgHasProperty(SerializedVarReceiveInput var,
+                                     SerializedVarReceiveInput name,
+                                     SerializedVarOutParam exception,
+                                     bool* result) {
+  *result = ppb_var_target()->HasProperty(var.Get(dispatcher()),
+                                          name.Get(dispatcher()),
+                                          exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Proxy::OnMsgHasMethodDeprecated(SerializedVarReceiveInput var,
+                                             SerializedVarReceiveInput name,
+                                             SerializedVarOutParam exception,
+                                             bool* result) {
+  *result = ppb_var_target()->HasMethod(var.Get(dispatcher()),
+                                        name.Get(dispatcher()),
+                                        exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Proxy::OnMsgGetProperty(SerializedVarReceiveInput var,
+                                     SerializedVarReceiveInput name,
+                                     SerializedVarOutParam exception,
+                                     SerializedVarReturnValue result) {
+  result.Return(dispatcher(), ppb_var_target()->GetProperty(
+      var.Get(dispatcher()), name.Get(dispatcher()),
+      exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Proxy::OnMsgEnumerateProperties(
+    SerializedVarReceiveInput var,
+    std::vector<pp::proxy::SerializedVar>* props,
+    SerializedVarOutParam exception) {
+  // FIXME(brettw) write this.
+}
+
+void PPB_Var_Proxy::OnMsgSetPropertyDeprecated(
+    SerializedVarReceiveInput var,
+    SerializedVarReceiveInput name,
+    SerializedVarReceiveInput value,
+    SerializedVarOutParam exception) {
+  ppb_var_target()->SetProperty(var.Get(dispatcher()),
+                                name.Get(dispatcher()),
+                                value.Get(dispatcher()),
+                                exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Proxy::OnMsgIsCallable(SerializedVarReceiveInput object,
+                                    bool* result) {
+  // FIXME(brettw) write this.
+}
+
+void PPB_Var_Proxy::OnMsgDeleteProperty(SerializedVarReceiveInput var,
+                                        SerializedVarReceiveInput name,
+                                        SerializedVarOutParam exception,
+                                        bool* result) {
+  // FIXME(brettw) write this.
+}
+
+void PPB_Var_Proxy::OnMsgCall(
+    SerializedVarReceiveInput object,
+    SerializedVarReceiveInput this_object,
+    SerializedVarReceiveInput method_name,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  // FIXME(brettw) write this.
+}
+
+void PPB_Var_Proxy::OnMsgCallDeprecated(
+    SerializedVarReceiveInput object,
+    SerializedVarReceiveInput method_name,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  uint32_t arg_count = 0;
+  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+  result.Return(dispatcher(), ppb_var_target()->Call(
+      object.Get(dispatcher()),
+      method_name.Get(dispatcher()),
+      arg_count, args,
+      exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Proxy::OnMsgConstruct(
+    SerializedVarReceiveInput var,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  uint32_t arg_count = 0;
+  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+  result.Return(dispatcher(), ppb_var_target()->Construct(
+      var.Get(dispatcher()), arg_count, args,
+      exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Proxy::OnMsgIsInstanceOfDeprecated(
+    pp::proxy::SerializedVarReceiveInput var,
+    int64 ppp_class,
+    int64* ppp_class_data,
+    bool* result) {
+  // TODO(brettw) write this.
+}
+
+void PPB_Var_Proxy::OnMsgCreateObjectDeprecated(
+    PP_Module module_id,
+    int64 ppp_class,
+    int64 ppp_class_data,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(), ppb_var_target()->CreateObject(
+      module_id,
+      reinterpret_cast<const PPP_Class_Deprecated*>(
+          static_cast<intptr_t>(ppp_class)),
+      reinterpret_cast<void*>(static_cast<intptr_t>(ppp_class_data))));
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppb_var_proxy.h b/ppapi/proxy/ppb_var_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d58a7625c1a25056a6b3b9236daa834a2c4ab05
--- /dev/null
+++ b/ppapi/proxy/ppb_var_proxy.h
@@ -0,0 +1,99 @@
+// 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_PPB_VAR_PROXY_H_
+#define PPAPI_PPB_VAR_PROXY_H_
+
+#include <vector>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVar;
+class SerializedVarReceiveInput;
+class SerializedVarVectorReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Var_Proxy : public InterfaceProxy {
+ public:
+  PPB_Var_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPB_Var_Proxy();
+
+  const PPB_Var_Deprecated* ppb_var_target() const {
+    return reinterpret_cast<const PPB_Var_Deprecated*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgConvertType(PP_Instance instance,
+                        SerializedVarReceiveInput var,
+                        int new_type,
+                        SerializedVarOutParam exception,
+                        SerializedVarReturnValue result);
+  void OnMsgHasProperty(SerializedVarReceiveInput var,
+                        SerializedVarReceiveInput name,
+                        SerializedVarOutParam exception,
+                        bool* result);
+  void OnMsgHasMethodDeprecated(SerializedVarReceiveInput var,
+                                SerializedVarReceiveInput name,
+                                SerializedVarOutParam exception,
+                                bool* result);
+  void OnMsgGetProperty(SerializedVarReceiveInput var,
+                        SerializedVarReceiveInput name,
+                        SerializedVarOutParam exception,
+                        SerializedVarReturnValue result);
+  void OnMsgEnumerateProperties(
+      SerializedVarReceiveInput var,
+      std::vector<pp::proxy::SerializedVar>* props,
+      SerializedVarOutParam exception);
+  void OnMsgSetPropertyDeprecated(SerializedVarReceiveInput var,
+                                  SerializedVarReceiveInput name,
+                                  SerializedVarReceiveInput value,
+                                  SerializedVarOutParam exception);
+  void OnMsgIsCallable(SerializedVarReceiveInput object, bool* result);
+  void OnMsgDeleteProperty(SerializedVarReceiveInput var,
+                           SerializedVarReceiveInput name,
+                           SerializedVarOutParam exception,
+                           bool* result);
+  void OnMsgCall(SerializedVarReceiveInput object,
+                 SerializedVarReceiveInput this_object,
+                 SerializedVarReceiveInput method_name,
+                 SerializedVarVectorReceiveInput arg_vector,
+                 SerializedVarOutParam exception,
+                 SerializedVarReturnValue result);
+  void OnMsgCallDeprecated(SerializedVarReceiveInput object,
+                           SerializedVarReceiveInput method_name,
+                           SerializedVarVectorReceiveInput arg_vector,
+                           SerializedVarOutParam exception,
+                           SerializedVarReturnValue result);
+  void OnMsgConstruct(SerializedVarReceiveInput var,
+                      SerializedVarVectorReceiveInput arg_vector,
+                      SerializedVarOutParam exception,
+                      SerializedVarReturnValue result);
+  void OnMsgIsInstanceOfDeprecated(pp::proxy::SerializedVarReceiveInput var,
+                                   int64 ppp_class,
+                                   int64* ppp_class_data,
+                                   bool* result);
+  void OnMsgCreateObjectDeprecated(PP_Module module_id,
+                                   int64 ppp_class,
+                                   int64 ppp_class_data,
+                                   SerializedVarReturnValue result);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PPB_VAR_PROXY_H_
diff --git a/ppapi/proxy/ppp_class_proxy.cc b/ppapi/proxy/ppp_class_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bc9a0bc6b76473f7a250b71ed7809fe7d0ce13b1
--- /dev/null
+++ b/ppapi/proxy/ppp_class_proxy.cc
@@ -0,0 +1,301 @@
+// 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/ppp_class_proxy.h"
+
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// PPP_Class in the browser implementation -------------------------------------
+
+// Represents a plugin-implemented class in the browser process. This just
+// stores the data necessary to call back the plugin.
+struct ObjectProxy {
+  ObjectProxy(Dispatcher* d, int64 p, int64 ud)
+      : dispatcher(d),
+        ppp_class(p),
+        user_data(ud) {
+  }
+
+  Dispatcher* dispatcher;
+  int64 ppp_class;
+  int64 user_data;
+};
+
+ObjectProxy* ToObjectProxy(void* data) {
+  return reinterpret_cast<ObjectProxy*>(data);
+}
+
+bool HasProperty(void* object, PP_Var name, PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+  bool result = false;
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+      SerializedVarSendInput(obj->dispatcher, name), &se, &result));
+  return result;
+}
+
+bool HasMethod(void* object, PP_Var name, PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+  bool result = false;
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+      SerializedVarSendInput(obj->dispatcher, name), &se, &result));
+  return result;
+}
+
+PP_Var GetProperty(void* object,
+                   PP_Var name,
+                   PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  ReceiveSerializedVarReturnValue result;
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+      SerializedVarSendInput(obj->dispatcher, name), &se, &result));
+  return result.Return(obj->dispatcher);
+}
+
+void GetAllPropertyNames(void* object,
+                         uint32_t* property_count,
+                         PP_Var** properties,
+                         PP_Var* exception) {
+  // FIXME
+}
+
+void SetProperty(void* object,
+                 PP_Var name,
+                 PP_Var value,
+                 PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+      SerializedVarSendInput(obj->dispatcher, name),
+      SerializedVarSendInput(obj->dispatcher, value), &se));
+}
+
+void RemoveProperty(void* object,
+                    PP_Var name,
+                    PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+      SerializedVarSendInput(obj->dispatcher, name), &se));
+}
+
+PP_Var Call(void* object,
+            PP_Var method_name,
+            uint32_t argc,
+            PP_Var* argv,
+            PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+
+  ReceiveSerializedVarReturnValue result;
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  std::vector<SerializedVar> argv_vect;
+  SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
+                                        &argv_vect);
+
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_Call(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+      SerializedVarSendInput(obj->dispatcher, method_name), argv_vect,
+      &se, &result));
+  return result.Return(obj->dispatcher);
+}
+
+PP_Var Construct(void* object,
+                 uint32_t argc,
+                 PP_Var* argv,
+                 PP_Var* exception) {
+  ObjectProxy* obj = ToObjectProxy(object);
+
+  ReceiveSerializedVarReturnValue result;
+  ReceiveSerializedException se(obj->dispatcher, exception);
+  std::vector<SerializedVar> argv_vect;
+  SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
+                                        &argv_vect);
+
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_Construct(
+      INTERFACE_ID_PPP_CLASS,
+      obj->ppp_class, obj->user_data, argv_vect, &se, &result));
+  return result.Return(obj->dispatcher);
+}
+
+void Deallocate(void* object) {
+  ObjectProxy* obj = ToObjectProxy(object);
+  obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate(
+      INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data));
+  delete obj;
+}
+
+const PPP_Class_Deprecated class_interface = {
+  &HasProperty,
+  &HasMethod,
+  &GetProperty,
+  &GetAllPropertyNames,
+  &SetProperty,
+  &RemoveProperty,
+  &Call,
+  &Construct,
+  &Deallocate
+};
+
+// Plugin helper functions -----------------------------------------------------
+
+// Converts an int64 object from IPC to a PPP_Class* for calling into the
+// plugin's implementation.
+const PPP_Class_Deprecated* ToPPPClass(int64 value) {
+  return reinterpret_cast<const PPP_Class_Deprecated*>(
+      static_cast<intptr_t>(value));
+}
+
+// Converts an int64 object from IPC to a void* for calling into the plugin's
+// implementation as the user data.
+void* ToUserData(int64 value) {
+  return reinterpret_cast<void*>(static_cast<intptr_t>(value));
+}
+
+}  // namespace
+
+// PPP_Class_Proxy -------------------------------------------------------------
+
+PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher)
+    : InterfaceProxy(dispatcher, NULL) {
+}
+
+PPP_Class_Proxy::~PPP_Class_Proxy() {
+}
+
+// static
+PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var,
+                                            Dispatcher* dispatcher,
+                                            PP_Module module_id,
+                                            int64 ppp_class,
+                                            int64 class_data) {
+  ObjectProxy* object_proxy = new ObjectProxy(dispatcher,
+                                              ppp_class, class_data);
+  return var->CreateObject(module_id, &class_interface, object_proxy);
+}
+
+const void* PPP_Class_Proxy::GetSourceInterface() const {
+  return &class_interface;
+}
+
+InterfaceID PPP_Class_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPP_CLASS;
+}
+
+void PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPP_Class_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasProperty,
+                        OnMsgHasProperty)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasMethod,
+                        OnMsgHasMethod)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_GetProperty,
+                        OnMsgGetProperty)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_EnumerateProperties,
+                        OnMsgEnumerateProperties)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_SetProperty,
+                        OnMsgSetProperty)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Call,
+                        OnMsgCall)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Construct,
+                        OnMsgConstruct)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Deallocate,
+                        OnMsgDeallocate)
+  IPC_END_MESSAGE_MAP()
+}
+
+void PPP_Class_Proxy::OnMsgHasProperty(int64 ppp_class, int64 object,
+                                       SerializedVarReceiveInput property,
+                                       SerializedVarOutParam exception,
+                                       bool* result) {
+  *result = ToPPPClass(ppp_class)->HasProperty(ToUserData(object),
+      property.Get(dispatcher()), exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgHasMethod(int64 ppp_class, int64 object,
+                                     SerializedVarReceiveInput property,
+                                     SerializedVarOutParam exception,
+                                     bool* result) {
+  *result = ToPPPClass(ppp_class)->HasMethod(ToUserData(object),
+      property.Get(dispatcher()), exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgGetProperty(int64 ppp_class, int64 object,
+                                       SerializedVarReceiveInput property,
+                                       SerializedVarOutParam exception,
+                                       SerializedVarReturnValue result) {
+  result.Return(dispatcher(), ToPPPClass(ppp_class)->GetProperty(
+      ToUserData(object), property.Get(dispatcher()),
+      exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgEnumerateProperties(
+    int64 ppp_class, int64 object,
+    std::vector<pp::proxy::SerializedVar>* props,
+    SerializedVarOutParam exception) {
+  // FIXME
+}
+
+void PPP_Class_Proxy::OnMsgSetProperty(int64 ppp_class, int64 object,
+                                       SerializedVarReceiveInput property,
+                                       SerializedVarReceiveInput value,
+                                       SerializedVarOutParam exception) {
+  ToPPPClass(ppp_class)->SetProperty(
+      ToUserData(object), property.Get(dispatcher()), value.Get(dispatcher()),
+      exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgRemoveProperty(int64 ppp_class, int64 object,
+                                          SerializedVarReceiveInput property,
+                                          SerializedVarOutParam exception) {
+  ToPPPClass(ppp_class)->RemoveProperty(
+      ToUserData(object), property.Get(dispatcher()),
+      exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgCall(
+    int64 ppp_class, int64 object,
+    SerializedVarReceiveInput method_name,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  uint32_t arg_count = 0;
+  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+  result.Return(dispatcher(), ToPPPClass(ppp_class)->Call(
+      ToUserData(object), method_name.Get(dispatcher()),
+      arg_count, args, exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgConstruct(
+    int64 ppp_class, int64 object,
+    SerializedVarVectorReceiveInput arg_vector,
+    SerializedVarOutParam exception,
+    SerializedVarReturnValue result) {
+  uint32_t arg_count = 0;
+  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+  result.Return(dispatcher(), ToPPPClass(ppp_class)->Construct(
+      ToUserData(object), arg_count, args, exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgDeallocate(int64 ppp_class, int64 object) {
+  ToPPPClass(ppp_class)->Deallocate(ToUserData(object));
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppp_class_proxy.h b/ppapi/proxy/ppp_class_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..b22d86a04d5ae4a85bdf693d52dc6c9fd813eead
--- /dev/null
+++ b/ppapi/proxy/ppp_class_proxy.h
@@ -0,0 +1,89 @@
+// 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_PPP_CLASS_PROXY_H_
+#define PPAPI_PROXY_PPP_CLASS_PROXY_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+struct PPP_Class_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVar;
+class SerializedVarReceiveInput;
+class SerializedVarVectorReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPP_Class_Proxy : public InterfaceProxy {
+ public:
+  // PPP_Class isn't a normal interface that you can query for, so this
+  // constructor doesn't take an interface pointer.
+  PPP_Class_Proxy(Dispatcher* dispatcher);
+  virtual ~PPP_Class_Proxy();
+
+  // Creates a proxied object in the browser process. This takes the browser's
+  // PPB_Var_Deprecated interface to use to create the object. The class and
+  static PP_Var CreateProxiedObject(const PPB_Var_Deprecated* var,
+                                    Dispatcher* dispatcher,
+                                    PP_Module module_id,
+                                    int64 ppp_class,
+                                    int64 class_data);
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // IPC message handlers.
+  void OnMsgHasProperty(int64 ppp_class, int64 object,
+                        SerializedVarReceiveInput property,
+                        SerializedVarOutParam exception,
+                        bool* result);
+  void OnMsgHasMethod(int64 ppp_class, int64 object,
+                      SerializedVarReceiveInput property,
+                      SerializedVarOutParam exception,
+                      bool* result);
+  void OnMsgGetProperty(int64 ppp_class, int64 object,
+                        SerializedVarReceiveInput property,
+                        SerializedVarOutParam exception,
+                        SerializedVarReturnValue result);
+  void OnMsgEnumerateProperties(
+      int64 ppp_class, int64 object,
+      std::vector<pp::proxy::SerializedVar>* props,
+      SerializedVarOutParam exception);
+  void OnMsgSetProperty(int64 ppp_class, int64 object,
+                        SerializedVarReceiveInput property,
+                        SerializedVarReceiveInput value,
+                        SerializedVarOutParam exception);
+  void OnMsgRemoveProperty(int64 ppp_class, int64 object,
+                           SerializedVarReceiveInput property,
+                           SerializedVarOutParam exception);
+  void OnMsgCall(int64 ppp_class, int64 object,
+                 SerializedVarReceiveInput method_name,
+                 SerializedVarVectorReceiveInput arg_vector,
+                 SerializedVarOutParam exception,
+                 SerializedVarReturnValue result);
+  void OnMsgConstruct(int64 ppp_class, int64 object,
+                      SerializedVarVectorReceiveInput arg_vector,
+                      SerializedVarOutParam exception,
+                      SerializedVarReturnValue result);
+  void OnMsgDeallocate(int64 ppp_class, int64 object);
+
+  DISALLOW_COPY_AND_ASSIGN(PPP_Class_Proxy);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PPP_CLASS_PROXY_H_
diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..770c5626076f20ca294b1625bec0bfd37be79083
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_proxy.cc
@@ -0,0 +1,198 @@
+// 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/ppp_instance_proxy.h"
+
+#include <algorithm>
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/ppapi_message_helpers.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+bool DidCreate(PP_Instance instance,
+               uint32_t argc,
+               const char* argn[],
+               const char* argv[]) {
+  std::vector<std::string> argn_vect;
+  std::vector<std::string> argv_vect;
+  for (uint32_t i = 0; i < argc; i++) {
+    argn_vect.push_back(std::string(argn[i]));
+    argv_vect.push_back(std::string(argv[i]));
+  }
+
+  bool result = false;
+  HostDispatcher::GetForInstance(instance)->Send(
+      new PpapiMsg_PPPInstance_DidCreate(INTERFACE_ID_PPP_INSTANCE, instance,
+                                         argn_vect, argv_vect, &result));
+  return result;
+}
+
+void DidDestroy(PP_Instance instance) {
+  HostDispatcher::GetForInstance(instance)->Send(
+      new PpapiMsg_PPPInstance_DidDestroy(INTERFACE_ID_PPP_INSTANCE, instance));
+}
+
+void DidChangeView(PP_Instance instance,
+                   const PP_Rect* position,
+                   const PP_Rect* clip) {
+  HostDispatcher::GetForInstance(instance)->Send(
+      new PpapiMsg_PPPInstance_DidChangeView(INTERFACE_ID_PPP_INSTANCE,
+                                             instance, *position, *clip));
+}
+
+void DidChangeFocus(PP_Instance instance, bool has_focus) {
+  HostDispatcher::GetForInstance(instance)->Send(
+      new PpapiMsg_PPPInstance_DidChangeFocus(INTERFACE_ID_PPP_INSTANCE,
+                                              instance, has_focus));
+}
+
+bool HandleInputEvent(PP_Instance instance,
+                      const PP_InputEvent* event) {
+  bool result = false;
+  HostDispatcher::GetForInstance(instance)->Send(
+      new PpapiMsg_PPPInstance_HandleInputEvent(INTERFACE_ID_PPP_INSTANCE,
+                                                instance, *event, &result));
+  return result;
+}
+
+bool HandleDocumentLoad(PP_Instance instance,
+                        PP_Resource url_loader) {
+  bool result = false;
+  HostDispatcher::GetForInstance(instance)->Send(
+      new PpapiMsg_PPPInstance_HandleDocumentLoad(INTERFACE_ID_PPP_INSTANCE,
+                                                  instance, url_loader,
+                                                  &result));
+  return result;
+}
+
+PP_Var GetInstanceObject(PP_Instance instance) {
+  Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+  ReceiveSerializedVarReturnValue result;
+  dispatcher->Send(new PpapiMsg_PPPInstance_GetInstanceObject(
+      instance, INTERFACE_ID_PPP_INSTANCE, &result));
+  return result.Return(dispatcher);
+}
+
+static const PPP_Instance instance_interface = {
+  &DidCreate,
+  &DidDestroy,
+  &DidChangeView,
+  &DidChangeFocus,
+  &HandleInputEvent,
+  &HandleDocumentLoad,
+  &GetInstanceObject
+};
+
+}  // namespace
+
+PPP_Instance_Proxy::PPP_Instance_Proxy(Dispatcher* dispatcher,
+                                       const void* target_interface)
+    : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPP_Instance_Proxy::~PPP_Instance_Proxy() {
+}
+
+const void* PPP_Instance_Proxy::GetSourceInterface() const {
+  return &instance_interface;
+}
+
+InterfaceID PPP_Instance_Proxy::GetInterfaceId() const {
+  return INTERFACE_ID_PPP_INSTANCE;
+}
+
+void PPP_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Proxy, msg)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate,
+                        OnMsgDidCreate)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy,
+                        OnMsgDidDestroy)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView,
+                        OnMsgDidChangeView)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus,
+                        OnMsgDidChangeFocus)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleInputEvent,
+                        OnMsgHandleInputEvent)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad,
+                        OnMsgHandleDocumentLoad)
+    IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_GetInstanceObject,
+                        OnMsgGetInstanceObject)
+  IPC_END_MESSAGE_MAP()
+}
+
+void PPP_Instance_Proxy::OnMsgDidCreate(
+    PP_Instance instance,
+    const std::vector<std::string>& argn,
+    const std::vector<std::string>& argv,
+    bool* result) {
+  *result = false;
+  if (argn.size() != argv.size())
+    return;
+
+  // Make sure the arrays always have at least one element so we can take the
+  // address below.
+  std::vector<const char*> argn_array;
+  std::vector<const char*> argv_array;
+  argn_array.resize(std::max(static_cast<size_t>(1), argn.size()));
+  argv_array.resize(std::max(static_cast<size_t>(1), argn.size()));
+  for (size_t i = 0; i < argn.size(); i++) {
+    argn_array[i] = argn[i].c_str();
+    argv_array[i] = argv[i].c_str();
+  }
+
+  DCHECK(ppp_instance_target());
+  *result = ppp_instance_target()->DidCreate(instance,
+                                             static_cast<uint32_t>(argn.size()),
+                                             &argn_array[0], &argv_array[0]);
+  DCHECK(*result);
+}
+
+void PPP_Instance_Proxy::OnMsgDidDestroy(PP_Instance instance) {
+  ppp_instance_target()->DidDestroy(instance);
+}
+
+void PPP_Instance_Proxy::OnMsgDidChangeView(PP_Instance instance,
+                                            const PP_Rect& position,
+                                            const PP_Rect& clip) {
+  ppp_instance_target()->DidChangeView(instance, &position, &clip);
+}
+
+void PPP_Instance_Proxy::OnMsgDidChangeFocus(PP_Instance instance,
+                                             bool has_focus) {
+  ppp_instance_target()->DidChangeFocus(instance, has_focus);
+}
+
+void PPP_Instance_Proxy::OnMsgHandleInputEvent(PP_Instance instance,
+                                               const PP_InputEvent& event,
+                                               bool* result) {
+  *result = ppp_instance_target()->HandleInputEvent(instance, &event);
+}
+
+void PPP_Instance_Proxy::OnMsgHandleDocumentLoad(PP_Instance instance,
+                                                 PP_Resource url_loader,
+                                                 bool* result) {
+  NOTREACHED();
+  /* TODO(brettw) write this. We need to convert the PP_Resource to a URL
+     loader proxy resource + object, but that currently isn't implemented.
+  *result = ppp_instance_target()->HandleDocumentLoad(
+      instance, url_loader DO SOMETHING WITH THIS);
+  */
+}
+
+void PPP_Instance_Proxy::OnMsgGetInstanceObject(
+    PP_Instance instance,
+    SerializedVarReturnValue result) {
+  result.Return(dispatcher(),
+                ppp_instance_target()->GetInstanceObject(instance));
+}
+
+}  // namespace proxy
+}  // namespace pp
diff --git a/ppapi/proxy/ppp_instance_proxy.h b/ppapi/proxy/ppp_instance_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fe40b9c969c7c81a058d8f2820d21d6d6ec2fc5
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_proxy.h
@@ -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.
+
+#ifndef PPAPI_PROXY_PPP_INSTANCE_PROXY_H_
+#define PPAPI_PROXY_PPP_INSTANCE_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PP_InputEvent;
+struct PP_Rect;
+struct PPP_Instance;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPP_Instance_Proxy : public InterfaceProxy {
+ public:
+  PPP_Instance_Proxy(Dispatcher* dispatcher, const void* target_interface);
+  virtual ~PPP_Instance_Proxy();
+
+  const PPP_Instance* ppp_instance_target() const {
+    return reinterpret_cast<const PPP_Instance*>(target_interface());
+  }
+
+  // InterfaceProxy implementation.
+  virtual const void* GetSourceInterface() const;
+  virtual InterfaceID GetInterfaceId() const;
+  virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+  // Message handlers.
+  void OnMsgDidCreate(PP_Instance instance,
+                      const std::vector<std::string>& argn,
+                      const std::vector<std::string>& argv,
+                      bool* result);
+  void OnMsgDidDestroy(PP_Instance instance);
+  void OnMsgDidChangeView(PP_Instance instance,
+                          const PP_Rect& position,
+                          const PP_Rect& clip);
+  void OnMsgDidChangeFocus(PP_Instance instance, bool has_focus);
+  void OnMsgHandleInputEvent(PP_Instance instance,
+                             const PP_InputEvent& event,
+                             bool* result);
+  void OnMsgHandleDocumentLoad(PP_Instance instance,
+                               PP_Resource url_loader,
+                               bool* result);
+  void OnMsgGetInstanceObject(PP_Instance instance,
+                              SerializedVarReturnValue result);
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_PPP_INSTANCE_PROXY_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
+
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d4230d228e3fb10af9be94e8f59f75ab3d7b300
--- /dev/null
+++ b/ppapi/proxy/serialized_var.h
@@ -0,0 +1,451 @@
+// 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_SERIALIZED_VAR_H_
+#define PPAPI_PROXY_SERIALIZED_VAR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/linked_ptr.h"
+#include "ppapi/c/pp_var.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+class VarSerializationRules;
+
+// This class encapsulates a var so that we can serialize and deserialize it
+// The problem is that for strings, serialization and deserialization requires
+// knowledge from outside about how to get at or create a string. So this
+// object groups the var with a dispatcher so that string values can be set or
+// gotten.
+//
+// Declare IPC messages as using this type, but don't use it directly (it has
+// no useful public methods). Instead, instantiate one of the helper classes
+// below which are conveniently named for each use case to prevent screwups.
+//
+// Design background
+// -----------------
+// This is sadly super complicated. The IPC must all use the same type and it
+// must include a var and a dispatcher (this is a SerializedVar). But there are
+// many combinations of proper reference counting for sending and receiving
+// different types and when different data is avaliable (like the Dispatcher is
+// not available at IPC read time). So SerializedVar has to encapsulate all of
+// these modes.
+//
+// This makes SerializedVar complicate and easy to mess up. To make it
+// reasonable to use all functions are protected and there are a use-specific
+// classes that encapsulate exactly one type of use in a way that typically
+// won't compile if you do the wrong thing.
+//
+// The IPC system is designed to pass things around and will make copies in
+// some cases, so our system must be designed so that this stuff will work.
+// This is challenging when the SerializedVar must to some cleanup after the
+// message is sent. To work around this, we create an inner class using a
+// linked_ptr so all copies of a SerializedVar can share and we can guarantee
+// that the actual data will get cleaned up on shutdown.
+//
+// Constness
+// ---------
+// SerializedVar basically doesn't support const. Everything is mutable and
+// most functions are declared const. This unfortunateness is because of the
+// way the IPC system works. When deserializing, it will have a const
+// SerializedVar in a Tuple and this will be given to the function. We kind of
+// want to modify that to convert strings and do refcounting.
+//
+// The helper classes used for accessing the SerializedVar have more reasonable
+// behavior and will enforce that you don't do stupid things.
+class SerializedVar {
+ public:
+  enum CleanupMode {
+    // The serialized var won't do anything special in the destructor (default).
+    CLEANUP_NONE,
+
+    // The serialized var will call EndSendPassRef in the destructor.
+    END_SEND_PASS_REF,
+
+    // The serialized var will call EndReceiveCallerOwned in the destructor.
+    END_RECEIVE_CALLER_OWNED
+  };
+
+  SerializedVar();
+  ~SerializedVar();
+
+  // Backend implementation for IPC::ParamTraits<SerializedVar>.
+  void WriteToMessage(IPC::Message* m) const {
+    inner_->WriteToMessage(m);
+  }
+  bool ReadFromMessage(const IPC::Message* m, void** iter) {
+    return inner_->ReadFromMessage(m, iter);
+  }
+
+ protected:
+  friend class SerializedVarReceiveInput;
+  friend class SerializedVarReturnValue;
+  friend class SerializedVarOutParam;
+  friend class SerializedVarSendInput;
+  friend class SerializedVarVectorReceiveInput;
+
+  SerializedVar(VarSerializationRules* serialization_rules);
+  SerializedVar(VarSerializationRules* serialization, const PP_Var& var);
+
+  VarSerializationRules* serialization_rules() const {
+    return inner_->serialization_rules();
+  }
+  void set_serialization_rules(VarSerializationRules* s) const {
+    inner_->set_serialization_rules(s);
+  }
+
+  void set_cleanup_mode(CleanupMode cm) const {
+    inner_->set_cleanup_mode(cm);
+  }
+
+  // Returns the completed var for this object. The serialization rules must
+  // have been set already, and any string conversions must already have
+  // happened.
+  PP_Var GetVar() const {
+    return inner_->GetVar();
+  }
+
+  // Returns the var which has not had a string serialization happen yet. This
+  // is used for actually converting a string PP_Var to the string literal.
+  PP_Var GetIncompleteVar() const {
+    return inner_->GetIncompleteVar();
+  }
+
+  void SetVar(const PP_Var& var) const {
+    inner_->SetVar(var);
+  }
+
+  // When this serialized var is a string var, returns the associated string.
+  // with the value. This can be called if the var isn't a string, but will
+  // just return the empty string in this case.
+  const std::string& GetString() const {
+    return inner_->GetString();
+  }
+
+  // Returns a pointer to the inner string associated with this class. The
+  // derived classes will use this when converting a PP_Var to the string
+  // literal. This can be called if the var isn't a string, but the value
+  // should not be written to (this simplifies the callers who can always pass
+  // the result of this function call to the VarSerializationRules classes).
+  std::string* GetStringPtr() const {
+    return inner_->GetStringPtr();
+  }
+
+ private:
+  class Inner {
+   public:
+    Inner();
+    Inner(VarSerializationRules* serialization_rules);
+    Inner(VarSerializationRules* serialization_rules, const PP_Var& var);
+    ~Inner();
+
+    VarSerializationRules* serialization_rules() {
+      return serialization_rules_;
+    }
+    void set_serialization_rules(VarSerializationRules* serialization_rules) {
+      serialization_rules_ = serialization_rules;
+    }
+
+    void set_cleanup_mode(CleanupMode cm) { cleanup_mode_ = cm; }
+
+    // See outer class's declarations above.
+    PP_Var GetVar() const;
+    PP_Var GetIncompleteVar() const;
+    void SetVar(PP_Var var);
+    const std::string& GetString() const;
+    std::string* GetStringPtr();
+
+    void WriteToMessage(IPC::Message* m) const;
+    bool ReadFromMessage(const IPC::Message* m, void** iter);
+
+   private:
+    // Rules for serializing and deserializing vars for this process type.
+    // This may be NULL, but must be set before trying to serialize to IPC when
+    // sending, or before converting back to a PP_Var when receiving.
+    VarSerializationRules* serialization_rules_;
+
+    // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
+    // string_value_ contains the string. This means that the caller hasn't
+    // called Deserialize with a valid Dispatcher yet, which is how we can
+    // convert the serialized string value to a PP_Var string ID.
+    //
+    // This var may not be complete until the serialization rules are set when
+    // reading from IPC since we'll need that to convert the string_value to
+    // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
+    PP_Var var_;
+
+    // Holds the literal string value to/from IPC. This will be valid of the
+    // var_ is VARTYPE_STRING.
+    std::string string_value_;
+
+    CleanupMode cleanup_mode_;
+
+#ifndef NDEBUG
+    // When being sent or received over IPC, we should only be serialized or
+    // deserialized once. These flags help us assert this is true.
+    mutable bool has_been_serialized_;
+    mutable bool has_been_deserialized_;
+#endif
+
+    DISALLOW_COPY_AND_ASSIGN(Inner);
+  };
+
+  mutable linked_ptr<Inner> inner_;
+};
+
+// Helpers for message sending side --------------------------------------------
+
+// For sending a value to the remote side.
+//
+// Example for API:
+//   void MyFunction(PP_Var)
+// IPC message:
+//   IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
+// Sender would be:
+//   void MyFunctionProxy(PP_Var param) {
+//     Send(new MyFunctionMsg(SerializedVarSendInput(param));
+//   }
+class SerializedVarSendInput : public SerializedVar {
+ public:
+  SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var);
+
+  // Helper function for serializing a vector of input vars for serialization.
+  static void ConvertVector(Dispatcher* dispatcher,
+                            const PP_Var* input,
+                            size_t input_count,
+                            std::vector<SerializedVar>* output);
+
+ private:
+  // Disallow the empty constructor, but keep the default copy constructor
+  // which is required to send the object to the IPC system.
+  SerializedVarSendInput();
+};
+
+// For the calling side of a function returning a var. The sending side uses
+// SerializedVarReturnValue.
+//
+// Example for API:
+//   PP_Var MyFunction()
+// IPC message:
+//   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+//   PP_Var MyFunctionProxy() {
+//     ReceiveSerializedVarReturnValue result;
+//     Send(new MyFunctionMsg(&result));
+//     return result.Return(dispatcher());
+//   }
+class ReceiveSerializedVarReturnValue : public SerializedVar {
+ public:
+  // Note that we can't set the dispatcher in the constructor because the
+  // data will be overridden when the return value is set.
+  ReceiveSerializedVarReturnValue();
+
+  PP_Var Return(Dispatcher* dispatcher);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue);
+};
+
+// Example for API:
+//   "void MyFunction(PP_Var* exception);"
+// IPC message:
+//   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+//   void OnMsgMyFunction(PP_Var* exception) {
+//     ReceiveSerializedException se(dispatcher(), exception)
+//     Send(new PpapiHostMsg_Foo(&se));
+//   }
+class ReceiveSerializedException : public SerializedVar {
+ public:
+  ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception);
+  ~ReceiveSerializedException();
+
+  // Returns true if the exception passed in the constructor is set. Check
+  // this before actually issuing the IPC.
+  bool IsThrown() const;
+
+ private:
+  // The input/output exception we're wrapping. May be NULL.
+  PP_Var* exception_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException);
+};
+
+// Helper class for when we're returning a vector of Vars. When it goes out
+// of scope it will automatically convert the vector filled by the IPC layer
+// into the array specified by the constructor params.
+//
+// Example for API:
+//   "void MyFunction(uint32_t* count, PP_Var** vars);"
+// IPC message:
+//   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>);
+// Proxy function:
+//   void MyFunction(uint32_t* count, PP_Var** vars) {
+//     ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars);
+//     Send(new MyMsg(vect.OutParam()));
+//   }
+class ReceiveSerializedVarVectorOutParam {
+ public:
+  ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher,
+                                     uint32_t* output_count,
+                                     PP_Var** output);
+  ~ReceiveSerializedVarVectorOutParam();
+
+  std::vector<SerializedVar>* OutParam();
+
+ private:
+  Dispatcher* dispatcher_;
+  uint32_t* output_count_;
+  PP_Var** output_;
+
+  std::vector<SerializedVar> vector_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam);
+};
+
+// Helpers for message receiving side ------------------------------------------
+
+// For receiving a value from the remote side.
+//
+// Example for API:
+//   void MyFunction(PP_Var)
+// IPC message:
+//   IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
+// Message handler would be:
+//   void OnMsgMyFunction(SerializedVarReceiveInput param) {
+//     MyFunction(param.Get());
+//   }
+class SerializedVarReceiveInput {
+ public:
+  // We rely on the implicit constructor here since the IPC layer will call
+  // us with a SerializedVar. Pass this object by value, the copy constructor
+  // will pass along the pointer (as cheap as passing a pointer arg).
+  SerializedVarReceiveInput(const SerializedVar& serialized);
+  ~SerializedVarReceiveInput();
+
+  PP_Var Get(Dispatcher* dispatcher);
+
+ private:
+  const SerializedVar& serialized_;
+
+  // Since the SerializedVar is const, we can't set its dispatcher (which is
+  // OK since we don't need to). But since we need it for our own uses, we
+  // track it here. Will be NULL before Get() is called.
+  Dispatcher* dispatcher_;
+  PP_Var var_;
+};
+
+// For receiving an input vector of vars from the remote side.
+//
+// Example:
+//   OnMsgMyFunction(SerializedVarVectorReceiveInput vector) {
+//     uint32_t size;
+//     PP_Var* array = vector.Get(dispatcher, &size);
+//     MyFunction(size, array);
+//   }
+class SerializedVarVectorReceiveInput {
+ public:
+  SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized);
+  ~SerializedVarVectorReceiveInput();
+
+  // Only call Get() once. It will return a pointer to the converted array and
+  // place the array size in the out param. Will return NULL when the array is
+  // empty.
+  PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size);
+
+ private:
+  const std::vector<SerializedVar>& serialized_;
+
+  // Filled by Get().
+  std::vector<PP_Var> deserialized_;
+};
+
+// For the receiving side of a function returning a var. The calling side uses
+// ReceiveSerializedVarReturnValue.
+//
+// Example for API:
+//   PP_Var MyFunction()
+// IPC message:
+//   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+//   void OnMsgMyFunction(SerializedVarReturnValue result) {
+//     result.Return(dispatcher(), MyFunction());
+//   }
+class SerializedVarReturnValue {
+ public:
+  // We rely on the implicit constructor here since the IPC layer will call
+  // us with a SerializedVar*. Pass this object by value, the copy constructor
+  // will pass along the pointer (as cheap as passing a pointer arg).
+  SerializedVarReturnValue(SerializedVar* serialized);
+
+  void Return(Dispatcher* dispatcher, const PP_Var& var);
+
+ private:
+  SerializedVar* serialized_;
+};
+
+// For writing an out param to the remote side.
+//
+// Example for API:
+//   "void MyFunction(PP_Var* out);"
+// IPC message:
+//   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+//   void OnMsgMyFunction(SerializedVarOutParam out_param) {
+//     MyFunction(out_param.OutParam(dispatcher()));
+//   }
+class SerializedVarOutParam {
+ public:
+  // We rely on the implicit constructor here since the IPC layer will call
+  // us with a SerializedVar*. Pass this object by value, the copy constructor
+  // will pass along the pointer (as cheap as passing a pointer arg).
+  SerializedVarOutParam(SerializedVar* serialized);
+  ~SerializedVarOutParam();
+
+  // Call this function only once. The caller should write its result to the
+  // returned var pointer before this class goes out of scope. The var's
+  // initial value will be VARTYPE_UNDEFINED.
+  PP_Var* OutParam(Dispatcher* dispatcher);
+
+ private:
+  SerializedVar* serialized_;
+
+  // This is the value actually written by the code and returned by OutParam.
+  // We'll write this into serialized_ in our destructor.
+  PP_Var writable_var_;
+};
+
+// For returning an array of PP_Vars to the other side and transferring
+// ownership.
+//
+class SerializedVarVectorOutParam {
+ public:
+  SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized);
+  ~SerializedVarVectorOutParam();
+
+  uint32_t* CountOutParam() { return &count_; }
+  PP_Var** ArrayOutParam(Dispatcher* dispatcher);
+
+ private:
+  Dispatcher* dispatcher_;
+  std::vector<SerializedVar>* serialized_;
+
+  uint32_t count_;
+  PP_Var* array_;
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_SERIALIZED_VAR_H_
+
diff --git a/ppapi/proxy/var_serialization_rules.h b/ppapi/proxy/var_serialization_rules.h
new file mode 100644
index 0000000000000000000000000000000000000000..bf00547124505bc06bf70c8d60dd720fdd1e001d
--- /dev/null
+++ b/ppapi/proxy/var_serialization_rules.h
@@ -0,0 +1,85 @@
+// 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_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
+
+#include "ppapi/c/pp_var.h"
+
+#include <string>
+
+namespace pp {
+namespace proxy {
+
+// Encapsulates the rules for serializing and deserializing vars to and from
+// the local process. The renderer and the plugin process each have separate
+// bookkeeping rules.
+class VarSerializationRules {
+ public:
+  virtual ~VarSerializationRules() {}
+
+  // Caller-owned calls --------------------------------------------------------
+  //
+  // A caller-owned call is when doing a function call with a "normal" input
+  // argument. The caller has a reference to the var, and the caller is
+  // responsible for freeing that reference.
+
+  // Prepares the given var for sending to the callee. If the var is a string,
+  // the value of that string will be placed in *str_val. If the var is not
+  // a string, str_val will beuntouched and may be NULL.
+  virtual void SendCallerOwned(const PP_Var& var, std::string* str_val) = 0;
+
+  // When receiving a caller-owned variable, normally we don't have to do
+  // anything. However, in the case of strings, we need to deserialize the
+  // string from IPC, create a new PP_Var string in the local process, call the
+  // function, and then destroy the temporary string. These two functions
+  // handle that process
+  //
+  // BeginReceiveCallerOwned takes a var from IPC and an optional pointer to
+  // the deserialized string (which will be used only when var is a
+  // VARTYPE_STRING and may be NULL otherwise) and returns a new var
+  // representing the input in the local process. The output will be the same
+  // as the input except for strings.
+  //
+  // EndReceiveCallerOwned destroys the string created by Begin* and does
+  // nothing otherwise. It should be called with the result of Begin*.
+  virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
+                                         const std::string* str_val) = 0;
+  virtual void EndReceiveCallerOwned(const PP_Var& var) = 0;
+
+  // Passinag refs -------------------------------------------------------------
+  //
+  // A pass-ref transfer is when ownership of a reference is passed from
+  // onen side to the other. Normally, this happens via return values and
+  // output arguments, as for exceptions. The code generating the value
+  // (the function returning it in the case of a return value) will AddRef
+  // the var on behalf of the consumer of the value. Responsibility for
+  // Release is on the consumer (the caller of the function in the case of a
+  // return value).
+
+  // Creates a var in the context of the local process from the given
+  // deserialized var and deserialized string (which will be used only when var
+  // is a VARTYPE_STRING and may be NULL otherwise). The input var/string
+  // should be the result of calling SendPassRef in the remote process.
+  virtual PP_Var ReceivePassRef(const PP_Var& var,
+                                const std::string& str_val) = 0;
+
+  // Prepares a var to be sent to the remote side. One local reference will
+  // be passed to the remote side. Call Begin* before doing the send and End*
+  // after doing the send. See SendCallerOwned for a description of the string.
+  virtual void BeginSendPassRef(const PP_Var& var, std::string* str_val) = 0;
+  virtual void EndSendPassRef(const PP_Var& var) = 0;
+
+  // ---------------------------------------------------------------------------
+
+  virtual void ReleaseObjectRef(const PP_Var& var) = 0;
+
+ protected:
+  VarSerializationRules() {}
+};
+
+}  // namespace proxy
+}  // namespace pp
+
+#endif  // PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_