Add back IE proxy handling for CheckForUpdates.
Also remove branch-info.txt inadvertently committed to trunk.
Patch by: scottb
Review by: jat
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6390 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/jni/linux/LowLevelMoz.cpp b/jni/linux/LowLevelMoz.cpp
new file mode 100644
index 0000000..9c3aba2
--- /dev/null
+++ b/jni/linux/LowLevelMoz.cpp
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+// Mozilla-specific hosted-mode methods
+
+// Define to log debug-level output rather than just warnings.
+#define DEBUG
+
+#include <cstdio>
+#include <cstdarg>
+#include <cwchar>
+
+// Mozilla header files
+#include "mozilla-headers.h"
+
+#include <jni.h>
+#include "gwt-jni.h"
+#include "JsRootedValue.h"
+#include "ExternalWrapper.h"
+#include "Tracer.h"
+#include "JsStringWrap.h"
+
+/*
+ * Debug definitions -- define FILETRACE to have debug output written to
+ * a file named gwt-ll.log, or JAVATRACE to have debug output passed to the
+ * Java LowLevelMoz.trace method.
+ */
+#ifdef ENABLE_TRACING
+#define FILETRACE
+//#define JAVATRACE
+#endif
+
+// include javah-generated header to make sure we match
+#include "LowLevelMoz.h"
+
+JNIEnv* savedJNIEnv = 0;
+jclass lowLevelMozClass;
+
+// Only include debugging code if we are tracing somewhere.
+#ifdef ENABLE_TRACING
+
+/*
+ * Template so vsnprintf/vswprintf can be used interchangeably in the
+ * append_sprintf template below.
+ * buf - pointer to the start of the output buffer
+ * len - maximum number of characters to write into the buffer
+ * (including the null terminator)
+ * fmt - printf-style format string
+ * args - stdarg-style variable arguments list
+ * Returns the number of characters written (excluding the null terminator)
+ * or -1 if an error occurred.
+ *
+ * Note that %lc and %ls are only legal in the wchar_t implementation.
+ */
+template<class charT>
+int safe_vsprintf(charT* buf, size_t len, const charT* fmt, va_list args);
+
+// specialization for char that maps to vsnprintf
+template<>
+inline int safe_vsprintf<char>(char* buf, size_t len, const char* fmt,
+ va_list args) {
+ return ::vsnprintf(buf, len, fmt, args);
+}
+
+// specialization for wchar_t that maps to vswprintf
+template<>
+inline int safe_vsprintf<wchar_t>(wchar_t* buf, size_t len, const wchar_t* fmt,
+ va_list args) {
+ return ::vswprintf(buf, len, fmt, args);
+}
+
+/*
+ * Safely append to a string buffer, updating the output pointer and always
+ * reserving the last character of the buffer for a null terminator.
+ * bufStart - pointer to the start of the output buffer
+ * bufEnd - pointer just past the end of the output buffer
+ * fmt - format string
+ * additional arguments as passed to *printf
+ * Returns the number of characters actually written, not including the null
+ * terminator. Nothing is written, including the null terminator, if the
+ * buffer start points beyond the output buffer.
+ *
+ * Templated to work with any character type that has a safe_vsprintf
+ * implementation.
+ */
+template<class charT>
+static int append_sprintf(charT* bufStart, const charT* bufEnd,
+ const charT* fmt, ...) {
+ va_list args;
+ va_start(args, fmt); // initialize variable arguments list
+ // compute space left in buffer: -1 for null terminator
+ int maxlen = bufEnd - bufStart - 1;
+ if (maxlen <= 0) return 0;
+ int n = safe_vsprintf(bufStart, maxlen, fmt, args);
+ va_end(args);
+ if (n > maxlen) {
+ n = maxlen;
+ }
+ bufStart[n] = 0;
+ return n;
+}
+
+/*
+ * Log a given jsval with a prefix.
+ * cx - JSContext for the JS execution context to use
+ * val - jsval to print
+ * prefix - string to print before the value, defaults to empty string
+ *
+ * TODO(jat): this whole printf-style logging needs to be replaced, but we
+ * run into library version issues if we use C++ iostreams so we would need
+ * to implement our own equivalent. Given that this code is all likely to
+ * be rewritten for out-of-process hosted mode, it seems unlikely to be worth
+ * the effort until that is completed.
+ */
+void PrintJSValue(JSContext* cx, jsval val, char* prefix="") {
+ JSType type = JS_TypeOfValue(cx, val);
+ const char* typeString=JS_GetTypeName(cx, type);
+ static const int BUF_SIZE = 256;
+ char buf[BUF_SIZE];
+ const char *bufEnd = buf + BUF_SIZE;
+ char* p = buf;
+ p += append_sprintf(p, bufEnd, "%s%s", prefix, typeString);
+ switch(type) {
+ case JSTYPE_VOID:
+ break;
+ case JSTYPE_BOOLEAN:
+ p += append_sprintf(p, bufEnd, ": %s",
+ JSVAL_TO_BOOLEAN(val) ? "true" : "false");
+ break;
+ case JSTYPE_NUMBER:
+ if (JSVAL_IS_INT(val)) {
+ p += append_sprintf(p, bufEnd, ": %d", JSVAL_TO_INT(val));
+ } else {
+ p += append_sprintf(p, bufEnd, ": %lf", (double)*JSVAL_TO_DOUBLE(val));
+ }
+ break;
+ case JSTYPE_OBJECT: {
+ JSObject* obj = JSVAL_TO_OBJECT(val);
+ if (!JSVAL_IS_OBJECT(val)) break;
+ JSClass* clazz = obj ? JS_GET_CLASS(cx, obj) : 0;
+ p += append_sprintf(p, bufEnd, " @ %08x, class %s",
+ (unsigned)obj, clazz ? clazz->name : "<null>");
+ break;
+ }
+ case JSTYPE_FUNCTION:
+ case JSTYPE_LIMIT:
+ break;
+ case JSTYPE_STRING: {
+ /*
+ * TODO(jat): support JS strings with international characters
+ */
+ JsStringWrap str(cx, JSVAL_TO_STRING(val));
+ p += append_sprintf(p, bufEnd, ": %.*s", str.length(), str.bytes());
+ break;
+ }
+ }
+ Tracer::log("%s", buf);
+}
+#else
+// Include a null version just to keep from cluttering up call sites.
+static inline void PrintJSValue(JSContext* cx, jsval val, char* prefix="") { }
+#endif
+
+
+static bool InitGlobals(JNIEnv* env, jclass llClass) {
+ if (savedJNIEnv)
+ return false;
+
+#ifdef FILETRACE
+ Tracer::setFile("gwt-ll.log");
+#endif // FILETRACE
+
+#ifdef JAVATRACE
+ Tracer::setJava(env, llClass);
+#endif // JAVATRACE
+
+#ifdef DEBUG
+ Tracer::setLevel(Tracer::LEVEL_DEBUG);
+#endif
+
+ savedJNIEnv = env;
+ lowLevelMozClass = static_cast<jclass>(env->NewGlobalRef(llClass));
+ return true;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _executeScriptWithInfo
+ * Signature: (ILjava/lang/String;Ljava/lang/String;I)Z
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1executeScriptWithInfo
+ (JNIEnv* env, jclass llClass, jint scriptObjectInt, jstring code,
+ jstring file, jint line)
+{
+ Tracer tracer("LowLevelMoz._executeScriptWithInfo");
+ JStringWrap jcode(env, code);
+ if (!jcode.jstr()) {
+ tracer.setFail("null code string");
+ return JNI_FALSE;
+ }
+ JStringWrap jfile(env, file);
+ if (!jfile.str()) {
+ tracer.setFail("null file name");
+ return JNI_FALSE;
+ }
+ tracer.log("code=%s, file=%s, line=%d", jcode.str(), jfile.str(), line);
+ JSContext* cx = JsRootedValue::currentContext();
+ nsCOMPtr<nsIScriptContext> scriptContext(GetScriptContextFromJSContext(cx));
+
+ nsIScriptGlobalObject* scriptObject =
+ NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjectInt);
+ JSObject* scriptWindow =
+ reinterpret_cast<JSObject*>(scriptObject->GetGlobalJSObject());
+ nsXPIDLString scriptString;
+ scriptString = jcode.jstr();
+
+ nsXPIDLString aRetValue;
+ PRBool aIsUndefined;
+ if (NS_FAILED(scriptContext->EvaluateString(scriptString, scriptWindow, 0,
+ jfile.str(), line, 0, aRetValue, &aIsUndefined))) {
+ tracer.setFail("EvaluateString failed");
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _invoke
+ * Signature: (ILjava/lang/String;I[I)I
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1invoke
+ (JNIEnv* env, jclass, jint scriptObjInt, jstring methodName, jint jsThisInt,
+ jintArray jsArgsInt, jint jsRetValInt)
+{
+ Tracer tracer("LowLevelMoz._invoke");
+
+ JStringWrap methodStr(env, methodName);
+ if (!methodStr.str()) {
+ tracer.setFail("null method name");
+ return JNI_FALSE;
+ }
+ JsRootedValue* jsThisRV = reinterpret_cast<JsRootedValue*>(jsThisInt);
+ jint jsArgc = env->GetArrayLength(jsArgsInt);
+ tracer.log("method=%s, jsthis=%08x, #args=%d", methodStr.str(), jsThisInt,
+ jsArgc);
+ JSContext* cx = JsRootedValue::currentContext();
+ nsIScriptGlobalObject* scriptObject =
+ NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ JSObject* scriptWindow
+ = reinterpret_cast<JSObject*>(scriptObject->GetGlobalJSObject());
+
+ jsval fval;
+ if (!JS_GetProperty(cx, scriptWindow, methodStr.str(), &fval)) {
+ tracer.setFail("JS_GetProperty(method) failed");
+ return JNI_FALSE;
+ }
+ JSFunction* jsFunction = JS_ValueToFunction(cx, fval);
+ if (!jsFunction) {
+ tracer.setFail("JS_ValueToFunction failed");
+ return JNI_FALSE;
+ }
+
+ // extract arguments in jsval form
+ nsAutoArrayPtr<jint> jsargvals(new jint[jsArgc]);
+ if (!jsargvals) {
+ tracer.setFail("failed to allocate arg array");
+ return JNI_FALSE;
+ }
+ env->GetIntArrayRegion(jsArgsInt, 0, jsArgc, jsargvals);
+ if (env->ExceptionCheck()) {
+ tracer.setFail("copy from Java array failed");
+ return JNI_FALSE;
+ }
+ nsAutoArrayPtr<jsval> jsargs(new jsval[jsArgc]);
+ for (int i = 0; i < jsArgc; ++i) {
+ JsRootedValue* arg = reinterpret_cast<JsRootedValue*>(jsargvals[i]);
+ jsargs[i] = arg->getValue();
+ }
+
+ jsval jsrval;
+ JSObject* jsThis;
+ if (jsThisRV->isNull()) {
+ jsThis = scriptWindow;
+ } else {
+ jsThis = jsThisRV->getObject();
+ }
+
+ PrintJSValue(cx, OBJECT_TO_JSVAL(jsThis), "jsThis=");
+ for (int i = 0; i < jsArgc; ++i) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "arg[%d]=", i);
+ PrintJSValue(cx, jsargs[i], buf);
+ }
+ //tracer.log("fval = %08x, args=%08x", fval, jsargs.get());
+ if (!JS_CallFunctionValue(cx, jsThis, fval, jsArgc, jsargs.get(), &jsrval)) {
+ tracer.setFail("JS_CallFunctionValue failed");
+ return JNI_FALSE;
+ }
+
+ PrintJSValue(cx, jsrval, "return value=");
+ JsRootedValue* returnVal = reinterpret_cast<JsRootedValue*>(jsRetValInt);
+ returnVal->setValue(jsrval);
+ return JNI_TRUE;
+}
+
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _raiseJavaScriptException
+ * Signature: ()Z
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1raiseJavaScriptException
+ (JNIEnv* env, jclass)
+{
+ Tracer tracer("LowLevelMoz._raiseJavaScriptException");
+ JS_SetPendingException(JsRootedValue::currentContext(), JSVAL_NULL);
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _registerExternalFactoryHandler
+ * Signature: ()Z
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1registerExternalFactoryHandler
+ (JNIEnv* env, jclass llClass)
+{
+ if (!InitGlobals(env, llClass))
+ return JNI_FALSE;
+
+ // tracing isn't setup until after InitGlobals is called
+ Tracer tracer("LowLevelMoz._registerExternalFactoryHandler");
+
+ char buf[256];
+ sprintf(buf, " jniEnv=%08x, llClass=%08x", (unsigned)env, (unsigned)llClass);
+ tracer.log(buf);
+
+ // Register "window.external" as our own class
+ if (NS_FAILED(nsComponentManager::RegisterFactory(
+ kGwtExternalCID, "externalFactory", GWT_EXTERNAL_CONTRACTID,
+ new nsRpExternalFactory(), PR_TRUE))) {
+ tracer.setFail("RegisterFactory failed");
+ return JNI_FALSE;
+ }
+
+ nsCOMPtr<nsICategoryManager> categoryManager =
+ do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
+ if (!categoryManager) {
+ tracer.setFail("unable to get category manager");
+ return JNI_FALSE;
+ }
+
+ nsXPIDLCString previous;
+ if (NS_FAILED(categoryManager->AddCategoryEntry(
+ JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY, "external", GWT_EXTERNAL_CONTRACTID,
+ PR_TRUE, PR_TRUE, getter_Copies(previous)))) {
+ tracer.setFail("AddCategoryEntry failed");
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}