Bug 586869 - Remove abandoned and unbuildable extensions/jssh, r+a=ted

This commit is contained in:
Phil Ringnalda 2010-12-11 10:53:38 -08:00
Родитель 4ebc8be897
Коммит c9efb237e4
17 изменённых файлов: 0 добавлений и 2981 удалений

Просмотреть файл

@ -1,172 +0,0 @@
2005-08-03 Alex Fritze <alex@croczilla.com>
* nsJSShStarter.js:
Register as command line handler rather than hooking into profile startup.
2005-01-31 Alex Fritze <alex@croczilla.com>
* resources/content/jssh-debug.js:
Add explanatory notes about pushContext() & its problems with QueryInterface.
2004-05-24 Alex Fritze <alex@croczilla.com>
* resources/content/jssh-debug.js: * moz-jssh.el:
Fix escaping of '//.*//.*' lines in jssh-eval-* functions.
* jssh-debug.el:
Add 'time()' function.
2004-05-24 Alex Fritze <alex@croczilla.com>
* moz-jssh.el:
Fix escaping of '//.*//.*' lines in jssh-eval-* functions.
* jssh-debug.el:
Add 'time()' function.
2004-05-07 Alex Fritze <alex@croczilla.com>
* moz-jssh.el:
Add moz-jssh-buffer-shell function which opens a jssh shell with
global object given by 'moz-jssh-buffer-globalobj'.
Also, moz-jssh-eval-internal is now fixed for commands strings
that change the context object.
* jssh-debug.js:
exit() is now overriden to unwind the context stack (global
object stack).
pushContext(obj) now sandwiches the jssh object between 'obj' and
obj.__proto__ rather than appending it to the end of the chain. This
is to prevent other objects that share 'obj's prototype inheriting
jssh's properties.
2004-04-25 Alex Fritze <alex@croczilla.com>
* moz-jssh.el:
moz-jssh-eval-buffer will now eval the given buffer on the object
given by the variable moz-jssh-buffer-globalobj. The idea is that
this variable is specified buffer-locally in the local variable
list of a file (e.g. in the first line between -*-'s).
2004-04-21 Alex Fritze <alex@croczilla.com>
* Makefile.in:
* nsJSSh.cpp:
* nsJSShServer.cpp:
Convert build to statically link the xpcom glue lib rather than
linking against xpcom.dll. The main reason is so that we can use a
debug build of the jssh component in a mozilla release build. If
we link a debug jssh against xpcom.dll and try to use it in a
non-debug Mozilla, Windows (not Linux for some reason - even in a
stripped build) will complain about missing nsDebug::*
symbols. The downside of linking in the xpcom glue lib is that it
increases the jssh xpi size by ~25KB, but I guess we can live with
that.
2004-04-20 Alex Fritze <alex@croczilla.com>
* Makefile.in:
* install.js:
Add XPI build. Run 'make xpi' to build dist/jssh-date-arch.xpi.
* nsJSSh.h:
* nsJSSh.cpp:
Update for nsIScriptObjectPrincipal deCOMification change.
2004-03-31 Alex Fritze <alex@croczilla.com>
* nsIJSShServer.idl:
* nsJSSh.cpp:
* nsJSShServer.cpp:
* jssh-debug.js:
Add support for blocking shells. nsIJSShServer::runShell() now
takes a boolean 'blocking' argument which controls whether the
shell will block the ui thread or not. jssh-debug.js adds a global
function 'jssh(startupURI)' which starts a nested blocking shell.
* nsJSSh.h:
Increase input buffer size to 100kB.
* nsIJSShServer.idl:
* nsJSSh.cpp:
* nsJSSh.h:
* nsJSShServer.cpp:
Remove redundant 'interactive' parameter from
nsIJSShServer::runShell(). The same effect of a non-interactive
shell can be achieved by passing 'null' as the input stream.
* nsJSSh.cpp:
Add new global functions:
getInputStream(): returns the current input stream (nsIInputStream)
getOutputStream(): returns the current output stream (nsIOutputStream)
2004-03-30 Alex Fritze <alex@croczilla.com>
* nsJSSh.cpp:
Add global 'debugBreak' function. Causes a break into the debugger
(debug builds only + on Linux the environment variable
'XPCOM_DEBUG_BREAK' needs to be set to 'trap').
* nsJSSh.cpp:
Add global 'flushEventQueue' function.
2004-03-26 Alex Fritze <alex@croczilla.com>
* nsJSSh.cpp:
* nsJSSh.h:
* jssh-debug.js:
* Makefile.in:
Use a wrapped native object implementing nsIScriptObjectPrincipal
instead of setting a security manager for the context with
SetSecurityManagerForJSContext(). Fixes the security-related
problems described in bug 238572.
2004-03-24 Alex Fritze <alex@croczilla.com>
* configure.xul:
Make the taskbarOverlay work on the jssh-server *service* rather
than a jssh-server instance so that it plays nice with the '-jssh'
commandline option.
* nsIJSShServer.idl:
* nsJSShServer.cpp:
* nsJSShServer.h:
Add serverListening, serverPort, serverStartupURI and
serverLoopbackOnly attributes to nsIJSShServer.
* nsJSShStarter.js:
* Makefile.in:
Added nsJSShStarter.js JS XPCOM component which automatically
starts a jssh server if mozilla is started with '-jssh'
* moz-jssh.el:
Added some keybindings:
[(control c) m j] creates a moz-jssh buffer
[(control c) m e] jssh-evaluates the current buffer
2004-03-15 Alex Fritze <alex@croczilla.com>
* nsIJSShServer.idl:
* nsJSShServer.cpp:
* configure.xul:
Add 'loopbackOnly'-option to nsIJSShServer::startServerSocket().
2004-03-14 Alex Fritze <alex@croczilla.com>
* nsJSSh.cpp:
Fix crash when foreign context objects set with 'setContextObj()'
get garbarge collected.
* jssh-debug.js:
Add functions for context pushing/popping. 'pushContext(obj)'
installs the jssh context into the proto chain of 'obj' and sets
'obj' as the current context object. 'popContext()' restores the
previous context object.
* moz-jssh.el:
Fix escaping of '//'-style comments in jssh-eval-* functions.
2004-02-19 Alex Fritze <alex@croczilla.com>
* moz-jssh.el:
Add moz-jssh-eval-buffer function.

Просмотреть файл

@ -1,46 +0,0 @@
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = jssh
XPIDL_MODULE = jssh
LIBRARY_NAME = jssh
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = nsJSShModule
CPPSRCS = \
nsJSShServer.cpp \
nsJSShModule.cpp \
nsJSSh.cpp \
$(NULL)
XPIDLSRCS = nsIJSShServer.idl \
nsIJSSh.idl \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(XPCOM_GLUE_LDOPTS) \
$(NSPR_LIBS) \
$(MOZ_JS_LIBS) \
$(NULL)
EXTRA_COMPONENTS = nsJSShStarter.js
include $(topsrcdir)/config/rules.mk
DEFINES += -DJS_THREADSAFE
XPI_FILE = jssh-$(shell date +%Y%m%d)-$(OS_ARCH).xpi
xpi::
zip -j $(DIST)/$(XPI_FILE) $(srcdir)/install.js
cd $(DIST); zip -r $(XPI_FILE) \
bin/components/jssh.xpt \
bin/components/$(LIB_PREFIX)jssh$(DLL_SUFFIX) \
bin/components/nsJSShStarter.js \
bin/chrome/jssh.jar

Просмотреть файл

@ -1,67 +0,0 @@
/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var rv;
rv = initInstall("JSSh JavaScript Shell Server", "JSSh", "0.1");
logComment("initInstall: " + rv);
var programFolder = getFolder("Program");
logComment("programFolder: "+programFolder);
rv = addDirectory("Program", "0.1", "bin", programFolder, "", true);
logComment("addDirectory(bin): " + rv);
var chromeFolder = getFolder("Chrome", "jssh.jar");
logComment("chromeFolder: "+chromeFolder);
rv = registerChrome(CONTENT | DELAYED_CHROME, chromeFolder, "content/jssh/");
if (rv == ACCESS_DENIED) {
alert("Unable to write to program directory " + programFolder + ".\n You will need to restart the browser with administrator/root privileges to install this software. After installing as root (or administrator), you will need to restart the browser one more time to register the installed software.\n After the second restart, you can go back to running the browser without privileges!");
cancelInstall(rv);
logComment("cancelInstall() due to error: " + rv);
}
else if (rv != SUCCESS) {
cancelInstall(rv);
logComment("cancelInstall() due to error: " + rv);
}
else {
performInstall();
logComment("performInstall(): " + rv);
}

Просмотреть файл

@ -1,3 +0,0 @@
jssh.jar:
% content jssh %content/jssh/
content/jssh/jssh-debug.js (resources/content/jssh-debug.js)

Просмотреть файл

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/* this interface is only used internally for thread proxy purposes */
[uuid(c305066d-424f-41d8-9a07-4a9791d15085)]
interface nsIJSSh : nsISupports
{
void init();
void cleanup();
void executeBuffer();
boolean isBufferCompilable();
};

Просмотреть файл

@ -1,99 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIInputStream;
interface nsIOutputStream;
%{ C++
// {A1764959-87D8-4249-A432-8005DE1372FC}
#define NS_JSSHSERVER_CID \
{ 0xa1764959, 0x87d8, 0x4249, { 0xa4, 0x32, 0x80, 0x05, 0xde, 0x13, 0x72, 0xfc } }
#define NS_JSSHSERVER_CONTRACTID "@mozilla.org/jssh-server;1"
%}
[scriptable, uuid(f8b2b6bc-4f1d-42e2-af46-9a2d6ca627bf)]
interface nsIJSShServer : nsISupports
{
/* start listening for jssh connections on the given port.
'startupURI' specifies an optional script that will be executed for
new connections.
If 'loopbackOnly' is true, the server socket will only listen for connections on the
local loopback interface (localhost, 127.0.0.1). */
void startServerSocket(in unsigned long port, in AUTF8String startupURI,
in boolean loopbackOnly);
/* stop listening for connections */
void stopServerSocket();
/* true if the server is currently active */
readonly attribute boolean serverListening;
/* Port that the server is currently listening on. Zero if the
* server is not active. */
readonly attribute unsigned long serverPort;
/* startupURI of the currently active server. Empty string if the
* server is not active. */
readonly attribute AUTF8String serverStartupURI;
/* 'loopbackOnly' flag of the currently active server. false if the
* server is not active */
readonly attribute boolean serverLoopbackOnly;
/* run a jssh session with the given input and output streams.
* 'startupURI' specifies an optional script that will be executed
* on session startup.
*
* if 'input' is null, this will be a non-interactive session, with
* no input being collected from the input stream . The idea is that
* the session input is taken from startupURI. Even for
* non-interactive sessions, output (via 'print') can still be
* collected with the output stream object.
*
* if 'blocking' is 'true', then the shell will block the main ui
* thread. Otherwise this will be an asynchronous shell (but
* execution of commands will still be proxied onto the main ui
* thread).
*/
void runShell(in nsIInputStream input, in nsIOutputStream output,
in string startupURI, in boolean blocking);
};

Просмотреть файл

@ -1,838 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsJSSh.h"
#include "nsIJSRuntimeService.h"
#include "nsIServiceManager.h"
#include "nsIXPConnect.h"
#include "nsIProxyObjectManager.h"
#include "nsIScriptSecurityManager.h"
#include "nsIIOService.h"
#include "nsNetCID.h"
#include "nsIChannel.h"
#include "nsThreadUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "nsMemory.h"
#include "nsAutoPtr.h"
#ifdef PR_LOGGING
PRLogModuleInfo *gJSShLog = PR_NewLogModule("jssh");
#endif
//**********************************************************************
// Javascript Environment
const char *gWelcome = "Welcome to the Mozilla JavaScript Shell!\n";
const char *gGoodbye = "Goodbye!\n";
// GetJSShGlobal: helper for native js functions to obtain the global
// JSSh object
PRBool GetJSShGlobal(JSContext *cx, JSObject *obj, nsJSSh** shell)
{
JSAutoRequest ar(cx);
#ifdef DEBUG
// printf("GetJSShGlobal(cx=%p, obj=%p)\n", cx, obj);
#endif
JSObject *parent, *global = obj;
if (!global) {
NS_ERROR("need a non-null obj to find script global");
return PR_FALSE;
}
// in most of our cases, 'global' is already the correct obj, since
// we use bound methods. For cases where we call
// GetJSShGlobal from an unbound method, we need to walk the
// parent chain:
// XXX I think the comment above is obsolete. We only call
// GetJSShGlobal from bound methods, in which case the
// parent is the global obj. For non-bound methods, walking the
// parent chain to obtain the global object will only work when the
// method is rooted in the current script context, so it is not
// reliable (???). ASSERTION below to test the assumption. Once proven,
// remove loop.
while ((parent = JS_GetParent(cx, global))) {
NS_ERROR("Parent chain weirdness. Probably benign, but we should not reach this.");
#ifdef DEBUG
// printf(" obj's parent = %p\n", parent);
#endif
global = parent;
}
// JSClass* clazz = JS_GET_CLASS(cx, global);
// if (!IS_WRAPPER_CLASS(clazz)) {
// NS_ERROR("the script global's class is not of the right type");
// return PR_FALSE;
// }
// XXX use GetWrappedNativeOfJSObject
nsIXPConnectWrappedNative *wrapper = static_cast<nsIXPConnectWrappedNative*>(JS_GetPrivate(cx, global));
nsCOMPtr<nsISupports> native;
wrapper->GetNative(getter_AddRefs(native));
nsCOMPtr<nsIJSSh> jssh = do_QueryInterface(native);
NS_ASSERTION(jssh, "no jssh global");
*shell = static_cast<nsJSSh*>((nsIJSSh*)(jssh.get()));
return PR_TRUE;
}
static void
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
// xxx getting the global obj from the cx. will that give us grief?
JSObject* obj = JS_GetGlobalObject(cx);
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return;
// XXX use JSErrorReport for better info
PRUint32 bytesWritten;
if (shell->mOutput) {
if (shell->mEmitHeader) {
char buf[80];
sprintf(buf, "[%d]", strlen(message));
shell->mOutput->Write(buf, strlen(buf), &bytesWritten);
}
shell->mOutput->Write(message, strlen(message), &bytesWritten);
}
}
static JSBool
Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
JSAutoRequest ar(cx);
PRUint32 bytesWritten;
#ifdef DEBUG
// nsCOMPtr<nsIThread> thread;
// nsIThread::GetCurrent(getter_AddRefs(thread));
// printf("printing on thread %p, shell %p, output %p, cx=%p, obj=%p\n", thread.get(), shell, shell->mOutput, cx, obj);
#endif
for (unsigned int i=0; i<argc; ++i) {
JSString *str = JS_ValueToString(cx, argv[i]);
if (!str) return JS_FALSE;
JSAutoByteString bytes(cx, str);
if (!bytes) return JS_FALSE;
if (shell->mOutput) {
if (shell->mEmitHeader) {
char buf[80];
sprintf(buf, "[%d]", JS_GetStringLength(str));
shell->mOutput->Write(buf, strlen(buf), &bytesWritten);
}
shell->mOutput->Write(bytes.ptr(), strlen(bytes), &bytesWritten);
}
else
printf("%s", bytes.ptr()); // use cout if no output stream given.
#ifdef DEBUG
// printf("%s", bytes.ptr());
#endif
}
return JS_TRUE;
}
static JSBool
Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
PRUint32 bytesWritten;
if (shell->mOutput)
shell->mOutput->Write(gGoodbye, strlen(gGoodbye), &bytesWritten);
shell->mQuit = PR_TRUE;
return JS_TRUE;
}
static JSBool
Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
JSAutoRequest ar(cx);
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
for (unsigned int i=0; i<argc; ++i) {
JSString *str = JS_ValueToString(cx, argv[i]);
if (!str) return JS_FALSE;
//argv[i] = STRING_TO_JSVAL(str);
JSAutoByteString url(cx, str);
if (!url) return JS_FALSE;
if (!shell->LoadURL(url, rval))
return JS_FALSE;
}
return JS_TRUE;
}
static JSBool
FlushEventQueue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
NS_ProcessPendingEvents(nsnull);
return JS_TRUE;
}
static JSBool
Suspend(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
PR_AtomicIncrement(&shell->mSuspendCount);
while (shell->mSuspendCount) {
LOG(("|"));
NS_ProcessNextEvent(thread);
}
return JS_TRUE;
}
static JSBool
Resume(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
PR_AtomicDecrement(&shell->mSuspendCount);
return JS_TRUE;
}
static JSBool
AddressOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
if (argc!=1) return JS_FALSE;
JSAutoRequest ar(cx);
// xxx If argv[0] is not an obj already, we'll get a transient
// address from JS_ValueToObject. Maybe we should throw an exception
// instead.
JSObject *arg_obj;
if (!JS_ValueToObject(cx, argv[0], &arg_obj)) {
return JS_FALSE;
}
char buf[80];
sprintf(buf, "%p", arg_obj);
JSString *str = JS_NewStringCopyZ(cx, buf);
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
static JSBool
SetProtocol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
if (argc!=1) return JS_FALSE;
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
JSAutoRequest ar(cx);
JSString *protocol = JS_ValueToString(cx, argv[0]);
if (!protocol) return JS_FALSE;
if (JS_MatchStringAndAscii(protocol, "interactive")) {
shell->mEmitHeader = PR_FALSE;
shell->mPrompt = NS_LITERAL_CSTRING("\n> ");
shell->mProtocol = protocol;
}
else if (JS_MatchStringAndAscii(protocol, "synchronous")) {
shell->mEmitHeader = PR_TRUE;
shell->mPrompt = NS_LITERAL_CSTRING("\n> ");
shell->mProtocol = protocol;
}
else if (JS_MatchStringAndAscii(protocol, "plain")) {
shell->mEmitHeader = PR_FALSE;
shell->mPrompt = NS_LITERAL_CSTRING("\n");
shell->mProtocol = protocol;
}
else return JS_FALSE;
return JS_TRUE;
}
static JSBool
GetProtocol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
JSAutoRequest ar(cx);
JSString *str = JS_NewStringCopyZ(cx, shell->mProtocol.get());
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
static JSBool
SetContextObj(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
JSAutoRequest ar(cx);
if (argc!=1) return JS_FALSE;
JSObject *arg_obj;
if (!JS_ValueToObject(cx, argv[0], &arg_obj)) {
return JS_FALSE;
}
if (shell->mContextObj != shell->mGlobal)
JS_RemoveRoot(cx, &(shell->mContextObj));
shell->mContextObj = arg_obj;
if (shell->mContextObj != shell->mGlobal)
JS_AddRoot(cx, &(shell->mContextObj));
return JS_TRUE;
}
static JSBool
DebugBreak(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
NS_BREAK();
return JS_TRUE;
}
static JSBool
GetInputStream(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
JSAutoRequest ar(cx);
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
if (!xpc) {
NS_ERROR("failed to get xpconnect service");
return JS_FALSE;
}
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
xpc->WrapNative(cx, shell->mGlobal, shell->mInput,
NS_GET_IID(nsIInputStream),
getter_AddRefs(wrapper));
if (!wrapper) {
NS_ERROR("could not wrap input stream object");
return JS_FALSE;
}
JSObject* wrapper_jsobj = nsnull;
wrapper->GetJSObject(&wrapper_jsobj);
NS_ASSERTION(wrapper_jsobj, "could not get jsobject of wrapped native");
*rval = OBJECT_TO_JSVAL(wrapper_jsobj);
return JS_TRUE;
}
static JSBool
GetOutputStream(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsJSSh* shell;
if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
JSAutoRequest ar(cx);
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
if (!xpc) {
NS_ERROR("failed to get xpconnect service");
return JS_FALSE;
}
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
xpc->WrapNative(cx, shell->mGlobal, shell->mOutput,
NS_GET_IID(nsIOutputStream),
getter_AddRefs(wrapper));
if (!wrapper) {
NS_ERROR("could not wrap output stream object");
return JS_FALSE;
}
JSObject* wrapper_jsobj = nsnull;
wrapper->GetJSObject(&wrapper_jsobj);
NS_ASSERTION(wrapper_jsobj, "could not get jsobject of wrapped native");
*rval = OBJECT_TO_JSVAL(wrapper_jsobj);
return JS_TRUE;
}
// these all need JSFUN_BOUND_METHOD flags, so that we can do
// things like:
// win.p = print, where win is rooted in some other global
// object.
static JSFunctionSpec global_functions[] = {
{"print", Print, 1, JSFUN_BOUND_METHOD, 0},
{"dump", Print, 1, JSFUN_BOUND_METHOD, 0},
{"quit", Quit, 0, JSFUN_BOUND_METHOD, 0},
{"exit", Quit, 0, JSFUN_BOUND_METHOD, 0},
{"load", Load, 1, JSFUN_BOUND_METHOD, 0},
{"suspend", Suspend, 0, JSFUN_BOUND_METHOD, 0},
{"resume", Resume, 0, JSFUN_BOUND_METHOD, 0},
{"flushEventQueue", FlushEventQueue,0, JSFUN_BOUND_METHOD, 0},
{"addressOf", AddressOf, 1, 0, 0},
{"setProtocol", SetProtocol, 1, JSFUN_BOUND_METHOD, 0},
{"getProtocol", GetProtocol, 0, JSFUN_BOUND_METHOD, 0},
{"setContextObj", SetContextObj, 1, JSFUN_BOUND_METHOD, 0},
{"debugBreak", DebugBreak, 0, JSFUN_BOUND_METHOD, 0},
{"getInputStream", GetInputStream, 0, JSFUN_BOUND_METHOD, 0},
{"getOutputStream", GetOutputStream,0, JSFUN_BOUND_METHOD, 0},
{nsnull, nsnull, 0, 0, 0}
};
//**********************************************************************
// nsJSSh Implementation
nsJSSh::nsJSSh(nsIInputStream* input,
nsIOutputStream*output,
const nsACString &startupURI) :
mInput(input), mOutput(output), mQuit(PR_FALSE), mStartupURI(startupURI),
mSuspendCount(0), mPrompt("\n> "),
mEmitHeader(PR_FALSE), mProtocol("interactive")
{
}
nsJSSh::~nsJSSh()
{
LOG(("JSSh: ~connection!\n"));
}
already_AddRefed<nsIRunnable>
CreateJSSh(nsIInputStream* input, nsIOutputStream*output,
const nsACString &startupURI)
{
nsIRunnable* obj = new nsJSSh(input, output, startupURI);
NS_IF_ADDREF(obj);
return obj;
}
//----------------------------------------------------------------------
// nsISupports methods:
NS_IMPL_THREADSAFE_ADDREF(nsJSSh)
NS_IMPL_THREADSAFE_RELEASE(nsJSSh)
NS_INTERFACE_MAP_BEGIN(nsJSSh)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSSh)
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
NS_INTERFACE_MAP_ENTRY(nsIJSSh)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsIRunnable methods:
NS_IMETHODIMP nsJSSh::Run()
{
nsCOMPtr<nsIJSSh> proxied_shell;
if (!NS_IsMainThread()) {
nsCOMPtr<nsIProxyObjectManager> pom = do_GetService(NS_XPCOMPROXY_CONTRACTID);
NS_ASSERTION(pom, "uh-oh, no proxy object manager!");
pom->GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIJSSh),
(nsIJSSh*)this,
NS_PROXY_SYNC,
getter_AddRefs(proxied_shell));
}
else {
LOG(("jssh shell will block main thread!\n"));
proxied_shell = this;
}
proxied_shell->Init();
if (mInput) {
// read-eval-print loop
PRUint32 bytesWritten;
if (mOutput && !mProtocol.Equals(NS_LITERAL_CSTRING("plain")))
mOutput->Write(gWelcome, strlen(gWelcome), &bytesWritten);
while (!mQuit) {
if (mOutput)
mOutput->Write(mPrompt.get(), mPrompt.Length(), &bytesWritten);
// accumulate input until we get a compilable unit:
PRBool iscompilable;
mBufferPtr = 0;
#ifdef DEBUG
// nsCOMPtr<nsIThread> thread;
// nsIThread::GetCurrent(getter_AddRefs(thread));
// printf("blocking on thread %p\n", thread.get());
#endif
do {
PRUint32 bytesRead = 0;
mInput->Read(mBuffer+mBufferPtr, 1, &bytesRead);
if (bytesRead) {
++mBufferPtr;
}
else {
// connection was terminated by the client
mQuit = PR_TRUE;
break;
}
// XXX signal buffer overflow ??
// XXX ideally we want a dynamically resizing buffer.
}while (mBufferPtr<cBufferSize &&
(mBuffer[mBufferPtr-1]!=10 || (NS_SUCCEEDED(proxied_shell->IsBufferCompilable(&iscompilable)) && !iscompilable)));
NS_ASSERTION(mBufferPtr<cBufferSize, "buffer overflow");
proxied_shell->ExecuteBuffer();
}
}
proxied_shell->Cleanup();
if (!NS_IsMainThread()) {
// Shutdown the current thread, which must be done from the main thread.
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
nsCOMPtr<nsIThread> proxied_thread;
nsCOMPtr<nsIProxyObjectManager> pom = do_GetService(NS_XPCOMPROXY_CONTRACTID);
NS_ASSERTION(pom, "uh-oh, no proxy object manager!");
pom->GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIThread),
thread.get(),
NS_PROXY_ASYNC,
getter_AddRefs(proxied_thread));
if (proxied_thread)
proxied_thread->Shutdown();
}
return NS_OK;
}
//----------------------------------------------------------------------
// nsIJSSh methods
NS_IMETHODIMP nsJSSh::Init()
{
nsCOMPtr<nsIScriptSecurityManager> ssm = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
if (!ssm) {
NS_ERROR("failed to get script security manager");
return NS_ERROR_FAILURE;
}
ssm->GetSystemPrincipal(getter_AddRefs(mPrincipal));
if (!mPrincipal) {
NS_ERROR("failed to get system principal");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
if (!xpc) {
NS_ERROR("failed to get xpconnect service");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
// get the JSRuntime from the runtime svc
if (!rtsvc) {
NS_ERROR("failed to get nsJSRuntimeService");
return NS_ERROR_FAILURE;
}
JSRuntime *rt = nsnull;
if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
NS_ERROR("failed to get JSRuntime from nsJSRuntimeService");
return NS_ERROR_FAILURE;
}
mJSContext = JS_NewContext(rt, 8192);
if (!mJSContext) {
NS_ERROR("JS_NewContext failed");
return NS_ERROR_FAILURE;
}
JSAutoRequest ar(mJSContext);
// Enable e4x:
JS_SetOptions(mJSContext, JS_GetOptions(mJSContext) | JSOPTION_XML);
// Always use the latest js version
JS_SetVersion(mJSContext, JSVERSION_LATEST);
mContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (!mContextStack) {
NS_ERROR("failed to get the nsThreadJSContextStack service");
return NS_ERROR_FAILURE;
}
JS_SetErrorReporter(mJSContext, my_ErrorReporter);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
xpc->InitClassesWithNewWrappedGlobal(mJSContext, (nsIJSSh*)this,
NS_GET_IID(nsISupports),
mPrincipal, nsnull, PR_TRUE,
getter_AddRefs(holder));
if (!holder) {
NS_ERROR("global initialization failed");
return NS_ERROR_FAILURE;
}
holder->GetJSObject(&mGlobal);
if (!mGlobal) {
NS_ERROR("bad global object");
return NS_ERROR_FAILURE;
}
mContextObj = mGlobal;
if (!JS_DefineFunctions(mJSContext, mGlobal, global_functions)) {
NS_ERROR("failed to initialise global functions");
return NS_ERROR_FAILURE;
}
if (!mStartupURI.IsEmpty())
LoadURL(mStartupURI.get());
return NS_OK;
}
NS_IMETHODIMP nsJSSh::Cleanup()
{
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
if (!xpc) {
NS_ERROR("failed to get xpconnect service");
return NS_ERROR_FAILURE;
}
{
JSAutoRequest ar(mJSContext);
if (mContextObj != mGlobal)
JS_RemoveRoot(mJSContext, &(mContextObj));
JS_ClearScope(mJSContext, mGlobal);
JS_GC(mJSContext);
}
JS_DestroyContext(mJSContext);
return NS_OK;
}
NS_IMETHODIMP nsJSSh::ExecuteBuffer()
{
#ifdef DEBUG
// nsCOMPtr<nsIThread> thread;
// nsIThread::GetCurrent(getter_AddRefs(thread));
// printf("executing on thread %p\n", thread.get());
#endif
JS_BeginRequest(mJSContext);
JS_ClearPendingException(mJSContext);
JSPrincipals *jsprincipals;
mPrincipal->GetJSPrincipals(mJSContext, &jsprincipals);
if(NS_FAILED(mContextStack->Push(mJSContext))) {
NS_ERROR("failed to push the current JSContext on the nsThreadJSContextStack");
return NS_ERROR_FAILURE;
}
JSScript *script = JS_CompileScriptForPrincipals(mJSContext, mContextObj, jsprincipals, mBuffer, mBufferPtr, "interactive", 0);
if (script) {
jsval result;
if (JS_ExecuteScript(mJSContext, mContextObj, script, &result) && result!=JSVAL_VOID && mOutput) {
// XXX for some wrapped native objects the following code will crash; probably because the
// native object is getting released before we reach this:
JSString *str = JS_ValueToString(mJSContext, result);
if (str) {
nsDependentString chars(reinterpret_cast<const PRUnichar*>
(JS_GetStringChars(str)),
JS_GetStringLength(str));
NS_ConvertUTF16toUTF8 cstr(chars);
PRUint32 bytesWritten;
mOutput->Write(cstr.get(), cstr.Length(), &bytesWritten);
}
}
JS_DestroyScript(mJSContext, script);
}
JSContext *oldcx;
mContextStack->Pop(&oldcx);
NS_ASSERTION(oldcx == mJSContext, "JS thread context push/pop mismatch");
JSPRINCIPALS_DROP(mJSContext, jsprincipals);
JS_EndRequest(mJSContext);
return NS_OK;
}
NS_IMETHODIMP nsJSSh::IsBufferCompilable(PRBool *_retval)
{
JSAutoRequest ar(mJSContext);
*_retval = JS_BufferIsCompilableUnit(mJSContext, mContextObj, mBuffer, mBufferPtr);
return NS_OK;
}
//----------------------------------------------------------------------
// nsIScriptObjectPrincipal methods:
nsIPrincipal *
nsJSSh::GetPrincipal()
{
return mPrincipal;
}
//----------------------------------------------------------------------
// nsIXPCScriptable methods:
#define XPC_MAP_CLASSNAME nsJSSh
#define XPC_MAP_QUOTED_CLASSNAME "JSSh"
#define XPC_MAP_WANT_NEWRESOLVE
#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \
nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \
nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
nsIXPCScriptable::DONT_ENUM_STATIC_PROPS | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
#include "xpc_map_end.h" /* This will #undef the above */
/* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx,
in JSObjectPtr obj, in jsval id, in PRUint32 flags, out JSObjectPtr objp); */
NS_IMETHODIMP
nsJSSh::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval id, PRUint32 flags,
JSObject * *objp, PRBool *_retval)
{
JSBool resolved;
JSAutoRequest ar(cx);
*_retval = JS_ResolveStandardClass(cx, obj, id, &resolved);
if (*_retval && resolved)
*objp = obj;
return NS_OK;
}
//----------------------------------------------------------------------
// Implementation helpers:
PRBool nsJSSh::LoadURL(const char *url, jsval* retval)
{
nsCOMPtr<nsIIOService> ioserv = do_GetService(NS_IOSERVICE_CONTRACTID);
if (!ioserv) {
NS_ERROR("could not get io service");
return PR_FALSE;
}
nsCOMPtr<nsIChannel> channel;
ioserv->NewChannel(nsDependentCString(url), nsnull, nsnull, getter_AddRefs(channel));
if (!channel) {
NS_ERROR("could not create channel");
return PR_FALSE;
}
nsCOMPtr<nsIInputStream> instream;
channel->Open(getter_AddRefs(instream));
if (!instream) {
NS_ERROR("could not open stream");
return PR_FALSE;
}
nsCString buffer;
nsAutoArrayPtr<char> buf(new char[1024]);
if (!buf) {
NS_ERROR("could not alloc buffer");
return PR_FALSE;
}
PRUint32 bytesRead = 0;
do {
if (NS_FAILED(instream->Read(buf, 1024, &bytesRead))) {
NS_ERROR("stream read error");
return PR_FALSE;
}
buffer.Append(buf, bytesRead);
LOG(("appended %d bytes:\n%s", bytesRead, buffer.get()));
} while (bytesRead > 0);
LOG(("loaded %d bytes:\n%s", buffer.Length(), buffer.get()));
JS_BeginRequest(mJSContext);
JSPrincipals *jsprincipals;
mPrincipal->GetJSPrincipals(mJSContext, &jsprincipals);
if(NS_FAILED(mContextStack->Push(mJSContext))) {
NS_ERROR("failed to push the current JSContext on the nsThreadJSContextStack");
return NS_ERROR_FAILURE;
}
jsval result;
JSBool ok = JS_EvaluateScriptForPrincipals(mJSContext, mContextObj,
jsprincipals, buffer.get(),
buffer.Length(),
url, 1, &result);
JSPRINCIPALS_DROP(mJSContext, jsprincipals);
JSContext *oldcx;
mContextStack->Pop(&oldcx);
NS_ASSERTION(oldcx == mJSContext, "JS thread context push/pop mismatch");
if (ok && retval) *retval=result;
JS_EndRequest(mJSContext);
return ok;
}

