From 8cc9dd62ea7a7d60ce5486fbd62baf9266fa0f15 Mon Sep 17 00:00:00 2001
From: "ajwong@chromium.org"
 <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Mon, 28 Jun 2010 15:13:10 +0000
Subject: [PATCH] Add in support for internal pepper plugins into the
 PepperPluginRegistry and pepper::PluginModule.

Used Chromoting's plugin as the first attempt at using this interface.

BUG=none
TEST=compiles

Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=50667

Review URL: http://codereview.chromium.org/2843018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50976 0039d316-1c4b-4281-b951-d872f2087c98
---
 chrome/chrome_common.gypi                    |   5 +
 chrome/common/DEPS                           |   1 +
 chrome/common/pepper_plugin_registry.cc      |  66 ++++-
 chrome/common/pepper_plugin_registry.h       |  11 +-
 remoting/client/plugin/chromoting_plugin.cc  |  24 +-
 remoting/client/plugin/chromoting_plugin.h   |  16 +-
 remoting/client/plugin/pepper_entrypoints.cc | 239 +++++++++++++++++++
 remoting/client/plugin/pepper_entrypoints.h  |  20 ++
 remoting/remoting.gyp                        |  90 ++++---
 webkit/glue/plugins/pepper_plugin_module.cc  | 109 ++++++---
 webkit/glue/plugins/pepper_plugin_module.h   |  41 +++-
 11 files changed, 514 insertions(+), 108 deletions(-)
 create mode 100644 remoting/client/plugin/pepper_entrypoints.cc
 create mode 100644 remoting/client/plugin/pepper_entrypoints.h

diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 9e5e5624b9470..31572eb39ebca 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -311,6 +311,11 @@
             'common/sandbox_policy.cc',
           ],
         }],
