OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 #include "remoting/client/pepper/pepper_plugin.h" | |
6 #include "third_party/npapi/bindings/npapi.h" | |
7 #include "third_party/npapi/bindings/nphostapi.h" | |
8 | |
9 #if __GNUC__ >= 4 | |
10 # define EXPORT __attribute__ ((visibility("default"))) | |
11 # define PRIVATE __attribute__ ((visibility("hidden"))) | |
12 #else | |
13 # define EXPORT | |
14 # define PRIVATE | |
15 #endif | |
16 | |
17 // | |
18 // External Plugin Implementation | |
19 // | |
20 | |
21 // Plugin info. | |
22 // These routines are defined externally and provide the code that is specific | |
23 // to this particular plugin. | |
24 | |
25 // Initialize general plugin information. | |
26 extern void InitializePluginInfo(pepper::PepperPlugin::Info* plugin_info); | |
27 | |
28 // Routine to create the PepperPlugin subclass that implements all of the | |
29 // plugin-specific functionality. | |
30 extern pepper::PepperPlugin* CreatePlugin(NPNetscapeFuncs* browser_funcs, | |
31 NPP instance); | |
32 | |
33 namespace pepper { | |
34 | |
35 // | |
36 // Globals | |
37 // | |
38 | |
39 // Pointer to struct containing all the callbacks provided by the browser | |
40 // to the plugin. | |
41 NPNetscapeFuncs* g_browser_funcs = NULL; | |
42 | |
43 // General information (name/description) about this plugin. | |
44 PepperPlugin::Info g_plugin_info = { false, NULL, NULL, NULL }; | |
45 | |
46 | |
47 // | |
48 // Internal setup routines | |
49 // | |
50 | |
51 PRIVATE void Initialize(NPNetscapeFuncs* browser_funcs) { | |
52 g_browser_funcs = browser_funcs; | |
53 if (!g_plugin_info.initialized) { | |
54 InitializePluginInfo(&g_plugin_info); | |
55 } | |
56 } | |
57 | |
58 // Populate the NPPluginFuncs struct so that the browser knows how to find | |
59 // each entry point for the plugin. | |
60 PRIVATE void SetupEntryPoints(NPPluginFuncs* plugin_funcs) { | |
61 plugin_funcs->version = ((NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR); | |
62 plugin_funcs->size = sizeof(NPPluginFuncs); | |
63 plugin_funcs->newp = NPP_New; | |
64 plugin_funcs->destroy = NPP_Destroy; | |
65 plugin_funcs->setwindow = NPP_SetWindow; | |
66 plugin_funcs->newstream = NPP_NewStream; | |
67 plugin_funcs->destroystream = NPP_DestroyStream; | |
68 plugin_funcs->asfile = NPP_StreamAsFile; | |
69 plugin_funcs->writeready = NPP_WriteReady; | |
70 plugin_funcs->write = NPP_Write; | |
71 plugin_funcs->print = NPP_Print; | |
72 plugin_funcs->event = NPP_HandleEvent; | |
73 plugin_funcs->urlnotify = NPP_URLNotify; | |
74 plugin_funcs->javaClass = NULL; | |
75 plugin_funcs->getvalue = NPP_GetValue; | |
76 plugin_funcs->setvalue = NPP_SetValue; | |
77 } | |
78 | |
79 // Get the PepperPlugin from the private data storage in the instance. | |
80 PRIVATE PepperPlugin* GetPlugin(NPP instance) { | |
81 return static_cast<PepperPlugin*>(instance->pdata); | |
82 } | |
83 | |
84 } // namespace pepper | |
85 | |
86 | |
87 // | |
88 // Exported interfaces | |
89 // Routines to initialize/shutdown the plugin. | |
90 // | |
91 | |
92 extern "C" { | |
93 | |
94 #if defined(OS_POSIX) && !defined(OS_MACOSX) | |
95 | |
96 // Get the MIME-type associated with this plugin. | |
97 // Linux-only. Mac & Windows use a different mechanism for associating a | |
98 // MIME-type with the plugin. | |
99 // Note that this is called before NPP_Initialize(). | |
100 EXPORT const char* API_CALL NP_GetMIMEDescription() { | |
101 if (!pepper::g_plugin_info.initialized) { | |
102 InitializePluginInfo(&pepper::g_plugin_info); | |
103 } | |
104 return pepper::g_plugin_info.mime_description; | |
105 } | |
106 | |
107 // Old version of NPP_GetValue, required for Linux. | |
108 // Simply redirects to the NPP_GetValue. | |
109 EXPORT NPError API_CALL NP_GetValue(NPP instance, | |
110 NPPVariable variable, | |
111 void* value) { | |
112 return NPP_GetValue(instance, variable, value); | |
113 } | |
114 | |
115 // NP_Initialize for Linux. | |
116 // This is the equivalent of NP_Initialize and NP_GetEntryPoints for Mac/Win. | |
117 EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs, | |
118 NPPluginFuncs* plugin_funcs) { | |
119 pepper::Initialize(browser_funcs); | |
120 pepper::SetupEntryPoints(plugin_funcs); | |
121 return NPERR_NO_ERROR; | |
122 } | |
123 | |
124 #else | |
125 | |
126 // NP_Initialize for Mac/Windows. | |
127 EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs) { | |
128 pepper::Initialize(browser_funcs); | |
129 return NPERR_NO_ERROR; | |
130 } | |
131 | |
132 // NP_GetEntryPoints for Mac/Windows. | |
133 EXPORT NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) { | |
134 pepper::SetupEntryPoints(plugin_funcs); | |
135 return NPERR_NO_ERROR; | |
136 } | |
137 | |
138 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) | |
139 | |
140 EXPORT NPError API_CALL NP_Shutdown() { | |
141 pepper::g_browser_funcs = NULL; | |
142 return NPERR_NO_ERROR; | |
143 } | |
144 | |
145 } // extern "C" | |
146 | |
147 | |
148 // | |
149 // Plugin Entrypoints | |
150 // Entry points that the plugin makes available to the browser. | |
151 // | |
152 | |
153 EXPORT NPError NPP_New(NPMIMEType pluginType, | |
154 NPP instance, | |
155 uint16 mode, | |
156 int16 argc, | |
157 char* argn[], | |
158 char* argv[], | |
159 NPSavedData* saved) { | |
160 if (!instance) { | |
161 return NPERR_INVALID_INSTANCE_ERROR; | |
162 } | |
163 | |
164 pepper::PepperPlugin* plugin | |
165 = CreatePlugin(pepper::g_browser_funcs, instance); | |
166 NPError result = plugin->New(pluginType, argc, argn, argv); | |
167 if (result != NPERR_NO_ERROR) { | |
168 delete plugin; | |
169 return result; | |
170 } | |
171 | |
172 instance->pdata = plugin; | |
173 return NPERR_NO_ERROR; | |
174 } | |
175 | |
176 EXPORT NPError NPP_Destroy(NPP instance, NPSavedData** save) { | |
177 if (!instance) { | |
178 return NPERR_INVALID_INSTANCE_ERROR; | |
179 } | |
180 | |
181 NPError result = NPERR_NO_ERROR; | |
182 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
183 if (plugin) { | |
184 result = plugin->Destroy(save); | |
185 if (result != NPERR_NO_ERROR) { | |
186 return result; | |
187 } | |
188 delete plugin; | |
189 instance->pdata = NULL; | |
190 } | |
191 return result; | |
192 } | |
193 | |
194 EXPORT NPError NPP_SetWindow(NPP instance, NPWindow* window) { | |
195 if (!instance) { | |
196 return NPERR_INVALID_INSTANCE_ERROR; | |
197 } | |
198 | |
199 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
200 if (plugin) { | |
201 return plugin->SetWindow(window); | |
202 } | |
203 | |
204 return NPERR_GENERIC_ERROR; | |
205 } | |
206 | |
207 EXPORT NPError NPP_NewStream(NPP instance, | |
208 NPMIMEType type, | |
209 NPStream* stream, | |
210 NPBool seekable, | |
211 uint16* stype) { | |
212 if (!instance) { | |
213 return NPERR_INVALID_INSTANCE_ERROR; | |
214 } | |
215 | |
216 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
217 if (plugin) { | |
218 return plugin->NewStream(type, stream, seekable, stype); | |
219 } | |
220 | |
221 return NPERR_GENERIC_ERROR; | |
222 } | |
223 | |
224 EXPORT NPError NPP_DestroyStream(NPP instance, | |
225 NPStream* stream, | |
226 NPReason reason) { | |
227 if (!instance) { | |
228 return NPERR_INVALID_INSTANCE_ERROR; | |
229 } | |
230 | |
231 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
232 if (plugin) { | |
233 return plugin->DestroyStream(stream, reason); | |
234 } | |
235 | |
236 return NPERR_GENERIC_ERROR; | |
237 } | |
238 | |
239 EXPORT void NPP_StreamAsFile(NPP instance, | |
240 NPStream* stream, | |
241 const char* fname) { | |
242 if (!instance) { | |
243 return; | |
244 } | |
245 | |
246 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
247 if (plugin) { | |
248 plugin->StreamAsFile(stream, fname); | |
249 } | |
250 } | |
251 | |
252 EXPORT int32 NPP_WriteReady(NPP instance, | |
253 NPStream* stream) { | |
254 if (!instance) { | |
255 return 0; | |
256 } | |
257 | |
258 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
259 if (plugin) { | |
260 return plugin->WriteReady(stream); | |
261 } | |
262 | |
263 return 0; | |
264 } | |
265 | |
266 EXPORT int32 NPP_Write(NPP instance, | |
267 NPStream* stream, | |
268 int32 offset, | |
269 int32 len, | |
270 void* buffer) { | |
271 if (!instance) { | |
272 return 0; | |
273 } | |
274 | |
275 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
276 if (plugin) { | |
277 return plugin->Write(stream, offset, len, buffer); | |
278 } | |
279 | |
280 return 0; | |
281 } | |
282 | |
283 EXPORT void NPP_Print(NPP instance, | |
284 NPPrint* platformPrint) { | |
285 if (!instance) { | |
286 return; | |
287 } | |
288 | |
289 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
290 if (plugin) { | |
291 plugin->Print(platformPrint); | |
292 } | |
293 } | |
294 | |
295 EXPORT int16 NPP_HandleEvent(NPP instance, | |
296 void* event) { | |
297 if (!instance) { | |
298 return false; | |
299 } | |
300 | |
301 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
302 if (plugin) { | |
303 return plugin->HandleEvent(event); | |
304 } | |
305 | |
306 return false; | |
307 } | |
308 | |
309 EXPORT void NPP_URLNotify(NPP instance, | |
310 const char* url, | |
311 NPReason reason, | |
312 void* notifyData) { | |
313 if (!instance) { | |
314 return; | |
315 } | |
316 | |
317 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
318 if (plugin) { | |
319 plugin->URLNotify(url, reason, notifyData); | |
320 } | |
321 } | |
322 | |
323 EXPORT NPError NPP_GetValue(NPP instance, | |
324 NPPVariable variable, | |
325 void* value) { | |
326 #if defined(OS_POSIX) && !defined(OS_MACOSX) | |
327 // Note that it is valid to call this routine before the plugin instance | |
328 // has been created. | |
329 // For example, the browser requests the name/description when plugin | |
330 // is loaded or when about:plugins is opened (whichever comes first). | |
331 // Thus, we can't check for a valid instance instance here and bail if | |
332 // it's not setup (like we do for the other routines). | |
333 | |
334 // If the name/description is being requested, then get that directly. | |
335 if (variable == NPPVpluginNameString) { | |
336 *((const char**)value) = pepper::g_plugin_info.plugin_name; | |
337 return NPERR_NO_ERROR; | |
338 } | |
339 if (variable == NPPVpluginDescriptionString) { | |
340 *((const char**)value) = pepper::g_plugin_info.plugin_description; | |
341 return NPERR_NO_ERROR; | |
342 } | |
343 if (variable == NPPVpluginNeedsXEmbed) { | |
344 *(static_cast<NPBool*>(value)) = true; | |
345 return NPERR_NO_ERROR; | |
346 } | |
347 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) | |
348 | |
349 if (instance) { | |
350 // If we have an instance, then let the plugin handle the call. | |
351 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
352 if (plugin) { | |
353 return plugin->GetValue(variable, value); | |
354 } | |
355 } | |
356 | |
357 return NPERR_GENERIC_ERROR; | |
358 } | |
359 | |
360 EXPORT NPError NPP_SetValue(NPP instance, | |
361 NPNVariable variable, | |
362 void* value) { | |
363 if (!instance) { | |
364 return NPERR_INVALID_INSTANCE_ERROR; | |
365 } | |
366 | |
367 pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); | |
368 if (plugin) { | |
369 return plugin->SetValue(variable, value); | |
370 } | |
371 | |
372 return NPERR_GENERIC_ERROR; | |
373 } | |
OLD | NEW |