Просмотреть файл

@ -1,108 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __NS_JSSH_H__
#define __NS_JSSH_H__
#include "jsapi.h"
#include "nsCOMPtr.h"
#include "nsIRunnable.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIJSSh.h"
#include "nsIJSContextStack.h"
#include "nsIPrincipal.h"
#include "nsStringAPI.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIXPCScriptable.h"
#ifdef MOZ_LOGGING
#define FORCE_PR_LOG
#endif
#include "prlog.h"
// NSPR_LOG_MODULES=jssh
#ifdef PR_LOGGING
extern PRLogModuleInfo *gJSShLog;
#define LOG(args) PR_LOG(gJSShLog, PR_LOG_DEBUG, args)
#else
#define LOG(args)
#endif
class nsJSSh : public nsIRunnable, public nsIJSSh,
public nsIScriptObjectPrincipal,
public nsIXPCScriptable
{
public:
nsJSSh(nsIInputStream* input, nsIOutputStream*output,
const nsACString &startupURI);
~nsJSSh();
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIJSSH
// nsIScriptObjectPrincipal:
virtual nsIPrincipal *GetPrincipal();
NS_DECL_NSIXPCSCRIPTABLE
public:
PRBool LoadURL(const char *url, jsval* retval=nsnull);
nsCOMPtr<nsIInputStream> mInput;
nsCOMPtr<nsIOutputStream> mOutput;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIJSContextStack> mContextStack;
PRInt32 mSuspendCount; // for suspend()-resume()
enum { cBufferSize=100*1024 };
char mBuffer[cBufferSize];
int mBufferPtr;
JSContext* mJSContext;
JSObject *mGlobal;
JSObject *mContextObj;
PRBool mQuit;
nsCString mStartupURI;
nsCString mPrompt;
PRBool mEmitHeader;
nsCString mProtocol;
};
already_AddRefed<nsIRunnable>
CreateJSSh(nsIInputStream* input, nsIOutputStream*output,
const nsACString &startupURI);
#endif // __NS_JSSH_H__

