diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-01 16:16:50 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-01 16:16:50 +0000 |
commit | 1758e88fd909ea0ffd49621e8066ffad5627ffdf (patch) | |
tree | c304a5eed047cae5665f5af1739d84655fb5815d /ppapi/cpp/module.cc | |
parent | e7d8b51953b7d3b2b8a0aba46132305b32f3efce (diff) | |
download | chromium_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.cc | 198 |
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 |