diff --git a/Makefile.am b/Makefile.am index 3d87903d..ba9a5232 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,6 +25,10 @@ if ENABLE_PREVIEWER SUBDIRS += previewer endif +if ENABLE_BROWSER_PLUGIN +SUBDIRS += browser-plugin +endif + NULL = pkgconfigdir = $(libdir)/pkgconfig diff --git a/browser-plugin/EvBrowserPlugin.cpp b/browser-plugin/EvBrowserPlugin.cpp new file mode 100644 index 00000000..a974eb8a --- /dev/null +++ b/browser-plugin/EvBrowserPlugin.cpp @@ -0,0 +1,711 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "EvBrowserPlugin.h" + +#include "EvBrowserPluginToolbar.h" +#include "npfunctions.h" +#include +#include +#include +#include + +struct EvBrowserPluginClass { + enum Methods { + GoToPage, + ToggleContinuous, + ToggleDual, + ZoomIn, + ZoomOut, + Download, + Print, + + NumMethodIdentifiers + }; + + enum Properties { + CurrentPage, + PageCount, + Zoom, + ZoomMode, + Continuous, + Dual, + Toolbar, + + NumPropertyIdentifiers + }; + + EvBrowserPlugin* createObject(NPP instance) + { + if (!identifiersInitialized) { + NPN_GetStringIdentifiers(methodIdentifierNames, NumMethodIdentifiers, methodIdentifiers); + NPN_GetStringIdentifiers(propertyIdentifierNames, NumPropertyIdentifiers, propertyIdentifiers); + identifiersInitialized = true; + } + + return static_cast(NPN_CreateObject(instance, &npClass)); + } + + NPClass npClass; + + const NPUTF8 *methodIdentifierNames[NumMethodIdentifiers]; + const NPUTF8 *propertyIdentifierNames[NumPropertyIdentifiers]; + bool identifiersInitialized; + NPIdentifier methodIdentifiers[NumMethodIdentifiers]; + NPIdentifier propertyIdentifiers[NumPropertyIdentifiers]; +}; + +EvBrowserPlugin *EvBrowserPlugin::create(NPP instance) +{ + return s_pluginClass.createObject(instance); +} + +const char *EvBrowserPlugin::nameString() +{ + return "Evince Browser Plugin"; +} + +const char *EvBrowserPlugin::descriptionString() +{ + return "The Evince " PACKAGE_VERSION " plugin handles documents inside the browser window."; +} + +EvBrowserPlugin::EvBrowserPlugin(NPP instance) + : m_NPP(instance) + , m_window(nullptr) + , m_model(nullptr) + , m_view(nullptr) + , m_toolbar(nullptr) +{ + m_NPP->pdata = this; +} + +EvBrowserPlugin::~EvBrowserPlugin() +{ + if (m_window) + gtk_widget_destroy(m_window); + g_clear_object(&m_model); + m_NPP->pdata = nullptr; +} + +template +static inline void parseInteger(const char *strValue, IntegerType &intValue) +{ + static const IntegerType intMax = std::numeric_limits::max(); + static const bool isSigned = std::numeric_limits::is_signed; + + if (!strValue) + return; + + char *endPtr = nullptr; + errno = 0; + gint64 value = isSigned ? g_ascii_strtoll(strValue, &endPtr, 0) : g_ascii_strtoull(strValue, &endPtr, 0); + if (endPtr != strValue && errno == 0 && value <= intMax) + intValue = static_cast(value); +} + +static inline void parseDouble(const char *strValue, double &doubleValue) +{ + if (!strValue) + return; + + char *endPtr = nullptr; + errno = 0; + double value = g_ascii_strtod(strValue, &endPtr); + if (endPtr != strValue && errno == 0) + doubleValue = value; +} + +static inline void parseBoolean(const char *strValue, bool &boolValue) +{ + if (!strValue) + return; + + unique_gptr value(g_ascii_strdown(strValue, -1)); + if (g_ascii_strcasecmp(value.get(), "false") == 0 || g_ascii_strcasecmp(value.get(), "no") == 0) + boolValue = false; + else if (g_ascii_strcasecmp(value.get(), "true") == 0 || g_ascii_strcasecmp(value.get(), "yes") == 0) + boolValue = true; + else { + int intValue = boolValue; + parseInteger(strValue, intValue); + boolValue = intValue > 0; + } +} + +static inline void parseZoomMode(const char *strValue, EvSizingMode &sizingModeValue) +{ + if (!strValue) + return; + + unique_gptr value(g_ascii_strdown(strValue, -1)); + if (g_ascii_strcasecmp(value.get(), "none") == 0) + sizingModeValue = EV_SIZING_FREE; + else if (g_ascii_strcasecmp(value.get(), "fit-page") == 0) + sizingModeValue = EV_SIZING_FIT_PAGE; + else if (g_ascii_strcasecmp(value.get(), "fit-width") == 0) + sizingModeValue = EV_SIZING_FIT_WIDTH; + else if (g_ascii_strcasecmp(value.get(), "auto") == 0) + sizingModeValue = EV_SIZING_AUTOMATIC; +} + +NPError EvBrowserPlugin::initialize(NPMIMEType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *) +{ + // Default values. + bool toolbarVisible = true; + unsigned currentPage = 1; + EvSizingMode sizingMode = EV_SIZING_AUTOMATIC; + bool continuous = true; + bool dual = false; + double zoom = 0; + + for (int16_t i = 0; i < argc; ++i) { + if (g_ascii_strcasecmp(argn[i], "toolbar") == 0) + parseBoolean(argv[i], toolbarVisible); + else if (g_ascii_strcasecmp(argn[i], "currentpage") == 0) + parseInteger(argv[i], currentPage); + else if (g_ascii_strcasecmp(argn[i], "zoom") == 0) + parseDouble(argv[i], zoom); + else if (g_ascii_strcasecmp(argn[i], "zoommode") == 0) + parseZoomMode(argv[i], sizingMode); + else if (g_ascii_strcasecmp(argn[i], "continuous") == 0) + parseBoolean(argv[i], continuous); + else if (g_ascii_strcasecmp(argn[i], "dual") == 0) + parseBoolean(argv[i], dual); + } + + m_model = ev_document_model_new(); + if (currentPage > 0) + ev_document_model_set_page(m_model, currentPage - 1); + ev_document_model_set_continuous(m_model, continuous); + ev_document_model_set_page_layout(m_model, dual ? EV_PAGE_LAYOUT_DUAL : EV_PAGE_LAYOUT_SINGLE); + if (zoom) { + ev_document_model_set_sizing_mode(m_model, EV_SIZING_FREE); + ev_document_model_set_scale(m_model, zoom); + } else + ev_document_model_set_sizing_mode(m_model, sizingMode); + + m_view = EV_VIEW(ev_view_new()); + ev_view_set_model(m_view, m_model); + + m_toolbar = ev_browser_plugin_toolbar_new(this); + if (toolbarVisible) + gtk_widget_show(m_toolbar); + + return NPERR_NO_ERROR; +} + +NPError EvBrowserPlugin::setWindow(NPWindow *window) +{ + if (!m_window) { + m_window = gtk_plug_new(reinterpret_cast(window->window)); + gtk_widget_realize(m_window); + + GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(vbox), m_toolbar, FALSE, FALSE, 0); + + GtkWidget *scrolledWindow = gtk_scrolled_window_new(nullptr, nullptr); + gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(m_view)); + gtk_widget_show(GTK_WIDGET(m_view)); + + gtk_box_pack_start(GTK_BOX(vbox), scrolledWindow, TRUE, TRUE, 0); + gtk_widget_show(scrolledWindow); + + gtk_container_add(GTK_CONTAINER(m_window), vbox); + gtk_widget_show(vbox); + } + + gtk_widget_set_size_request(m_window, window->width, window->height); + gtk_widget_show(m_window); + + return NPERR_NO_ERROR; +} + +NPError EvBrowserPlugin::newStream(NPMIMEType, NPStream *stream, NPBool seekable, uint16_t *stype) +{ + m_url.reset(g_strdup(stream->url)); + *stype = NP_ASFILEONLY; + return NPERR_NO_ERROR; +} + +NPError EvBrowserPlugin::destroyStream(NPStream *, NPReason) +{ + return NPERR_NO_ERROR; +} + +void EvBrowserPlugin::streamAsFile(NPStream *, const char *fname) +{ + GFile *file = g_file_new_for_commandline_arg(fname); + unique_gptr uri(g_file_get_uri(file)); + g_object_unref(file); + + // Load the document synchronously here because the temporary file created by the browser + // is deleted when this function returns. + GError *error = nullptr; + EvDocument *document = ev_document_factory_get_document(uri.get(), &error); + if (!document) { + g_printerr("Error loading document %s: %s\n", uri.get(), error->message); + g_error_free(error); + } else { + ev_document_model_set_document(m_model, document); + g_object_unref(document); + + ev_view_set_loading(EV_VIEW(m_view), FALSE); + } +} + +int32_t EvBrowserPlugin::writeReady(NPStream *) +{ + return 0; +} + +int32_t EvBrowserPlugin::write(NPStream *, int32_t /*offset*/, int32_t /*len*/, void */*buffer*/) +{ + return 0; +} + +void EvBrowserPlugin::print(NPPrint *) +{ + +} + +int16_t EvBrowserPlugin::handleEvent(XEvent *) +{ + return 0; +} + +void EvBrowserPlugin::urlNotify(const char */*url*/, NPReason, void */*notifyData*/) +{ + +} + +unsigned EvBrowserPlugin::currentPage() const +{ + g_return_val_if_fail(EV_IS_DOCUMENT_MODEL(m_model), 0); + return ev_document_model_get_page(m_model); +} + +unsigned EvBrowserPlugin::pageCount() const +{ + g_return_val_if_fail(EV_IS_DOCUMENT_MODEL(m_model), 0); + EvDocument *document = ev_document_model_get_document(m_model); + return document ? ev_document_get_n_pages(document) : 0; +} + +double EvBrowserPlugin::zoom() const +{ + g_return_val_if_fail(EV_IS_DOCUMENT_MODEL(m_model), 1); + return ev_document_model_get_scale(m_model); +} + +void EvBrowserPlugin::setZoom(double scale) +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_sizing_mode(m_model, EV_SIZING_FREE); + ev_document_model_set_scale(m_model, scale); +} + +void EvBrowserPlugin::goToPreviousPage() +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_page(m_model, ev_document_model_get_page(m_model) - 1); +} + +void EvBrowserPlugin::goToNextPage() +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_page(m_model, ev_document_model_get_page(m_model) + 1); +} + +void EvBrowserPlugin::goToPage(unsigned page) +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_page(m_model, page - 1); +} + +void EvBrowserPlugin::goToPage(const char *pageLabel) +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_page_by_label(m_model, pageLabel); +} + +void EvBrowserPlugin::activateLink(EvLink *link) +{ + g_return_if_fail(EV_IS_VIEW(m_view)); + g_return_if_fail(EV_IS_LINK(link)); + ev_view_handle_link(m_view, link); + gtk_widget_grab_focus(GTK_WIDGET(m_view)); +} + +bool EvBrowserPlugin::isContinuous() const +{ + g_return_val_if_fail(EV_IS_DOCUMENT_MODEL(m_model), false); + return ev_document_model_get_continuous(m_model); +} + +void EvBrowserPlugin::setContinuous(bool continuous) +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_continuous(m_model, continuous); +} + +void EvBrowserPlugin::toggleContinuous() +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_continuous(m_model, !ev_document_model_get_continuous(m_model)); +} + +bool EvBrowserPlugin::isDual() const +{ + g_return_val_if_fail(EV_IS_DOCUMENT_MODEL(m_model), false); + return ev_document_model_get_page_layout(m_model) == EV_PAGE_LAYOUT_DUAL; +} + +void EvBrowserPlugin::setDual(bool dual) +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_page_layout(m_model, dual ? EV_PAGE_LAYOUT_DUAL : EV_PAGE_LAYOUT_SINGLE); +} + +void EvBrowserPlugin::toggleDual() +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_page_layout(m_model, isDual() ? EV_PAGE_LAYOUT_SINGLE : EV_PAGE_LAYOUT_DUAL); +} + +void EvBrowserPlugin::zoomIn() +{ + g_return_if_fail(EV_IS_VIEW(m_view)); + ev_document_model_set_sizing_mode(m_model, EV_SIZING_FREE); + ev_view_zoom_in(m_view); +} + +void EvBrowserPlugin::zoomOut() +{ + g_return_if_fail(EV_IS_VIEW(m_view)); + ev_document_model_set_sizing_mode(m_model, EV_SIZING_FREE); + ev_view_zoom_out(m_view); +} + +EvSizingMode EvBrowserPlugin::sizingMode() const +{ + g_return_val_if_fail(EV_IS_DOCUMENT_MODEL(m_model), EV_SIZING_FREE); + return ev_document_model_get_sizing_mode(m_model); +} + +void EvBrowserPlugin::setSizingMode(EvSizingMode sizingMode) +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + ev_document_model_set_sizing_mode(m_model, sizingMode); +} + +void EvBrowserPlugin::download() const +{ + g_return_if_fail(m_url); + // Since I don't know how to force a download in the browser, I use + // a special frame name here that Epiphany will check in the new window policy + // callback to start the download. + NPN_GetURL(m_NPP, m_url.get(), "_evince_download"); +} + +void EvBrowserPlugin::print() const +{ + g_return_if_fail(EV_IS_DOCUMENT_MODEL(m_model)); + + EvDocument *document = ev_document_model_get_document(m_model); + if (!document) + return; + + EvPrintOperation *printOperation = ev_print_operation_new(document); + if (!printOperation) + return; + + unique_gptr outputBasename(g_path_get_basename(m_url.get())); + if (char *dot = g_strrstr(outputBasename.get(), ".")) + dot[0] = '\0'; + + unique_gptr unescapedBasename(g_uri_unescape_string(outputBasename.get(), nullptr)); + // Set output basename for printing to file. + GtkPrintSettings *printSettings = gtk_print_settings_new(); + gtk_print_settings_set(printSettings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME, unescapedBasename.get()); + + if (const char *title = ev_document_get_title(document)) + ev_print_operation_set_job_name(printOperation, title); + ev_print_operation_set_current_page(printOperation, ev_document_model_get_page(m_model)); + ev_print_operation_set_print_settings(printOperation, printSettings); + g_object_unref(printSettings); + + g_signal_connect(printOperation, "done", G_CALLBACK(g_object_unref), nullptr); + + GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(m_view)); + ev_print_operation_run(printOperation, GTK_IS_WINDOW(toplevel) ? GTK_WINDOW(toplevel) : nullptr); +} + +bool EvBrowserPlugin::canDownload() const +{ + // Download is only available for Epiphany for now. + return g_strrstr(NPN_UserAgent(m_NPP), "Epiphany"); +} + +bool EvBrowserPlugin::toolbarVisible() const +{ + g_return_val_if_fail(EV_IS_BROWSER_PLUGIN_TOOLBAR(m_toolbar), false); + return gtk_widget_get_visible(m_toolbar); +} + +void EvBrowserPlugin::setToolbarVisible(bool isVisible) +{ + g_return_if_fail(EV_IS_BROWSER_PLUGIN_TOOLBAR(m_toolbar)); + if (isVisible) + gtk_widget_show(m_toolbar); + else + gtk_widget_hide(m_toolbar); +} + +// Scripting interface +NPObject *EvBrowserPlugin::allocate(NPP instance, NPClass *) +{ + return new EvBrowserPlugin(instance); +} + +void EvBrowserPlugin::deallocate(NPObject *npObject) +{ + delete static_cast(npObject); +} + +void EvBrowserPlugin::invalidate(NPObject *) +{ +} + +bool EvBrowserPlugin::hasMethod(NPObject *npObject, NPIdentifier name) +{ + for (unsigned i = 0; i < EvBrowserPluginClass::Methods::NumMethodIdentifiers; ++i) { + if (name == s_pluginClass.methodIdentifiers[i]) { + if (i == EvBrowserPluginClass::Methods::Download) + return static_cast(npObject)->canDownload(); + return true; + } + } + return false; +} + +bool EvBrowserPlugin::invoke(NPObject *npObject, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) +{ + EvBrowserPlugin *plugin = static_cast(npObject); + + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::GoToPage]) { + if (argCount != 1) + return false; + + if (NPVARIANT_IS_DOUBLE(args[0])) + plugin->goToPage(static_cast(NPVARIANT_TO_DOUBLE(args[0]))); + else if (NPVARIANT_IS_STRING(args[0])) { + unique_gptr pageLabel(g_strndup(NPVARIANT_TO_STRING(args[0]).UTF8Characters, NPVARIANT_TO_STRING(args[0]).UTF8Length)); + plugin->goToPage(pageLabel.get()); + } else + return false; + + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::ToggleContinuous]) { + plugin->toggleContinuous(); + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::ToggleDual]) { + plugin->toggleDual(); + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::ZoomIn]) { + plugin->zoomIn(); + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::ZoomOut]) { + plugin->zoomOut(); + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::Download]) { + plugin->download(); + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == s_pluginClass.methodIdentifiers[EvBrowserPluginClass::Methods::Print]) { + plugin->print(); + VOID_TO_NPVARIANT(*result); + return true; + } + return false; +} + +bool EvBrowserPlugin::hasProperty(NPObject *npObject, NPIdentifier name) +{ + for (unsigned i = 0; i < EvBrowserPluginClass::Properties::NumPropertyIdentifiers; ++i) { + if (name == s_pluginClass.propertyIdentifiers[i]) + return true; + } + return false; +} + +bool EvBrowserPlugin::getProperty(NPObject *npObject, NPIdentifier name, NPVariant *value) +{ + EvBrowserPlugin *plugin = static_cast(npObject); + + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::CurrentPage]) { + INT32_TO_NPVARIANT(plugin->currentPage() + 1, *value); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::PageCount]) { + INT32_TO_NPVARIANT(plugin->pageCount(), *value); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Zoom]) { + DOUBLE_TO_NPVARIANT(plugin->zoom(), *value); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::ZoomMode]) { + const char *zoomMode; + + switch (plugin->sizingMode()) { + case EV_SIZING_FREE: + zoomMode = "none"; + break; + case EV_SIZING_FIT_PAGE: + zoomMode = "fit-page"; + break; + case EV_SIZING_FIT_WIDTH: + zoomMode = "fit-width"; + break; + case EV_SIZING_AUTOMATIC: + zoomMode = "auto"; + break; + default: + return false; + } + + size_t zoomModeLength = strlen(zoomMode); + char *result = static_cast(NPN_MemAlloc(zoomModeLength + 1)); + memcpy(result, zoomMode, zoomModeLength); + result[zoomModeLength] = '\0'; + + STRINGZ_TO_NPVARIANT(result, *value); + + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Continuous]) { + BOOLEAN_TO_NPVARIANT(plugin->isContinuous(), *value); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Dual]) { + BOOLEAN_TO_NPVARIANT(plugin->isDual(), *value); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Toolbar]) { + BOOLEAN_TO_NPVARIANT(plugin->toolbarVisible(), *value); + return true; + } + + return false; +} + +bool EvBrowserPlugin::setProperty(NPObject *npObject, NPIdentifier name, const NPVariant *value) +{ + EvBrowserPlugin *plugin = static_cast(npObject); + + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::CurrentPage]) { + plugin->goToPage(static_cast(NPVARIANT_TO_DOUBLE(*value))); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Zoom]) { + plugin->setZoom(NPVARIANT_TO_DOUBLE(*value)); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::ZoomMode]) { + unique_gptr zoomMode(g_strndup(NPVARIANT_TO_STRING(*value).UTF8Characters, NPVARIANT_TO_STRING(*value).UTF8Length)); + + if (g_strcmp0(zoomMode.get(), "none") == 0) + plugin->setSizingMode(EV_SIZING_FREE); + else if (g_strcmp0(zoomMode.get(), "fit-page") == 0) + plugin->setSizingMode(EV_SIZING_FIT_PAGE); + else if (g_strcmp0(zoomMode.get(), "fit-width") == 0) + plugin->setSizingMode(EV_SIZING_FIT_WIDTH); + else if (g_strcmp0(zoomMode.get(), "auto") == 0) + plugin->setSizingMode(EV_SIZING_AUTOMATIC); + else + return false; + + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Continuous]) { + plugin->setContinuous(NPVARIANT_TO_BOOLEAN(*value)); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Dual]) { + plugin->setDual(NPVARIANT_TO_BOOLEAN(*value)); + return true; + } + if (name == s_pluginClass.propertyIdentifiers[EvBrowserPluginClass::Properties::Toolbar]) { + plugin->setToolbarVisible(NPVARIANT_TO_BOOLEAN(*value)); + return true; + } + + return false; +} + +EvBrowserPluginClass EvBrowserPlugin::s_pluginClass { + { + NP_CLASS_STRUCT_VERSION, + allocate, + deallocate, + invalidate, + hasMethod, + invoke, + nullptr, // NPClass::invokeDefault + hasProperty, + getProperty, + setProperty, + nullptr, // NPClass::removeProperty + nullptr, // NPClass::enumerate + nullptr // NPClass::construct + }, + // methodIdentifierNames + { + "goToPage", + "toggleContinuous", + "toggleDual", + "zoomIn", + "zoomOut", + "download", + "print" + }, + // propertyIdentifierNames + { + "currentPage", + "pageCount", + "zoom", + "zoomMode", + "continuous", + "dual", + "toolbar" + }, + false // identifiersInitialized +}; diff --git a/browser-plugin/EvBrowserPlugin.gresource.xml b/browser-plugin/EvBrowserPlugin.gresource.xml new file mode 100644 index 00000000..4d3a5660 --- /dev/null +++ b/browser-plugin/EvBrowserPlugin.gresource.xml @@ -0,0 +1,23 @@ + + + + + evince-browser.css + thumbnail-frame.png + + diff --git a/browser-plugin/EvBrowserPlugin.h b/browser-plugin/EvBrowserPlugin.h new file mode 100644 index 00000000..b6e16382 --- /dev/null +++ b/browser-plugin/EvBrowserPlugin.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef EvBrowserPlugin_h +#define EvBrowserPlugin_h + +#include +#include +#include "EvMemoryUtils.h" +#include "npapi.h" +#include "npruntime.h" + +typedef union _XEvent XEvent; +struct EvBrowserPluginClass; + +class EvBrowserPlugin: public NPObject { +public: + static EvBrowserPlugin* create(NPP); + + static const char *nameString(); + static const char *descriptionString(); + + // NPP API + NPError initialize(NPMIMEType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *); + NPError setWindow(NPWindow *); + NPError newStream(NPMIMEType, NPStream *, NPBool seekable, uint16_t *stype); + NPError destroyStream(NPStream *, NPReason); + void streamAsFile(NPStream *, const char *fname); + int32_t writeReady(NPStream *); + int32_t write(NPStream *, int32_t offset, int32_t len, void *buffer); + void print(NPPrint *); + int16_t handleEvent(XEvent *); + void urlNotify(const char *url, NPReason, void *notifyData); + + // Viewer API + EvDocumentModel *model() const { return m_model; } + unsigned currentPage() const; + unsigned pageCount() const; + double zoom() const; + void setZoom(double scale); + void goToPreviousPage(); + void goToNextPage(); + void goToPage(unsigned page); + void goToPage(const char *pageLabel); + void activateLink(EvLink *); + bool isContinuous() const; + void setContinuous(bool); + void toggleContinuous(); + bool isDual() const; + void setDual(bool); + void toggleDual(); + void zoomIn(); + void zoomOut(); + EvSizingMode sizingMode() const; + void setSizingMode(EvSizingMode); + void download() const; + void print() const; + bool toolbarVisible() const; + void setToolbarVisible(bool); + + bool canDownload() const; + +private: + EvBrowserPlugin(NPP); + virtual ~EvBrowserPlugin(); + + // Scripting interface + static NPObject *allocate(NPP, NPClass *); + static void deallocate(NPObject *); + static void invalidate(NPObject *); + static bool hasMethod(NPObject *, NPIdentifier name); + static bool invoke(NPObject *, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result); + static bool hasProperty(NPObject *, NPIdentifier name); + static bool getProperty(NPObject *, NPIdentifier name, NPVariant *); + static bool setProperty(NPObject *, NPIdentifier name, const NPVariant *); + + NPP m_NPP; + GtkWidget *m_window; + EvDocumentModel *m_model; + EvView *m_view; + GtkWidget *m_toolbar; + unique_gptr m_url; + + static EvBrowserPluginClass s_pluginClass; +}; + +#endif // EvBrowserPlugin_h diff --git a/browser-plugin/EvBrowserPluginMain.cpp b/browser-plugin/EvBrowserPluginMain.cpp new file mode 100644 index 00000000..fb749f4e --- /dev/null +++ b/browser-plugin/EvBrowserPluginMain.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "EvBrowserPlugin.h" +#include "EvMemoryUtils.h" +#include "npfunctions.h" +#include "npruntime.h" + +static NPNetscapeFuncs *browser; +static unique_gptr mimeDescription; + +static EvBrowserPlugin *pluginForInstance(NPP instance) +{ + if (!instance) + return nullptr; + + return static_cast(instance->pdata); +} + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *savedData) +{ + if (!instance) + return NPERR_INVALID_INSTANCE_ERROR; + + return EvBrowserPlugin::create(instance)->initialize(pluginType, mode, argc, argn, argv, savedData); +} + +NPError NPP_Destroy(NPP instance, NPSavedData **saveData) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return NPERR_INVALID_INSTANCE_ERROR; + + browser->releaseobject(static_cast(plugin)); + return NPERR_NO_ERROR; +} + +NPError NPP_SetWindow(NPP instance, NPWindow *window) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return NPERR_INVALID_INSTANCE_ERROR; + + return plugin->setWindow(window); +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16_t *stype) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return NPERR_INVALID_INSTANCE_ERROR; + + return plugin->newStream(type, stream, seekable, stype); +} + +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return NPERR_INVALID_INSTANCE_ERROR; + + return plugin->destroyStream(stream, reason); +} + +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return; + + return plugin->streamAsFile(stream, fname); +} + +int32_t NPP_WriteReady(NPP instance, NPStream *stream) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return -1; + + return plugin->writeReady(stream); +} + +int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, void *buffer) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return -1; + + return plugin->write(stream, offset, len, buffer); +} + +void NPP_Print(NPP instance, NPPrint *platformPrint) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return; + + return plugin->print(platformPrint); +} + +int16_t NPP_HandleEvent(NPP instance, void *event) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return 0; + + return plugin->handleEvent(static_cast(event)); +} + +void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) +{ + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return; + + return plugin->urlNotify(url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) +{ + switch (variable) { + case NPPVpluginNameString: + *((char **)value) = const_cast(EvBrowserPlugin::nameString()); + return NPERR_NO_ERROR; + case NPPVpluginDescriptionString: + *((char **)value) = const_cast(EvBrowserPlugin::descriptionString()); + return NPERR_NO_ERROR; + case NPPVpluginNeedsXEmbed: + *((NPBool *)value) = TRUE; + return NPERR_NO_ERROR; + case NPPVpluginScriptableNPObject: { + EvBrowserPlugin *plugin = pluginForInstance(instance); + if (!plugin) + return NPERR_INVALID_PLUGIN_ERROR; + + browser->retainobject(static_cast(plugin)); + *((NPObject **)value) = plugin; + return NPERR_NO_ERROR; + } + default: + return NPERR_INVALID_PARAM; + } + + return NPERR_GENERIC_ERROR; +} + +NPError NPP_SetValue(NPP, NPNVariable, void *) +{ + return NPERR_NO_ERROR; +} + +static void initializePluginFuncs(NPPluginFuncs *pluginFuncs) +{ + pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; + pluginFuncs->size = sizeof(pluginFuncs); + pluginFuncs->newp = NPP_New; + pluginFuncs->destroy = NPP_Destroy; + pluginFuncs->setwindow = NPP_SetWindow; + pluginFuncs->newstream = NPP_NewStream; + pluginFuncs->destroystream = NPP_DestroyStream; + pluginFuncs->asfile = NPP_StreamAsFile; + pluginFuncs->writeready = NPP_WriteReady; + pluginFuncs->write = NPP_Write; + pluginFuncs->print = NPP_Print; + pluginFuncs->event = NPP_HandleEvent; + pluginFuncs->urlnotify = NPP_URLNotify; + pluginFuncs->getvalue = NPP_GetValue; + pluginFuncs->setvalue = NPP_SetValue; +} + +NPError NP_Initialize(NPNetscapeFuncs *browserFuncs, NPPluginFuncs *pluginFuncs) +{ + if (!browserFuncs || !pluginFuncs) + return NPERR_INVALID_FUNCTABLE_ERROR; + + if ((browserFuncs->version >> 8) > NP_VERSION_MAJOR) + return NPERR_INCOMPATIBLE_VERSION_ERROR; + + if (!ev_init()) + return NPERR_GENERIC_ERROR; + + gtk_init(nullptr, nullptr); + + browser = browserFuncs; + initializePluginFuncs(pluginFuncs); + + GBytes *resourceData = g_resources_lookup_data("/org/gnome/evince/browser/ui/evince-browser.css", G_RESOURCE_LOOKUP_FLAGS_NONE, nullptr); + if (resourceData) { + GtkCssProvider *cssProvider = gtk_css_provider_new(); + + gtk_css_provider_load_from_data(cssProvider, static_cast(g_bytes_get_data(resourceData, nullptr)), g_bytes_get_size(resourceData), nullptr); + g_bytes_unref(resourceData); + + gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + g_object_unref(cssProvider); + } + + return NPERR_NO_ERROR; +} + +NPError NP_Shutdown() +{ + ev_shutdown(); + return NPERR_NO_ERROR; +} + +static const struct { + const char *mime; + const char *extensions; +} mimeExtensions[] = { + { "application/postscript", "ps" }, + { "application/x-ext-ps", "ps" }, + { "application/x-bzpostscript", "ps.bz2" }, + { "application/x-gzpostscript", "ps.gz" }, + { "image/x-eps", "eps,epsi,epsf" }, + { "application/x-ext-eps", "eps,epsi,epsf" }, + { "image/x-bzeps", "eps.bz2,epsi.bz2,epsf.bz2" }, + { "image/x-gzeps", "eps.gz,epsi.gz,epsf.gz" }, + { "image/tiff", "tif,tiff" }, + { "application/pdf", "pdf" }, + { "application/x-ext-pdf", "pdf" }, + { "application/x-bzpdf", "pdf.bz2" }, + { "application/x-gzpdf", "pdf.gz" }, + { "application/x-xzpdf", "pdf.xz" }, + { "application/x-dvi", "dvi" }, + { "application/x-ext-dvi", "dvi" }, + { "application/x-bzdvi", "dvi.bz2" }, + { "application/x-gzdvi", "dvi.gz" }, + { "application/x-cbr", "cbr" }, + { "application/x-ext-cbr", "cbr" }, + { "application/x-cbz", "cbz" }, + { "application/x-ext-cbz", "cbz" }, + { "application/x-cb7", "cb7" }, + { "application/x-ext-cb7", "cb7" }, + { "application/x-cbt", "cbt" }, + { "application/x-ext-cbt", "cbt" }, + { "image/vnd.djvu", "djvu,djv" }, + { "application/x-ext-djv", "djv" }, + { "application/x-ext-djvu", "djvu" }, + { "application/oxps", "xps,oxps" }, + { "application/vnd.ms-xpsdocument", "xps,oxps" } +}; + +const char *NP_GetMIMEDescription() +{ + if (mimeDescription) + return mimeDescription.get(); + + if (!ev_init()) + return nullptr; + + GString *mimeDescriptionStr = g_string_new(nullptr); + + GList *typesInfo = ev_backends_manager_get_all_types_info(); + for (GList *l = typesInfo; l; l = g_list_next(l)) { + EvTypeInfo *info = static_cast(l->data); + + for (unsigned i = 0; info->mime_types[i]; ++i) { + const char *extensions = [](const char *mime) -> const char * { + for (unsigned i = 0; i < G_N_ELEMENTS(mimeExtensions); ++i) { + if (g_ascii_strcasecmp(mimeExtensions[i].mime, mime) == 0) + return mimeExtensions[i].extensions; + } + + return nullptr; + }(info->mime_types[i]); + + if (!extensions) + continue; + + g_string_append_printf(mimeDescriptionStr, "%s:%s:%s;", + info->mime_types[i], + extensions, + info->desc); + } + } + g_list_free(typesInfo); + + mimeDescription.reset(g_string_free(mimeDescriptionStr, FALSE)); + + ev_shutdown(); + + return mimeDescription.get(); +} + +NPError NP_GetValue(void *, NPPVariable variable, void *value) +{ + return NPP_GetValue(nullptr, variable, value); +} + +NPObject *NPN_CreateObject(NPP instance, NPClass *npClass) +{ + return browser->createobject(instance, npClass); +} + +void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers) +{ + browser->getstringidentifiers(names, nameCount, identifiers); +} + +NPError NPN_GetURL(NPP instance, const char* url, const char* target) +{ + return browser->geturl(instance, url, target); +} + +const char *NPN_UserAgent(NPP instance) +{ + return browser->uagent(instance); +} + +void *NPN_MemAlloc(uint32_t size) +{ + return browser->memalloc(size); +} + +void NPN_MemFree(void* ptr) +{ + if (ptr) + browser->memfree(ptr); +} + +static void __attribute__((constructor)) browserPluginConstructor() +{ + ev_init(); +} + +static void __attribute__((destructor)) browserPluginDestructor() +{ + ev_shutdown(); +} diff --git a/browser-plugin/EvBrowserPluginToolbar.cpp b/browser-plugin/EvBrowserPluginToolbar.cpp new file mode 100644 index 00000000..0e487bb7 --- /dev/null +++ b/browser-plugin/EvBrowserPluginToolbar.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "EvBrowserPluginToolbar.h" + +#include "ev-page-action-widget.h" +#include + +enum { + PROP_0, + PROP_PLUGIN +}; + +struct _EvBrowserPluginToolbarPrivate { + EvBrowserPlugin *plugin; + + GtkWidget *continuousToggleButton; + GtkWidget *dualToggleButton; + GtkWidget *zoomFitPageRadioButton; + GtkWidget *zoomFitWidthRadioButton; + GtkWidget *zoomAutomaticRadioButton; +}; + +G_DEFINE_TYPE(EvBrowserPluginToolbar, ev_browser_plugin_toolbar, GTK_TYPE_TOOLBAR) + +static void goToPreviousPage(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->goToPreviousPage(); +} + +static void goToNextPage(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->goToNextPage(); +} + +static void activateLink(EvBrowserPluginToolbar *toolbar, EvLink *link) +{ + toolbar->priv->plugin->activateLink(link); +} + +static void toggleContinuous(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->toggleContinuous(); +} + +static void toggleDual(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->toggleDual(); +} + +static void zoomIn(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->zoomIn(); +} + +static void zoomOut(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->zoomOut(); +} + +static void zoomFitPageToggled(EvBrowserPluginToolbar *toolbar) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toolbar->priv->zoomFitPageRadioButton))) + toolbar->priv->plugin->setSizingMode(EV_SIZING_FIT_PAGE); +} + +static void zoomFitWidthToggled(EvBrowserPluginToolbar *toolbar) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toolbar->priv->zoomFitWidthRadioButton))) + toolbar->priv->plugin->setSizingMode(EV_SIZING_FIT_WIDTH); +} + +static void zoomAutomaticToggled(EvBrowserPluginToolbar *toolbar) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toolbar->priv->zoomAutomaticRadioButton))) + toolbar->priv->plugin->setSizingMode(EV_SIZING_AUTOMATIC); +} + +static void printDocument(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->print(); +} + +static void downloadDocument(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv->plugin->download(); +} + +class SignalBlocker { +public: + SignalBlocker(gpointer instance, void (* closure)(EvBrowserPluginToolbar *), gpointer data) + : m_instance(instance) + , m_closure(reinterpret_cast(closure)) + , m_data(data) + { + g_signal_handlers_block_by_func(m_instance, m_closure, m_data); + } + + ~SignalBlocker() + { + g_signal_handlers_unblock_by_func(m_instance, m_closure, m_data); + } + +private: + gpointer m_instance; + gpointer m_closure; + gpointer m_data; +}; + +static void continuousChanged(EvDocumentModel *model, GParamSpec *, EvBrowserPluginToolbar *toolbar) +{ + SignalBlocker blocker(toolbar->priv->continuousToggleButton, toggleContinuous, toolbar); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->priv->continuousToggleButton), + toolbar->priv->plugin->isContinuous()); +} + +static void dualPageChanged(EvDocumentModel *model, GParamSpec *, EvBrowserPluginToolbar *toolbar) +{ + SignalBlocker blocker(toolbar->priv->dualToggleButton, toggleDual, toolbar); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->priv->dualToggleButton), + toolbar->priv->plugin->isDual()); +} + +static void sizingModeChanged(EvDocumentModel *model, GParamSpec *, EvBrowserPluginToolbar *toolbar) +{ + { + SignalBlocker fitPageBlocker(toolbar->priv->zoomFitPageRadioButton, zoomFitPageToggled, toolbar); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(toolbar->priv->zoomFitPageRadioButton), + toolbar->priv->plugin->sizingMode() == EV_SIZING_FIT_PAGE); + } + + { + SignalBlocker fitWidthBlocker(toolbar->priv->zoomFitPageRadioButton, zoomFitWidthToggled, toolbar); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(toolbar->priv->zoomFitWidthRadioButton), + toolbar->priv->plugin->sizingMode() == EV_SIZING_FIT_WIDTH); + } + + { + SignalBlocker automaticBlocker(toolbar->priv->zoomAutomaticRadioButton, zoomAutomaticToggled, toolbar); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(toolbar->priv->zoomAutomaticRadioButton), + toolbar->priv->plugin->sizingMode() == EV_SIZING_AUTOMATIC); + } +} + +static void evBrowserPluginToolbarSetProperty(GObject *object, guint propID, const GValue *value, GParamSpec *paramSpec) +{ + EvBrowserPluginToolbar *toolbar = EV_BROWSER_PLUGIN_TOOLBAR(object); + + switch (propID) { + case PROP_PLUGIN: + toolbar->priv->plugin = static_cast(g_value_get_pointer(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec); + } +} + +static GtkWidget *createButton(EvBrowserPluginToolbar *toolbar, const char *iconName, const char *description, GCallback callback) +{ + GtkWidget *button = gtk_button_new(); + + gtk_widget_set_valign(button, GTK_ALIGN_CENTER); + gtk_widget_set_tooltip_text(button, description); + gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_icon_name(iconName, GTK_ICON_SIZE_MENU)); + gtk_button_set_label(GTK_BUTTON(button), nullptr); + gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); + g_signal_connect_swapped(button, "clicked", callback, toolbar); + + return button; +} + +static GtkWidget *createToggleButton(EvBrowserPluginToolbar *toolbar, const char *iconName, const char *description, bool initialState, GCallback callback) +{ + GtkWidget *button = gtk_toggle_button_new(); + + gtk_widget_set_valign(button, GTK_ALIGN_CENTER); + gtk_widget_set_tooltip_text(button, description); + gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_icon_name(iconName, GTK_ICON_SIZE_MENU)); + gtk_button_set_label(GTK_BUTTON(button), nullptr); + gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), initialState); + g_signal_connect_swapped(button, "toggled", callback, toolbar); + + return button; +} + +static GtkWidget *createMenuButton(EvBrowserPluginToolbar *toolbar, const gchar *iconName, GtkWidget *menu, GtkAlign menuAlign) +{ + GtkWidget *button = gtk_menu_button_new(); + + gtk_widget_set_valign(button, GTK_ALIGN_CENTER); + gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_icon_name(iconName, GTK_ICON_SIZE_MENU)); + gtk_widget_set_halign(menu, menuAlign); + gtk_menu_button_set_popup(GTK_MENU_BUTTON(button), menu); + + return button; +} + +static GtkWidget *createButtonGroup(EvBrowserPluginToolbar *toolbar) +{ + GtkWidget *box = gtk_box_new(gtk_orientable_get_orientation(GTK_ORIENTABLE(toolbar)), 0); + + GtkStyleContext *styleContext = gtk_widget_get_style_context(box); + gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_RAISED); + gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_LINKED); + + return box; +} + +static GtkWidget *createSizingModeMenu(EvBrowserPluginToolbar *toolbar) +{ + GtkWidget *menu = gtk_menu_new(); + + GtkWidget *menuItem = gtk_check_menu_item_new_with_mnemonic(_("Fit Pa_ge")); + toolbar->priv->zoomFitPageRadioButton = menuItem; + gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(menuItem), TRUE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuItem), + toolbar->priv->plugin->sizingMode() == EV_SIZING_FIT_PAGE); + g_signal_connect_swapped(menuItem, "toggled", G_CALLBACK(zoomFitPageToggled), toolbar); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem); + gtk_widget_show(menuItem); + + menuItem = gtk_check_menu_item_new_with_mnemonic(_("Fit _Width")); + toolbar->priv->zoomFitWidthRadioButton = menuItem; + gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(menuItem), TRUE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuItem), + toolbar->priv->plugin->sizingMode() == EV_SIZING_FIT_WIDTH); + g_signal_connect_swapped(menuItem, "toggled", G_CALLBACK(zoomFitWidthToggled), toolbar); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem); + gtk_widget_show(menuItem); + + menuItem = gtk_check_menu_item_new_with_mnemonic(_("_Automatic")); + toolbar->priv->zoomAutomaticRadioButton = menuItem; + gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(menuItem), TRUE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuItem), + toolbar->priv->plugin->sizingMode() == EV_SIZING_AUTOMATIC); + g_signal_connect_swapped(menuItem, "toggled", G_CALLBACK(zoomAutomaticToggled), toolbar); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem); + gtk_widget_show(menuItem); + + g_signal_connect(toolbar->priv->plugin->model(), "notify::sizing-mode", + G_CALLBACK(sizingModeChanged), toolbar); + + return menu; +} + +static void evBrowserPluginToolbarConstructed(GObject *object) +{ + G_OBJECT_CLASS(ev_browser_plugin_toolbar_parent_class)->constructed(object); + + EvBrowserPluginToolbar *toolbar = EV_BROWSER_PLUGIN_TOOLBAR(object); + bool rtl = gtk_widget_get_direction(GTK_WIDGET(toolbar)) == GTK_TEXT_DIR_RTL; + + GtkWidget *hbox = createButtonGroup(toolbar); + + // Navigation buttons + GtkWidget *button = createButton(toolbar, "go-up-symbolic", _("Go to the previous page"), G_CALLBACK(goToPreviousPage)); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + button = createButton(toolbar, "go-down-symbolic", _("Go to the next page"), G_CALLBACK(goToNextPage)); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + GtkWidget *toolItem = GTK_WIDGET(gtk_tool_item_new()); + if (rtl) + gtk_widget_set_margin_left(toolItem, 12); + else + gtk_widget_set_margin_right(toolItem, 12); + gtk_container_add(GTK_CONTAINER(toolItem), hbox); + gtk_widget_show(hbox); + + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); + + // Page Selector + toolItem = GTK_WIDGET(g_object_new(EV_TYPE_PAGE_ACTION_WIDGET, nullptr)); + ev_page_action_widget_set_model(EV_PAGE_ACTION_WIDGET(toolItem), toolbar->priv->plugin->model()); + g_signal_connect_swapped(toolItem, "activate-link", G_CALLBACK(activateLink), toolbar); + if (rtl) + gtk_widget_set_margin_left(toolItem, 12); + else + gtk_widget_set_margin_right(toolItem, 12); + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); + + // Separator + toolItem = GTK_WIDGET(gtk_tool_item_new()); + gtk_tool_item_set_expand(GTK_TOOL_ITEM(toolItem), TRUE); + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); + + // View mode + hbox = createButtonGroup(toolbar); + + button = createToggleButton(toolbar, "view-continuous-symbolic", _("Show the entire document"), + toolbar->priv->plugin->isContinuous(), G_CALLBACK(toggleContinuous)); + toolbar->priv->continuousToggleButton = button; + g_signal_connect(toolbar->priv->plugin->model(), "notify::continuous", + G_CALLBACK(continuousChanged), toolbar); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + button = createToggleButton(toolbar, "view-dual-symbolic", _("Show two pages at once"), + toolbar->priv->plugin->isDual(), G_CALLBACK(toggleDual)); + toolbar->priv->dualToggleButton = button; + g_signal_connect(toolbar->priv->plugin->model(), "notify::dual-page", + G_CALLBACK(dualPageChanged), toolbar); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + toolItem = GTK_WIDGET(gtk_tool_item_new()); + if (rtl) + gtk_widget_set_margin_left(toolItem, 12); + else + gtk_widget_set_margin_right(toolItem, 12); + gtk_container_add(GTK_CONTAINER(toolItem), hbox); + gtk_widget_show(hbox); + + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); + + // Zoom + hbox = createButtonGroup(toolbar); + + button = createButton(toolbar, "zoom-in-symbolic", _("Enlarge the document"), G_CALLBACK(zoomIn)); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + button = createButton(toolbar, "zoom-out-symbolic", _("Shrink the document"), G_CALLBACK(zoomOut)); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + button = createMenuButton(toolbar, "go-down-symbolic", createSizingModeMenu(toolbar), GTK_ALIGN_END); + gtk_container_add(GTK_CONTAINER(hbox), button); + gtk_widget_show(button); + + toolItem = GTK_WIDGET(gtk_tool_item_new()); + if (rtl) + gtk_widget_set_margin_left(toolItem, 12); + else + gtk_widget_set_margin_right(toolItem, 12); + gtk_container_add(GTK_CONTAINER(toolItem), hbox); + gtk_widget_show(hbox); + + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); + + // Actions + // Only add download button if browser is Epiphany for now. + if (toolbar->priv->plugin->canDownload()) { + button = createButton(toolbar, "folder-download-symbolic", _("Download document"), G_CALLBACK(downloadDocument)); + toolItem = GTK_WIDGET(gtk_tool_item_new()); + gtk_container_add(GTK_CONTAINER(toolItem), button); + gtk_widget_show(button); + if (rtl) + gtk_widget_set_margin_left(toolItem, 6); + else + gtk_widget_set_margin_right(toolItem, 6); + + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); + } + + button = createButton(toolbar, "printer-symbolic", _("Print document"), G_CALLBACK(printDocument)); + toolItem = GTK_WIDGET(gtk_tool_item_new()); + gtk_container_add(GTK_CONTAINER(toolItem), button); + gtk_widget_show(button); + + gtk_container_add(GTK_CONTAINER(toolbar), toolItem); + gtk_widget_show(toolItem); +} + +static void ev_browser_plugin_toolbar_class_init(EvBrowserPluginToolbarClass *klass) +{ + GObjectClass *gObjectClass = G_OBJECT_CLASS(klass); + gObjectClass->set_property = evBrowserPluginToolbarSetProperty; + gObjectClass->constructed = evBrowserPluginToolbarConstructed; + + g_object_class_install_property(gObjectClass, + PROP_PLUGIN, + g_param_spec_pointer("plugin", + "Plugin", + "The plugin", + static_cast(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS))); + + g_type_class_add_private(gObjectClass, sizeof(EvBrowserPluginToolbarPrivate)); +} + +static void ev_browser_plugin_toolbar_init(EvBrowserPluginToolbar *toolbar) +{ + toolbar->priv = G_TYPE_INSTANCE_GET_PRIVATE(toolbar, EV_TYPE_BROWSER_PLUGIN_TOOLBAR, EvBrowserPluginToolbarPrivate); +} + +GtkWidget *ev_browser_plugin_toolbar_new(EvBrowserPlugin *plugin) +{ + return GTK_WIDGET(g_object_new(EV_TYPE_BROWSER_PLUGIN_TOOLBAR, "plugin", plugin, nullptr)); +} diff --git a/browser-plugin/EvBrowserPluginToolbar.h b/browser-plugin/EvBrowserPluginToolbar.h new file mode 100644 index 00000000..52049b5b --- /dev/null +++ b/browser-plugin/EvBrowserPluginToolbar.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef EvBrowserPluginToolbar_h +#define EvBrowserPluginToolbar_h + +#include "EvBrowserPlugin.h" +#include +#include + +G_BEGIN_DECLS + +#define EV_TYPE_BROWSER_PLUGIN_TOOLBAR (ev_browser_plugin_toolbar_get_type()) +#define EV_BROWSER_PLUGIN_TOOLBAR(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_BROWSER_PLUGIN_TOOLBAR, EvBrowserPluginToolbar)) +#define EV_IS_BROWSER_PLUGIN_TOOLBAR(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_BROWSER_PLUGIN_TOOLBAR)) +#define EV_BROWSER_PLUGIN_TOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_BROWSER_PLUGIN_TOOLBAR, EvBrowserPluginToolbarClass)) +#define EV_IS_BROWSER_PLUGIN_TOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_BROWSER_PLUGIN_TOOLBAR)) +#define EV_BROWSER_PLUGIN_TOOLBAR_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_BROWSER_PLUGIN_TOOLBAR, EvBrowserPluginToolbarClass)) + +typedef struct _EvBrowserPluginToolbar EvBrowserPluginToolbar; +typedef struct _EvBrowserPluginToolbarClass EvBrowserPluginToolbarClass; +typedef struct _EvBrowserPluginToolbarPrivate EvBrowserPluginToolbarPrivate; + +struct _EvBrowserPluginToolbar { + GtkToolbar base_instance; + + EvBrowserPluginToolbarPrivate *priv; +}; + +struct _EvBrowserPluginToolbarClass { + GtkToolbarClass base_class; +}; + +GType ev_browser_plugin_toolbar_get_type (void); +GtkWidget *ev_browser_plugin_toolbar_new (EvBrowserPlugin *plugin); + +G_END_DECLS + +#endif // EvBrowserPluginToolbar_h diff --git a/browser-plugin/EvMemoryUtils.h b/browser-plugin/EvMemoryUtils.h new file mode 100644 index 00000000..38d25119 --- /dev/null +++ b/browser-plugin/EvMemoryUtils.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef EvMemoryUtils_h +#define EvMemoryUtils_h + +#include +#include + +template +struct unique_gptr_deleter { + void operator()(T* ptr) const { g_free(ptr); } +}; + +template +using unique_gptr = std::unique_ptr>; + +#endif // EvMemoryUtils_h diff --git a/browser-plugin/Makefile.am b/browser-plugin/Makefile.am new file mode 100644 index 00000000..63b438f9 --- /dev/null +++ b/browser-plugin/Makefile.am @@ -0,0 +1,61 @@ +plugindir = $(BROWSER_PLUGIN_DIR) +plugin_LTLIBRARIES = libevbrowserplugin.la + +npapi_sources = \ + npapi/npapi.h \ + npapi/npfunctions.h \ + npapi/npruntime.h \ + npapi/nptypes.h + +libevbrowserplugin_la_SOURCES = \ + $(npapi_sources) \ + EvBrowserPluginMain.cpp \ + EvBrowserPlugin.h \ + EvBrowserPlugin.cpp \ + EvBrowserPluginToolbar.h \ + EvBrowserPluginToolbar.cpp + +nodist_libevbrowserplugin_la_SOURCES = \ + EvBrowserPluginResources.c + +libevbrowserplugin_la_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/browser-plugin/npapi \ + -I$(top_srcdir)/libdocument \ + -I$(top_srcdir)/libview \ + -I$(top_srcdir)/libmisc \ + -DGNOMELOCALEDIR=\"$(datadir)/locale\" \ + -DEVINCE_COMPILATION \ + -DXP_UNIX \ + -DMOZ_X11 \ + $(BROWSER_PLUGIN_CFLAGS) \ + $(AM_CPPFLAGS) + +libevbrowserplugin_la_CXXFLAGS = \ + -std=c++11 \ + -fno-exceptions \ + -fno-strict-aliasing \ + -fno-rtti \ + $(AM_CXXFLAGS) + +libevbrowserplugin_la_LDFLAGS = \ + -avoid-version \ + -export-symbols $(top_srcdir)/browser-plugin/plugin.symbols \ + -module \ + -no-undefined \ + -Wl,-z,nodelete \ + $(AM_LDFLAGS) + +libevbrowserplugin_la_LIBADD = \ + $(top_builddir)/libdocument/libevdocument3.la \ + $(top_builddir)/libview/libevview3.la \ + $(top_builddir)/libmisc/libevmisc.la \ + $(BROWSER_PLUGIN_LIBS) + +EvBrowserPluginResources.c: EvBrowserPlugin.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir=$(srcdir) --sourcedir=$(top_srcdir)/data $(srcdir)/EvBrowserPlugin.gresource.xml) + $(AM_V_GEN) XMLLINT=$(XMLLINT) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(top_srcdir)/data --generate-source $< + +EXTRA_DIST = \ + plugin.symbols + +-include $(top_srcdir)/git.mk diff --git a/browser-plugin/evince-browser.css b/browser-plugin/evince-browser.css new file mode 100644 index 00000000..2273f51c --- /dev/null +++ b/browser-plugin/evince-browser.css @@ -0,0 +1,19 @@ +.content-view.document-page { + border-style: solid; + border-width: 3px 3px 6px 4px; + border-image: url("resource:///org/gnome/evince/browser/ui/thumbnail-frame.png") 3 3 6 4; + background-color: @theme_bg_color; +} + +EvView { + background-color: @theme_bg_color; +} + +EvView:selected { + background-color: @theme_selected_bg_color; +} + +EvView.document-page { + background-color: white; + padding: 0; +} diff --git a/browser-plugin/npapi/npapi.h b/browser-plugin/npapi/npapi.h new file mode 100644 index 00000000..3d08b2ca --- /dev/null +++ b/browser-plugin/npapi/npapi.h @@ -0,0 +1,914 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef npapi_h_ +#define npapi_h_ + +#if defined(__OS2__) +#pragma pack(1) +#endif + +#include "nptypes.h" + +#if defined(__OS2__) || defined(OS2) +#ifndef XP_OS2 +#define XP_OS2 1 +#endif +#endif + +#if defined(_WIN32) && !defined(__SYMBIAN32__) +#include +#ifndef XP_WIN +#define XP_WIN 1 +#endif +#endif + +#if defined(__SYMBIAN32__) +#ifndef XP_SYMBIAN +#define XP_SYMBIAN 1 +#undef XP_WIN +#endif +#endif + +#if defined(__APPLE_CC__) && !defined(XP_UNIX) +#ifndef XP_MACOSX +#define XP_MACOSX 1 +#endif +#endif + +#if defined(XP_MACOSX) && defined(__LP64__) +#define NP_NO_QUICKDRAW +#define NP_NO_CARBON +#endif + +#if defined(XP_MACOSX) +#include +#include +#ifndef NP_NO_CARBON +#include +#endif +#endif + +#if defined(XP_UNIX) +#include +#if defined(MOZ_X11) +#include +#include +#endif +#endif + +#if defined(XP_SYMBIAN) +#include +#include +#endif + +/*----------------------------------------------------------------------*/ +/* Plugin Version Constants */ +/*----------------------------------------------------------------------*/ + +#define NP_VERSION_MAJOR 0 +#define NP_VERSION_MINOR 27 + + +/* The OS/2 version of Netscape uses RC_DATA to define the + mime types, file extensions, etc that are required. + Use a vertical bar to separate types, end types with \0. + FileVersion and ProductVersion are 32bit ints, all other + entries are strings that MUST be terminated with a \0. + +AN EXAMPLE: + +RCDATA NP_INFO_ProductVersion { 1,0,0,1,} + +RCDATA NP_INFO_MIMEType { "video/x-video|", + "video/x-flick\0" } +RCDATA NP_INFO_FileExtents { "avi|", + "flc\0" } +RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|", + "MMOS2 Flc/Fli player(*.flc)\0" } + +RCDATA NP_INFO_FileVersion { 1,0,0,1 } +RCDATA NP_INFO_CompanyName { "Netscape Communications\0" } +RCDATA NP_INFO_FileDescription { "NPAVI32 Extension DLL\0" +RCDATA NP_INFO_InternalName { "NPAVI32\0" ) +RCDATA NP_INFO_LegalCopyright { "Copyright Netscape Communications \251 1996\0" +RCDATA NP_INFO_OriginalFilename { "NVAPI32.DLL" } +RCDATA NP_INFO_ProductName { "NPAVI32 Dynamic Link Library\0" } +*/ +/* RC_DATA types for version info - required */ +#define NP_INFO_ProductVersion 1 +#define NP_INFO_MIMEType 2 +#define NP_INFO_FileOpenName 3 +#define NP_INFO_FileExtents 4 +/* RC_DATA types for version info - used if found */ +#define NP_INFO_FileDescription 5 +#define NP_INFO_ProductName 6 +/* RC_DATA types for version info - optional */ +#define NP_INFO_CompanyName 7 +#define NP_INFO_FileVersion 8 +#define NP_INFO_InternalName 9 +#define NP_INFO_LegalCopyright 10 +#define NP_INFO_OriginalFilename 11 + +#ifndef RC_INVOKED + +/*----------------------------------------------------------------------*/ +/* Definition of Basic Types */ +/*----------------------------------------------------------------------*/ + +typedef unsigned char NPBool; +typedef int16_t NPError; +typedef int16_t NPReason; +typedef char* NPMIMEType; + +/*----------------------------------------------------------------------*/ +/* Structures and definitions */ +/*----------------------------------------------------------------------*/ + +#if !defined(__LP64__) +#if defined(XP_MACOSX) +#pragma options align=mac68k +#endif +#endif /* __LP64__ */ + +/* + * NPP is a plug-in's opaque instance handle + */ +typedef struct _NPP +{ + void* pdata; /* plug-in private data */ + void* ndata; /* netscape private data */ +} NPP_t; + +typedef NPP_t* NPP; + +typedef struct _NPStream +{ + void* pdata; /* plug-in private data */ + void* ndata; /* netscape private data */ + const char* url; + uint32_t end; + uint32_t lastmodified; + void* notifyData; + const char* headers; /* Response headers from host. + * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS. + * Used for HTTP only; NULL for non-HTTP. + * Available from NPP_NewStream onwards. + * Plugin should copy this data before storing it. + * Includes HTTP status line and all headers, + * preferably verbatim as received from server, + * headers formatted as in HTTP ("Header: Value"), + * and newlines (\n, NOT \r\n) separating lines. + * Terminated by \n\0 (NOT \n\n\0). */ +} NPStream; + +typedef struct _NPByteRange +{ + int32_t offset; /* negative offset means from the end */ + uint32_t length; + struct _NPByteRange* next; +} NPByteRange; + +typedef struct _NPSavedData +{ + int32_t len; + void* buf; +} NPSavedData; + +typedef struct _NPRect +{ + uint16_t top; + uint16_t left; + uint16_t bottom; + uint16_t right; +} NPRect; + +typedef struct _NPSize +{ + int32_t width; + int32_t height; +} NPSize; + +typedef enum { + NPFocusNext = 0, + NPFocusPrevious = 1 +} NPFocusDirection; + +/* These formats describe the format in the memory byte-order. This means if + * a 32-bit value of a pixel is viewed on a little-endian system the layout will + * be 0xAARRGGBB. The Alpha channel will be stored in the most significant + * bits. */ +typedef enum { + /* 32-bit per pixel 8-bit per channel - premultiplied alpha */ + NPImageFormatBGRA32 = 0x1, + /* 32-bit per pixel 8-bit per channel - 1 unused channel */ + NPImageFormatBGRX32 = 0x2 +} NPImageFormat; + +typedef struct _NPAsyncSurface +{ + uint32_t version; + NPSize size; + NPImageFormat format; + union { + struct { + uint32_t stride; + void *data; + } bitmap; +#if defined(XP_WIN) + HANDLE sharedHandle; +#endif + }; +} NPAsyncSurface; + +/* Return values for NPP_HandleEvent */ +#define kNPEventNotHandled 0 +#define kNPEventHandled 1 +/* Exact meaning must be spec'd in event model. */ +#define kNPEventStartIME 2 + +#if defined(XP_UNIX) +/* + * Unix specific structures and definitions + */ + +/* + * Callback Structures. + * + * These are used to pass additional platform specific information. + */ +enum { + NP_SETWINDOW = 1, + NP_PRINT +}; + +typedef struct +{ + int32_t type; +} NPAnyCallbackStruct; + +typedef struct +{ + int32_t type; +#if defined(MOZ_X11) + Display* display; + Visual* visual; + Colormap colormap; + unsigned int depth; +#endif +} NPSetWindowCallbackStruct; + +typedef struct +{ + int32_t type; + FILE* fp; +} NPPrintCallbackStruct; + +#endif /* XP_UNIX */ + +typedef enum { +#if defined(XP_MACOSX) +#ifndef NP_NO_QUICKDRAW + NPDrawingModelQuickDraw = 0, +#endif + NPDrawingModelCoreGraphics = 1, + NPDrawingModelOpenGL = 2, + NPDrawingModelCoreAnimation = 3, + NPDrawingModelInvalidatingCoreAnimation = 4, +#endif +#if defined(XP_WIN) + NPDrawingModelSyncWin = 5, +#endif +#if defined(MOZ_X11) + NPDrawingModelSyncX = 6, +#endif + NPDrawingModelAsyncBitmapSurface = 7 +#if defined(XP_WIN) + , NPDrawingModelAsyncWindowsDXGISurface = 8 +#endif +} NPDrawingModel; + +#ifdef XP_MACOSX +typedef enum { +#ifndef NP_NO_CARBON + NPEventModelCarbon = 0, +#endif + NPEventModelCocoa = 1 +} NPEventModel; +#endif + +/* + * The following masks are applied on certain platforms to NPNV and + * NPPV selectors that pass around pointers to COM interfaces. Newer + * compilers on some platforms may generate vtables that are not + * compatible with older compilers. To prevent older plugins from + * not understanding a new browser's ABI, these masks change the + * values of those selectors on those platforms. To remain backwards + * compatible with different versions of the browser, plugins can + * use these masks to dynamically determine and use the correct C++ + * ABI that the browser is expecting. This does not apply to Windows + * as Microsoft's COM ABI will likely not change. + */ + +#define NP_ABI_GCC3_MASK 0x10000000 +/* + * gcc 3.x generated vtables on UNIX and OSX are incompatible with + * previous compilers. + */ +#if (defined(XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3)) +#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK +#else +#define _NP_ABI_MIXIN_FOR_GCC3 0 +#endif + +#if defined(XP_MACOSX) +#define NP_ABI_MACHO_MASK 0x01000000 +#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK +#else +#define _NP_ABI_MIXIN_FOR_MACHO 0 +#endif + +#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO) + +/* + * List of variable names for which NPP_GetValue shall be implemented + */ +typedef enum { + NPPVpluginNameString = 1, + NPPVpluginDescriptionString, + NPPVpluginWindowBool, + NPPVpluginTransparentBool, + NPPVjavaClass, + NPPVpluginWindowSize, + NPPVpluginTimerInterval, + NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), + NPPVpluginScriptableIID = 11, + NPPVjavascriptPushCallerBool = 12, + NPPVpluginKeepLibraryInMemory = 13, + NPPVpluginNeedsXEmbed = 14, + + /* Get the NPObject for scripting the plugin. Introduced in NPAPI minor version 14. + */ + NPPVpluginScriptableNPObject = 15, + + /* Get the plugin value (as \0-terminated UTF-8 string data) for + * form submission if the plugin is part of a form. Use + * NPN_MemAlloc() to allocate memory for the string data. Introduced + * in NPAPI minor version 15. + */ + NPPVformValue = 16, + + NPPVpluginUrlRequestsDisplayedBool = 17, + + /* Checks if the plugin is interested in receiving the http body of + * all http requests (including failed ones, http status != 200). + */ + NPPVpluginWantsAllNetworkStreams = 18, + + /* Browsers can retrieve a native ATK accessibility plug ID via this variable. */ + NPPVpluginNativeAccessibleAtkPlugId = 19, + + /* Checks to see if the plug-in would like the browser to load the "src" attribute. */ + NPPVpluginCancelSrcStream = 20, + + NPPVsupportsAdvancedKeyHandling = 21, + + NPPVpluginUsesDOMForCursorBool = 22, + + /* Used for negotiating drawing models */ + NPPVpluginDrawingModel = 1000 +#if defined(XP_MACOSX) + /* Used for negotiating event models */ + , NPPVpluginEventModel = 1001 + /* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */ + , NPPVpluginCoreAnimationLayer = 1003 +#endif + +#if defined(MOZ_PLATFORM_MAEMO) && ((MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)) + , NPPVpluginWindowlessLocalBool = 2002 +#endif +} NPPVariable; + +/* + * List of variable names for which NPN_GetValue should be implemented. + */ +typedef enum { + NPNVxDisplay = 1, + NPNVxtAppContext, + NPNVnetscapeWindow, + NPNVjavascriptEnabledBool, + NPNVasdEnabledBool, + NPNVisOfflineBool, + + NPNVserviceManager = (10 | NP_ABI_MASK), + NPNVDOMElement = (11 | NP_ABI_MASK), + NPNVDOMWindow = (12 | NP_ABI_MASK), + NPNVToolkit = (13 | NP_ABI_MASK), + NPNVSupportsXEmbedBool = 14, + + /* Get the NPObject wrapper for the browser window. */ + NPNVWindowNPObject = 15, + + /* Get the NPObject wrapper for the plugins DOM element. */ + NPNVPluginElementNPObject = 16, + + NPNVSupportsWindowless = 17, + + NPNVprivateModeBool = 18, + + NPNVsupportsAdvancedKeyHandling = 21, + + NPNVdocumentOrigin = 22, + + NPNVpluginDrawingModel = 1000 /* Get the current drawing model (NPDrawingModel) */ +#if defined(XP_MACOSX) + , NPNVcontentsScaleFactor = 1001 +#ifndef NP_NO_QUICKDRAW + , NPNVsupportsQuickDrawBool = 2000 +#endif + , NPNVsupportsCoreGraphicsBool = 2001 + , NPNVsupportsOpenGLBool = 2002 + , NPNVsupportsCoreAnimationBool = 2003 + , NPNVsupportsInvalidatingCoreAnimationBool = 2004 +#endif + , NPNVsupportsAsyncBitmapSurfaceBool = 2007 +#if defined(XP_WIN) + , NPNVsupportsAsyncWindowsDXGISurfaceBool = 2008 +#endif +#if defined(XP_MACOSX) +#ifndef NP_NO_CARBON + , NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */ +#endif + , NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */ + , NPNVsupportsUpdatedCocoaTextInputBool = 3002 /* TRUE if the browser supports the updated + Cocoa text input specification. */ + , NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports + CA model compositing */ +#endif +#if defined(MOZ_PLATFORM_MAEMO) && ((MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)) + , NPNVSupportsWindowlessLocal = 2002 +#endif +} NPNVariable; + +typedef enum { + NPNURLVCookie = 501, + NPNURLVProxy +} NPNURLVariable; + +/* + * The type of Toolkit the widgets use + */ +typedef enum { + NPNVGtk12 = 1, + NPNVGtk2 +} NPNToolkitType; + +/* + * The type of a NPWindow - it specifies the type of the data structure + * returned in the window field. + */ +typedef enum { + NPWindowTypeWindow = 1, + NPWindowTypeDrawable +} NPWindowType; + +typedef struct _NPWindow +{ + void* window; /* Platform specific window handle */ + /* OS/2: x - Position of bottom left corner */ + /* OS/2: y - relative to visible netscape window */ + int32_t x; /* Position of top left corner relative */ + int32_t y; /* to a netscape page. */ + uint32_t width; /* Maximum window size */ + uint32_t height; + NPRect clipRect; /* Clipping rectangle in port coordinates */ +#if (defined(XP_UNIX) || defined(XP_SYMBIAN)) && !defined(XP_MACOSX) + void * ws_info; /* Platform-dependent additional data */ +#endif /* XP_UNIX */ + NPWindowType type; /* Is this a window or a drawable? */ +} NPWindow; + +typedef struct _NPImageExpose +{ + char* data; /* image pointer */ + int32_t stride; /* Stride of data image pointer */ + int32_t depth; /* Depth of image pointer */ + int32_t x; /* Expose x */ + int32_t y; /* Expose y */ + uint32_t width; /* Expose width */ + uint32_t height; /* Expose height */ + NPSize dataSize; /* Data buffer size */ + float translateX; /* translate X matrix value */ + float translateY; /* translate Y matrix value */ + float scaleX; /* scale X matrix value */ + float scaleY; /* scale Y matrix value */ +} NPImageExpose; + +typedef struct _NPFullPrint +{ + NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */ + NPBool printOne; /* TRUE if plugin should print one copy to default + printer */ + void* platformPrint; /* Platform-specific printing info */ +} NPFullPrint; + +typedef struct _NPEmbedPrint +{ + NPWindow window; + void* platformPrint; /* Platform-specific printing info */ +} NPEmbedPrint; + +typedef struct _NPPrint +{ + uint16_t mode; /* NP_FULL or NP_EMBED */ + union + { + NPFullPrint fullPrint; /* if mode is NP_FULL */ + NPEmbedPrint embedPrint; /* if mode is NP_EMBED */ + } print; +} NPPrint; + +#if defined(XP_MACOSX) +#ifndef NP_NO_CARBON +typedef EventRecord NPEvent; +#endif +#elif defined(XP_SYMBIAN) +typedef QEvent NPEvent; +#elif defined(XP_WIN) +typedef struct _NPEvent +{ + uint16_t event; + uintptr_t wParam; + uintptr_t lParam; +} NPEvent; +#elif defined(XP_OS2) +typedef struct _NPEvent +{ + uint32_t event; + uint32_t wParam; + uint32_t lParam; +} NPEvent; +#elif defined(XP_UNIX) && defined(MOZ_X11) +typedef XEvent NPEvent; +#else +typedef void* NPEvent; +#endif + +#if defined(XP_MACOSX) +typedef void* NPRegion; +#ifndef NP_NO_QUICKDRAW +typedef RgnHandle NPQDRegion; +#endif +typedef CGPathRef NPCGRegion; +#elif defined(XP_WIN) +typedef HRGN NPRegion; +#elif defined(XP_UNIX) && defined(MOZ_X11) +typedef Region NPRegion; +#elif defined(XP_SYMBIAN) +typedef QRegion* NPRegion; +#else +typedef void *NPRegion; +#endif + +typedef struct _NPNSString NPNSString; +typedef struct _NPNSWindow NPNSWindow; +typedef struct _NPNSMenu NPNSMenu; + +#if defined(XP_MACOSX) +typedef NPNSMenu NPMenu; +#else +typedef void *NPMenu; +#endif + +typedef enum { + NPCoordinateSpacePlugin = 1, + NPCoordinateSpaceWindow, + NPCoordinateSpaceFlippedWindow, + NPCoordinateSpaceScreen, + NPCoordinateSpaceFlippedScreen +} NPCoordinateSpace; + +#if defined(XP_MACOSX) + +#ifndef NP_NO_QUICKDRAW +typedef struct NP_Port +{ + CGrafPtr port; + int32_t portx; /* position inside the topmost window */ + int32_t porty; +} NP_Port; +#endif /* NP_NO_QUICKDRAW */ + +/* + * NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics + * as its drawing model. + */ + +typedef struct NP_CGContext +{ + CGContextRef context; + void *window; /* A WindowRef under the Carbon event model. */ +} NP_CGContext; + +/* + * NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its + * drawing model. + */ + +typedef struct NP_GLContext +{ + CGLContextObj context; +#ifdef NP_NO_CARBON + NPNSWindow *window; +#else + void *window; /* Can be either an NSWindow or a WindowRef depending on the event model */ +#endif +} NP_GLContext; + +typedef enum { + NPCocoaEventDrawRect = 1, + NPCocoaEventMouseDown, + NPCocoaEventMouseUp, + NPCocoaEventMouseMoved, + NPCocoaEventMouseEntered, + NPCocoaEventMouseExited, + NPCocoaEventMouseDragged, + NPCocoaEventKeyDown, + NPCocoaEventKeyUp, + NPCocoaEventFlagsChanged, + NPCocoaEventFocusChanged, + NPCocoaEventWindowFocusChanged, + NPCocoaEventScrollWheel, + NPCocoaEventTextInput +} NPCocoaEventType; + +typedef struct _NPCocoaEvent { + NPCocoaEventType type; + uint32_t version; + union { + struct { + uint32_t modifierFlags; + double pluginX; + double pluginY; + int32_t buttonNumber; + int32_t clickCount; + double deltaX; + double deltaY; + double deltaZ; + } mouse; + struct { + uint32_t modifierFlags; + NPNSString *characters; + NPNSString *charactersIgnoringModifiers; + NPBool isARepeat; + uint16_t keyCode; + } key; + struct { + CGContextRef context; + double x; + double y; + double width; + double height; + } draw; + struct { + NPBool hasFocus; + } focus; + struct { + NPNSString *text; + } text; + } data; +} NPCocoaEvent; + +#ifndef NP_NO_CARBON +/* Non-standard event types that can be passed to HandleEvent */ +enum NPEventType { + NPEventType_GetFocusEvent = (osEvt + 16), + NPEventType_LoseFocusEvent, + NPEventType_AdjustCursorEvent, + NPEventType_MenuCommandEvent, + NPEventType_ClippingChangedEvent, + NPEventType_ScrollingBeginsEvent = 1000, + NPEventType_ScrollingEndsEvent +}; +#endif /* NP_NO_CARBON */ + +#endif /* XP_MACOSX */ + +/* + * Values for mode passed to NPP_New: + */ +#define NP_EMBED 1 +#define NP_FULL 2 + +/* + * Values for stream type passed to NPP_NewStream: + */ +#define NP_NORMAL 1 +#define NP_SEEK 2 +#define NP_ASFILE 3 +#define NP_ASFILEONLY 4 + +#define NP_MAXREADY (((unsigned)(~0)<<1)>>1) + +/* + * Flags for NPP_ClearSiteData. + */ +#define NP_CLEAR_ALL 0 +#define NP_CLEAR_CACHE (1 << 0) + +#if !defined(__LP64__) +#if defined(XP_MACOSX) +#pragma options align=reset +#endif +#endif /* __LP64__ */ + +/*----------------------------------------------------------------------*/ +/* Error and Reason Code definitions */ +/*----------------------------------------------------------------------*/ + +/* + * Values of type NPError: + */ +#define NPERR_BASE 0 +#define NPERR_NO_ERROR (NPERR_BASE + 0) +#define NPERR_GENERIC_ERROR (NPERR_BASE + 1) +#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2) +#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3) +#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4) +#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5) +#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6) +#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7) +#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8) +#define NPERR_INVALID_PARAM (NPERR_BASE + 9) +#define NPERR_INVALID_URL (NPERR_BASE + 10) +#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11) +#define NPERR_NO_DATA (NPERR_BASE + 12) +#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13) +#define NPERR_TIME_RANGE_NOT_SUPPORTED (NPERR_BASE + 14) +#define NPERR_MALFORMED_SITE (NPERR_BASE + 15) + +/* + * Values of type NPReason: + */ +#define NPRES_BASE 0 +#define NPRES_DONE (NPRES_BASE + 0) +#define NPRES_NETWORK_ERR (NPRES_BASE + 1) +#define NPRES_USER_BREAK (NPRES_BASE + 2) + +/* + * Don't use these obsolete error codes any more. + */ +#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR +#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR +#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK + +/* + * Version feature information + */ +#define NPVERS_HAS_STREAMOUTPUT 8 +#define NPVERS_HAS_NOTIFICATION 9 +#define NPVERS_HAS_LIVECONNECT 9 +#define NPVERS_68K_HAS_LIVECONNECT 11 +#define NPVERS_HAS_WINDOWLESS 11 +#define NPVERS_HAS_XPCONNECT_SCRIPTING 13 +#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14 +#define NPVERS_HAS_FORM_VALUES 15 +#define NPVERS_HAS_POPUPS_ENABLED_STATE 16 +#define NPVERS_HAS_RESPONSE_HEADERS 17 +#define NPVERS_HAS_NPOBJECT_ENUM 18 +#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19 +#define NPVERS_HAS_ALL_NETWORK_STREAMS 20 +#define NPVERS_HAS_URL_AND_AUTH_INFO 21 +#define NPVERS_HAS_PRIVATE_MODE 22 +#define NPVERS_MACOSX_HAS_COCOA_EVENTS 23 +#define NPVERS_HAS_ADVANCED_KEY_HANDLING 25 +#define NPVERS_HAS_URL_REDIRECT_HANDLING 26 +#define NPVERS_HAS_CLEAR_SITE_DATA 27 + +/*----------------------------------------------------------------------*/ +/* Function Prototypes */ +/*----------------------------------------------------------------------*/ + +#if defined(__OS2__) +#define NP_LOADDS _System +#else +#define NP_LOADDS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* NPP_* functions are provided by the plugin and called by the navigator. */ + +#if defined(XP_UNIX) +const char* NPP_GetMIMEDescription(void); +#endif + +NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, + uint16_t mode, int16_t argc, char* argn[], + char* argv[], NPSavedData* saved); +NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save); +NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window); +NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, + NPStream* stream, NPBool seekable, + uint16_t* stype); +NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, + NPReason reason); +int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream); +int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset, + int32_t len, void* buffer); +void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, + const char* fname); +void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint); +int16_t NP_LOADDS NPP_HandleEvent(NPP instance, void* event); +void NP_LOADDS NPP_URLNotify(NPP instance, const char* url, + NPReason reason, void* notifyData); +NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value); +NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value); +NPBool NP_LOADDS NPP_GotFocus(NPP instance, NPFocusDirection direction); +void NP_LOADDS NPP_LostFocus(NPP instance); +void NP_LOADDS NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData); +NPError NP_LOADDS NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge); +char** NP_LOADDS NPP_GetSitesWithData(void); +void NP_LOADDS NPP_DidComposite(NPP instance); + +/* NPN_* functions are provided by the navigator and called by the plugin. */ +void NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor, + int* netscape_major, int* netscape_minor); +NPError NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url, + const char* target, void* notifyData); +NPError NP_LOADDS NPN_GetURL(NPP instance, const char* url, + const char* target); +NPError NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url, + const char* target, uint32_t len, + const char* buf, NPBool file, + void* notifyData); +NPError NP_LOADDS NPN_PostURL(NPP instance, const char* url, + const char* target, uint32_t len, + const char* buf, NPBool file); +NPError NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList); +NPError NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type, + const char* target, NPStream** stream); +int32_t NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32_t len, + void* buffer); +NPError NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream, + NPReason reason); +void NP_LOADDS NPN_Status(NPP instance, const char* message); +const char* NP_LOADDS NPN_UserAgent(NPP instance); +void* NP_LOADDS NPN_MemAlloc(uint32_t size); +void NP_LOADDS NPN_MemFree(void* ptr); +uint32_t NP_LOADDS NPN_MemFlush(uint32_t size); +void NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages); +NPError NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable, + void *value); +NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable, + void *value); +void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect); +void NP_LOADDS NPN_InvalidateRegion(NPP instance, + NPRegion invalidRegion); +void NP_LOADDS NPN_ForceRedraw(NPP instance); +void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled); +void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance); +void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance, + void (*func) (void *), + void *userData); +NPError NP_LOADDS NPN_GetValueForURL(NPP instance, NPNURLVariable variable, + const char *url, char **value, + uint32_t *len); +NPError NP_LOADDS NPN_SetValueForURL(NPP instance, NPNURLVariable variable, + const char *url, const char *value, + uint32_t len); +NPError NP_LOADDS NPN_GetAuthenticationInfo(NPP instance, + const char *protocol, + const char *host, int32_t port, + const char *scheme, + const char *realm, + char **username, uint32_t *ulen, + char **password, + uint32_t *plen); +uint32_t NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)); +void NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID); +NPError NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu); +NPBool NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); +NPBool NP_LOADDS NPN_HandleEvent(NPP instance, void *event, NPBool handled); +NPBool NP_LOADDS NPN_UnfocusInstance(NPP instance, NPFocusDirection direction); +void NP_LOADDS NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow); +NPError NP_LOADDS NPN_InitAsyncSurface(NPP instance, NPSize *size, + NPImageFormat format, void *initData, + NPAsyncSurface *surface); +NPError NP_LOADDS NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface); +void NP_LOADDS NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* RC_INVOKED */ +#if defined(__OS2__) +#pragma pack() +#endif + +#endif /* npapi_h_ */ diff --git a/browser-plugin/npapi/npfunctions.h b/browser-plugin/npapi/npfunctions.h new file mode 100644 index 00000000..5207d3e4 --- /dev/null +++ b/browser-plugin/npapi/npfunctions.h @@ -0,0 +1,307 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef npfunctions_h_ +#define npfunctions_h_ + +#ifdef __OS2__ +#pragma pack(1) +#define NP_LOADDS _System +#else +#define NP_LOADDS +#endif + +#include "npapi.h" +#include "npruntime.h" + +#ifdef MOZ_WIDGET_ANDROID +#include +#endif + +typedef NPError (* NP_LOADDS NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved); +typedef NPError (* NP_LOADDS NPP_DestroyProcPtr)(NPP instance, NPSavedData** save); +typedef NPError (* NP_LOADDS NPP_SetWindowProcPtr)(NPP instance, NPWindow* window); +typedef NPError (* NP_LOADDS NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype); +typedef NPError (* NP_LOADDS NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason); +typedef int32_t (* NP_LOADDS NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream); +typedef int32_t (* NP_LOADDS NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer); +typedef void (* NP_LOADDS NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname); +typedef void (* NP_LOADDS NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint); +typedef int16_t (* NP_LOADDS NPP_HandleEventProcPtr)(NPP instance, void* event); +typedef void (* NP_LOADDS NPP_URLNotifyProcPtr)(NPP instance, const char* url, NPReason reason, void* notifyData); +/* Any NPObjects returned to the browser via NPP_GetValue should be retained + by the plugin on the way out. The browser is responsible for releasing. */ +typedef NPError (* NP_LOADDS NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value); +typedef NPError (* NP_LOADDS NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value); +typedef NPBool (* NP_LOADDS NPP_GotFocusPtr)(NPP instance, NPFocusDirection direction); +typedef void (* NP_LOADDS NPP_LostFocusPtr)(NPP instance); +typedef void (* NP_LOADDS NPP_URLRedirectNotifyPtr)(NPP instance, const char* url, int32_t status, void* notifyData); +typedef NPError (* NP_LOADDS NPP_ClearSiteDataPtr)(const char* site, uint64_t flags, uint64_t maxAge); +typedef char** (* NP_LOADDS NPP_GetSitesWithDataPtr)(void); +typedef void (* NP_LOADDS NPP_DidCompositePtr)(NPP instance); + +typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value); +typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value); +typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* url, const char* window, void* notifyData); +typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData); +typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* url, const char* window); +typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file); +typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList); +typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); +typedef int32_t (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len, void* buffer); +typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason); +typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message); +/* Browser manages the lifetime of the buffer returned by NPN_UserAgent, don't + depend on it sticking around and don't free it. */ +typedef const char* (*NPN_UserAgentProcPtr)(NPP instance); +typedef void* (*NPN_MemAllocProcPtr)(uint32_t size); +typedef void (*NPN_MemFreeProcPtr)(void* ptr); +typedef uint32_t (*NPN_MemFlushProcPtr)(uint32_t size); +typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages); +typedef void* (*NPN_GetJavaEnvProcPtr)(void); +typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance); +typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect); +typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region); +typedef void (*NPN_ForceRedrawProcPtr)(NPP instance); +typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr)(const NPUTF8* name); +typedef void (*NPN_GetStringIdentifiersProcPtr)(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers); +typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr)(int32_t intid); +typedef bool (*NPN_IdentifierIsStringProcPtr)(NPIdentifier identifier); +typedef NPUTF8* (*NPN_UTF8FromIdentifierProcPtr)(NPIdentifier identifier); +typedef int32_t (*NPN_IntFromIdentifierProcPtr)(NPIdentifier identifier); +typedef NPObject* (*NPN_CreateObjectProcPtr)(NPP npp, NPClass *aClass); +typedef NPObject* (*NPN_RetainObjectProcPtr)(NPObject *obj); +typedef void (*NPN_ReleaseObjectProcPtr)(NPObject *obj); +typedef bool (*NPN_InvokeProcPtr)(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result); +typedef bool (*NPN_InvokeDefaultProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result); +typedef bool (*NPN_EvaluateProcPtr)(NPP npp, NPObject *obj, NPString *script, NPVariant *result); +typedef bool (*NPN_GetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result); +typedef bool (*NPN_SetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value); +typedef bool (*NPN_RemovePropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName); +typedef bool (*NPN_HasPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName); +typedef bool (*NPN_HasMethodProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName); +typedef void (*NPN_ReleaseVariantValueProcPtr)(NPVariant *variant); +typedef void (*NPN_SetExceptionProcPtr)(NPObject *obj, const NPUTF8 *message); +typedef void (*NPN_PushPopupsEnabledStateProcPtr)(NPP npp, NPBool enabled); +typedef void (*NPN_PopPopupsEnabledStateProcPtr)(NPP npp); +typedef bool (*NPN_EnumerateProcPtr)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32_t *count); +typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance, void (*func)(void *), void *userData); +typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result); +typedef NPError (*NPN_GetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32_t *len); +typedef NPError (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32_t len); +typedef NPError (*NPN_GetAuthenticationInfoPtr)(NPP npp, const char *protocol, const char *host, int32_t port, const char *scheme, const char *realm, char **username, uint32_t *ulen, char **password, uint32_t *plen); +typedef uint32_t (*NPN_ScheduleTimerPtr)(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)); +typedef void (*NPN_UnscheduleTimerPtr)(NPP instance, uint32_t timerID); +typedef NPError (*NPN_PopUpContextMenuPtr)(NPP instance, NPMenu* menu); +typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); +typedef NPBool (*NPN_HandleEventPtr)(NPP instance, void *event, NPBool handled); +typedef NPBool (*NPN_UnfocusInstancePtr)(NPP instance, NPFocusDirection direction); +typedef void (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData, NPBool allow); +typedef NPError (*NPN_InitAsyncSurfacePtr)(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface); +typedef NPError (*NPN_FinalizeAsyncSurfacePtr)(NPP instance, NPAsyncSurface *surface); +typedef void (*NPN_SetCurrentAsyncSurfacePtr)(NPP instance, NPAsyncSurface *surface, NPRect *changed); + +typedef struct _NPPluginFuncs { + uint16_t size; + uint16_t version; + NPP_NewProcPtr newp; + NPP_DestroyProcPtr destroy; + NPP_SetWindowProcPtr setwindow; + NPP_NewStreamProcPtr newstream; + NPP_DestroyStreamProcPtr destroystream; + NPP_StreamAsFileProcPtr asfile; + NPP_WriteReadyProcPtr writeready; + NPP_WriteProcPtr write; + NPP_PrintProcPtr print; + NPP_HandleEventProcPtr event; + NPP_URLNotifyProcPtr urlnotify; + void* javaClass; + NPP_GetValueProcPtr getvalue; + NPP_SetValueProcPtr setvalue; + NPP_GotFocusPtr gotfocus; + NPP_LostFocusPtr lostfocus; + NPP_URLRedirectNotifyPtr urlredirectnotify; + NPP_ClearSiteDataPtr clearsitedata; + NPP_GetSitesWithDataPtr getsiteswithdata; + NPP_DidCompositePtr didComposite; +} NPPluginFuncs; + +typedef struct _NPNetscapeFuncs { + uint16_t size; + uint16_t version; + NPN_GetURLProcPtr geturl; + NPN_PostURLProcPtr posturl; + NPN_RequestReadProcPtr requestread; + NPN_NewStreamProcPtr newstream; + NPN_WriteProcPtr write; + NPN_DestroyStreamProcPtr destroystream; + NPN_StatusProcPtr status; + NPN_UserAgentProcPtr uagent; + NPN_MemAllocProcPtr memalloc; + NPN_MemFreeProcPtr memfree; + NPN_MemFlushProcPtr memflush; + NPN_ReloadPluginsProcPtr reloadplugins; + NPN_GetJavaEnvProcPtr getJavaEnv; + NPN_GetJavaPeerProcPtr getJavaPeer; + NPN_GetURLNotifyProcPtr geturlnotify; + NPN_PostURLNotifyProcPtr posturlnotify; + NPN_GetValueProcPtr getvalue; + NPN_SetValueProcPtr setvalue; + NPN_InvalidateRectProcPtr invalidaterect; + NPN_InvalidateRegionProcPtr invalidateregion; + NPN_ForceRedrawProcPtr forceredraw; + NPN_GetStringIdentifierProcPtr getstringidentifier; + NPN_GetStringIdentifiersProcPtr getstringidentifiers; + NPN_GetIntIdentifierProcPtr getintidentifier; + NPN_IdentifierIsStringProcPtr identifierisstring; + NPN_UTF8FromIdentifierProcPtr utf8fromidentifier; + NPN_IntFromIdentifierProcPtr intfromidentifier; + NPN_CreateObjectProcPtr createobject; + NPN_RetainObjectProcPtr retainobject; + NPN_ReleaseObjectProcPtr releaseobject; + NPN_InvokeProcPtr invoke; + NPN_InvokeDefaultProcPtr invokeDefault; + NPN_EvaluateProcPtr evaluate; + NPN_GetPropertyProcPtr getproperty; + NPN_SetPropertyProcPtr setproperty; + NPN_RemovePropertyProcPtr removeproperty; + NPN_HasPropertyProcPtr hasproperty; + NPN_HasMethodProcPtr hasmethod; + NPN_ReleaseVariantValueProcPtr releasevariantvalue; + NPN_SetExceptionProcPtr setexception; + NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate; + NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate; + NPN_EnumerateProcPtr enumerate; + NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall; + NPN_ConstructProcPtr construct; + NPN_GetValueForURLPtr getvalueforurl; + NPN_SetValueForURLPtr setvalueforurl; + NPN_GetAuthenticationInfoPtr getauthenticationinfo; + NPN_ScheduleTimerPtr scheduletimer; + NPN_UnscheduleTimerPtr unscheduletimer; + NPN_PopUpContextMenuPtr popupcontextmenu; + NPN_ConvertPointPtr convertpoint; + NPN_HandleEventPtr handleevent; + NPN_UnfocusInstancePtr unfocusinstance; + NPN_URLRedirectResponsePtr urlredirectresponse; + NPN_InitAsyncSurfacePtr initasyncsurface; + NPN_FinalizeAsyncSurfacePtr finalizeasyncsurface; + NPN_SetCurrentAsyncSurfacePtr setcurrentasyncsurface; +} NPNetscapeFuncs; + +#ifdef XP_MACOSX +/* + * Mac OS X version(s) of NP_GetMIMEDescription(const char *) + * These can be called to retreive MIME information from the plugin dynamically + * + * Note: For compatibility with Quicktime, BPSupportedMIMEtypes is another way + * to get mime info from the plugin only on OSX and may not be supported + * in furture version -- use NP_GetMIMEDescription instead + */ +enum +{ + kBPSupportedMIMETypesStructVers_1 = 1 +}; +typedef struct _BPSupportedMIMETypes +{ + SInt32 structVersion; /* struct version */ + Handle typeStrings; /* STR# formated handle, allocated by plug-in */ + Handle infoStrings; /* STR# formated handle, allocated by plug-in */ +} BPSupportedMIMETypes; +OSErr BP_GetSupportedMIMETypes(BPSupportedMIMETypes *mimeInfo, UInt32 flags); +#define NP_GETMIMEDESCRIPTION_NAME "NP_GetMIMEDescription" +typedef const char* (*NP_GetMIMEDescriptionProcPtr)(void); +typedef OSErr (*BP_GetSupportedMIMETypesProcPtr)(BPSupportedMIMETypes*, UInt32); +#endif + +#if defined(_WIN32) +#define OSCALL WINAPI +#else +#if defined(__OS2__) +#define OSCALL _System +#else +#define OSCALL +#endif +#endif + +#if defined(XP_UNIX) +/* GCC 3.3 and later support the visibility attribute. */ +#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +#define NP_VISIBILITY_DEFAULT __attribute__((visibility("default"))) +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#define NP_VISIBILITY_DEFAULT __global +#else +#define NP_VISIBILITY_DEFAULT +#endif +#define NP_EXPORT(__type) NP_VISIBILITY_DEFAULT __type +#endif + +#if defined(_WIN32) || defined (__OS2__) +#ifdef __cplusplus +extern "C" { +#endif +/* plugin meta member functions */ +#if defined(__OS2__) +typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */ + char *pMimeTypes; + char *pFileExtents; + char *pFileOpenTemplate; + char *pProductName; + char *pProductDescription; + unsigned long dwProductVersionMS; + unsigned long dwProductVersionLS; +} NPPluginData; +typedef NPError (OSCALL *NP_GetPluginDataFunc)(NPPluginData*); +NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData); +#endif +typedef NPError (OSCALL *NP_GetEntryPointsFunc)(NPPluginFuncs*); +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs); +typedef NPError (OSCALL *NP_InitializeFunc)(NPNetscapeFuncs*); +NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs); +typedef NPError (OSCALL *NP_ShutdownFunc)(void); +NPError OSCALL NP_Shutdown(void); +typedef const char* (*NP_GetMIMEDescriptionFunc)(void); +const char* NP_GetMIMEDescription(void); +#ifdef __cplusplus +} +#endif +#endif + +#if defined(__OS2__) +#pragma pack() +#endif + +#ifdef XP_UNIX +#ifdef __cplusplus +extern "C" { +#endif +typedef char* (*NP_GetPluginVersionFunc)(void); +NP_EXPORT(char*) NP_GetPluginVersion(void); +typedef const char* (*NP_GetMIMEDescriptionFunc)(void); +NP_EXPORT(const char*) NP_GetMIMEDescription(void); +#ifdef XP_MACOSX +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*); +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs); +typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*); +NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs); +#else +#ifdef MOZ_WIDGET_ANDROID +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*, JNIEnv* pEnv); +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, JNIEnv* pEnv); +#else +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*); +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs); +#endif +#endif +typedef NPError (*NP_ShutdownFunc)(void); +NP_EXPORT(NPError) NP_Shutdown(void); +typedef NPError (*NP_GetValueFunc)(void *, NPPVariable, void *); +NP_EXPORT(NPError) NP_GetValue(void *future, NPPVariable aVariable, void *aValue); +#ifdef __cplusplus +} +#endif +#endif + +#endif /* npfunctions_h_ */ diff --git a/browser-plugin/npapi/npruntime.h b/browser-plugin/npapi/npruntime.h new file mode 100644 index 00000000..6e891650 --- /dev/null +++ b/browser-plugin/npapi/npruntime.h @@ -0,0 +1,393 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (c) 2004, Apple Computer, Inc. and The Mozilla Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla + * Foundation ("Mozilla") nor the names of their contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR + * THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _NP_RUNTIME_H_ +#define _NP_RUNTIME_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nptypes.h" + +/* + This API is used to facilitate binding code written in C to script + objects. The API in this header does not assume the presence of a + user agent. That is, it can be used to bind C code to scripting + environments outside of the context of a user agent. + + However, the normal use of the this API is in the context of a + scripting environment running in a browser or other user agent. + In particular it is used to support the extended Netscape + script-ability API for plugins (NP-SAP). NP-SAP is an extension + of the Netscape plugin API. As such we have adopted the use of + the "NP" prefix for this API. + + The following NP{N|P}Variables were added to the Netscape plugin + API (in npapi.h): + + NPNVWindowNPObject + NPNVPluginElementNPObject + NPPVpluginScriptableNPObject + + These variables are exposed through NPN_GetValue() and + NPP_GetValue() (respectively) and are used to establish the + initial binding between the user agent and native code. The DOM + objects in the user agent can be examined and manipulated using + the NPN_ functions that operate on NPObjects described in this + header. + + To the extent possible the assumptions about the scripting + language used by the scripting environment have been minimized. +*/ + +#define NP_BEGIN_MACRO do { +#define NP_END_MACRO } while (0) + +/* + Objects (non-primitive data) passed between 'C' and script is + always wrapped in an NPObject. The 'interface' of an NPObject is + described by an NPClass. +*/ +typedef struct NPObject NPObject; +typedef struct NPClass NPClass; + +typedef char NPUTF8; +typedef struct _NPString { + const NPUTF8 *UTF8Characters; + uint32_t UTF8Length; +} NPString; + +typedef enum { + NPVariantType_Void, + NPVariantType_Null, + NPVariantType_Bool, + NPVariantType_Int32, + NPVariantType_Double, + NPVariantType_String, + NPVariantType_Object +} NPVariantType; + +typedef struct _NPVariant { + NPVariantType type; + union { + bool boolValue; + int32_t intValue; + double doubleValue; + NPString stringValue; + NPObject *objectValue; + } value; +} NPVariant; + +/* + NPN_ReleaseVariantValue is called on all 'out' parameters + references. Specifically it is to be called on variants that own + their value, as is the case with all non-const NPVariant* + arguments after a successful call to any methods (except this one) + in this API. + + After calling NPN_ReleaseVariantValue, the type of the variant + will be NPVariantType_Void. +*/ +void NPN_ReleaseVariantValue(NPVariant *variant); + +#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void) +#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null) +#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool) +#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32) +#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double) +#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String) +#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object) + +#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue) +#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue) +#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue) +#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue) +#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue) + +#define VOID_TO_NPVARIANT(_v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Void; \ + (_v).value.objectValue = NULL; \ +NP_END_MACRO + +#define NULL_TO_NPVARIANT(_v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Null; \ + (_v).value.objectValue = NULL; \ +NP_END_MACRO + +#define BOOLEAN_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Bool; \ + (_v).value.boolValue = !!(_val); \ +NP_END_MACRO + +#define INT32_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Int32; \ + (_v).value.intValue = _val; \ +NP_END_MACRO + +#define DOUBLE_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Double; \ + (_v).value.doubleValue = _val; \ +NP_END_MACRO + +#define STRINGZ_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_String; \ + NPString str = { _val, (uint32_t)(strlen(_val)) }; \ + (_v).value.stringValue = str; \ +NP_END_MACRO + +#define STRINGN_TO_NPVARIANT(_val, _len, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_String; \ + NPString str = { _val, (uint32_t)(_len) }; \ + (_v).value.stringValue = str; \ +NP_END_MACRO + +#define OBJECT_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Object; \ + (_v).value.objectValue = _val; \ +NP_END_MACRO + + +/* + Type mappings (JavaScript types have been used for illustration + purposes): + + JavaScript to C (NPVariant with type:) + undefined NPVariantType_Void + null NPVariantType_Null + Boolean NPVariantType_Bool + Number NPVariantType_Double or NPVariantType_Int32 + String NPVariantType_String + Object NPVariantType_Object + + C (NPVariant with type:) to JavaScript + NPVariantType_Void undefined + NPVariantType_Null null + NPVariantType_Bool Boolean + NPVariantType_Int32 Number + NPVariantType_Double Number + NPVariantType_String String + NPVariantType_Object Object +*/ + +typedef void *NPIdentifier; + +/* + NPObjects have methods and properties. Methods and properties are + identified with NPIdentifiers. These identifiers may be reflected + in script. NPIdentifiers can be either strings or integers, IOW, + methods and properties can be identified by either strings or + integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be + compared using ==. In case of any errors, the requested + NPIdentifier(s) will be NULL. NPIdentifier lifetime is controlled + by the browser. Plugins do not need to worry about memory management + with regards to NPIdentifiers. +*/ +NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name); +void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, + NPIdentifier *identifiers); +NPIdentifier NPN_GetIntIdentifier(int32_t intid); +bool NPN_IdentifierIsString(NPIdentifier identifier); + +/* + The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed. +*/ +NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier); + +/* + Get the integer represented by identifier. If identifier is not an + integer identifier, the behaviour is undefined. +*/ +int32_t NPN_IntFromIdentifier(NPIdentifier identifier); + +/* + NPObject behavior is implemented using the following set of + callback functions. + + The NPVariant *result argument of these functions (where + applicable) should be released using NPN_ReleaseVariantValue(). +*/ +typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass); +typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj); +typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj); +typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name); +typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, NPIdentifier name, + const NPVariant *args, uint32_t argCount, + NPVariant *result); +typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj, + const NPVariant *args, + uint32_t argCount, + NPVariant *result); +typedef bool (*NPHasPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name); +typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name, + NPVariant *result); +typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name, + const NPVariant *value); +typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, + NPIdentifier name); +typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, + uint32_t *count); +typedef bool (*NPConstructFunctionPtr)(NPObject *npobj, + const NPVariant *args, + uint32_t argCount, + NPVariant *result); + +/* + NPObjects returned by create, retain, invoke, and getProperty pass + a reference count to the caller. That is, the callee adds a + reference count which passes to the caller. It is the caller's + responsibility to release the returned object. + + NPInvokeFunctionPtr function may return 0 to indicate a void + result. + + NPInvalidateFunctionPtr is called by the scripting environment + when the native code is shutdown. Any attempt to message a + NPObject instance after the invalidate callback has been + called will result in undefined behavior, even if the native code + is still retaining those NPObject instances. (The runtime + will typically return immediately, with 0 or NULL, from an attempt + to dispatch to a NPObject, but this behavior should not be + depended upon.) + + The NPEnumerationFunctionPtr function may pass an array of + NPIdentifiers back to the caller. The callee allocs the memory of + the array using NPN_MemAlloc(), and it's the caller's responsibility + to release it using NPN_MemFree(). +*/ +struct NPClass +{ + uint32_t structVersion; + NPAllocateFunctionPtr allocate; + NPDeallocateFunctionPtr deallocate; + NPInvalidateFunctionPtr invalidate; + NPHasMethodFunctionPtr hasMethod; + NPInvokeFunctionPtr invoke; + NPInvokeDefaultFunctionPtr invokeDefault; + NPHasPropertyFunctionPtr hasProperty; + NPGetPropertyFunctionPtr getProperty; + NPSetPropertyFunctionPtr setProperty; + NPRemovePropertyFunctionPtr removeProperty; + NPEnumerationFunctionPtr enumerate; + NPConstructFunctionPtr construct; +}; + +#define NP_CLASS_STRUCT_VERSION 3 + +#define NP_CLASS_STRUCT_VERSION_ENUM 2 +#define NP_CLASS_STRUCT_VERSION_CTOR 3 + +#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \ + ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM) + +#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \ + ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR) + +struct NPObject { + NPClass *_class; + uint32_t referenceCount; + /* + * Additional space may be allocated here by types of NPObjects + */ +}; + +/* + If the class has an allocate function, NPN_CreateObject invokes + that function, otherwise a NPObject is allocated and + returned. This method will initialize the referenceCount member of + the NPObject to 1. +*/ +NPObject *NPN_CreateObject(NPP npp, NPClass *aClass); + +/* + Increment the NPObject's reference count. +*/ +NPObject *NPN_RetainObject(NPObject *npobj); + +/* + Decremented the NPObject's reference count. If the reference + count goes to zero, the class's destroy function is invoke if + specified, otherwise the object is freed directly. +*/ +void NPN_ReleaseObject(NPObject *npobj); + +/* + Functions to access script objects represented by NPObject. + + Calls to script objects are synchronous. If a function returns a + value, it will be supplied via the result NPVariant + argument. Successful calls will return true, false will be + returned in case of an error. + + Calls made from plugin code to script must be made from the thread + on which the plugin was initialized. +*/ + +bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, + const NPVariant *args, uint32_t argCount, NPVariant *result); +bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result); +bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, + NPVariant *result); +bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, + NPVariant *result); +bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, + const NPVariant *value); +bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); +bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); +bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName); +bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, + uint32_t *count); +bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result); + +/* + NPN_SetException may be called to trigger a script exception upon + return from entry points into NPObjects. Typical usage: + + NPN_SetException (npobj, message); +*/ +void NPN_SetException(NPObject *npobj, const NPUTF8 *message); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/browser-plugin/npapi/nptypes.h b/browser-plugin/npapi/nptypes.h new file mode 100644 index 00000000..6fbc7d11 --- /dev/null +++ b/browser-plugin/npapi/nptypes.h @@ -0,0 +1,88 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nptypes_h_ +#define nptypes_h_ + +/* + * Header file for ensuring that C99 types ([u]int32_t, [u]int64_t and bool) and + * true/false macros are available. + */ + +#if defined(WIN32) || defined(OS2) + /* + * Win32 and OS/2 don't know C99, so define [u]int_16/32/64 here. The bool + * is predefined tho, both in C and C++. + */ + typedef short int16_t; + typedef unsigned short uint16_t; + typedef int int32_t; + typedef unsigned int uint32_t; + typedef long long int64_t; + typedef unsigned long long uint64_t; +#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX) + /* + * AIX and SunOS ship a inttypes.h header that defines [u]int32_t, + * but not bool for C. + */ + #include + + #ifndef __cplusplus + typedef int bool; + #define true 1 + #define false 0 + #endif +#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD) + /* + * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and + * u_int32_t. + */ + #include + + /* + * BSD/OS ships no header that defines uint32_t, nor bool (for C) + */ + #if defined(bsdi) + typedef u_int32_t uint32_t; + typedef u_int64_t uint64_t; + + #if !defined(__cplusplus) + typedef int bool; + #define true 1 + #define false 0 + #endif + #else + /* + * FreeBSD and OpenBSD define uint32_t and bool. + */ + #include + #include + #endif +#elif defined(BEOS) + #include +#else + /* + * For those that ship a standard C99 stdint.h header file, include + * it. Can't do the same for stdbool.h tho, since some systems ship + * with a stdbool.h file that doesn't compile! + */ + #include + + #ifndef __cplusplus + #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95) + #include + #else + /* + * GCC 2.91 can't deal with a typedef for bool, but a #define + * works. + */ + #define bool int + #define true 1 + #define false 0 + #endif + #endif +#endif + +#endif /* nptypes_h_ */ diff --git a/browser-plugin/plugin.symbols b/browser-plugin/plugin.symbols new file mode 100644 index 00000000..c13252cf --- /dev/null +++ b/browser-plugin/plugin.symbols @@ -0,0 +1,4 @@ +NP_GetMIMEDescription +NP_GetValue +NP_Initialize +NP_Shutdown diff --git a/browser-plugin/tests/data-uri.html b/browser-plugin/tests/data-uri.html new file mode 100644 index 00000000..8f3c1d8b --- /dev/null +++ b/browser-plugin/tests/data-uri.html @@ -0,0 +1,12 @@ + + + Evince Browser Plugin Test: Data URI + + + +

Data URI

+ + The pdf could not be rendered. + + + diff --git a/browser-plugin/tests/iframe.html b/browser-plugin/tests/iframe.html new file mode 100644 index 00000000..ce893b04 --- /dev/null +++ b/browser-plugin/tests/iframe.html @@ -0,0 +1,15 @@ + + + Evince Browser Plugin Test: Iframe + + + +

PDF document inside an Iframe

+ + +
+