Просмотреть файл

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIGenericFactory.h"
#include "nsJSShServer.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSShServer)
static const nsModuleComponentInfo gComponents[] = {
{ "TCP/IP JavaScript Shell Server",
NS_JSSHSERVER_CID,
NS_JSSHSERVER_CONTRACTID,
nsJSShServerConstructor
}
};
NS_IMPL_NSGETMODULE(nsJSShModule, gComponents)

Просмотреть файл

@ -1,247 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsJSShServer.h"
#include "nsNetCID.h"
#include "nsISocketTransport.h"
#include "nsIComponentManager.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsThreadUtils.h"
#include "nsJSSh.h"
#include "nsComponentManagerUtils.h"
//**********************************************************************
// ConnectionListener helper class
class ConnectionListener : public nsIServerSocketListener
{
public:
ConnectionListener(const nsACString &startupURI);
~ConnectionListener();
NS_DECL_ISUPPORTS
NS_DECL_NSISERVERSOCKETLISTENER
private:
nsCString mStartupURI;
};
//----------------------------------------------------------------------
// Implementation
ConnectionListener::ConnectionListener(const nsACString &startupURI)
: mStartupURI(startupURI)
{
}
ConnectionListener::~ConnectionListener()
{
}
already_AddRefed<nsIServerSocketListener> CreateConnectionListener(const nsACString &startupURI)
{
nsIServerSocketListener* obj = new ConnectionListener(startupURI);
NS_IF_ADDREF(obj);
return obj;
}
//----------------------------------------------------------------------
// nsISupports methods:
NS_IMPL_THREADSAFE_ADDREF(ConnectionListener)
NS_IMPL_THREADSAFE_RELEASE(ConnectionListener)
NS_INTERFACE_MAP_BEGIN(ConnectionListener)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIServerSocketListener)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsIServerSocketListener methods:
/* void onSocketAccepted (in nsIServerSocket aServ, in nsISocketTransport aTransport); */
NS_IMETHODIMP ConnectionListener::OnSocketAccepted(nsIServerSocket *aServ, nsISocketTransport *aTransport)
{
nsCOMPtr<nsIInputStream> input;
nsCOMPtr<nsIOutputStream> output;
aTransport->OpenInputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(input));
aTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(output));
LOG(("JSSh server: new connection!\n"));
nsCOMPtr<nsIRunnable> shell = CreateJSSh(input, output, mStartupURI);
nsCOMPtr<nsIThread> thread;
NS_NewThread(getter_AddRefs(thread), shell);
return NS_OK;
}
/* void onStopListening (in nsIServerSocket aServ, in nsresult aStatus); */
NS_IMETHODIMP ConnectionListener::OnStopListening(nsIServerSocket *aServ, nsresult aStatus)
{
LOG(("JSSh server: stopped listening!\n"));
return NS_OK;
}
//**********************************************************************
// nsJSShServer implementation
nsJSShServer::nsJSShServer()
{
LOG(("nsJSShServer ctor\n"));
}
nsJSShServer::~nsJSShServer()
{
LOG(("nsJSShServer dtor\n"));
// XXX should we stop listening or not??
StopServerSocket();
}
//----------------------------------------------------------------------
// nsISupports methods:
NS_IMPL_ADDREF(nsJSShServer)
NS_IMPL_RELEASE(nsJSShServer)
NS_INTERFACE_MAP_BEGIN(nsJSShServer)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIJSShServer)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsIJSShServer methods:
/* void startServerSocket (in unsigned long port, in AUTF8String startupURI,
in boolean loopbackOnly); */
NS_IMETHODIMP
nsJSShServer::StartServerSocket(PRUint32 port, const nsACString & startupURI,
PRBool loopbackOnly)
{
if (mServerSocket) {
NS_ERROR("server socket already running");
return NS_ERROR_FAILURE;
}
mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
if (!mServerSocket) {
NS_ERROR("could not create server socket");
return NS_ERROR_FAILURE;
}
if (NS_FAILED(mServerSocket->Init(port, loopbackOnly, -1))) {
mServerSocket = nsnull;
NS_ERROR("server socket initialization error");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIServerSocketListener> listener = CreateConnectionListener(startupURI);
mServerSocket->AsyncListen(listener);
mServerPort = port;
mServerStartupURI = startupURI;
mServerLoopbackOnly = loopbackOnly;
return NS_OK;
}
/* void stopServerSocket (); */
NS_IMETHODIMP nsJSShServer::StopServerSocket()
{
if (mServerSocket)
mServerSocket->Close();
mServerSocket = nsnull;
mServerPort = 0;
mServerStartupURI.Truncate();
mServerLoopbackOnly = PR_FALSE;
return NS_OK;
}
/* void runShell (in nsIInputStream input, in nsIOutputStream output,
in string startupURI, in boolean blocking); */
NS_IMETHODIMP
nsJSShServer::RunShell(nsIInputStream *input, nsIOutputStream *output,
const char *startupURI, PRBool blocking)
{
nsCOMPtr<nsIRunnable> shell = CreateJSSh(input, output, nsCString(startupURI));
if (!blocking) {
nsCOMPtr<nsIThread> thread;
NS_NewThread(getter_AddRefs(thread), shell);
}
else
shell->Run();
return NS_OK;
}
/* readonly attribute boolean serverListening; */
NS_IMETHODIMP
nsJSShServer::GetServerListening(PRBool *aServerListening)
{
if (mServerSocket)
*aServerListening = PR_TRUE;
else
*aServerListening = PR_FALSE;
return NS_OK;
}
/* readonly attribute unsigned long serverPort; */
NS_IMETHODIMP
nsJSShServer::GetServerPort(PRUint32 *aServerPort)
{
*aServerPort = mServerPort;
return NS_OK;
}
/* readonly attribute AUTF8String serverStartupURI; */
NS_IMETHODIMP
nsJSShServer::GetServerStartupURI(nsACString & aServerStartupURI)
{
aServerStartupURI = mServerStartupURI;
return NS_OK;
}
/* readonly attribute boolean serverLoopbackOnly; */
NS_IMETHODIMP
nsJSShServer::GetServerLoopbackOnly(PRBool *aServerLoopbackOnly)
{
*aServerLoopbackOnly = mServerLoopbackOnly;
return NS_OK;
}

Просмотреть файл

@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __NS_JSSHSERVER_H__
#define __NS_JSSHSERVER_H__
#include "nsIJSShServer.h"
#include "nsCOMPtr.h"
#include "nsIServerSocket.h"
#include "nsStringAPI.h"
class nsJSShServer : public nsIJSShServer
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIJSSHSERVER
nsJSShServer();
~nsJSShServer();
private:
nsCOMPtr<nsIServerSocket> mServerSocket;
PRUint32 mServerPort;
nsCString mServerStartupURI;
PRBool mServerLoopbackOnly;
};
#endif // __NS_JSSHSERVER_H__

