static void init_methods_and_properties (void) { /* this is the JS public API; it is manipulated through NPIdentifiers for speed */ get_metadata_id = funcs.getstringidentifier ("getExtensionMetadata"); list_extensions_id = funcs.getstringidentifier ("listExtensions"); enable_extension_id = funcs.getstringidentifier ("setExtensionEnabled"); install_extension_id = funcs.getstringidentifier ("installExtension"); onextension_changed_id = funcs.getstringidentifier ("onchange"); }
NPIdentifier NPN_GetStringIdentifier(const NPUTF8 * name) { if (!NPNFuncs.getstringidentifier) return 0; return NPNFuncs.getstringidentifier(name); }
static inline gchar * get_string_property (NPP instance, NPObject *obj, const char *name) { NPVariant result = { NPVariantType_Void }; NPString result_str; gchar *result_copy; result_copy = NULL; if (!funcs.getproperty (instance, obj, funcs.getstringidentifier (name), &result)) goto out; if (!NPVARIANT_IS_STRING (result)) goto out; result_str = NPVARIANT_TO_STRING (result); result_copy = g_strndup (result_str.UTF8Characters, result_str.UTF8Length); out: funcs.releasevariantvalue (&result); return result_copy; }
NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name) { char msg[1024]; sprintf(msg, "NPN_GetStringIdentifier %s", name); logger->logMessage(msg); NPIdentifier rv = NPNFuncs.getstringidentifier(name); sprintf(msg, "--Return: 0x%x", rv); logger->logMessage(msg); return rv; }
SEXP R_NPAPI_GetProperty(SEXP plug, SEXP Robj, SEXP Rname, SEXP RconvRet) { NPP inst = (NPP) R_ExternalPtrAddr(GET_SLOT( plug , Rf_install( "ref" ) ) ); NPNetscapeFuncs *funcs = (NPNetscapeFuncs *) R_ExternalPtrAddr(GET_SLOT( GET_SLOT(plug, Rf_install("funcs")), Rf_install("ref"))); NPVariant *obj = (NPVariant *) R_ExternalPtrAddr(GET_SLOT( Robj , Rf_install( "ref" ) ) ); if(!NPVARIANT_IS_OBJECT(*obj)) { //What should we return in this case? Rf_error("Robj is not an NPVariant containing an NPObject."); return R_NilValue; } convert_t convRet = (convert_t) INTEGER(RconvRet)[0]; NPVariant *ret = (NPVariant *) funcs->memalloc(sizeof(NPVariant)); const char *ccname = CHAR(STRING_ELT(Rname, 0)); bool success = funcs->getproperty(inst, obj->value.objectValue, funcs->getstringidentifier(ccname), ret); if(!success) { Rf_error("Invoke failed."); return R_NilValue; } SEXP ans; PROTECT(ans = R_NilValue); //ConvertNPToR returns a bool which indicates whether it is safe to release the converted object. bool canfree = ConvertNPToR(ret, inst, funcs, convRet, &ans); if(canfree) funcs->releasevariantvalue(ret); UNPROTECT(1); return ans ; }
SEXP R_NPAPI_SetProperty(SEXP plug, SEXP Robj, SEXP Rname, SEXP Rval, SEXP RconvValue) { NPP inst = (NPP) R_ExternalPtrAddr(GET_SLOT( plug , Rf_install( "ref" ) ) ); NPNetscapeFuncs *funcs = (NPNetscapeFuncs *) R_ExternalPtrAddr(GET_SLOT( GET_SLOT(plug, Rf_install("funcs")), Rf_install("ref"))); NPVariant *obj = (NPVariant *) R_ExternalPtrAddr(GET_SLOT( Robj , Rf_install( "ref" ) ) ); if(!NPVARIANT_IS_OBJECT(*obj)) { //What should we return in this case? Rf_error("Robj is not an NPVariant containing an NPObject."); return R_NilValue; } convert_t convVal = (convert_t) INTEGER(RconvValue)[0]; //NPVariant *val = (NPVariant *) funcs->memalloc(sizeof(NPVariant)); NPVariant val; ConvertRToNP(Rval, inst, funcs, &val, convVal); const char *ccname = CHAR(STRING_ELT(Rname, 0)); bool success = funcs->setproperty(inst, obj->value.objectValue, funcs->getstringidentifier(ccname), &val); if(!success) { //funcs->memfree(val); Rf_error("SetProperty failed."); return R_NilValue; } else { funcs->releasevariantvalue(&val); //funcs->memfree(val); } return ScalarLogical(success) ; }
SEXP R_NPAPI_Invoke(SEXP plug, SEXP Robj, SEXP Rname, SEXP Rargs, SEXP RconvArgsEnum, SEXP RconvArgsFuns, SEXP RconvRet, SEXP RkeepRes ) { NPP inst = (NPP) R_ExternalPtrAddr(GET_SLOT( plug , Rf_install( "ref" ) ) ); NPNetscapeFuncs *funcs = (NPNetscapeFuncs *) R_ExternalPtrAddr(GET_SLOT( GET_SLOT(plug, Rf_install("funcs")), Rf_install("ref"))); NPVariant *obj = (NPVariant *) R_ExternalPtrAddr(GET_SLOT( Robj , Rf_install( "ref" ) ) ); if(!NPVARIANT_IS_OBJECT(*obj)) { //What should we return in this case? Rf_error("Robj is not an NPVariant containing an NPObject."); return R_NilValue; } //custom conversion functions are applied on R side for return value. convert_t convRet = (convert_t) INTEGER(RconvRet)[0]; convert_t curConvArg; int nargs = LENGTH(Rargs); NPVariant *args = (NPVariant *) funcs->memalloc(nargs*sizeof(NPVariant)); for(int i = 0; i < nargs; i++) { curConvArg = (convert_t) INTEGER(RconvArgsEnum)[i]; ConvertRToNP(VECTOR_ELT(Rargs, i), inst, funcs, &(args[i]), curConvArg); //If we have a custom converter we invoke it with here if(curConvArg == CONV_CUSTOM) { fprintf(stderr, "Custom argument converter detected. Attempting to call JS Conversion function.");fflush(stderr); funcs->invokeDefault(inst, ((NPVariant *) R_ExternalPtrAddr(GET_SLOT( VECTOR_ELT(RconvArgsFuns, i), Rf_install( "ref" ) ) ) ) -> value.objectValue, &args[i], 1, &args[i]) ; } } NPVariant *ret = (NPVariant *) funcs->memalloc(sizeof(NPVariant)); const char *ccname = CHAR(STRING_ELT(Rname, 0)); bool hasMethod = funcs->hasmethod(inst, obj->value.objectValue, funcs->getstringidentifier(ccname)); if(!hasMethod) { char msg[200]; sprintf(msg, "Object has no %s method.", ccname); Rf_error(msg); return R_NilValue; } bool success = funcs->invoke(inst, obj->value.objectValue, funcs->getstringidentifier(ccname), args, nargs, ret); if(!success) { fprintf(stderr, "\nInvocation of JS method %s failed.", ccname);fflush(stderr); } for(int j=0; j<nargs; j++) { if (NPVARIANT_IS_OBJECT(args[j])) funcs->releaseobject(args[j].value.objectValue); //funcs->releasevariantvalue(&args[j]); } funcs->memfree(args); if(!success) { char msg2[200]; sprintf(msg2, "Invoke failed for %s method.", ccname); Rf_error(msg2); return R_NilValue; } SEXP ans; //PROTECT(ans = R_NilValue); PROTECT(ans = NEW_INTEGER(1)); bool canfree = ConvertNPToR(ret, inst, funcs, convRet, &ans); bool keepRes = LOGICAL(RkeepRes)[0]; if(canfree || !keepRes) funcs->releasevariantvalue(ret); UNPROTECT(1); if(keepRes) return ans ; else return R_NilValue; }
NPError NPP_New(NPMIMEType mimetype, NPP instance, uint16_t mode, int16_t argc, char **argn, char **argv, NPSavedData *saved) { /* instance initialization function */ NPError ret = NPERR_NO_ERROR; PluginData *data; GError *error = NULL; /* first, check if the location is what we expect */ NPObject *window; NPVariant document; NPVariant location; NPVariant href; g_debug ("plugin created"); funcs.getvalue (instance, NPNVWindowNPObject, &window); funcs.getproperty (instance, window, funcs.getstringidentifier ("document"), &document); g_assert (NPVARIANT_IS_OBJECT (document)); funcs.getproperty (instance, NPVARIANT_TO_OBJECT (document), funcs.getstringidentifier ("location"), &location); g_assert (NPVARIANT_IS_OBJECT (location)); funcs.getproperty (instance, NPVARIANT_TO_OBJECT (location), funcs.getstringidentifier ("href"), &href); g_assert (NPVARIANT_IS_STRING (href)); if (strncmp (NPVARIANT_TO_STRING (href).UTF8Characters, ORIGIN, sizeof (ORIGIN)-1)) { g_debug ("origin does not match, is %s", NPVARIANT_TO_STRING (href).UTF8Characters); if (!ALLOW_FOREIGN_ORIGIN) { ret = NPERR_GENERIC_ERROR; goto out; } } data = g_slice_new (PluginData); instance->pdata = data; data->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, NULL, /* interface info */ "org.gnome.Shell", "/org/gnome/Shell", "org.gnome.Shell", NULL, /* GCancellable */ &error); if (!data->proxy) { /* ignore error if the shell is not running, otherwise warn */ if (error->domain != G_DBUS_ERROR || error->code != G_DBUS_ERROR_NAME_HAS_NO_OWNER) { g_warning ("Failed to set up Shell proxy: %s", error->message); g_error_clear (&error); } ret = NPERR_GENERIC_ERROR; } g_debug ("plugin created successfully"); out: funcs.releaseobject (window); funcs.releasevariantvalue (&document); funcs.releasevariantvalue (&location); funcs.releasevariantvalue (&href); return ret; }
static void init_methods_and_properties (void) { /* this is the JS public API; it is manipulated through NPIdentifiers for speed */ api_version_id = funcs.getstringidentifier ("apiVersion"); shell_version_id = funcs.getstringidentifier ("shellVersion"); get_info_id = funcs.getstringidentifier ("getExtensionInfo"); list_extensions_id = funcs.getstringidentifier ("listExtensions"); enable_extension_id = funcs.getstringidentifier ("setExtensionEnabled"); install_extension_id = funcs.getstringidentifier ("installExtension"); uninstall_extension_id = funcs.getstringidentifier ("uninstallExtension"); get_errors_id = funcs.getstringidentifier ("getExtensionErrors"); launch_extension_prefs_id = funcs.getstringidentifier ("launchExtensionPrefs"); onrestart_id = funcs.getstringidentifier ("onshellrestart"); onextension_changed_id = funcs.getstringidentifier ("onchange"); }
static gboolean check_origin_and_protocol (NPP instance) { gboolean ret = FALSE; NPError error; NPObject *window = NULL; NPVariant document = { NPVariantType_Void }; NPVariant location = { NPVariantType_Void }; gchar *hostname = NULL; gchar *protocol = NULL; error = funcs.getvalue (instance, NPNVWindowNPObject, &window); if (error != NPERR_NO_ERROR) goto out; if (!funcs.getproperty (instance, window, funcs.getstringidentifier ("document"), &document)) goto out; if (!NPVARIANT_IS_OBJECT (document)) goto out; if (!funcs.getproperty (instance, NPVARIANT_TO_OBJECT (document), funcs.getstringidentifier ("location"), &location)) goto out; if (!NPVARIANT_IS_OBJECT (location)) goto out; hostname = get_string_property (instance, NPVARIANT_TO_OBJECT (location), "hostname"); if (g_strcmp0 (hostname, ORIGIN)) { g_debug ("origin does not match, is %s", hostname); goto out; } protocol = get_string_property (instance, NPVARIANT_TO_OBJECT (location), "protocol"); if (g_strcmp0 (protocol, "https:") != 0) { g_debug ("protocol does not match, is %s", protocol); goto out; } ret = TRUE; out: g_free (protocol); g_free (hostname); funcs.releasevariantvalue (&location); funcs.releasevariantvalue (&document); if (window != NULL) funcs.releaseobject (window); return ret; }
static void cloud_spy_log (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer user_data) { NPNetscapeFuncs * browser = cloud_spy_nsfuncs; NPP instance = static_cast<NPP> (user_data); NPObject * window = NULL, * console = NULL; NPVariant variant, result; NPError error; (void) log_domain; (void) log_level; error = browser->getvalue (instance, NPNVWindowNPObject, &window); if (error != NPERR_NO_ERROR) goto beach; VOID_TO_NPVARIANT (variant); if (!browser->getproperty (instance, window, browser->getstringidentifier ("console"), &variant)) goto beach; console = NPVARIANT_TO_OBJECT (variant); STRINGZ_TO_NPVARIANT (message, variant); VOID_TO_NPVARIANT (result); if (!browser->invoke (instance, console, browser->getstringidentifier ("log"), &variant, 1, &result)) goto beach; browser->releasevariantvalue (&result); beach: if (console != NULL) browser->releaseobject (console); if (window != NULL) browser->releaseobject (window); }