| croczilla.com | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
JSSh - a TCP/IP JavaScript Shell Server for MozillaJSSh is a Mozilla C++ extension module that allows other programs (such as telnet) to establish JavaScript shell connections to a running Mozilla process via TCP/IP. This functionality is useful for interactive debugging/development of Mozilla applications, remotely controlling Mozilla, or for automated testing purposes. Note that JSSh is a binary component, which makes it a bit awkward to distribute as a firefox extension. There is a also a javascript-only component that apparently pretty much does what JSSh does. For details see Shane Caraveo's blog post here: jssh replacement? SD Connector. I haven't tried it out yet, but it looks promising! DownloadCVS: The JSSh code is checked into Mozilla trunk CVS in directory mozilla/extensions/jssh/. Building from sourceWhen building Mozilla (Firefox, Xulrunner, etc.), add the following to your .mozconfig:ac_add_options --enable-extensions=default,jssh,webservices
The Running itStart Mozilla (firefox, Xulrunner, etc.) with the command line option-jsshJSSh should now start up automatically and start listening on port 9997 (only on localhost). You should be able to connect to it with telnet: telnet localhost 9997Note that the telnet client shipping with MS Windows seems to have some CR/LF problems. As an alternative you can use (x)emacs (see below). You can also start a JSSh server manually from code; see below under 'Running a server'. Binary distribution; installing as an extensionInstalling JSSh as an extension is currently somewhat broken. There are some pointers here.Description (quite outdated - refers to version jssh-20030213)The JSSh module provides an XPCOM object with
CID: {A1764959-87D8-4249-A432-8005DE1372FC}
ContractID: "@mozilla.org/jssh-server;1"
implementing the following interface:
[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 */
void startServerSocket(in unsigned long port, in AUTF8String startupURI);
/* stop listening for connections */
void stopServerSocket();
/* run a jssh session with the given input and output streams.
'startupURI' specifies an optional script that will be executed
on session startup.
if 'interactive' is false, this will be a non-interactive session,
with no input being collected from the input stream (i.e. input should
be 'null'). 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. */
void runShell(in nsIInputStream input, in nsIOutputStream output,
in string startupURI, in boolean interactive);
};
Running a serverMethod 1: Automatically on startupAs described above under 'Running it'Method 2: From codeA JSSh server is started with code like this:
var server = Components.classes["@mozilla.org/jssh-server;1"]
.createInstance()
.QueryInterface(Components.interfaces.nsIJSShServer);
server.startServerSocket(9997, "");
This code will create a server socket listening for connections on port 9997. When a client, such as e.g. telnet, establishes a connection, the JSSh server creates a new fully-trusted JavaScript context for the global JavaScript runtime and drops into a read-eval-print loop. Each connections runs in its own thread, and many clients can connect simultaneously. Since Mozilla is not fully threadsafe, however, execution of JavaScript commands is being proxied onto the main UI thread.
The nsIJSShServer::startServerSocket() method takes the URL of a startup script
as an optional argument. The JSSh module comes with one such startup script,
Method 3: From Tools Menu (probably broken)As an alternative to starting a server from code, the JSSh module can also be started from the Tools menu in the Mozilla browser:
Shell features
There are no security restrictions on the JavaScript context exposed to clients.
It contains the usual standard JS objects, such as
print(str) : Print str
dump(str) : *deprecated*, synonym for print()
exit() : Terminate shell
quit() : *deprecated*, synonym for exit()
load(url) : Execute the script at 'url'
suspend() : Suspend shell I/O until a call to resume().
Used in conjunction with resume() to provide
synchronization to asynchronous processes such
as e.g. document loads.
resume() : Resume from a suspend()
addressOf(obj) : Provide string uniquely identifying the given object.
This function can be used to generate keys for
associative arrays.
setProtocol(p) : One of 'interactive' (the default) or 'synchronous'.
'interactive': - shows prompt ("\n> ") to prompt for input
'synchronous': - shows prompt ("\n> ") to prompt for input
- all output is either a prompt or of the
form "[n]str", where n is the number of
characters in str.
getProtocol() : Returns currently used protocol, see setProtocol(p)
setContextObj(obj) : Change to a different JavaScript context.
Can be used for executing code in a different context.
Switching back to the original context has to be done
by installing suitable switching code on the new
context prior to switching.
jssh-debug.js startup scriptThe JSSh module comes with the startup scriptchrome://jssh/content/jssh-debug.js, which defines some
functions useful for debugging or interactively developing js code.
The following functions are available:
help(func) : Show help for one of the functions defined in
jssh-debug.js
inspect(obj) : Dumps information about 'obj'.
subobjs(obj, type) : List all subobjects of object 'obj' that have type
'type' (default='object')
dumpIDL(iid) : Dumps idl code for interface 'iid'. 'iid' can either
be an interface, or a string of form
'Components.interfaces.nsIFoo' or just 'nsIFoo'
getWindows() : Returns an array of all currently open windows.
findClass(/regex/) : Finds registered classes matching /regex/
findInterface(/regex/) : Finds registered interfaces matching /regex/
dumpStack(offset, max) : Displays a stack trace up to depth 'max' (default: 10),
starting 'offset' frames below the current one.
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:
'old': old method that will be called.
'before', 'after': before and after methods
The default before and after methods recognise the
flags (set by defining/unset by deleting):
'stack' : show stack trace
'nargs' : don't show args
'nresult' : don't show result/exception status
on exiting.
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
dumpInstrumented() : Prints a list of all currently instrumented functions.
uninstrument(obj, fun) : Uninstruments a previously instrumented function 'fun'
on object 'obj'. 'fun' and 'obj' both need to be given
as strings that eval() to the desired objects.
domNode(base, child1, child2, ...)
: Returns the dom node identified by base and the child
offsets. A child offset can be an integer designating
a 'normal' child or can be of the form "a5" to
identify the anonymous child at position 5.
domDumpFull(node) : Dumps the *complete* DOM starting from node.
rdfDump(url) : Dumps the rdf datasource at 'url' in the following
form:
<Resource>
|
|--[Resource]--> <Resource>
|
|--[Resource]--> {literal}
If 'url' points to a remote datasource, it will be
refreshed before dumping.
domDump(node) : Dumps the DOM around 'node'
reloadXBLDocument(url) : Flushes the xbl file 'url' from the chrome cache.
If defined, reloadXBLDocumentHook(url) is called
before flushing.
reloadXULDocument(url) : Flushes the xul file 'url' from the chrome cache.
If defined, reloadXULDocumentHook(url) is called
before flushing.
XEmacs as a clientAny telnet-like program can be used as an interactive JSSh client (The telnet shipping with MS Windows seems to have some CR/LF problems, though). XEmacs is particularly suited as a client and the JSSh distribution
contains an Emacs-Lisp file,
(setq load-path
(append '("path_to_moz-jssh.el")
load-path))
(require 'moz-jssh)
moz-jssh.el defines several different functions as well as a mode (moz-jssh mode)
for connecting to a JSSh server
and executing JavaScript code.
To simply create an interactive moz-jssh mode shell, run the command
The host and port of the JSSh server are configured by the variables
Some of the moz-jssh.el functions, such as e.g. Example sessionThis is an example session with XEmacs connecting to a JSSh server running in a Mozilla browser (Startup script chrome://jssh/content/jssh-debug.js):
Welcome to the Mozilla JavaScript Shell!
> 5+5
10
> help(getWindows)
getWindows() returns a list of all currently open windows
> var w0 = getWindows()[0]
> inspect(w0.getBrowser)
* Object type: function
* Parent chain: [object ChromeWindow @ 0x80e1328]
* Arity: 0
* Function definition:
function getBrowser() {
if (!gBrowser) {
gBrowser = document.getElementById("content");
}
return gBrowser;
}
> var browser = w0.getBrowser()
> domDump(browser)
* Parent: <hbox>
<tabbrowser id='content' flex='1' contenttooltip='aHTMLTooltip'
contentcontextmenu='contentAreaContextMenu' onnewtab='BrowserOpenTab();'
onbookmarkgroup='addGroupmarkAs();' onclick='return contentAreaClick(event);'>
* Anonymous Children:
A[0]: <xul:stringbundle>
A[1]: <xul:tabbox>
> domDump(domNode(browser, 'a1'))
* Parent: <tabbrowser>
<xul:tabbox flex='1' eventnode='document' inherits='handleCtrlPageUpDown'
handleCtrlTab='true'>
* Children:
[0]: <xul:hbox>
[1]: <xul:tabpanels>
> domDump(domNode(browser, 'a1', 1))
* Parent: <xul:tabbox>
<xul:tabpanels flex='1' class='plain' selectedIndex='0'>
* Children:
[0]: <xul:browser>
[1]: <browser>
> domDump(domNode(browser, 'a1', 1, 1))
* Parent: <xul:tabpanels>
<browser type='content' contextmenu='contentAreaContextMenu'
tooltip='aHTMLTooltip'>
> browser.loadURI("http://www.croczilla.com/svg/")
> domDumpFull(browser.contentDocument)
<HTML><HEAD>
[...]
</BODY></HTML>
> instrument("browser", "loadURI")
> dumpInstrumented()
browser.loadURI
> browser.loadURI("http://www.croczilla.com/svg/samples/")
* Entering browser.loadURI
* Arguments(1): 'http://www.croczilla.com/svg/samples/'
* Exiting browser.loadURI
* Result: undefined
> exit()
Goodbye!
Process moz-jssh<1> exited abnormally with code 256
|
| (c)2005-2009 alex fritze | |