Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
EvBrowserPluginMain.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Igalia S.L.
3  *
4  * Evince is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * Evince is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "config.h"
20 
21 #include "EvBrowserPlugin.h"
22 #include "EvMemoryUtils.h"
23 #include "npfunctions.h"
24 #include "npruntime.h"
25 #include <gdk/gdk.h>
26 #ifdef GDK_WINDOWING_WAYLAND
27 #include <gdk/gdkwayland.h>
28 #endif
29 
32 
34 {
35  if (!instance)
36  return nullptr;
37 
38  return static_cast<EvBrowserPlugin *>(instance->pdata);
39 }
40 
41 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *savedData)
42 {
43  if (!instance)
45 
46  return EvBrowserPlugin::create(instance)->initialize(pluginType, mode, argc, argn, argv, savedData);
47 }
48 
49 NPError NPP_Destroy(NPP instance, NPSavedData **saveData)
50 {
51  EvBrowserPlugin *plugin = pluginForInstance(instance);
52  if (!plugin)
54 
55  browser->releaseobject(static_cast<NPObject *>(plugin));
56  return NPERR_NO_ERROR;
57 }
58 
60 {
61  EvBrowserPlugin *plugin = pluginForInstance(instance);
62  if (!plugin)
64 
65  return plugin->setWindow(window);
66 }
67 
68 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16_t *stype)
69 {
70  EvBrowserPlugin *plugin = pluginForInstance(instance);
71  if (!plugin)
73 
74  return plugin->newStream(type, stream, seekable, stype);
75 }
76 
77 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
78 {
79  EvBrowserPlugin *plugin = pluginForInstance(instance);
80  if (!plugin)
82 
83  return plugin->destroyStream(stream, reason);
84 }
85 
86 void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
87 {
88  EvBrowserPlugin *plugin = pluginForInstance(instance);
89  if (!plugin)
90  return;
91 
92  return plugin->streamAsFile(stream, fname);
93 }
94 
95 int32_t NPP_WriteReady(NPP instance, NPStream *stream)
96 {
97  EvBrowserPlugin *plugin = pluginForInstance(instance);
98  if (!plugin)
99  return -1;
100 
101  return plugin->writeReady(stream);
102 }
103 
104 int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, void *buffer)
105 {
106  EvBrowserPlugin *plugin = pluginForInstance(instance);
107  if (!plugin)
108  return -1;
109 
110  return plugin->write(stream, offset, len, buffer);
111 }
112 
113 void NPP_Print(NPP instance, NPPrint *platformPrint)
114 {
115  EvBrowserPlugin *plugin = pluginForInstance(instance);
116  if (!plugin)
117  return;
118 
119  return plugin->print(platformPrint);
120 }
121 
122 int16_t NPP_HandleEvent(NPP instance, void *event)
123 {
124  EvBrowserPlugin *plugin = pluginForInstance(instance);
125  if (!plugin)
126  return 0;
127 
128  return plugin->handleEvent(static_cast<XEvent *>(event));
129 }
130 
131 void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
132 {
133  EvBrowserPlugin *plugin = pluginForInstance(instance);
134  if (!plugin)
135  return;
136 
137  return plugin->urlNotify(url, reason, notifyData);
138 }
139 
140 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
141 {
142  switch (variable) {
144  *((char **)value) = const_cast<char *>(EvBrowserPlugin::nameString());
145  return NPERR_NO_ERROR;
147  *((char **)value) = const_cast<char *>(EvBrowserPlugin::descriptionString());
148  return NPERR_NO_ERROR;
150  *((NPBool *)value) = TRUE;
151  return NPERR_NO_ERROR;
153  EvBrowserPlugin *plugin = pluginForInstance(instance);
154  if (!plugin)
156 
157  browser->retainobject(static_cast<NPObject *>(plugin));
158  *((NPObject **)value) = plugin;
159  return NPERR_NO_ERROR;
160  }
161  default:
162  return NPERR_INVALID_PARAM;
163  }
164 
165  return NPERR_GENERIC_ERROR;
166 }
167 
169 {
170  return NPERR_NO_ERROR;
171 }
172 
173 static void initializePluginFuncs(NPPluginFuncs *pluginFuncs)
174 {
175  pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
176  pluginFuncs->size = sizeof(pluginFuncs);
177  pluginFuncs->newp = NPP_New;
178  pluginFuncs->destroy = NPP_Destroy;
179  pluginFuncs->setwindow = NPP_SetWindow;
180  pluginFuncs->newstream = NPP_NewStream;
181  pluginFuncs->destroystream = NPP_DestroyStream;
182  pluginFuncs->asfile = NPP_StreamAsFile;
183  pluginFuncs->writeready = NPP_WriteReady;
184  pluginFuncs->write = NPP_Write;
185  pluginFuncs->print = NPP_Print;
186  pluginFuncs->event = NPP_HandleEvent;
187  pluginFuncs->urlnotify = NPP_URLNotify;
188  pluginFuncs->getvalue = NPP_GetValue;
189  pluginFuncs->setvalue = NPP_SetValue;
190 }
191 
193 {
194  if (!browserFuncs || !pluginFuncs)
196 
197  if ((browserFuncs->version >> 8) > NP_VERSION_MAJOR)
199 
200  if (!ev_init())
201  return NPERR_GENERIC_ERROR;
202 
203  gtk_init(nullptr, nullptr);
204 
205 #ifdef GDK_WINDOWING_WAYLAND
206  if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
207  return NPERR_GENERIC_ERROR;
208 #endif
209 
210  browser = browserFuncs;
211  initializePluginFuncs(pluginFuncs);
212 
213  GBytes *resourceData = g_resources_lookup_data("/org/gnome/evince/browser/ui/evince-browser.css", G_RESOURCE_LOOKUP_FLAGS_NONE, nullptr);
214  if (resourceData) {
215  GtkCssProvider *cssProvider = gtk_css_provider_new();
216 
217  gtk_css_provider_load_from_data(cssProvider, static_cast<const gchar *>(g_bytes_get_data(resourceData, nullptr)), g_bytes_get_size(resourceData), nullptr);
218  g_bytes_unref(resourceData);
219 
220  gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
221  g_object_unref(cssProvider);
222  }
223 
224  return NPERR_NO_ERROR;
225 }
226 
228 {
229  ev_shutdown();
230  return NPERR_NO_ERROR;
231 }
232 
233 static const struct {
234  const char *mime;
235  const char *extensions;
236 } mimeExtensions[] = {
237  { "application/postscript", "ps" },
238  { "application/x-ext-ps", "ps" },
239  { "application/x-bzpostscript", "ps.bz2" },
240  { "application/x-gzpostscript", "ps.gz" },
241  { "image/x-eps", "eps,epsi,epsf" },
242  { "application/x-ext-eps", "eps,epsi,epsf" },
243  { "image/x-bzeps", "eps.bz2,epsi.bz2,epsf.bz2" },
244  { "image/x-gzeps", "eps.gz,epsi.gz,epsf.gz" },
245  { "image/tiff", "tif,tiff" },
246  { "application/pdf", "pdf" },
247  { "application/x-ext-pdf", "pdf" },
248  { "application/x-bzpdf", "pdf.bz2" },
249  { "application/x-gzpdf", "pdf.gz" },
250  { "application/x-xzpdf", "pdf.xz" },
251  { "application/x-dvi", "dvi" },
252  { "application/x-ext-dvi", "dvi" },
253  { "application/x-bzdvi", "dvi.bz2" },
254  { "application/x-gzdvi", "dvi.gz" },
255  { "application/x-cbr", "cbr" },
256  { "application/x-ext-cbr", "cbr" },
257  { "application/x-cbz", "cbz" },
258  { "application/x-ext-cbz", "cbz" },
259  { "application/x-cb7", "cb7" },
260  { "application/x-ext-cb7", "cb7" },
261  { "application/x-cbt", "cbt" },
262  { "application/x-ext-cbt", "cbt" },
263  { "image/vnd.djvu", "djvu,djv" },
264  { "image/vnd.djvu+multipage", "djvu,djv" },
265  { "application/x-ext-djv", "djv" },
266  { "application/x-ext-djvu", "djvu" },
267  { "application/oxps", "xps,oxps" },
268  { "application/vnd.ms-xpsdocument", "xps,oxps" }
269 };
270 
272 {
273  if (mimeDescription)
274  return mimeDescription.get();
275 
276  if (!ev_init())
277  return nullptr;
278 
279 #ifdef GDK_WINDOWING_WAYLAND
280  if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
281  return nullptr;
282 #endif
283 
284  GString *mimeDescriptionStr = g_string_new(nullptr);
285 
286  GList *typesInfo = ev_backends_manager_get_all_types_info();
287  for (GList *l = typesInfo; l; l = g_list_next(l)) {
288  EvTypeInfo *info = static_cast<EvTypeInfo *>(l->data);
289 
290  for (unsigned i = 0; info->mime_types[i]; ++i) {
291  const char *extensions = [](const char *mime) -> const char * {
292  for (unsigned i = 0; i < G_N_ELEMENTS(mimeExtensions); ++i) {
293  if (g_ascii_strcasecmp(mimeExtensions[i].mime, mime) == 0)
294  return mimeExtensions[i].extensions;
295  }
296 
297  return nullptr;
298  }(info->mime_types[i]);
299 
300  if (!extensions)
301  continue;
302 
303  g_string_append_printf(mimeDescriptionStr, "%s:%s:%s;",
304  info->mime_types[i],
305  extensions,
306  info->desc);
307  }
308  }
309  g_list_free(typesInfo);
310 
311  mimeDescription.reset(g_string_free(mimeDescriptionStr, FALSE));
312 
313  ev_shutdown();
314 
315  return mimeDescription.get();
316 }
317 
318 NPError NP_GetValue(void *, NPPVariable variable, void *value)
319 {
320  return NPP_GetValue(nullptr, variable, value);
321 }
322 
323 NPObject *NPN_CreateObject(NPP instance, NPClass *npClass)
324 {
325  return browser->createobject(instance, npClass);
326 }
327 
328 void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
329 {
330  browser->getstringidentifiers(names, nameCount, identifiers);
331 }
332 
333 NPError NPN_GetURL(NPP instance, const char* url, const char* target)
334 {
335  return browser->geturl(instance, url, target);
336 }
337 
338 const char *NPN_UserAgent(NPP instance)
339 {
340  return browser->uagent(instance);
341 }
342 
343 void *NPN_MemAlloc(uint32_t size)
344 {
345  return browser->memalloc(size);
346 }
347 
348 void NPN_MemFree(void* ptr)
349 {
350  if (ptr)
351  browser->memfree(ptr);
352 }
353 
354 static void __attribute__((constructor)) browserPluginConstructor()
355 {
356  ev_init();
357 }
358 
359 static void __attribute__((destructor)) browserPluginDestructor()
360 {
361  ev_shutdown();
362 }