summaryrefslogtreecommitdiff
path: root/chromium/ppapi/cpp/module.cc
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/ppapi/cpp/module.cc
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'chromium/ppapi/cpp/module.cc')
-rw-r--r--chromium/ppapi/cpp/module.cc219
1 files changed, 219 insertions, 0 deletions
diff --git a/chromium/ppapi/cpp/module.cc b/chromium/ppapi/cpp/module.cc
new file mode 100644
index 00000000000..505991d6e58
--- /dev/null
+++ b/chromium/ppapi/cpp/module.cc
@@ -0,0 +1,219 @@
+// Copyright (c) 2012 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 different 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_input_event.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/c/ppp_messaging.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/resource.h"
+#include "ppapi/cpp/url_loader.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/cpp/view.h"
+
+namespace pp {
+
+// PPP_InputEvent implementation -----------------------------------------------
+
+PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resource) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return PP_FALSE;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return PP_FALSE;
+
+ return PP_FromBool(instance->HandleInputEvent(InputEvent(resource)));
+}
+
+const PPP_InputEvent input_event_interface = {
+ &InputEvent_HandleEvent
+};
+
+// PPP_Instance implementation -------------------------------------------------
+
+PP_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 PP_FALSE;
+
+ Instance* instance = module_singleton->CreateInstance(pp_instance);
+ if (!instance)
+ return PP_FALSE;
+ module_singleton->current_instances_[pp_instance] = instance;
+ return PP_FromBool(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,
+ PP_Resource view_resource) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->DidChangeView(View(view_resource));
+}
+
+void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->DidChangeFocus(PP_ToBool(has_focus));
+}
+
+PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
+ PP_Resource pp_url_loader) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return PP_FALSE;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return PP_FALSE;
+ return PP_FromBool(instance->HandleDocumentLoad(URLLoader(pp_url_loader)));
+}
+
+static PPP_Instance instance_interface = {
+ &Instance_DidCreate,
+ &Instance_DidDestroy,
+ &Instance_DidChangeView,
+ &Instance_DidChangeFocus,
+ &Instance_HandleDocumentLoad
+};
+
+// PPP_Messaging implementation ------------------------------------------------
+
+void Messaging_HandleMessage(PP_Instance pp_instance, PP_Var var) {
+ Module* module_singleton = Module::Get();
+ if (!module_singleton)
+ return;
+ Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->HandleMessage(Var(PASS_REF, var));
+}
+
+static PPP_Messaging instance_messaging_interface = {
+ &Messaging_HandleMessage
+};
+
+// Module ----------------------------------------------------------------------
+
+Module::Module() : pp_module_(0), get_browser_interface_(NULL), core_(NULL) {
+}
+
+Module::~Module() {
+ delete core_;
+ core_ = NULL;
+}
+
+bool Module::Init() {
+ return true;
+}
+
+const void* Module::GetPluginInterface(const char* interface_name) {
+ if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0)
+ return &input_event_interface;
+ if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
+ return &instance_interface;
+ if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0)
+ return &instance_messaging_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