+        ['remoting==1', {
+          'dependencies': [
+            '../remoting/remoting.gyp:chromoting_plugin',
+          ],
+        }],
       ],
       'export_dependent_settings': [
         '../app/app.gyp:app_base',
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index c3db484d1b896..75629ca9c257a 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -3,6 +3,7 @@ include_rules = [
   "+grit",  # For generated headers
   "+libxml",
   "+media/audio",
+  "+remoting/client/plugin",
   "+sandbox/src",
   "+skia/include",
   "+webkit/default_plugin",
diff --git a/chrome/common/pepper_plugin_registry.cc b/chrome/common/pepper_plugin_registry.cc
index 0a23ecaaa9134..e7771c4b71986 100644
--- a/chrome/common/pepper_plugin_registry.cc
+++ b/chrome/common/pepper_plugin_registry.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/string_util.h"
 #include "chrome/common/chrome_switches.h"
+#include "remoting/client/plugin/pepper_entrypoints.h"
 
 // static
 PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
@@ -16,6 +17,21 @@ PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
 
 // static
 void PepperPluginRegistry::GetList(std::vector<PepperPluginInfo>* plugins) {
+  InternalPluginInfoList internal_plugin_info;
+  GetInternalPluginInfo(&internal_plugin_info);
+  for (InternalPluginInfoList::const_iterator it =
+         internal_plugin_info.begin();
+       it != internal_plugin_info.end();
+       ++it) {
+    plugins->push_back(*it);
+  }
+
+  GetPluginInfoFromSwitch(plugins);
+}
+
+// static
+void PepperPluginRegistry::GetPluginInfoFromSwitch(
+    std::vector<PepperPluginInfo>* plugins) {
   const std::wstring& value = CommandLine::ForCurrentProcess()->GetSwitchValue(
       switches::kRegisterPepperPlugins);
   if (value.empty())
@@ -44,6 +60,35 @@ void PepperPluginRegistry::GetList(std::vector<PepperPluginInfo>* plugins) {
   }
 }
 
+// static
+void PepperPluginRegistry::GetInternalPluginInfo(
+    InternalPluginInfoList* plugin_info) {
+  // Currently, to centralize the internal plugin registration logic, we
+  // hardcode the list of plugins, mimetypes, and registration information
+  // in this function.  This is gross, but because the GetList() function is
+  // called from both the renderer and browser the other option is to force a
+  // special register function for each plugin to be called by both
+  // RendererMain() and BrowserMain().  This seemed like the better tradeoff.
+  //
+  // TODO(ajwong): Think up a better way to maintain the plugin registration
+  // information. Pehraps by construction of a singly linked list of
+  // plugin initializers that is built with static initializers?
+
+#if defined(ENABLE_REMOTING)
+  InternalPluginInfo info;
+  // Add the chromoting plugin.
+  info.path =
+      FilePath(FILE_PATH_LITERAL("internal-chromoting"));
+  info.mime_types.push_back("pepper-application/x-chromoting");
+  info.entry_points.get_interface = remoting::PPP_GetInterface;
+  info.entry_points.initialize_module = remoting::PPP_InitializeModule;
+  info.entry_points.shutdown_module = remoting::PPP_ShutdownModule;
+
+  plugin_info->push_back(info);
+#endif
+
+}
+
 pepper::PluginModule* PepperPluginRegistry::GetModule(
     const FilePath& path) const {
   ModuleMap::const_iterator it = modules_.find(path);
@@ -53,8 +98,27 @@ pepper::PluginModule* PepperPluginRegistry::GetModule(
 }
 
 PepperPluginRegistry::PepperPluginRegistry() {
+  InternalPluginInfoList internal_plugin_info;
+  GetInternalPluginInfo(&internal_plugin_info);
+  // Register modules for these suckers.
+  for (InternalPluginInfoList::const_iterator it =
+         internal_plugin_info.begin();
+       it != internal_plugin_info.end();
+       ++it) {
+    const FilePath& path = it->path;
+    ModuleHandle module =
+        pepper::PluginModule::CreateInternalModule(it->entry_points);
+    if (!module) {
+      DLOG(ERROR) << "Failed to load pepper module: " << path.value();
+      continue;
+    }
+    modules_[path] = module;
+  }
+
+  // Add the modules specified on the command line last so that they can
+  // override the internal plugins.
   std::vector<PepperPluginInfo> plugins;
-  GetList(&plugins);
+  GetPluginInfoFromSwitch(&plugins);
   for (size_t i = 0; i < plugins.size(); ++i) {
     const FilePath& path = plugins[i].path;
     ModuleHandle module = pepper::PluginModule::CreateModule(path);
diff --git a/chrome/common/pepper_plugin_registry.h b/chrome/common/pepper_plugin_registry.h
index 940a1ba9551db..9949ed46be689 100644
--- a/chrome/common/pepper_plugin_registry.h
+++ b/chrome/common/pepper_plugin_registry.h
@@ -7,11 +7,12 @@
 
 #include <string>
 #include <map>
+#include <vector>
 
 #include "webkit/glue/plugins/pepper_plugin_module.h"
 
 struct PepperPluginInfo {
-  FilePath path;
+  FilePath path;  // Internal plugins are of the form "internal-[name]".
   std::vector<std::string> mime_types;
 };
 
@@ -28,6 +29,14 @@ class PepperPluginRegistry {
   pepper::PluginModule* GetModule(const FilePath& path) const;
 
  private:
+  static void GetPluginInfoFromSwitch(std::vector<PepperPluginInfo>* plugins);
+
+  struct InternalPluginInfo : public PepperPluginInfo {
+    pepper::PluginModule::EntryPoints entry_points;
+  };
+  typedef std::vector<InternalPluginInfo> InternalPluginInfoList;
+  static void GetInternalPluginInfo(InternalPluginInfoList* plugin_info);
+
   PepperPluginRegistry();
 
   typedef scoped_refptr<pepper::PluginModule> ModuleHandle;
diff --git a/remoting/client/plugin/chromoting_plugin.cc b/remoting/client/plugin/chromoting_plugin.cc
index 88b19cbde2baf..c5b5b030edb60 100644
--- a/remoting/client/plugin/chromoting_plugin.cc
+++ b/remoting/client/plugin/chromoting_plugin.cc
@@ -24,13 +24,15 @@ using std::vector;
 
 namespace remoting {
 
-const char* ChromotingPlugin::kMimeType =
-    "pepper-application/x-chromoting-plugin::Chromoting";
-
-ChromotingPlugin::ChromotingPlugin(PP_Instance instance)
-    : pp::Instance(instance),
-      width_(0),
-      height_(0) {
+const char* ChromotingPlugin::kMimeType = "pepper-application/x-chromoting";
+
+ChromotingPlugin::ChromotingPlugin(PP_Instance pp_instance,
+                                   const PPB_Instance* ppb_instance_funcs)
+    : width_(0),
+      height_(0),
+      drawing_context_(NULL),
+      pp_instance_(pp_instance),
+      ppb_instance_funcs_(ppb_instance_funcs) {
 }
 
 ChromotingPlugin::~ChromotingPlugin() {
@@ -115,8 +117,13 @@ void ChromotingPlugin::ViewChanged(const PP_Rect& position,
   width_ = position.size.width;
   height_ = position.size.height;
 
+  /*
+   * TODO(ajwong): Reenable this code once we fingure out how we want to
+   * abstract away the C-api for DeviceContext2D.
   device_context_ = pp::DeviceContext2D(width_, height_, false);
-  if (!BindGraphicsDeviceContext(device_context_)) {
+  if (!ppb_instance_funcs_->BindGraphicsDeviceContext(
+      pp_instance_,
+      device_context_.pp_resource())) {
     LOG(ERROR) << "Couldn't bind the device context.";
     return;
   }
@@ -133,6 +140,7 @@ void ChromotingPlugin::ViewChanged(const PP_Rect& position,
   } else {
     LOG(ERROR) << "Unable to allocate image.";
   }
+  */
 
   //client_->SetViewport(0, 0, width_, height_);
   //client_->Repaint();
diff --git a/remoting/client/plugin/chromoting_plugin.h b/remoting/client/plugin/chromoting_plugin.h
index d19b6122e511f..757e038c3bfa4 100644
--- a/remoting/client/plugin/chromoting_plugin.h
+++ b/remoting/client/plugin/chromoting_plugin.h
@@ -11,8 +11,11 @@
 #include "base/scoped_ptr.h"
 #include "remoting/client/host_connection.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
-#include "third_party/ppapi/cpp/device_context_2d.h"
-#include "third_party/ppapi/cpp/instance.h"
+#include "third_party/ppapi/c/pp_event.h"
+#include "third_party/ppapi/c/pp_instance.h"
+#include "third_party/ppapi/c/pp_rect.h"
+#include "third_party/ppapi/c/pp_resource.h"
+#include "third_party/ppapi/c/ppb_instance.h"
 
 namespace base {
 class Thread;
@@ -27,7 +30,7 @@ class PepperView;
 
 class ChromotingClient;
 
-class ChromotingPlugin : public pp::Instance {
+class ChromotingPlugin {
  public:
   // The mimetype for which this plugin is registered.
   //
@@ -35,7 +38,7 @@ class ChromotingPlugin : public pp::Instance {
   // point.  I think we should handle a special protocol (eg., chromotocol://)
   static const char *kMimeType;
 
-  ChromotingPlugin(PP_Instance instance);
+  ChromotingPlugin(PP_Instance instance, const PPB_Instance* instance_funcs);
   virtual ~ChromotingPlugin();
 
   virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
@@ -55,7 +58,10 @@ class ChromotingPlugin : public pp::Instance {
   int width_;
   int height_;
 
-  pp::DeviceContext2D device_context_;
+  PP_Resource drawing_context_;
+
+  PP_Instance pp_instance_;
+  const PPB_Instance* ppb_instance_funcs_;
 
   scoped_ptr<base::Thread> main_thread_;
   scoped_ptr<JingleThread> network_thread_;
diff --git a/remoting/client/plugin/pepper_entrypoints.cc b/remoting/client/plugin/pepper_entrypoints.cc
new file mode 100644
index 0000000000000..c8a0895698bbc
--- /dev/null
+++ b/remoting/client/plugin/pepper_entrypoints.cc
@@ -0,0 +1,239 @@
+// 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 "remoting/client/plugin/pepper_entrypoints.h"
+
+#include "remoting/client/plugin/chromoting_plugin.h"
+#include "third_party/ppapi/c/pp_instance.h"
+#include "third_party/ppapi/c/pp_module.h"
+#include "third_party/ppapi/c/ppp_instance.h"
+#include "third_party/ppapi/cpp/instance.h"
+#include "third_party/ppapi/cpp/module.h"
+
+static const int kModuleInitSuccess = 0;
+static const int kModuleInitFailure = 1;
+
+namespace remoting {
+
+// Fork of ppapi::Module
+//
+// TODO(ajwong): Generalize this into something that other internal plugins can
+// use.  Either that, or attempt to refactor the external ppapi C++ wrapper to
+// make it friendly for multiple Modules in one process.  I think we can do this
+// by:
+//    1) Moving the singleton Module instance + C-bindings into another class
+//       (eg., ModuleExporter) under a different gyp targe.
+//    2) Extracting the idea of a "Browser" out of the module that returns
+//       PPB_Core, etc.  This can be a singleton per process regardless of
+//       module.
+//    3) Migrate all PPB related objects to get data out of Browser interface
+//       instead of Module::Get().
+class ChromotingModule {
+ public:
+  ChromotingModule() {}
+
+  // This function will be automatically called after the object is created.
+  // This is where you can put functions that rely on other parts of the API,
+  // now that the module has been created.
+  virtual bool Init() { return true; }
+
+  PP_Module pp_module() const { return pp_module_; }
+  const PPB_Core& core() const { return *core_; }
+
+  // Implements GetInterface for the browser to get plugin interfaces. Override
+  // if you need to implement your own interface types that this wrapper
+  // doesn't support.
+  virtual const void* GetInstanceInterface(const char* interface_name) {
+    if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
+      return &instance_interface_;
+
+    return NULL;
+  }
+
+  // Returns an interface in the browser.
+  const void* GetBrowserInterface(const char* interface_name) {
+    return get_browser_interface_(interface_name);
+  }
+
+  // Returns the object associated with this PP_Instance, or NULL if one is
+  // not found.
+  ChromotingPlugin* InstanceForPPInstance(PP_Instance instance) {
+    InstanceMap::iterator found = current_instances_.find(instance);
+    if (found == current_instances_.end())
+      return NULL;
+    return found->second;
+  }
+
+  // Sets the browser interface and calls the regular init function that
+  // can be overridden by the base classes.
+  //
+  // TODO(brettw) make this private when I can figure out how to make the
+  // initialize function a friend.
+  bool InternalInit(PP_Module mod,
+                    PPB_GetInterface get_browser_interface) {
+    pp_module_ = mod;
+    get_browser_interface_ = get_browser_interface;
+    core_ = reinterpret_cast<const PPB_Core*>(GetBrowserInterface(
+        PPB_CORE_INTERFACE));
+    if (!core_)
+      return false;  // Can't run without the core interface.
+
+    return Init();
+  }
+
+  // Implementation of Global PPP functions ---------------------------------
+  static int PPP_InitializeModule(PP_Module module_id,
+                                  PPB_GetInterface get_browser_interface) {
+    ChromotingModule* module = new ChromotingModule();
+    if (!module)
+      return kModuleInitFailure;
+
+    if (!module->InternalInit(module_id, get_browser_interface)) {
+      delete module;
+      return kModuleInitFailure;
+    }
+
+    module_singleton_ = module;
+    return kModuleInitSuccess;
+  }
+
+  static void PPP_ShutdownModule() {
+    delete module_singleton_;
+    module_singleton_ = NULL;
+  }
+
+  static const void* PPP_GetInterface(const char* interface_name) {
+    if (!module_singleton_)
+      return NULL;
+    return module_singleton_->GetInstanceInterface(interface_name);
+  }
+
+ protected:
+  virtual ChromotingPlugin* CreateInstance(PP_Instance instance) {
+    const PPB_Instance* ppb_instance_funcs =
+        reinterpret_cast<const PPB_Instance *>(
+            module_singleton_->GetBrowserInterface(PPB_INSTANCE_INTERFACE));
+    return new ChromotingPlugin(instance, ppb_instance_funcs);
+  }
+
+ private:
+  static bool Instance_New(PP_Instance instance) {
+    if (!module_singleton_)
+      return false;
+    ChromotingPlugin* obj = module_singleton_->CreateInstance(instance);
+    if (obj) {
+      module_singleton_->current_instances_[instance] = obj;
+      return true;
+    }
+    return false;
+  }
+
+  static void Instance_Delete(PP_Instance instance) {
+    if (!module_singleton_)
+      return;
+    ChromotingModule::InstanceMap::iterator found =
+        module_singleton_->current_instances_.find(instance);
+    if (found == module_singleton_->current_instances_.end())
+      return;
+
+    // Remove it from the map before deleting to try to catch reentrancy.
+    ChromotingPlugin* obj = found->second;
+    module_singleton_->current_instances_.erase(found);
+    delete obj;
+  }
+
+  static bool Instance_Initialize(PP_Instance pp_instance,
+                                  uint32_t argc,
+                                  const char* argn[],
+                                  const char* argv[]) {
+    if (!module_singleton_)
+      return false;
+    ChromotingPlugin* instance =
+        module_singleton_->InstanceForPPInstance(pp_instance);
+    if (!instance)
+      return false;
+    return instance->Init(argc, argn, argv);
+  }
+
+  static bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
+                                          PP_Resource url_loader) {
+    return false;
+  }
+
+  static bool Instance_HandleEvent(PP_Instance pp_instance,
+                                   const PP_Event* event) {
+    if (!module_singleton_)
+      return false;
+    ChromotingPlugin* instance =
+        module_singleton_->InstanceForPPInstance(pp_instance);
+    if (!instance)
+      return false;
+    return instance->HandleEvent(*event);
+  }
+
+  static PP_Var Instance_GetInstanceObject(PP_Instance pp_instance) {
+    PP_Var var;
+    var.type = PP_VarType_Void;
+    return var;
+  }
+
+  static void Instance_ViewChanged(PP_Instance pp_instance,
+                                   const PP_Rect* position,
+                                   const PP_Rect* clip) {
+    if (!module_singleton_)
+      return;
+    ChromotingPlugin* instance =
+        module_singleton_->InstanceForPPInstance(pp_instance);
+    if (!instance)
+      return;
+    instance->ViewChanged(*position, *clip);
+  }
+
+  // Bindings and identifiers to and from the browser.
+  PP_Module pp_module_;
+  PPB_GetInterface get_browser_interface_;
+  PPB_Core const* core_;
+
+  // Instance tracking.
+  typedef std::map<PP_Instance, ChromotingPlugin*> InstanceMap;
+  InstanceMap current_instances_;
+
+  // Static members for the ppapi C-bridge.
+  static PPP_Instance instance_interface_;
+  static ChromotingModule* module_singleton_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromotingModule);
+};
+
+ChromotingModule* ChromotingModule::module_singleton_ = NULL;
+
+PPP_Instance ChromotingModule::instance_interface_ = {
+  &ChromotingModule::Instance_New,
+  &ChromotingModule::Instance_Delete,
+  &ChromotingModule::Instance_Initialize,
+  &ChromotingModule::Instance_HandleDocumentLoad,
+  &ChromotingModule::Instance_HandleEvent,
+  &ChromotingModule::Instance_GetInstanceObject,
+  &ChromotingModule::Instance_ViewChanged,
+};
+
+// Implementation of Global PPP functions ---------------------------------
+//
+// TODO(ajwong): This is to get around friending issues. Fix it after we decide
+// whether or not ChromotingModule should be generalized.
+int PPP_InitializeModule(PP_Module module_id,
+                         PPB_GetInterface get_browser_interface) {
+  return ChromotingModule::PPP_InitializeModule(module_id,
+                                                get_browser_interface);
+}
+
+void PPP_ShutdownModule() {
+  return ChromotingModule::PPP_ShutdownModule();
+}
+
+const void* PPP_GetInterface(const char* interface_name) {
+  return ChromotingModule::PPP_GetInterface(interface_name);
+}
+
+}  // namespace remoting
diff --git a/remoting/client/plugin/pepper_entrypoints.h b/remoting/client/plugin/pepper_entrypoints.h
new file mode 100644
index 0000000000000..ab6de20b3cb05
--- /dev/null
+++ b/remoting/client/plugin/pepper_entrypoints.h
@@ -0,0 +1,20 @@
+// 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 REMOTING_CLIENT_PLUGIN_PEPPER_ENTRYPOINTS_
+#define REMOTING_CLIENT_PLUGIN_PEPPER_ENTRYPOINTS_
+
+#include "third_party/ppapi/c/pp_module.h"
+#include "third_party/ppapi/c/ppb.h"
+
+namespace remoting {
+
+int PPP_InitializeModule(PP_Module module_id,
+                         PPB_GetInterface get_browser_interface);
+void PPP_ShutdownModule();
+const void* PPP_GetInterface(const char* interface_name);
+
+}  // namespace remoting
+
+#endif  // REMOTING_CLIENT_PLUGIN_PEPPER_ENTRYPOINTS_
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index f8a2f895a634c..1e037ef83ec20 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -16,46 +16,8 @@
   },
 
   'conditions': [
-    # Chromoting Client targets
     ['OS=="linux" or OS=="mac"', {
       'targets': [
-        {
-          'target_name': 'chromoting_client_plugin',
-          'type': 'static_library',
-          'defines': [
-            'HAVE_STDINT_H',  # Required by on2_integer.h
-          ],
-          'dependencies': [
-            'chromoting_base',
-            'chromoting_client',
-            'chromoting_jingle_glue',
-            '../third_party/ppapi/ppapi.gyp:ppapi_cpp',
-            '../third_party/zlib/zlib.gyp:zlib',
-          ],
-          'sources': [
-            'client/plugin/chromoting_plugin.cc',
-            'client/plugin/chromoting_plugin.h',
-            'client/plugin/pepper_view.cc',
-            'client/plugin/pepper_view.h',
-            '../media/base/yuv_convert.cc',
-            '../media/base/yuv_convert.h',
-            '../media/base/yuv_row.h',
-            '../media/base/yuv_row_posix.cc',
-            '../media/base/yuv_row_table.cc',
-          ],
-          'conditions': [
-            ['OS=="win"', {
-              'sources': [
-                '../media/base/yuv_row_win.cc',
-              ],
-            }],
-            ['OS=="linux" and target_arch=="x64" and linux_fpic!=1', {
-              # Shared libraries need -fPIC on x86-64
-              'cflags': ['-fPIC'],
-            }],
-          ],  # end of 'conditions'
-        },  # end of target 'chromoting_client_plugin'
-
         # Simple webserver for testing chromoting client plugin.
         {
           'target_name': 'chromoting_client_test_webserver',
@@ -63,13 +25,13 @@
           'sources': [
             'tools/client_webserver/main.c',
           ],
-        },  # end of target 'chromoting_client_test_webserver'
-
-      ],  # end of Client targets
-    }],  # end of OS conditions for Client targets
+        }
+      ],  # end of target 'chromoting_client_test_webserver'
+    }],
 
     # TODO(hclam): Enable this target for mac.
     ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+
       'targets': [
         {
           'target_name': 'chromoting_x11_client',
@@ -99,6 +61,45 @@
   ],  # end of 'conditions'
 
   'targets': [
+    {
+      'target_name': 'chromoting_plugin',
+      'type': 'static_library',
+      'defines': [
+        'HAVE_STDINT_H',  # Required by on2_integer.h
+      ],
+      'dependencies': [
+        'chromoting_base',
+        'chromoting_client',
+        'chromoting_jingle_glue',
+        '../third_party/ppapi/ppapi.gyp:ppapi_c',
+        '../third_party/zlib/zlib.gyp:zlib',
+      ],
+      'sources': [
+        'client/plugin/chromoting_plugin.cc',
+        'client/plugin/chromoting_plugin.h',
+        'client/plugin/pepper_entrypoints.cc',
+        'client/plugin/pepper_entrypoints.h',
+        'client/plugin/pepper_view.cc',
+        'client/plugin/pepper_view.h',
+        '../media/base/yuv_convert.cc',
+        '../media/base/yuv_convert.h',
+        '../media/base/yuv_row.h',
+        '../media/base/yuv_row_table.cc',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'sources': [
+            '../media/base/yuv_row_win.cc',
+          ],
+        }],
+        ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="mac"', {
+          'sources': [
+            '../media/base/yuv_row_posix.cc',
+          ],
+        }],
+      ],  # end of 'conditions'
+    },  # end of target 'chromoting_plugin'
+
     {
       'target_name': 'chromoting_base',
       'type': '<(library)',
@@ -311,11 +312,6 @@
         '../gfx/gfx.gyp:*',
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
-        '../third_party/WebKit/WebKit/chromium/WebKit.gyp:webkit',
-        '../webkit/support/webkit_support.gyp:appcache',
-        '../webkit/support/webkit_support.gyp:database',
-        '../webkit/support/webkit_support.gyp:glue',
-        '../webkit/support/webkit_support.gyp:webkit_support',
       ],
       'include_dirs': [
         '../testing/gmock/include',
diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc
index 3f5d767cf2098..4bb5ea11d1278 100644
--- a/webkit/glue/plugins/pepper_plugin_module.cc
+++ b/webkit/glue/plugins/pepper_plugin_module.cc
@@ -44,9 +44,6 @@
 #include "webkit/glue/plugins/pepper_url_response_info.h"
 #include "webkit/glue/plugins/pepper_var.h"
 
-typedef bool (*PPP_InitializeModuleFunc)(PP_Module, PPB_GetInterface);
-typedef void (*PPP_ShutdownModuleFunc)();
-
 namespace pepper {
 
 namespace {
@@ -187,11 +184,9 @@ const void* GetInterface(const char* name) {
 
 }  // namespace
 
-PluginModule::PluginModule(const FilePath& filename)
-    : filename_(filename),
-      initialized_(false),
-      library_(0),
-      ppp_get_interface_(NULL) {
+PluginModule::PluginModule()
+    : initialized_(false),
+      library_(NULL) {
   GetMainThreadMessageLoop();  // Initialize the main thread message loop.
   GetLivePluginSet()->insert(this);
 }
@@ -203,25 +198,31 @@ PluginModule::~PluginModule() {
 
   GetLivePluginSet()->erase(this);
 
-  if (library_) {
-    PPP_ShutdownModuleFunc shutdown_module =
-        reinterpret_cast<PPP_ShutdownModuleFunc>(
-            base::GetFunctionPointerFromNativeLibrary(library_,
-                                                      "PPP_ShutdownModule"));
-    if (shutdown_module)
-      shutdown_module();
+  if (entry_points_.shutdown_module)
+    entry_points_.shutdown_module();
+
+  if (library_)
     base::UnloadNativeLibrary(library_);
-  }
 }
 
 // static
 scoped_refptr<PluginModule> PluginModule::CreateModule(
-    const FilePath& filename) {
+    const FilePath& path) {
   // FIXME(brettw) do uniquifying of the plugin here like the NPAPI one.
 
-  scoped_refptr<PluginModule> lib(new PluginModule(filename));
-  if (!lib->Load())
-    lib = NULL;
+  scoped_refptr<PluginModule> lib(new PluginModule());
+  if (!lib->InitFromFile(path))
+    return NULL;
+
+  return lib;
+}
+
+scoped_refptr<PluginModule> PluginModule::CreateInternalModule(
+    EntryPoints entry_points) {
+  scoped_refptr<PluginModule> lib(new PluginModule());
+  if (!lib->InitFromEntryPoints(entry_points))
+    return NULL;
+
   return lib;
 }
 
@@ -233,39 +234,71 @@ PluginModule* PluginModule::FromPPModule(PP_Module module) {
   return lib;
 }
 
-bool PluginModule::Load() {
+bool PluginModule::InitFromEntryPoints(const EntryPoints& entry_points) {
   if (initialized_)
     return true;
+
+  // Attempt to run the initialization funciton.
+  int retval = entry_points.initialize_module(GetPPModule(), &GetInterface);
+  if (retval != 0) {
+    LOG(WARNING) << "PPP_InitializeModule returned failure " << retval;
+    return false;
+  }
+
+  entry_points_ = entry_points;
   initialized_ = true;
+  return true;
+}
 
-  library_ = base::LoadNativeLibrary(filename_);
-  if (!library_)
+bool PluginModule::InitFromFile(const FilePath& path) {
+  if (initialized_)
+    return true;
+
+  base::NativeLibrary library = base::LoadNativeLibrary(path);
+  if (!library)
     return false;
 
-  // Save the GetInterface function pointer for later.
-  ppp_get_interface_ =
+  EntryPoints entry_points;
+  if (!LoadEntryPoints(library, &entry_points) ||
+      !InitFromEntryPoints(entry_points)) {
+    base::UnloadNativeLibrary(library);
+    return false;
+  }
+
+  // We let InitFromEntryPoints() handle setting the all the internal state
+  // of the object other than the |library_| reference.
+  library_ = library;
+  return true;
+}
+
+// static
+bool PluginModule::LoadEntryPoints(const base::NativeLibrary& library,
+                                   EntryPoints* entry_points) {
+
+  entry_points->get_interface =
       reinterpret_cast<PPP_GetInterfaceFunc>(
-          base::GetFunctionPointerFromNativeLibrary(library_,
+          base::GetFunctionPointerFromNativeLibrary(library,
                                                     "PPP_GetInterface"));
-  if (!ppp_get_interface_) {
+  if (!entry_points->get_interface) {
     LOG(WARNING) << "No PPP_GetInterface in plugin library";
     return false;
   }
 
-  // Call the plugin initialize function.
-  PPP_InitializeModuleFunc initialize_module =
+  entry_points->initialize_module =
       reinterpret_cast<PPP_InitializeModuleFunc>(
-          base::GetFunctionPointerFromNativeLibrary(library_,
+          base::GetFunctionPointerFromNativeLibrary(library,
                                                     "PPP_InitializeModule"));
-  if (!initialize_module) {
+  if (!entry_points->initialize_module) {
     LOG(WARNING) << "No PPP_InitializeModule in plugin library";
     return false;
   }
-  int retval = initialize_module(GetPPModule(), &GetInterface);
-  if (retval != 0) {
-    LOG(WARNING) << "PPP_InitializeModule returned failure " << retval;
-    return false;
-  }
+
+  // It's okay for PPP_ShutdownModule to not be defined and shutdown_module to
+  // be NULL.
+  entry_points->shutdown_module =
+      reinterpret_cast<PPP_ShutdownModuleFunc>(
+          base::GetFunctionPointerFromNativeLibrary(library,
+                                                    "PPP_ShutdownModule"));
 
   return true;
 }
@@ -293,9 +326,9 @@ PluginInstance* PluginModule::GetSomeInstance() const {
 }
 
 const void* PluginModule::GetPluginInterface(const char* name) const {
-  if (!ppp_get_interface_)
+  if (!entry_points_.get_interface)
     return NULL;
-  return ppp_get_interface_(name);
+  return entry_points_.get_interface(name);
 }
 
 void PluginModule::InstanceCreated(PluginInstance* instance) {
diff --git a/webkit/glue/plugins/pepper_plugin_module.h b/webkit/glue/plugins/pepper_plugin_module.h
index 0498c451d6a28..1b2d9fb60ad07 100644
--- a/webkit/glue/plugins/pepper_plugin_module.h
+++ b/webkit/glue/plugins/pepper_plugin_module.h
@@ -12,6 +12,7 @@
 #include "base/native_library.h"
 #include "base/ref_counted.h"
 #include "third_party/ppapi/c/pp_module.h"
+#include "third_party/ppapi/c/ppb.h"
 
 namespace pepper {
 
@@ -20,9 +21,27 @@ class PluginInstance;
 
 class PluginModule : public base::RefCounted<PluginModule> {
  public:
+  typedef const void* (*PPP_GetInterfaceFunc)(const char*);
+  typedef int (*PPP_InitializeModuleFunc)(PP_Module, PPB_GetInterface);
+  typedef void (*PPP_ShutdownModuleFunc)();
+
+  struct EntryPoints {
+    EntryPoints()
+        : get_interface(NULL),
+          initialize_module(NULL),
+          shutdown_module(NULL) {
+    }
+
+    PPP_GetInterfaceFunc get_interface;
+    PPP_InitializeModuleFunc initialize_module;
+    PPP_ShutdownModuleFunc shutdown_module;
+  };
+
   ~PluginModule();
 
-  static scoped_refptr<PluginModule> CreateModule(const FilePath& filename);
+  static scoped_refptr<PluginModule> CreateModule(const FilePath& path);
+  static scoped_refptr<PluginModule> CreateInternalModule(
+      EntryPoints entry_points);
 
   // Converts the given module ID to an actual module object. Will return NULL
   // if the module is invalid.
@@ -47,18 +66,24 @@ class PluginModule : public base::RefCounted<PluginModule> {
   void InstanceDeleted(PluginInstance* instance);
 
  private:
-  typedef const void* (*PPP_GetInterfaceFunc)(const char*);
-
-  explicit PluginModule(const FilePath& filename);
+  PluginModule();
 
-  bool Load();
-
-  FilePath filename_;
+  bool InitFromEntryPoints(const EntryPoints& entry_points);
+  bool InitFromFile(const FilePath& path);
+  static bool LoadEntryPoints(const base::NativeLibrary& library,
+                              EntryPoints* entry_points);
 
   bool initialized_;
+
+  // Holds a reference to the base::NativeLibrary handle if this PluginModule
+  // instance wraps functions loaded from a library.  Can be NULL.  If
+  // |library_| is non-NULL, PluginModule will attempt to unload the library
+  // during destruction.
   base::NativeLibrary library_;
 
-  PPP_GetInterfaceFunc ppp_get_interface_;
+  // Contains pointers to the entry points of the actual plugin
+  // implementation.
+  EntryPoints entry_points_;
 
   // Non-owning pointers to all instances associated with this module. When
   // there are no more instances, this object should be deleted.
-- 
GitLab