summaryrefslogtreecommitdiffstats
path: root/ppapi/cpp/module.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 16:16:50 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 16:16:50 +0000
commit1758e88fd909ea0ffd49621e8066ffad5627ffdf (patch)
treec304a5eed047cae5665f5af1739d84655fb5815d /ppapi/cpp/module.cc
parente7d8b51953b7d3b2b8a0aba46132305b32f3efce (diff)
downloadchromium_src-1758e88fd909ea0ffd49621e8066ffad5627ffdf.zip
chromium_src-1758e88fd909ea0ffd49621e8066ffad5627ffdf.tar.gz
chromium_src-1758e88fd909ea0ffd49621e8066ffad5627ffdf.tar.bz2
Move PPAPI into the Chrome repo. The old repo was
http://ppapi.googlecode.com/ TEST=none BUG=none git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64613 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/cpp/module.cc')
-rw-r--r--ppapi/cpp/module.cc198
1 files changed, 198 insertions, 0 deletions
diff --git a/ppapi/cpp/module.cc b/ppapi/cpp/module.cc
new file mode 100644
index 0000000..fe32569
--- /dev/null
+++ b/ppapi/cpp/module.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.
+
+// Note that the single accessor, Module::Get(), is not actually implemented
+// in this file. This is an intentional hook that allows users of ppapi's
+// C++ wrapper objects to provide difference semantics for how the singleton
+// object is accessed.
+//
+// In general, users of ppapi will also link in ppp_entrypoints.cc, which
+// provides a simple default implementation of Module::Get().
+//
+// A notable exception where the default ppp_entrypoints will not work is
+// when implementing "internal plugins" that are statically linked into the
+// browser. In this case, the process may actually have multiple Modules
+// loaded at once making a traditional "singleton" unworkable. To get around
+// this, the users of ppapi need to get creative about how to properly
+// implement the Module::Get() so that ppapi's C++ wrappers can find the
+// right Module object. One example solution is to use thread local storage
+// to change the Module* returned based on which thread is invoking the
+// function. Leaving Module::Get() unimplemented provides a hook for
+// implementing such behavior.
+
+#include "ppapi/cpp/module.h"
+
+#include <string.h>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/cpp/dev/url_loader_dev.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/resource.h"
+#include "ppapi/cpp/var.h"
+
+namespace pp {
+
+// PPP_Instance implementation -------------------------------------------------
+
+bool Instance_DidCreate(PP_Instance pp_instance,
+ uint32_t argc,
+ const char* argn[],
+ const char* argv[]) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return false;
+
+ Instance* instance = module_singleton->CreateInstance(pp_instance);
+ if (!instance)
+ return false;
+ module_singleton->current_instances_[pp_instance] = instance;
+ return instance->Init(argc, argn, argv);
+}
+
+void Instance_DidDestroy(PP_Instance instance) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return;
+ Module::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.
+ Instance* obj = found->second;
+ module_singleton->current_instances_.erase(found);
+ delete obj;
+}
+
+void Instance_DidChangeView(PP_Instance pp_instance,
+ const PP_Rect* position,
+ const PP_Rect* clip) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->DidChangeView(*position, *clip);
+}
+
+void Instance_DidChangeFocus(PP_Instance pp_instance, bool has_focus) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->DidChangeFocus(has_focus);
+}
+
+bool Instance_HandleInputEvent(PP_Instance pp_instance,
+ const PP_InputEvent* event) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return false;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return false;
+ return instance->HandleInputEvent(*event);
+}
+
+bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
+ PP_Resource pp_url_loader) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return false;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return false;
+ return instance->HandleDocumentLoad(URLLoader_Dev(pp_url_loader));
+}
+
+PP_Var Instance_GetInstanceObject(PP_Instance pp_instance) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return Var().Detach();
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return Var().Detach();
+ return instance->GetInstanceObject().Detach();
+}
+
+static PPP_Instance instance_interface = {
+ &Instance_DidCreate,
+ &Instance_DidDestroy,
+ &Instance_DidChangeView,
+ &Instance_DidChangeFocus,
+ &Instance_HandleInputEvent,
+ &Instance_HandleDocumentLoad,
+ &Instance_GetInstanceObject
+};
+
+// Module ----------------------------------------------------------------------
+
+Module::Module() : pp_module_(0), get_browser_interface_(NULL), core_(NULL) {
+}
+
+Module::~Module() {
+ delete core_;
+ core_ = NULL;
+}
+
+const void* Module::GetPluginInterface(const char* interface_name) {
+ if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
+ return &instance_interface;
+
+ // Now see if anything was dynamically registered.
+ InterfaceMap::const_iterator found = additional_interfaces_.find(
+ std::string(interface_name));
+ if (found != additional_interfaces_.end())
+ return found->second;
+
+ return NULL;
+}
+
+const void* Module::GetBrowserInterface(const char* interface_name) {
+ return get_browser_interface_(interface_name);
+}
+
+Instance* Module::InstanceForPPInstance(PP_Instance instance) {
+ InstanceMap::iterator found = current_instances_.find(instance);
+ if (found == current_instances_.end())
+ return NULL;
+ return found->second;
+}
+
+void Module::AddPluginInterface(const std::string& interface_name,
+ const void* vtable) {
+ // Verify that we're not trying to register an interface that's already
+ // handled, and if it is, that we're re-registering with the same vtable.
+ // Calling GetPluginInterface rather than looking it up in the map allows
+ // us to also catch "internal" ones in addition to just previously added ones.
+ const void* existing_interface = GetPluginInterface(interface_name.c_str());
+ if (existing_interface) {
+ PP_DCHECK(vtable == existing_interface);
+ return;
+ }
+ additional_interfaces_[interface_name] = vtable;
+}
+
+bool Module::InternalInit(PP_Module mod,
+ PPB_GetInterface get_browser_interface) {
+ pp_module_ = mod;
+ get_browser_interface_ = get_browser_interface;
+
+ // Get the core interface which we require to run.
+ const PPB_Core* core = reinterpret_cast<const PPB_Core*>(GetBrowserInterface(
+ PPB_CORE_INTERFACE));
+ if (!core)
+ return false;
+ core_ = new Core(core);
+
+ return Init();
+}
+
+} // namespace pp