Pepper_47_C++_interfaces
module.cc
Go to the documentation of this file.
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Note that the single accessor, Module::Get(), is not actually implemented
6 // in this file. This is an intentional hook that allows users of ppapi's
7 // C++ wrapper objects to provide different semantics for how the singleton
8 // object is accessed.
9 //
10 // In general, users of ppapi will also link in ppp_entrypoints.cc, which
11 // provides a simple default implementation of Module::Get().
12 //
13 // A notable exception where the default ppp_entrypoints will not work is
14 // when implementing "internal plugins" that are statically linked into the
15 // browser. In this case, the process may actually have multiple Modules
16 // loaded at once making a traditional "singleton" unworkable. To get around
17 // this, the users of ppapi need to get creative about how to properly
18 // implement the Module::Get() so that ppapi's C++ wrappers can find the
19 // right Module object. One example solution is to use thread local storage
20 // to change the Module* returned based on which thread is invoking the
21 // function. Leaving Module::Get() unimplemented provides a hook for
22 // implementing such behavior.
23 
24 #include "ppapi/cpp/module.h"
25 
26 #include <string.h>
27 
28 #include "ppapi/c/pp_instance.h"
29 #include "ppapi/c/pp_var.h"
30 #include "ppapi/c/ppp_input_event.h"
31 #include "ppapi/c/ppp_instance.h"
32 #include "ppapi/c/ppp_messaging.h"
33 #include "ppapi/cpp/input_event.h"
34 #include "ppapi/cpp/instance.h"
35 #include "ppapi/cpp/rect.h"
36 #include "ppapi/cpp/resource.h"
37 #include "ppapi/cpp/url_loader.h"
38 #include "ppapi/cpp/var.h"
39 #include "ppapi/cpp/view.h"
40 
41 namespace pp {
42 
43 // PPP_InputEvent implementation -----------------------------------------------
44 
45 PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resource) {
46  Module* module_singleton = Module::Get();
47  if (!module_singleton)
48  return PP_FALSE;
49  Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
50  if (!instance)
51  return PP_FALSE;
52 
53  return PP_FromBool(instance->HandleInputEvent(InputEvent(resource)));
54 }
55 
56 const PPP_InputEvent input_event_interface = {
58 };
59 
60 // PPP_Instance implementation -------------------------------------------------
61 
62 PP_Bool Instance_DidCreate(PP_Instance pp_instance,
63  uint32_t argc,
64  const char* argn[],
65  const char* argv[]) {
66  Module* module_singleton = Module::Get();
67  if (!module_singleton)
68  return PP_FALSE;
69 
70  Instance* instance = module_singleton->CreateInstance(pp_instance);
71  if (!instance)
72  return PP_FALSE;
73  module_singleton->current_instances_[pp_instance] = instance;
74  return PP_FromBool(instance->Init(argc, argn, argv));
75 }
76 
77 void Instance_DidDestroy(PP_Instance instance) {
78  Module* module_singleton = Module::Get();
79  if (!module_singleton)
80  return;
81  Module::InstanceMap::iterator found =
82  module_singleton->current_instances_.find(instance);
83  if (found == module_singleton->current_instances_.end())
84  return;
85 
86  // Remove it from the map before deleting to try to catch reentrancy.
87  Instance* obj = found->second;
88  module_singleton->current_instances_.erase(found);
89  delete obj;
90 }
91 
92 void Instance_DidChangeView(PP_Instance pp_instance,
93  PP_Resource view_resource) {
94  Module* module_singleton = Module::Get();
95  if (!module_singleton)
96  return;
97  Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
98  if (!instance)
99  return;
100  instance->DidChangeView(View(view_resource));
101 }
102 
103 void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
104  Module* module_singleton = Module::Get();
105  if (!module_singleton)
106  return;
107  Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
108  if (!instance)
109  return;
110  instance->DidChangeFocus(PP_ToBool(has_focus));
111 }
112 
113 PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
114  PP_Resource pp_url_loader) {
115  Module* module_singleton = Module::Get();
116  if (!module_singleton)
117  return PP_FALSE;
118  Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
119  if (!instance)
120  return PP_FALSE;
121  return PP_FromBool(instance->HandleDocumentLoad(URLLoader(pp_url_loader)));
122 }
123 
124 static PPP_Instance instance_interface = {
130 };
131 
132 // PPP_Messaging implementation ------------------------------------------------
133 
134 void Messaging_HandleMessage(PP_Instance pp_instance, PP_Var var) {
135  Module* module_singleton = Module::Get();
136  if (!module_singleton)
137  return;
138  Instance* instance = module_singleton->InstanceForPPInstance(pp_instance);
139  if (!instance)
140  return;
141  instance->HandleMessage(Var(PASS_REF, var));
142 }
143 
144 static PPP_Messaging instance_messaging_interface = {
146 };
147 
148 // Module ----------------------------------------------------------------------
149 
150 Module::Module() : pp_module_(0), get_browser_interface_(NULL), core_(NULL) {
151 }
152 
154  delete core_;
155  core_ = NULL;
156 }
157 
158 bool Module::Init() {
159  return true;
160 }
161 
162 const void* Module::GetPluginInterface(const char* interface_name) {
163  if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0)
164  return &input_event_interface;
165  if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
166  return &instance_interface;
167  if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0)
169 
170  // Now see if anything was dynamically registered.
171  InterfaceMap::const_iterator found = additional_interfaces_.find(
172  std::string(interface_name));
173  if (found != additional_interfaces_.end())
174  return found->second;
175 
176  return NULL;
177 }
178 
179 const void* Module::GetBrowserInterface(const char* interface_name) {
180  return get_browser_interface_(interface_name);
181 }
182 
183 Instance* Module::InstanceForPPInstance(PP_Instance instance) {
184  InstanceMap::iterator found = current_instances_.find(instance);
185  if (found == current_instances_.end())
186  return NULL;
187  return found->second;
188 }
189 
190 void Module::AddPluginInterface(const std::string& interface_name,
191  const void* vtable) {
192  // Verify that we're not trying to register an interface that's already
193  // handled, and if it is, that we're re-registering with the same vtable.
194  // Calling GetPluginInterface rather than looking it up in the map allows
195  // us to also catch "internal" ones in addition to just previously added ones.
196  const void* existing_interface = GetPluginInterface(interface_name.c_str());
197  if (existing_interface) {
198  PP_DCHECK(vtable == existing_interface);
199  return;
200  }
201  additional_interfaces_[interface_name] = vtable;
202 }
203 
204 bool Module::InternalInit(PP_Module mod,
205  PPB_GetInterface get_browser_interface) {
206  pp_module_ = mod;
207  get_browser_interface_ = get_browser_interface;
208 
209  // Get the core interface which we require to run.
210  const PPB_Core* core = reinterpret_cast<const PPB_Core*>(GetBrowserInterface(
211  PPB_CORE_INTERFACE));
212  if (!core)
213  return false;
214  core_ = new Core(core);
215 
216  return Init();
217 }
218 
219 } // namespace pp
virtual Instance * CreateInstance(PP_Instance instance)=0
PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resource)
Definition: module.cc:45
virtual bool Init(uint32_t argc, const char *argn[], const char *argv[])
Definition: instance.cc:88
Core * core()
Definition: module.h:74
#define PP_DCHECK(a)
Definition: logging.h:16
virtual void DidChangeView(const View &view)
Definition: instance.cc:93
void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus)
Definition: module.cc:103
virtual ~Module()
Definition: module.cc:153
virtual bool HandleInputEvent(const pp::InputEvent &event)
Definition: instance.cc:110
virtual void HandleMessage(const Var &message)
Definition: instance.cc:114
const void * GetBrowserInterface(const char *interface_name)
Definition: module.cc:179
void AddPluginInterface(const std::string &interface_name, const void *vtable)
Definition: module.cc:190
PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance, PP_Resource pp_url_loader)
Definition: module.cc:113
virtual void DidChangeFocus(bool has_focus)
Definition: instance.cc:102
virtual bool Init()
Definition: module.cc:158
static PPP_Instance instance_interface
Definition: module.cc:124
bool InternalInit(PP_Module mod, PPB_GetInterface get_browser_interface)
Definition: module.cc:204
const PPP_InputEvent input_event_interface
Definition: module.cc:56
Instance * InstanceForPPInstance(PP_Instance instance)
Definition: module.cc:183
void Messaging_HandleMessage(PP_Instance pp_instance, PP_Var var)
Definition: module.cc:134
PP_Bool Instance_DidCreate(PP_Instance pp_instance, uint32_t argc, const char *argn[], const char *argv[])
Definition: module.cc:62
Definition: view.h:20
void Instance_DidDestroy(PP_Instance instance)
Definition: module.cc:77
void Instance_DidChangeView(PP_Instance pp_instance, PP_Resource view_resource)
Definition: module.cc:92
PPB_GetInterface get_browser_interface() const
Definition: module.h:63
static PPP_Messaging instance_messaging_interface
Definition: module.cc:144
A generic type used for passing data types between the module and the page.
Definition: var.h:21
APIs related to memory management, time, and threads.
Definition: core.h:19
virtual bool HandleDocumentLoad(const URLLoader &url_loader)
Definition: instance.cc:106
static Module * Get()
const void * GetPluginInterface(const char *interface_name)
Definition: module.cc:162