Просмотреть файл

@ -1,171 +0,0 @@
/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
try {
// this will only work pending bug#238324
importModule("resource:/jscodelib/JSComponentUtils.js");
}
catch(e) {
var ComponentUtils = {
generateFactory: function(ctor, interfaces) {
return {
createInstance: function(outer, iid) {
if (outer) throw Components.results.NS_ERROR_NO_AGGREGATION;
if (!interfaces)
return ctor().QueryInterface(iid);
for (var i=interfaces.length; i>=0; --i) {
if (iid.equals(interfaces[i])) break;
}
if (i<0 && !iid.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return ctor();
}
}
},
generateNSGetModule: function(classArray, postRegister, preUnregister) {
var module = {
getClassObject: function(compMgr, cid, iid) {
if (!iid.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NO_INTERFACE;
for (var i=0; i<classArray.length; ++i) {
if(cid.equals(classArray[i].cid))
return classArray[i].factory;
}
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
registerSelf: function(compMgr, fileSpec, location, type) {
debug("*** registering "+fileSpec.leafName+": [ ");
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
for (var i=0; i<classArray.length; ++i) {
debug(classArray[i].className+" ");
compMgr.registerFactoryLocation(classArray[i].cid,
classArray[i].className,
classArray[i].contractID,
fileSpec,
location,
type);
}
if (postRegister)
postRegister(compMgr, fileSpec, classArray);
debug("]\n");
},
unregisterSelf: function(compMgr, fileSpec, location) {
debug("*** unregistering "+fileSpec.leafName+": [ ");
if (preUnregister)
preUnregister(compMgr, fileSpec, classArray);
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
for (var i=0; i<classArray.length; ++i) {
debug(classArray[i].className+" ");
compMgr.unregisterFactoryLocation(classArray[i].cid, fileSpec);
}
debug("]\n");
},
canUnload: function(compMgr) {
return true;
}
};
return function(compMgr, fileSpec) {
return module;
}
},
get categoryManager() {
return Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
}
};
}
//----------------------------------------------------------------------
// JSShStarter class
// constructor
function JSShStarter() {
}
JSShStarter.prototype = {
// nsICommandLineHandler methods:
handle : function(commandline) {
debug("JSShStarter: checking for -jssh startup option\n");
if (commandline.handleFlag("jssh", false)) {
// start a jssh server with startupURI
// "chrome://jssh/content/jssh-debug.js". We use 'getService'
// instead of 'createInstance' to get a well-known, globally
// accessible instance of a jssh-server.
// XXX Todo: get port, startupURI and loopbackOnly from prefs.
var port = commandline.handleFlagWithParam("jssh-port", false) || 9997;
Components.classes["@mozilla.org/jssh-server;1"]
.getService(Components.interfaces.nsIJSShServer)
.startServerSocket(port, "chrome://jssh/content/jssh-debug.js", true);
debug("JSShStarter: JSSh server started on port " + port + "\n");
}
},
helpInfo : " -jssh Start a JSSh server on port 9997.\n" +
" -jssh-port <port> Change the JSSh server port.\n",
};
//----------------------------------------------------------------------
NSGetModule = ComponentUtils.generateNSGetModule(
[
{
className : "JSShStarter",
cid : Components.ID("28CA200A-C070-4454-AD47-551FBAE1C48C"),
contractID : "@mozilla.org/jssh-runner;1",
factory : ComponentUtils.generateFactory(function(){ return new JSShStarter();},
[Components.interfaces.nsICommandLineHandler])
}
],
function(mgr,file,arr) {
debug("register as command-line-handler");
ComponentUtils.categoryManager.addCategoryEntry("command-line-handler",
"a-jssh",
arr[0].contractID,
true, true);
},
function(mgr,file,arr) {
debug("unregister as command-line-handler");
ComponentUtils.categoryManager.deleteCategoryEntry("command-line-handler",
"a-jssh", true);
}
);

Просмотреть файл

@ -1,98 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<dialog id="jssh_configure" title="Configure JSSh"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept,cancel"
onload="init();"
ondialogaccept="return doOK();"
ondialogcancel="return doCancel();">
<script>
var enablectrl;
var portctrl;
var scriptctrl;
function init() {
enablectrl = document.getElementById("enable");
portctrl = document.getElementById("port");
loopbackctrl = document.getElementById("loopback");
scriptctrl = document.getElementById("script");
if (!opener.jssh_server)
opener.jssh_server = { server: Components.classes["@mozilla.org/jssh-server;1"]
.getService(Components.interfaces.nsIJSShServer),
port: 9997,
useLoopbackOnly: true,
script: "chrome://jssh/content/jssh-debug.js" };
// the server might have been started from elsewhere, in which
// case we need to get the port, etc. parameters directly from the server:
if (opener.jssh_server.server.serverListening) {
opener.jssh_server.port = opener.jssh_server.server.serverPort;
opener.jssh_server.script = opener.jssh_server.server.serverStartupURI;
opener.jssh_server.useLoopbackOnly = opener.jssh_server.server.serverLoopbackOnly;
}
enablectrl.checked = (opener.jssh_server.server.serverListening);
portctrl.value = opener.jssh_server.port;
loopbackctrl.checked = opener.jssh_server.useLoopbackOnly;
scriptctrl.value = opener.jssh_server.script;
}
function doOK() {
// stop current server instance:
if (opener.jssh_server.server.serverListening) {
opener.jssh_server.server.stopServerSocket();
}
// take new values from ui:
opener.jssh_server.port = portctrl.value;
opener.jssh_server.useLoopbackOnly = loopbackctrl.checked;
opener.jssh_server.script = scriptctrl.value;
// start new server instance if requested:
if (enablectrl.checked) {
try {
opener.jssh_server.server.startServerSocket(opener.jssh_server.port, opener.jssh_server.script,
opener.jssh_server.useLoopbackOnly);
alert("The JSSh server is now running on port "+opener.jssh_server.port+".");
}catch(e){
alert("The JSSh server could not be started at the given port");
return false;
}
}
return true;
}
function doCancel() {
return true;
}
</script>
<description value="JSSh - JavaScript TCP/IP shell server"/>
<description maxwidth="300px">
Warning: If your computer is connected to the internet and you haven't
got a properly configured firewall, enabling JSSh on other interfaces
besides the loopback interface means that *ANYONE* can connect to your
machine and execute potentially harmful code!
</description>
<checkbox id="enable" label="Listen for connections"/>
<grid>
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row>
<label control="port" value="Port to listen on:"/>
<textbox id="port" size="5"/>
</row>
<row>
<label control="script" value="Startup script:"/>
<textbox id="script" />
</row>
</rows>
</grid>
<checkbox id="loopback" label="Restrict to local loopback interface (127.0.0.1/localhost)"/>
</dialog>

Просмотреть файл

@ -1,28 +0,0 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the packages being supplied by this jar -->
<RDF:Seq about="urn:mozilla:package:root">
<RDF:li resource="urn:mozilla:package:jssh"/>
</RDF:Seq>
<!-- package information -->
<RDF:Description about="urn:mozilla:package:jssh"
chrome:displayName="JavaScript Shell Server UI"
chrome:author="Alex Fritze"
chrome:name="jssh" >
</RDF:Description>
<!-- overlay information -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li resource="chrome://communicator/content/tasksOverlay.xul"/>
</RDF:Seq>
<!-- Communicator Overlays -->
<RDF:Seq about="chrome://communicator/content/tasksOverlay.xul">
<RDF:li>chrome://jssh/content/tasksOverlay.xul</RDF:li>
</RDF:Seq>
</RDF:RDF>

Просмотреть файл

@ -1,602 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript Shell project.
*
* The Initial Developer of the Original Code is
* Alex Fritze.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//**********************************************************************
// a startup script with some debugging functions for JSSh
//**********************************************************************
// Debugger interface
// if (!debugservice)
// var debugservice = Components.classes["@mozilla.org/js/jsd/debugger-service;1"]
// .getService(Components.interfaces.jsdIDebuggerService);
//**********************************************************************
// General purpose commands
//----------------------------------------------------------------------
var _help_strings = {};
function help(func) {
if (!func) {
print("Usage: help(command);\n");
print("Available commands are:\n");
for (var i in _help_strings) print(i+" ");
return;
}
if (typeof func == "function") {
func = func.name;
}
var str = _help_strings[func];
if (!str) {
print("unknown command! Try help();\n");
return;
}
print(str+"\n");
}
//----------------------------------------------------------------------
_help_strings.inspect = "inspect(obj) dumps information about obj";
function inspect(obj) {
if(!obj) {
dump(obj);
return;
}
print("* Object type: "+typeof obj+"\n");
switch(typeof obj) {
case "object":
print("* Prototype chain: ");
try {
var proto = obj.__proto__;
while (proto) {
try {
print(proto);
} catch(e) {
// obj.__proto__.toString threw an exception!
print("[proto.toString = "+obj.__proto__.toString+"]");
}
finally { dump(" "); }
proto = proto.__proto__;
}
} catch(e) {dump("...(?)");}
print("\n");
print("* String value: "+ obj+"\n");
print("* Members: ");
for (var i in obj) {
try {
dump(i);
}
catch(e) { dump("(?)"); }
finally { dump(" "); }
// xxx sometimes make moz hang. e.g. for inspect(debugservice)
// try{
// dump("("+(typeof obj[i])[0]+") ");
// }
// catch(e) { dump("(?) "); }
}
print("\n");
break;
case "function":
print("* Arity: "+obj.length+"\n");
print("* Function definition: ");
print(obj);
break;
case "xml":
print(obj.toXMLString()+"\n");
break;
default:
print("* String value: "+ obj +"\n");
break;
}
}
//----------------------------------------------------------------------
_help_strings.subobjs = "subobjs(obj, type) list all subobjects of object obj that have type 'type' (default='object')";
function subobjs(obj, type) {
if (!type) type="object";
for (var o in obj) {
try {
if (typeof obj[o]==type)
print(o+" ");
}
catch(e) {
print(o+"(?) ");
}
}
print("\n");
}
//----------------------------------------------------------------------
_help_strings.dumpIDL = "dumpIDL(iid) dumps idl code for interface iid.\niid can either be an interface, or a string of form 'Components.interfaces.nsIFoo' or just 'nsIFoo'";
function dumpIDL(iid) {
var gen = Components.classes["@mozilla.org/interfaceinfotoidl;1"]
.createInstance(Components.interfaces.nsIInterfaceInfoToIDL);
if (typeof iid == "string") {
if (!/Components.interfaces./.test(iid)) {
iid = "Components.interfaces."+iid;
}
iid = eval(iid);
}
dump(gen.generateIDL(iid, false, false));
}
//----------------------------------------------------------------------
_help_strings.getWindows = "getWindows() returns a list of all currently open windows";
function getWindows() {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var enumerator = wm.getEnumerator(null);
var retval = [];
while (enumerator.hasMoreElements())
retval.push(enumerator.getNext());
return retval;
}
//----------------------------------------------------------------------
_help_strings.findClass = "findClass(/regex/) finds registered classes matching /regex/";
function findClass(regex) {
for (var c in Components.classes)
if (regex.test(c)) print(c+" ");
}
//----------------------------------------------------------------------
_help_strings.findInterface = "findInterface(/regex/) finds registered interfaces matching /regex/";
function findInterface(regex) {
for (var i in Components.interfaces)
if (regex.test(i)) print(i+" ");
}
//----------------------------------------------------------------------
_help_strings.dumpStack = "dumpStack(offset, max_depth) displays a stack trace up to depth max_depth (default: 10) starting 'offset' frames below the current one";
function dumpStack(offset, max_depth) {
if (!offset || offset<0) offset = 0;
if (!max_depth) max_depth = 10;
var frame = Components.stack;
while(--max_depth && (frame=frame.caller)) {
if (!offset)
dump(frame+"\n");
else
--offset;
}
}
//----------------------------------------------------------------------
_help_strings.jssh = "jssh(startupURI) runs a blocking interactive javascript shell";
function jssh(startupURI) {
Components.classes["@mozilla.org/jssh-server;1"]
.getService(Components.interfaces.nsIJSShServer)
.runShell(getInputStream(), getOutputStream(), startupURI, true);
}
//----------------------------------------------------------------------
_help_strings.hex = "hex(str, octets_per_line) returns the hexadecimal representation of the given string. octets_per_line is optional and defaults to 4.";
function hex(str, octets_per_line) {
var rv = "";
if (!octets_per_line) octets_per_line = 4;
for (var i=0, l=str.length; i<l; ++i) {
var code = str.charCodeAt(i).toString(16);
if (code.length == 1) code = "0"+code;
rv += code + " ";
if (i % octets_per_line == octets_per_line-1) rv += "\n";
}
return rv;
}
//**********************************************************************
// Function instrumentation:
// global hash to keep track of instrumented objs/funcs
if (!_instrumented_objects)
var _instrumented_objects = {};
//----------------------------------------------------------------------
_help_strings.getInstrumented = "getInstrumented(obj, func) returns an object with instrumentation data for the given (obj, func). It can be used to change instrumentation functions or operation-flags for the instrumentation functions . Members include \n'old': old method that will be called.\n'before', 'after': before and after methods\nThe default before and after methods recognise the flags (set by defining/unset by deleting):\n'stack' : show stack trace\n'nargs' : don't show args\n'nresult' : don't show result/exception status on exiting.";
function getInstrumented(obj, func) {
return _instrumented_objects[obj][func];
}
//----------------------------------------------------------------------
_help_strings.instrument = "instrument(obj, func, beforeHook, afterHook) instruments func on obj. obj and func need to be strings. Optional beforeHook and afterHook are the methods called before and after the instrumented method is being called. Signature for before hook functions is hook(obj, func, argv). Signature for after hook functions is hook(obj, func, argv, retval, exception). Return value of after hook will be taken as return value for function call";
// default hooks for instrumented functions:
function _defaultBeforeHook(obj, func, argv) {
print("* Entering "+obj+"."+func+"\n");
if (getInstrumented(obj,func)["nargs"]===undefined) {
print("* Arguments("+argv.length+"): " );
for (var i=0;i<argv.length;++i) print("'"+argv[i]+"' ");
print("\n");
}
if (getInstrumented(obj,func)["stack"]!==undefined) {
print("* Stack: \n");
dumpStack(2);
}
}
function _defaultAfterHook(obj, func, argv, retval, ex) {
print("* Exiting "+obj+"."+func+"\n");
if (getInstrumented(obj,func)["nresult"]===undefined){
print("* Result: ");
if (!ex)
print(retval+"\n");
else
print("An exception was thrown!\n");
}
return retval;
}
function instrument(obj, func, beforeHook, afterHook) {
if (typeof obj!="string"||typeof func!="string") {
help("instrument");
return;
}
if (!_instrumented_objects[obj])
_instrumented_objects[obj] = {};
if (_instrumented_objects[obj][func]) {
print("obj.function is already instrumented!");
return;
}
if (!beforeHook) beforeHook = _defaultBeforeHook;
if (!afterHook) afterHook = _defaultAfterHook;
_instrumented_objects[obj][func] = {};
_instrumented_objects[obj][func]["old"] = eval(obj)[func];
_instrumented_objects[obj][func]["before"] = beforeHook;
_instrumented_objects[obj][func]["after"] = afterHook;
eval(obj)[func] = function() {
_instrumented_objects[obj][func]["before"](obj, func, arguments);
var retval;
var ex;
try {
retval = _instrumented_objects[obj][func]["old"].apply(this, arguments);
}
catch(e) {
ex = e;
throw (e);
}
finally {
retval = _instrumented_objects[obj][func]["after"](obj, func, arguments, retval, ex);
}
return retval;
}
}
//----------------------------------------------------------------------
_help_strings.dumpInstrumented = "dumpInstrumented() prints a list of all currently instrumented functions.";
function dumpInstrumented() {
for (var obj in _instrumented_objects) {
for (var method in _instrumented_objects[obj]) {
dump(obj+"."+method+" ");
}
}
print("\n");
}
//----------------------------------------------------------------------
_help_strings.uninstrument = "uninstrument(obj, func) uninstruments func on obj. obj and func need to be strings.";
function uninstrument(obj, func) {
if (typeof obj!="string"||typeof func!="string") {
help("uninstrument");
return;
}
if (!_instrumented_objects[obj] || !_instrumented_objects[obj][func]) {
print("obj.function is not instrumented!");
return;
}
eval(obj)[func] = _instrumented_objects[obj][func]["old"];
delete _instrumented_objects[obj][func];
}
//**********************************************************************
// DOM utils:
//----------------------------------------------------------------------
_help_strings.domNode = "domNode(base, child1, child2, ...) returns the dom node identified by base and the child offsets. The child offset can be of form 'a5' to identify the anonymous child at position 5.";
function domNode(base) {
var node = base;
for (var i=1; i<arguments.length; ++i) {
if (typeof arguments[i] == "number") {
node = node.childNodes[arguments[i]];
}
else if(arguments[i][0]=='a') {
var idx = arguments[i].substring(1, arguments[i].length);
node = node.ownerDocument.getAnonymousNodes(node)[idx];
}
}
return node;
}
//----------------------------------------------------------------------
_help_strings.domDumpFull = "domDumpFull(node) dumps the *complete* DOM starting from node.";
function domDumpFull(node) {
var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
.getService(Components.interfaces.nsIDOMSerializer);
print(serializer.serializeToString(node));
}
//----------------------------------------------------------------------
_help_strings.domDump = "domDump(node) dumps the DOM around 'node'";
function domDump(node){
var wantChildren = false;
var wantAnonChildren = false;
switch(node.nodeType) {
case Components.interfaces.nsIDOMNode.DOCUMENT_NODE:
print("<#document>\n");
wantChildren = true;
break;
case Components.interfaces.nsIDOMNode.ELEMENT_NODE:
print("* Parent: <"+node.parentNode.nodeName+">\n");
print("<"+node.nodeName);
for (var i=0; i<node.attributes.length;++i) {
var attr = node.attributes.item(i);
print(" "+attr.nodeName+"='"+attr.nodeValue+"'");
}
print(">\n");
wantChildren = true;
wantAnonChildren = true;
break;
default:
break;
}
if (wantChildren && node.hasChildNodes()) {
print("* Children: \n");
for (var i=0; i<node.childNodes.length;++i) {
print(" ["+i+"]: <"+node.childNodes[i].nodeName+">\n");
}
}
if (wantAnonChildren) {
var anlist = node.ownerDocument.getAnonymousNodes(node);
if (anlist && anlist.length) {
print("* Anonymous Children: \n");
for (var i=0; i<anlist.length;++i) {
print(" A["+i+"]: <"+anlist[i].nodeName+">\n");
}
}
}
}
//**********************************************************************
// RDF utils:
//----------------------------------------------------------------------
_help_strings.rdfDump = "rdfDump(url) dumps the rdf datasource at 'url' in the following form:\n\n"+
" <Resource> \n"+
" |\n"+
" |--[Resource]--> <Resource>\n"+
" |\n"+
" |--[Resource]--> {literal}\n\n"+
"If 'url' points to a remote datasource, it will be refreshed before dumping.";
function rdfDump(url) {
var RDFService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
var ds = RDFService.GetDataSourceBlocking(url);
// make sure the ds is up-to-date:
try {
var remote = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
remote.Refresh(true);
}
catch(e) {
// not a remote ds.
}
const RESOURCE_IID = Components.interfaces.nsIRDFResource;
const LITERAL_IID = Components.interfaces.nsIRDFLiteral;
const DATE_IID = Components.interfaces.nsIRDFDate;
const INT_IID = Components.interfaces.nsIRDFInt;
const BLOB_IID = Components.interfaces.nsIRDFBlob;
var resources = ds.GetAllResources();
while (resources.hasMoreElements()) {
var resource = resources.getNext().QueryInterface(RESOURCE_IID);
print("\n<" + resource.Value + ">\n");
var arcs = ds.ArcLabelsOut(resource);
while (arcs.hasMoreElements()) {
var arc = arcs.getNext().QueryInterface(RESOURCE_IID);
print(" |\n");
print(" |--["+arc.Value +"]--> ");
var targets = ds.GetTargets(resource,arc,true);
while (targets.hasMoreElements()) {
var target = targets.getNext();
// target can be resource or literal string, date, int or blob:
try {
var target_as_resource = target.QueryInterface(RESOURCE_IID);
print("<"+target_as_resource.Value+"> ");
continue;
} catch(e) {}
try {
var target_as_literal = target.QueryInterface(LITERAL_IID);
print("{String=\""+target_as_literal.Value+"\"} ");
continue;
} catch(e) {}
try {
var target_as_date = target.QueryInterface(DATE_IID);
print("{Date="+target_as_date.Value+"} ");
continue;
} catch(e) {}
try {
var target_as_int = target.QueryInterface(INT_IID);
print("{Int="+target_as_int.Value+"} ");
continue;
} catch(e) {}
try {
var target_as_blob = target.QueryInterface(INT_BLOB);
print("{Blob with length="+target_as_blob.length+"} ");
continue;
} catch(e) {}
}
print("\n");
}
}
}
//**********************************************************************
// Support for 'live' development:
//
// pushContext(obj) inserts the JSSh object into the prototype chain
// of obj and set obj as the current context object. This then gives
// the appearance as if obj is the current 'global' object. So
// e.g. variables that are set with 'var foo = ...' will end up in
// obj. Function calls 'bar()' map to 'obj->bar()'.
//
// XXX JSSh is inserted at the top of the prototype chain, between obj
// and its old prototype. This is so that we don't get JSSh functions
// appearing in *all* objects. (If we inserted JSSh at the bottom of
// the proto chain, its functions would be "inherited" by all objects
// that are rooted in the same object). The problem with this scheme
// is that JSSh can shadow certain functions, most notably
// QueryInterface, when JSSh is inserted between a wrapped native and
// its prototype.
// global context stack
if (!_context_objects)
var _context_objects = [{obj:this,proto:this.__proto__}];
//----------------------------------------------------------------------
_help_strings.pushContext = "pushContext(obj) installs the jssh context into the proto chain of 'obj' and sets 'obj' as the current context object";
function pushContext(obj) {
var context = {"obj":obj, "proto":obj.__proto__};
// sandwich jssh object between obj and its prototype:
_context_objects[0].obj.__proto__ = obj.__proto__;
obj.__proto__ = _context_objects[0].obj;
// push context and set new context object:
_context_objects.push(context);
setContextObj(obj);
}
//----------------------------------------------------------------------
_help_strings.popContext = "popContext() restores the context object set before the last call to pushContext(.)";
function popContext() {
if (_context_objects.length<2) {
print("Context stack empty\n");
return;
}
var context = _context_objects.pop();
// remove jssh obj from proto chain:
context.obj.__proto__ = context.proto;
// restore jssh object's prototype:
_context_objects[0].obj.__proto__ = _context_objects[_context_objects.length-1].proto;
// switch to previous context:
setContextObj(_context_objects[_context_objects.length-1].obj);
}
// override global 'exit()' function to pop the context stack:
exit = (function() {
var _old_exit = exit;
return function() {
try {
while(_context_objects.length>1)
popContext();
} catch(e) {}
_old_exit();
}})();
//----------------------------------------------------------------------
_help_strings.reloadXBLDocument = "reloadXBLDocument(url) reloads the xbl file 'url'. If defined, reloadXBLDocumentHook(url) is called before reloading.";
function reloadXBLDocument(url){
try {
reloadXBLDocumentHook(url);
}catch(e){}
var chromeCache = Components.classes["@mozilla.org/xul/xul-prototype-cache;1"].getService(Components.interfaces.nsIChromeCache);
// Clear and reload the chrome file:
chromeCache.flushXBLDocument(url);
getWindows()[0].document.loadBindingDocument(url);
}
//----------------------------------------------------------------------
_help_strings.reloadXULDocument = "reloadXULDocument(url) reloads the xul file 'url'. If defined, reloadXULDocumentHook(url) is called before reloading.";
function reloadXULDocument(url){
try {
reloadXULDocumentHook(url);
}catch(e){}
var chromeCache = Components.classes["@mozilla.org/xul/xul-prototype-cache;1"].getService(Components.interfaces.nsIChromeCache);
// Clear and reload the chrome file:
chromeCache.flushXULPrototype(url);
}
//----------------------------------------------------------------------
_help_strings.time = "time(fct) returns execution time of 'fct' in milliseconds.";
function time(fct) {
var start = new Date();
fct();
var end = new Date();
return end.getTime() - start.getTime();
}
////////////////////////////////////////////////////////////////////////
// ZAP specific debug functions:
//----------------------------------------------------------------------
_help_strings.lastError = "lastError() returns the last verbose error from the zap verbose error service";
function lastError() {
var errorService = Components.classes["@mozilla.org/zap/verbose-error-service;1"]
.getService(Components.interfaces.zapIVerboseErrorService);
return errorService.lastMessage;
}
//----------------------------------------------------------------------
_help_strings.dialogs = "dialogs() returns a list of currently active dialogs & associated info";
function dialogs() {
var rv = "";
var pool = getWindows()[0].wSipStack.wrappedJSObject.dialogPool;
for (var d in pool) {
rv += "callid="+pool[d].callID+"\n"+
"state="+pool[d].dialogState+"\n"+
"local tag="+pool[d].localTag+
" remote tag="+pool[d].remoteTag+"\n"+
"local uri="+pool[d].localURI.serialize()+"\n"+
"remote uri="+pool[d].remoteURI.serialize()+"\n"+
"remote target="+pool[d].remoteTarget.serialize()+"\n"+
"local seq="+pool[d].localSequenceNumber+
" remote seq="+pool[d].remoteSequenceNumber+
"\n\n";
}
return rv;
}

Просмотреть файл

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<overlay id="jsshTasksOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript">
function jssh_configure() {
window.openDialog("chrome://jssh/content/configure.xul", "jssh_configure", "chrome");
}
</script>
<menupopup id="toolsPopup">
<menuitem id="menu_jssh" label="JSSh"
oncommand="jssh_configure();" />
</menupopup>
</overlay>

Просмотреть файл

@ -1,318 +0,0 @@
;;; moz-jssh.el
;;; utilities for connecting to a live mozilla jssh server
;;;
;;; copyright (c)2003 Alex Fritze <alex@croczilla.com>
(provide 'moz-jssh)
(require 'cl)
(defvar moz-jssh-host "localhost" "*Host that JSSh server is running on")
(defvar moz-jssh-port 9997 "*Port that JSSh service is running on")
;; ----------------------------------------------------------------------
;; Functions for evaluating js code
(defun* moz-jssh-eval-internal (command process &key obj)
"Execute js command line 'command' for jssh process 'process'. If the
optional arg :obj is specified, the command will be executed on the
given object. Newlines in 'command' will be replaced with a space and comments will be properly escaped."
(let ((finished nil)
(result "")
(unparsed "")
(parse-reply (function (lambda (str)
(cond ((string-match "^\\[\\([^\]]*\\)\\]" str)
(let ((l (string-to-number
(substring str
(match-beginning 1)
(match-end 1))))
(start (+ 1 (match-end 1))))
(cond ((> (+ start l) (length str))
(setq unparsed str))
(t
(setq result
(concat result
(substring str
start (+ start l))))
(funcall parse-reply (substring str (+ start l)))))))
((string-match "\n> $" str)
(setq finished t))
(t
(setq unparsed str))))))
(null-filter (function (lambda (proc mess) nil)))
(receive-filter (function (lambda (proc mess)
(setq mess (concat unparsed mess))
(setq unparsed "")
(funcall parse-reply mess)))))
(unwind-protect
(progn
;; set up the session
(set-process-filter process null-filter)
(process-send-string process (concat "__JSSH_protocol__ = getProtocol();"
"setProtocol('synchronous');"
(if obj (concat obj
".__JSSH_shell__ = this;"
"setContextObj(" obj ");"))
"\n"))
;; eat prompt
(accept-process-output process)
;; send the command
;; XXX our protocol currently requires that there is a single
;; newline at the end of the command only (have to be careful with
;; '//'-style comments and '//' in strings):
(let ((commandlist (split-string command "\n")))
(setq commandlist (mapcar (lambda (s)
(replace-in-string s "^\\(\\(\\(/[^/]\\)\\|[^\"/]\\|\\(\"[^\"]*\"\\)\\)*\\)\\(//.*\\)$" "\\1 "))
commandlist))
(setq command (apply 'concat commandlist)))
;;(setq result (concat result "Command:\n" command "\n\nResult:\n"))
(set-process-filter process receive-filter)
(process-send-string process (concat command "\n"))
;; wait for output
(while (not finished) (accept-process-output process))
;; now restore the session
(set-process-filter process null-filter)
(if obj
(progn
(process-send-string process "__JSSH_shell__.setContextObj(__JSSH_shell__)\n")
;; eat prompt
(accept-process-output process)))
(process-send-string process (concat "setProtocol(__JSSH_protocol__);"
"delete __JSSH_protocol__;"
"delete " (if obj obj "this") ".__JSSH_shell__;\n"))
;; eat prompt
(accept-process-output process))
;; remove filter, so that future output goes whereever it is supposed to:
(set-process-filter process nil))
result))
(defun* moz-jssh-eval-anonymous (command &rest rest &key &allow-other-keys)
"Evaluate a command in a temporary anonymous Mozilla JavaScript
shell. Optional keyed parameters will be passed to
`moz-jssh-eval-internal'."
(interactive "sCommand: ")
(let ((initialized nil)
(result nil)
(conn (open-network-stream "moz-jssh"
(buffer-name)
moz-jssh-host moz-jssh-port)))
(set-process-filter conn (function (lambda (proc mess)
(if (string-match "\n> $" mess)
(setq initialized t)))))
(unwind-protect
(progn
(while (not initialized) (accept-process-output conn))
(setq result (apply 'moz-jssh-eval-internal command conn :allow-other-keys t rest)))
(delete-process conn))
(if (interactive-p)
(if (string-match "\n" result) ; more than one line
(with-output-to-temp-buffer "*moz-jssh-eval-anonymous*"
(princ result))
(message "%s" result))
result)))
(defun get-region-string ()
"Helper to return the current region as a string, or nil otherwise."
(let ((buf (zmacs-region-buffer)))
(if buf
(buffer-substring (mark t buf) (point buf)))))
(defun* moz-jssh-eval (&optional &rest rest &key cmd buffer &allow-other-keys)
"Evaluate the jssh command line given by the active region, the cmd
argument or interactively prompted for. If the optional argument
buffer is given, the command will be executed for the jssh-process
attached to that buffer. If the buffer doesn't have an attached
jssh-process, or the arg doesn't name a valid buffer, then the command
will be executed in a temporary shell. If the argument buffer is not
given, the command will be executed for the current buffer if that
buffer has an attached jssh-process. If it hasn't, the command will
be executed in the buffer *moz-jssh* if it exists or in a temporary
shell if there is no buffer called *moz-jssh*. Additional (keyed)
arguments can be given and will be passed to
`moz-jssh-eval-internal'."
(interactive)
(or cmd (setq cmd (get-region-string)))
(if (and (interactive-p) (not cmd))
(setq cmd (read-input "Command: ")))
(let ((result (cond ((and (or (stringp buffer) (bufferp buffer))
(get-buffer-process buffer)
(string-match "moz-jssh" (process-name (get-buffer-process buffer))))
(apply 'moz-jssh-eval-internal
cmd
(get-buffer-process buffer)
:allow-other-keys t rest))
((and (not buffer)
(get-buffer-process (current-buffer))
(string-match "moz-jssh" (process-name (get-buffer-process (current-buffer)))))
(apply 'moz-jssh-eval-internal
cmd
(get-buffer-process (current-buffer))
:allow-other-keys t rest))
((and (not buffer)
(get-buffer-process "*moz-jssh*")
(string-match "moz-jssh" (process-name (get-buffer-process "*moz-jssh*"))))
(apply 'moz-jssh-eval-internal
cmd
(get-buffer-process "*moz-jssh*")
:allow-other-keys t rest))
(t
(apply 'moz-jssh-eval-anonymous
cmd
:allow-other-keys t rest)))))
(if (interactive-p)
(if (string-match "\n" result) ; more than one line
(with-output-to-temp-buffer "*moz-jssh-eval*"
(princ result))
(message "%s" result)) result)))
(defvar moz-jssh-buffer-globalobj nil "js object that a call to
`moz-jssh-eval-buffer' will be evaluted on.")
(defun* moz-jssh-eval-buffer (&optional &rest rest &allow-other-keys)
"Evaluate the current buffer in a jssh shell. If the variable
`moz-jssh-buffer-globalobj' is not null and there is a jssh shell
buffer called *moz-jssh*, then this buffer will be used as the
executing shell. Otherwise a temporary shell will be created. The
buffer content will be executed on the object given by
`moz-jssh-buffer-globalobj' or on the shell's global object if
`moz-jssh-buffer-globalobj' is null. Output will be shown in the
buffer *moz-jssh-eval*. Additional (keyed) arguments can be given and
will be passed to `moz-jssh-eval-internal'."
(interactive)
(let ((result (cond ((and (not moz-jssh-buffer-globalobj)
(get-buffer-process "*moz-jssh*")
(string-match "moz-jssh" (process-name (get-buffer-process "*moz-jssh*"))))
(apply 'moz-jssh-eval-internal
(buffer-string)
(get-buffer-process "*moz-jssh*")
:allow-other-keys t rest))
(t
(apply 'moz-jssh-eval-anonymous
(buffer-string)
:obj moz-jssh-buffer-globalobj
:allow-other-keys t rest)))))
(if (interactive-p)
(if (string-match "\n" result) ; more than one line
(with-output-to-temp-buffer "*moz-jssh-eval*"
(princ result))
(message "%s" result)) result)))
;; ----------------------------------------------------------------------
;; some inspection functions:
(defun* moz-jssh-inspect (obj &rest rest &allow-other-keys)
"Inspect the given object"
(interactive "sObject to inspect: ")
(let ((result (apply 'moz-jssh-eval
:cmd (concat "inspect(" obj ");")
:allow-other-keys t rest)))
(if (interactive-p)
(if (string-match "\n" result) ; multi-line result
(with-output-to-temp-buffer "*moz-jssh-inspect*"
(save-excursion
(set-buffer "*moz-jssh-inspect*")
(javascript-mode)
(font-lock-mode))
(princ (concat "inspect(" obj ") :\n" result)))
(message "%s" (concat "inspect(" obj ") -> " result)))
result)))
(defun* moz-jssh-inspect-interface (itf &rest rest &allow-other-keys)
"Shows the IDL definition of the given interface"
(interactive "sInterface name: ")
(let ((result (apply 'moz-jssh-eval
:cmd (concat "dumpIDL(\"" itf "\");")
:allow-other-keys t rest)))
(if (interactive-p)
(if (string-match "\n" result) ; multi-line result
(with-output-to-temp-buffer "*moz-jssh-inspect*"
(save-excursion
(set-buffer "*moz-jssh-inspect*")
(idl-mode)
(font-lock-mode))
(princ result))
(message "%s" result))
result)))
;; ----------------------------------------------------------------------
;; Shell for interacting with Mozilla through a JavaScript shell
(defun moz-jssh ()
"Connect to a running Mozilla JavaScript shell (jssh) server. "
(interactive)
(require 'comint)
(unless (comint-check-proc "*moz-jssh*")
(set-buffer
(make-comint "moz-jssh" (cons moz-jssh-host moz-jssh-port)))
(moz-jssh-mode))
(pop-to-buffer "*moz-jssh*"))
;; ----------------------------------------------------------------------
;; Open a shell for current buffer.
(defun moz-jssh-buffer-shell ()
"Connect to a running Mozilla JavaScript shell (jssh) server. Same
as `moz-jssh', but honours the variable moz-jssh-buffer-globalobj if
defined."
(interactive)
(require 'comint)
(let* ((procname (concat "moz-jssh"
(if moz-jssh-buffer-globalobj
(concat "-" (buffer-name)))))
(buffername (concat "*" procname "*"))
;; need to save gobj because it is buffer local & we're going
;; to switch buffers:
(gobj moz-jssh-buffer-globalobj))
(unless (comint-check-proc buffername)
(set-buffer
(make-comint procname (cons moz-jssh-host moz-jssh-port)))
(moz-jssh-mode)
(if (not gobj)
()
;; eat greeting & prompt before sending command. XXX this is
;; getting a bit dodgy.time to rewrite the protocol.
(accept-process-output (get-buffer-process buffername) 1)
(accept-process-output (get-buffer-process buffername) 1)
(message "%s" (moz-jssh-eval :cmd (concat "pushContext(" gobj ")")))))
(pop-to-buffer buffername)))
;; ----------------------------------------------------------------------
;; Major mode for moz-jssh buffers
(defvar moz-jssh-mode-map nil)
(defun moz-jssh-mode-commands (map)
(define-key map [(home)] 'comint-bol)
(define-key map [(control c)(i)] 'moz-jssh-inspect))
(defun moz-jssh-mode ()
"Major mode for interacting with a Mozilla JavaScript shell.
\\{moz-jssh-mode-map}
"
(comint-mode)
(setq comint-prompt-regexp "^> *"
mode-name "moz-jssh"
major-mode 'moz-jssh-mode)
(if moz-jssh-mode-map
nil
(setq moz-jssh-mode-map (copy-keymap comint-mode-map)) ; XXX could inherit instead of copying
(moz-jssh-mode-commands moz-jssh-mode-map))
(use-local-map moz-jssh-mode-map))
;;----------------------------------------------------------------------
;; global keybindings
(if (keymapp 'moz-prefix)
()
(define-prefix-command 'moz-prefix)
(global-set-key [(control c) m] 'moz-prefix))
(global-set-key [(control c) m j] 'moz-jssh)
(global-set-key [(control c) m s] 'moz-jssh-buffer-shell)
(global-set-key [(control c) m e] 'moz-jssh-eval-buffer)