From d07e2f7e5bf9d689941c023410d25789bc4b1531 Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Tue, 25 Apr 2017 16:21:09 -0500 Subject: build: Pull pacrunner forward to mozjs38 Mozjs185 is getting really old and unsupported. Newer versions of the mozjs JSAPI are C++ based. So we convert the plugin to C++ and then apply necessarily API changes so that it can be built with the more recent mozjs38. For example we now need to "root" values being passed into the API in order to satisfy the JSAPI garbage collection rules. Further, a number of the APIs have been tweaked and moved into the JS namespace, so we namespace them appropriately and adjust their parameters. --- Makefile.am | 15 ++-- configure.ac | 4 +- plugins/mozjs.c | 246 ----------------------------------------------------- plugins/mozjs.cc | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 263 insertions(+), 255 deletions(-) delete mode 100644 plugins/mozjs.c create mode 100644 plugins/mozjs.cc diff --git a/Makefile.am b/Makefile.am index ee84b75..65cc8c9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,9 +31,10 @@ endif if MOZJS js_sources = src/js_funcs.c builtin_modules += mozjs -builtin_sources += plugins/mozjs.c -builtin_cflags += @MOZJS_CFLAGS@ -builtin_libadd += @MOZJS_LIBS@ +builtin_libadd += plugins/libmozjsplugin.a @MOZJS_LIBS@ -lstdc++ +noinst_LIBRARIES += plugins/libmozjsplugin.a +plugins_libmozjsplugin_a_SOURCES = plugins/mozjs.cc +plugins_libmozjsplugin_a_CXXFLAGS = $(AM_CFLAGS) @MOZJS_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ endif if V8 @@ -137,16 +138,16 @@ unit_test_pacrunner_LDADD += @CURL_LIBS@ endif if MOZJS -unit_test_pacrunner_SOURCES += plugins/mozjs.c - +unit_test_pacrunner_SOURCES += plugins/mozjs.cc +unit_test_pacrunner_CXXFLAGS = $(AM_CFLAGS) @MOZJS_CFLAGS@ unit_test_pacrunner_LDADD += @MOZJS_LIBS@ @PTHREAD_LIBS@ noinst_PROGRAMS += unit/test-mozjs unit_test_mozjs_SOURCES = unit/test-mozjs.c src/pacrunner.h \ src/proxy.c src/manual.c src/download.c \ - src/js.c plugins/mozjs.c $(js_sources) - + src/js.c plugins/mozjs.cc $(js_sources) +unit_test_mozjs_CXXFLAGS = $(AM_CFLAGS) @MOZJS_CFLAGS@ unit_test_mozjs_LDADD = @MOZJS_LIBS@ @GLIB_LIBS@ @PTHREAD_LIBS@ endif diff --git a/configure.ac b/configure.ac index 888c873..bf76fbb 100644 --- a/configure.ac +++ b/configure.ac @@ -76,8 +76,8 @@ AM_CONDITIONAL(DUKTAPE, test "${enable_duktape}" = "yes") AC_ARG_ENABLE(mozjs, AC_HELP_STRING([--enable-mozjs], [enable Mozilla Javascript plugin support])) if (test "${enable_mozjs}" = "yes"); then - PKG_CHECK_MODULES(MOZJS, mozjs185, dummy=yes, - AC_MSG_ERROR(Mozilla Javascript >= 1.8 is required)) + PKG_CHECK_MODULES(MOZJS, mozjs-38, dummy=yes, + AC_MSG_ERROR(Mozilla Javascript version 38 is required)) AC_SUBST(MOZJS_CFLAGS) AC_SUBST(MOZJS_LIBS) fi diff --git a/plugins/mozjs.c b/plugins/mozjs.c deleted file mode 100644 index a923203..0000000 --- a/plugins/mozjs.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * - * PACrunner - Proxy configuration daemon - * - * Copyright (C) 2010-2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#pragma GCC diagnostic ignored "-Wredundant-decls" -#include -#pragma GCC diagnostic error "-Wredundant-decls" - -#include "pacrunner.h" -#include "js.h" - -static pthread_mutex_t mozjs_mutex = PTHREAD_MUTEX_INITIALIZER; - -struct pacrunner_mozjs { - struct pacrunner_proxy *proxy; - JSContext *jsctx; - JSObject *jsobj; -}; - -static JSBool myipaddress(JSContext *jsctx, uintN argc, jsval *vp) -{ - struct pacrunner_mozjs *ctx = JS_GetContextPrivate(jsctx); - char address[NI_MAXHOST]; - - DBG(""); - - JS_SET_RVAL(jsctx, vp, JSVAL_NULL); - - if (!ctx) - return JS_TRUE; - - if (__pacrunner_js_getipaddr(ctx->proxy, address, sizeof(address)) < 0) - return JS_TRUE; - - DBG("address %s", address); - - JS_SET_RVAL(jsctx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(jsctx, - address))); - - return JS_TRUE; -} - -static JSBool dnsresolve(JSContext *jsctx, uintN argc, jsval *vp) -{ - struct pacrunner_mozjs *ctx = JS_GetContextPrivate(jsctx); - char address[NI_MAXHOST]; - jsval *argv = JS_ARGV(jsctx, vp); - char *host = JS_EncodeString(jsctx, JS_ValueToString(jsctx, argv[0])); - - DBG("host %s", host); - - JS_SET_RVAL(jsctx, vp, JSVAL_NULL); - - if (!ctx) - goto out; - - if (__pacrunner_js_resolve(ctx->proxy, host, address, sizeof(address)) < 0) - goto out; - - DBG("address %s", address); - - JS_SET_RVAL(jsctx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(jsctx, address))); - - out: - JS_free(jsctx, host); - return JS_TRUE; - -} - -static JSClass jscls = { - "global", JSCLASS_GLOBAL_FLAGS, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_StrictPropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static JSRuntime *jsrun; - -static int create_object(struct pacrunner_proxy *proxy) -{ - struct pacrunner_mozjs *ctx; - const char *script; - jsval rval; - - script = pacrunner_proxy_get_script(proxy); - if (!script) - return 0; - - ctx = g_malloc0(sizeof(struct pacrunner_mozjs)); - - ctx->proxy = proxy; - ctx->jsctx = JS_NewContext(jsrun, 8 * 1024); - if (!ctx->jsctx) { - g_free(ctx); - return -ENOMEM; - } - JS_SetContextPrivate(ctx->jsctx, ctx); - __pacrunner_proxy_set_jsctx(proxy, ctx); - -#if JS_VERSION >= 185 - ctx->jsobj = JS_NewCompartmentAndGlobalObject(ctx->jsctx, &jscls, - NULL); -#else - ctx->jsobj = JS_NewObject(ctx->jsctx, &jscls, NULL, NULL); -#endif - - if (!JS_InitStandardClasses(ctx->jsctx, ctx->jsobj)) - pacrunner_error("Failed to init JS standard classes"); - - JS_DefineFunction(ctx->jsctx, ctx->jsobj, "myIpAddress", - myipaddress, 0, 0); - JS_DefineFunction(ctx->jsctx, ctx->jsobj, - "dnsResolve", dnsresolve, 1, 0); - - JS_EvaluateScript(ctx->jsctx, ctx->jsobj, __pacrunner_js_routines, - strlen(__pacrunner_js_routines), NULL, 0, &rval); - - JS_EvaluateScript(ctx->jsctx, ctx->jsobj, script, strlen(script), - "wpad.dat", 0, &rval); - - return 0; -} - -static int mozjs_clear_proxy(struct pacrunner_proxy *proxy) -{ - struct pacrunner_mozjs *ctx = __pacrunner_proxy_get_jsctx(proxy); - - DBG("proxy %p ctx %p", proxy, ctx); - - if (!ctx) - return -EINVAL; - - JS_DestroyContext(ctx->jsctx); - __pacrunner_proxy_set_jsctx(proxy, NULL); - - return 0; -} - -static int mozjs_set_proxy(struct pacrunner_proxy *proxy) -{ - DBG("proxy %p", proxy); - - if (!proxy) - return 0; - - mozjs_clear_proxy(proxy); - - return create_object(proxy); -} - -static char * mozjs_execute(struct pacrunner_proxy *proxy, const char *url, - const char *host) -{ - struct pacrunner_mozjs *ctx = __pacrunner_proxy_get_jsctx(proxy); - JSBool result; - jsval rval, args[2]; - char *answer, *g_answer; - - DBG("proxy %p ctx %p url %s host %s", proxy, ctx, url, host); - - if (!ctx) - return NULL; - - pthread_mutex_lock(&mozjs_mutex); - - JS_BeginRequest(ctx->jsctx); - - args[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(ctx->jsctx, url)); - args[1] = STRING_TO_JSVAL(JS_NewStringCopyZ(ctx->jsctx, host)); - - result = JS_CallFunctionName(ctx->jsctx, ctx->jsobj, - "FindProxyForURL", 2, args, &rval); - - JS_EndRequest(ctx->jsctx); - - JS_MaybeGC(ctx->jsctx); - - pthread_mutex_unlock(&mozjs_mutex); - - if (result) { - answer = JS_EncodeString(ctx->jsctx, - JS_ValueToString(ctx->jsctx, rval)); - g_answer = g_strdup(answer); - JS_free(ctx->jsctx, answer); - return g_answer; - } - - return NULL; -} - -static struct pacrunner_js_driver mozjs_driver = { - .name = "mozjs", - .priority = PACRUNNER_JS_PRIORITY_DEFAULT, - .set_proxy = mozjs_set_proxy, - .clear_proxy = mozjs_clear_proxy, - .execute = mozjs_execute, -}; - -static int mozjs_init(void) -{ - DBG(""); - - jsrun = JS_NewRuntime(8 * 1024 * 1024); - - return pacrunner_js_driver_register(&mozjs_driver); -} - -static void mozjs_exit(void) -{ - DBG(""); - - pacrunner_js_driver_unregister(&mozjs_driver); - - JS_DestroyRuntime(jsrun); -} - -PACRUNNER_PLUGIN_DEFINE(mozjs, mozjs_init, mozjs_exit) diff --git a/plugins/mozjs.cc b/plugins/mozjs.cc new file mode 100644 index 0000000..e10b297 --- /dev/null +++ b/plugins/mozjs.cc @@ -0,0 +1,253 @@ +/* + * + * PACrunner - Proxy configuration daemon + * + * Copyright (C) 2010-2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#include +#pragma GCC diagnostic error "-Wredundant-decls" +#pragma GCC diagnostic error "-Winvalid-offsetof" + +extern "C" { +#include "pacrunner.h" +#include "js.h" +} + +static pthread_mutex_t mozjs_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct pacrunner_mozjs { + struct pacrunner_proxy *proxy; + JSContext *jsctx; + JSObject *jsobj; + JSAutoCompartment *jsac; +}; + +static bool myipaddress(JSContext *jsctx, unsigned argc, jsval *vp) +{ + struct pacrunner_mozjs *ctx = (pacrunner_mozjs *)JS_GetContextPrivate(jsctx); + char address[NI_MAXHOST]; + + DBG(""); + + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + args.rval().setNull(); + + if (!ctx) + return true; + + if (__pacrunner_js_getipaddr(ctx->proxy, address, sizeof(address)) < 0) + return true; + + DBG("address %s", address); + + args.rval().setString(JS_NewStringCopyZ(jsctx,address)); + + return true; +} + +static bool dnsresolve(JSContext *jsctx, unsigned argc, jsval *vp) +{ + struct pacrunner_mozjs *ctx = (pacrunner_mozjs *)JS_GetContextPrivate(jsctx); + char address[NI_MAXHOST]; + JS::CallArgs args = JS::CallArgsFromVp(argc,vp); + char * host = JS_EncodeString(jsctx, args[0].toString()); + + DBG("host %s", host); + + if (!ctx) + goto out; + + if (__pacrunner_js_resolve(ctx->proxy, host, address, sizeof(address)) < 0) + goto out; + + DBG("address %s", address); + + args.rval().setString(JS_NewStringCopyZ(jsctx,address)); + + out: + JS_free(jsctx, host); + return true; + +} + +static JSClass jscls = { + "global", JSCLASS_GLOBAL_FLAGS, +}; + +static JSRuntime *jsrun; + +static int create_object(struct pacrunner_proxy *proxy) +{ + struct pacrunner_mozjs *ctx; + const char *script; + + script = pacrunner_proxy_get_script(proxy); + if (!script) + return 0; + + ctx = (pacrunner_mozjs *)g_malloc0(sizeof(struct pacrunner_mozjs)); + + ctx->proxy = proxy; + ctx->jsctx = JS_NewContext(jsrun, 8 * 1024); + if (!ctx->jsctx) { + g_free(ctx); + return -ENOMEM; + } + JS_SetContextPrivate(ctx->jsctx, ctx); + __pacrunner_proxy_set_jsctx(proxy, ctx); + + JS::CompartmentOptions compart_opts; + compart_opts.setVersion(JSVERSION_LATEST); + ctx->jsobj = JS_NewGlobalObject(ctx->jsctx, &jscls, nullptr, + JS::DontFireOnNewGlobalHook, compart_opts); + JS::RootedObject jsobj(ctx->jsctx,ctx->jsobj); + + ctx->jsac = new JSAutoCompartment(ctx->jsctx, jsobj); + + if (!JS_InitStandardClasses(ctx->jsctx, jsobj)) + pacrunner_error("Failed to init JS standard classes"); + + JS_DefineFunction(ctx->jsctx, jsobj, "myIpAddress", myipaddress, 0, 0); + JS_DefineFunction(ctx->jsctx, jsobj, "dnsResolve", dnsresolve, 1, 0); + + JS::RootedValue rval(ctx->jsctx); + JS::CompileOptions opts(ctx->jsctx); + opts.setIntroductionType("pacrunner") + .setUTF8(true) + .setCompileAndGo(true); + + JS::Evaluate(ctx->jsctx, JS::HandleObject(jsobj), opts, + __pacrunner_js_routines, strlen(__pacrunner_js_routines) + , &rval); + + JS::Evaluate(ctx->jsctx, jsobj, opts, script, strlen(script), &rval); + + return 0; +} + +static int mozjs_clear_proxy(struct pacrunner_proxy *proxy) +{ + struct pacrunner_mozjs *ctx = (pacrunner_mozjs *)__pacrunner_proxy_get_jsctx(proxy); + + DBG("proxy %p ctx %p", proxy, ctx); + + if (!ctx) + return -EINVAL; + + delete ctx->jsac; + JS_DestroyContext(ctx->jsctx); + __pacrunner_proxy_set_jsctx(proxy, NULL); + g_free(ctx); + + return 0; +} + +static int mozjs_set_proxy(struct pacrunner_proxy *proxy) +{ + DBG("proxy %p", proxy); + if (!proxy) + return 0; + + mozjs_clear_proxy(proxy); + + return create_object(proxy); +} + +static char * mozjs_execute(struct pacrunner_proxy *proxy, const char *url, + const char *host) +{ + struct pacrunner_mozjs *ctx = (pacrunner_mozjs *)__pacrunner_proxy_get_jsctx(proxy); + bool result; + char *answer, *g_answer; + DBG("proxy %p ctx %p url %s host %s", proxy, ctx, url, host); + + if (!ctx) + return NULL; + + pthread_mutex_lock(&mozjs_mutex); + + JS_BeginRequest(ctx->jsctx); + JS::RootedValue rval(ctx->jsctx); + JS::AutoValueArray<2> args(ctx->jsctx); + + args[0].setString(JS_NewStringCopyZ(ctx->jsctx, url)); + args[1].setString(JS_NewStringCopyZ(ctx->jsctx, host)); + + + JS::RootedObject jsobj(ctx->jsctx,ctx->jsobj); + + result = JS_CallFunctionName(ctx->jsctx, jsobj, "FindProxyForURL", args , &rval); + + JS_EndRequest(ctx->jsctx); + + JS_MaybeGC(ctx->jsctx); + + pthread_mutex_unlock(&mozjs_mutex); + + if (result) { + answer = JS_EncodeString(ctx->jsctx, rval.toString()); + g_answer = g_strdup(answer); + JS_free(ctx->jsctx, answer); + return g_answer; + } + + return NULL; +} + +static struct pacrunner_js_driver mozjs_driver = { + .name = "mozjs", + .priority = PACRUNNER_JS_PRIORITY_DEFAULT, + .set_proxy = mozjs_set_proxy, + .clear_proxy = mozjs_clear_proxy, + .execute = mozjs_execute, +}; + +static int mozjs_init(void) +{ + DBG(""); + JS_Init(); + jsrun = JS_NewRuntime(JS::DefaultHeapMaxBytes, 8 * 1024 * 1024 ); + + return pacrunner_js_driver_register(&mozjs_driver); +} + +static void mozjs_exit(void) +{ + DBG(""); + + pacrunner_js_driver_unregister(&mozjs_driver); + + JS_DestroyRuntime(jsrun); + JS_ShutDown(); +} + +PACRUNNER_PLUGIN_DEFINE(mozjs, mozjs_init, mozjs_exit) -- cgit 1.2.3-korg