зеркало из https://github.com/mozilla/pjs.git
615 строки
18 KiB
JavaScript
615 строки
18 KiB
JavaScript
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* ***** 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 JavaScript Debugger.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Robert Ginda, <rginda@netscape.com>, original author
|
|
*
|
|
* 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 ***** */
|
|
|
|
/* components defined in this file */
|
|
const CLINE_SERVICE_CTRID =
|
|
"@mozilla.org/commandlinehandler/general-startup;1?type=venkman";
|
|
const CLINE_SERVICE_CID =
|
|
Components.ID("{18269616-1dd2-11b2-afa8-b612439bda27}");
|
|
const JSDPROT_HANDLER_CTRID =
|
|
"@mozilla.org/network/protocol;1?name=x-jsd";
|
|
const JSDPROT_HANDLER_CID =
|
|
Components.ID("{12ec790d-304e-4525-89a9-3e723d489d14}");
|
|
const JSDCNT_HANDLER_CTRID =
|
|
"@mozilla.org/uriloader/content-handler;1?type=x-application-jsd";
|
|
const JSDCNT_HANDLER_CID =
|
|
Components.ID("{306670f0-47bb-466b-b53b-613235623bbd}");
|
|
|
|
/* components used by this file */
|
|
const CATMAN_CTRID = "@mozilla.org/categorymanager;1";
|
|
const STRING_STREAM_CTRID = "@mozilla.org/io/string-input-stream;1";
|
|
const MEDIATOR_CTRID =
|
|
"@mozilla.org/appshell/window-mediator;1";
|
|
const ASS_CONTRACTID =
|
|
"@mozilla.org/appshell/appShellService;1";
|
|
const SIMPLEURI_CTRID = "@mozilla.org/network/simple-uri;1";
|
|
|
|
const nsIWindowMediator = Components.interfaces.nsIWindowMediator;
|
|
const nsIAppShellService = Components.interfaces.nsIAppShellService;
|
|
const nsICmdLineHandler = Components.interfaces.nsICmdLineHandler;
|
|
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
|
|
const nsICategoryManager = Components.interfaces.nsICategoryManager;
|
|
const nsIContentHandler = Components.interfaces.nsIContentHandler;
|
|
const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
|
|
const nsIURI = Components.interfaces.nsIURI;
|
|
const nsIURL = Components.interfaces.nsIURL;
|
|
const nsIStringInputStream = Components.interfaces.nsIStringInputStream;
|
|
const nsIChannel = Components.interfaces.nsIChannel;
|
|
const nsIRequest = Components.interfaces.nsIRequest;
|
|
const nsIProgressEventSink = Components.interfaces.nsIProgressEventSink;
|
|
const nsISupports = Components.interfaces.nsISupports;
|
|
const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
|
|
const nsICommandLine = Components.interfaces.nsICommandLine;
|
|
|
|
function findDebuggerWindow ()
|
|
{
|
|
var windowManager =
|
|
Components.classes[MEDIATOR_CTRID].getService(nsIWindowMediator);
|
|
return windowManager.getMostRecentWindow("mozapp:venkman");
|
|
}
|
|
|
|
function openDebuggerWindow(args)
|
|
{
|
|
var ass = Components.classes[ASS_CONTRACTID].getService(nsIAppShellService);
|
|
var window = ass.hiddenDOMWindow;
|
|
window.openDialog("chrome://venkman/content/venkman.xul", "_blank",
|
|
"chrome,menubar,toolbar,resizable,dialog=no", args);
|
|
}
|
|
|
|
function safeHTML(str)
|
|
{
|
|
function replaceChars(ch)
|
|
{
|
|
switch (ch)
|
|
{
|
|
case "<":
|
|
return "<";
|
|
|
|
case ">":
|
|
return ">";
|
|
|
|
case "&":
|
|
return "&";
|
|
|
|
case "'":
|
|
return "'";
|
|
|
|
case '"':
|
|
return """;
|
|
}
|
|
|
|
return "?";
|
|
};
|
|
|
|
return String(str).replace(/[<>&"']/g, replaceChars);
|
|
}
|
|
|
|
/* Command Line handler service */
|
|
function CLineService()
|
|
{}
|
|
|
|
/* nsISupports */
|
|
CLineService.prototype.QueryInterface =
|
|
function handler_QI(iid)
|
|
{
|
|
if (iid.equals(nsISupports) ||
|
|
(nsICommandLineHandler && iid.equals(nsICommandLineHandler)) ||
|
|
(nsICmdLineHandler && iid.equals(nsICmdLineHandler)))
|
|
{
|
|
return this;
|
|
}
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
}
|
|
|
|
/* nsICmdLineHandler */
|
|
CLineService.prototype.commandLineArgument = "-venkman";
|
|
CLineService.prototype.prefNameForStartup = "general.startup.venkman";
|
|
CLineService.prototype.chromeUrlForTask = "chrome://venkman/content";
|
|
CLineService.prototype.helpText = "Start with JavaScript Debugger (Venkman).";
|
|
CLineService.prototype.handlesArgs = false;
|
|
CLineService.prototype.defaultArgs = "";
|
|
CLineService.prototype.openWindowWithArgs = false;
|
|
|
|
/* nsICommandLineHandler */
|
|
|
|
CLineService.prototype.handle =
|
|
function handler_handle(cmdLine)
|
|
{
|
|
try
|
|
{
|
|
if (cmdLine.handleFlag("venkman", false))
|
|
openDebuggerWindow(null);
|
|
}
|
|
catch (e)
|
|
{
|
|
debug(e);
|
|
}
|
|
}
|
|
|
|
CLineService.prototype.helpInfo =
|
|
" -venkman Start with JavaScript debugger (Venkman).\n"
|
|
|
|
/* factory for command line handler service (CLineService) */
|
|
var CLineFactory = new Object();
|
|
|
|
CLineFactory.createInstance =
|
|
function clf_create (outer, iid) {
|
|
if (outer != null)
|
|
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
|
|
|
return new CLineService().QueryInterface(iid);
|
|
}
|
|
|
|
/* x-jsd: protocol handler */
|
|
|
|
const JSD_DEFAULT_PORT = 2206; /* Dana's apartment number. */
|
|
|
|
/* protocol handler factory object */
|
|
var JSDProtocolHandlerFactory = new Object();
|
|
|
|
JSDProtocolHandlerFactory.createInstance =
|
|
function jsdhf_create (outer, iid) {
|
|
if (outer != null)
|
|
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
|
|
|
if (!iid.equals(nsIProtocolHandler) && !iid.equals(nsISupports))
|
|
throw Components.results.NS_ERROR_INVALID_ARG;
|
|
|
|
return new JSDProtocolHandler();
|
|
}
|
|
|
|
function JSDURI (spec, charset)
|
|
{
|
|
this.spec = this.prePath = spec;
|
|
this.charset = this.originCharset = charset;
|
|
}
|
|
|
|
JSDURI.prototype.QueryInterface =
|
|
function jsdch_qi (iid)
|
|
{
|
|
if (!iid.equals(nsIURI) && !iid.equals(nsIURL) &&
|
|
!iid.equals(nsISupports))
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
return this;
|
|
}
|
|
|
|
JSDURI.prototype.scheme = "x-jsd";
|
|
|
|
JSDURI.prototype.fileBaseName =
|
|
JSDURI.prototype.fileExtension =
|
|
JSDURI.prototype.filePath =
|
|
JSDURI.prototype.param =
|
|
JSDURI.prototype.query =
|
|
JSDURI.prototype.ref =
|
|
JSDURI.prototype.directory =
|
|
JSDURI.prototype.fileName =
|
|
JSDURI.prototype.username =
|
|
JSDURI.prototype.password =
|
|
JSDURI.prototype.hostPort =
|
|
JSDURI.prototype.path =
|
|
JSDURI.prototype.asciiHost =
|
|
JSDURI.prototype.userPass = "";
|
|
|
|
JSDURI.prototype.port = JSD_DEFAULT_PORT;
|
|
|
|
JSDURI.prototype.schemeIs =
|
|
function jsduri_schemeis (scheme)
|
|
{
|
|
return scheme.toLowerCase() == "x-jsd";
|
|
}
|
|
|
|
JSDURI.prototype.getCommonBaseSpec =
|
|
function jsduri_commonbase (uri)
|
|
{
|
|
return "x-jsd:";
|
|
}
|
|
|
|
JSDURI.prototype.getRelativeSpec =
|
|
function jsduri_commonbase (uri)
|
|
{
|
|
return uri;
|
|
}
|
|
|
|
JSDURI.prototype.equals =
|
|
function jsduri_equals (uri)
|
|
{
|
|
return uri.spec == this.spec;
|
|
}
|
|
|
|
JSDURI.prototype.clone =
|
|
function jsduri_clone ()
|
|
{
|
|
return new JSDURI (this.spec);
|
|
}
|
|
|
|
JSDURI.prototype.resolve =
|
|
function jsduri_resolve(path)
|
|
{
|
|
//dump ("resolve " + path + " from " + this.spec + "\n");
|
|
if (path[0] == "#")
|
|
return this.spec + path;
|
|
|
|
return path;
|
|
}
|
|
|
|
function JSDProtocolHandler()
|
|
{
|
|
/* nothing here */
|
|
}
|
|
|
|
JSDProtocolHandler.prototype.scheme = "x-jsd";
|
|
JSDProtocolHandler.prototype.defaultPort = JSD_DEFAULT_PORT;
|
|
JSDProtocolHandler.prototype.protocolFlags = nsIProtocolHandler.URI_NORELATIVE ||
|
|
nsIProtocolHandler.URI_NOAUTH;
|
|
|
|
JSDProtocolHandler.prototype.allowPort =
|
|
function jsdph_allowport (aPort, aScheme)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
JSDProtocolHandler.prototype.newURI =
|
|
function jsdph_newuri (spec, charset, baseURI)
|
|
{
|
|
var clazz = Components.classes[SIMPLEURI_CTRID];
|
|
var uri = clazz.createInstance(nsIURI);
|
|
uri.spec = spec;
|
|
return uri;
|
|
}
|
|
|
|
JSDProtocolHandler.prototype.newChannel =
|
|
function jsdph_newchannel (uri)
|
|
{
|
|
return new JSDChannel (uri);
|
|
}
|
|
|
|
function JSDChannel (uri)
|
|
{
|
|
this.URI = uri;
|
|
this.originalURI = uri;
|
|
this._isPending = false;
|
|
var clazz = Components.classes[STRING_STREAM_CTRID];
|
|
this.stringStream = clazz.createInstance(nsIStringInputStream);
|
|
}
|
|
|
|
JSDChannel.prototype.QueryInterface =
|
|
function jsdch_qi (iid)
|
|
{
|
|
|
|
if (!iid.equals(nsIChannel) && !iid.equals(nsIRequest) &&
|
|
!iid.equals(nsISupports))
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
return this;
|
|
}
|
|
|
|
/* nsIChannel */
|
|
JSDChannel.prototype.loadAttributes = null;
|
|
JSDChannel.prototype.contentType = "text/html";
|
|
JSDChannel.prototype.contentLength = -1;
|
|
JSDChannel.prototype.owner = null;
|
|
JSDChannel.prototype.loadGroup = null;
|
|
JSDChannel.prototype.notificationCallbacks = null;
|
|
JSDChannel.prototype.securityInfo = null;
|
|
|
|
JSDChannel.prototype.open =
|
|
function jsdch_open()
|
|
{
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
JSDChannel.prototype.asyncOpen =
|
|
function jsdch_aopen (streamListener, context)
|
|
{
|
|
this.streamListener = streamListener;
|
|
this.context = context;
|
|
this._isPending = true;
|
|
|
|
if (!window && this.URI.spec == "x-jsd:debugger")
|
|
{
|
|
this.contentType = "x-application-jsd";
|
|
this.contentLength = 0;
|
|
streamListener.onStartRequest(this, context);
|
|
return;
|
|
}
|
|
|
|
var window = findDebuggerWindow();
|
|
var ary = this.URI.spec.match (/x-jsd:([^:]+)/);
|
|
var exception;
|
|
|
|
if (this.loadGroup)
|
|
this.loadGroup.addRequest (this, null);
|
|
|
|
if (window && "console" in window && ary)
|
|
{
|
|
try
|
|
{
|
|
window.asyncOpenJSDURL (this, streamListener, context);
|
|
return;
|
|
}
|
|
catch (ex)
|
|
{
|
|
exception = ex;
|
|
}
|
|
}
|
|
|
|
var str =
|
|
"<html><head><title>Error</title></head><body>Could not load <<b>" +
|
|
safeHTML(this.URI.spec) + "</b>><br>";
|
|
|
|
if (!ary)
|
|
{
|
|
str += "<b>Error parsing uri.</b>";
|
|
}
|
|
else if (exception)
|
|
{
|
|
str += "<b>Internal error: " + safeHTML(exception) + "</b><br><pre>" +
|
|
safeHTML(exception.stack);
|
|
}
|
|
else
|
|
{
|
|
str += "<b>Debugger is not running.</b>";
|
|
}
|
|
|
|
str += "</body></html>";
|
|
|
|
this.respond (str);
|
|
}
|
|
|
|
JSDChannel.prototype.respond =
|
|
function jsdch_respond (str)
|
|
{
|
|
this.streamListener.onStartRequest (this, this.context);
|
|
|
|
var len = str.length;
|
|
this.stringStream.setData (str, len);
|
|
this.streamListener.onDataAvailable (this, this.context,
|
|
this.stringStream, 0, len);
|
|
this.streamListener.onStopRequest (this, this.context,
|
|
Components.results.NS_OK);
|
|
if (this.loadGroup)
|
|
this.loadGroup.removeRequest (this, null, Components.results.NS_OK);
|
|
this._isPending = false;
|
|
}
|
|
|
|
/* nsIRequest */
|
|
JSDChannel.prototype.isPending =
|
|
function jsdch_ispending ()
|
|
{
|
|
return this._isPending;
|
|
}
|
|
|
|
JSDChannel.prototype.status = Components.results.NS_OK;
|
|
|
|
JSDChannel.prototype.cancel =
|
|
function jsdch_cancel (status)
|
|
{
|
|
if (this._isPending)
|
|
{
|
|
this._isPending = false;
|
|
this.streamListener.onStopRequest (this, this.context, status);
|
|
if (this.loadGroup)
|
|
{
|
|
try
|
|
{
|
|
this.loadGroup.removeRequest (this, null, status);
|
|
}
|
|
catch (ex)
|
|
{
|
|
debug ("we're not in the load group?\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
this.status = status;
|
|
}
|
|
|
|
JSDChannel.prototype.suspend =
|
|
JSDChannel.prototype.resume =
|
|
function jsdch_notimpl ()
|
|
{
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* x-application-jsd content handler */
|
|
function JSDContentHandler ()
|
|
{}
|
|
|
|
JSDContentHandler.prototype.QueryInterface =
|
|
function jsdh_qi(iid)
|
|
{
|
|
if (!iid.equals(nsIContentHandler) && !iid.equals(nsISupports))
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
return this;
|
|
}
|
|
|
|
JSDContentHandler.prototype.handleContent =
|
|
function jsdh_handle(contentType, windowTarget, request)
|
|
{
|
|
var e;
|
|
var channel = request.QueryInterface(nsIChannel);
|
|
|
|
// prevent someone from invoking the debugger remotely by serving
|
|
// up any old file with the x-application-jsd content type.
|
|
if (channel.URI.spec != "x-jsd:debugger")
|
|
{
|
|
debug ("Not handling content from unknown location ``" +
|
|
channel.URI.spec + "''");
|
|
return;
|
|
}
|
|
|
|
var window = findDebuggerWindow()
|
|
|
|
if (window)
|
|
{
|
|
window.focus();
|
|
}
|
|
else
|
|
{
|
|
var ass =
|
|
Components.classes[ASS_CONTRACTID].getService(nsIAppShellService);
|
|
window = ass.hiddenDOMWindow;
|
|
|
|
var args = new Object();
|
|
args.url = channel.URI.spec;
|
|
|
|
openDebuggerWindow(args);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* content handler factory object (IRCContentHandler) */
|
|
var JSDContentHandlerFactory = new Object();
|
|
|
|
JSDContentHandlerFactory.createInstance =
|
|
function jsdhf_create(outer, iid)
|
|
{
|
|
if (outer != null)
|
|
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
|
|
|
if (!iid.equals(nsIContentHandler) && !iid.equals(nsISupports))
|
|
throw Components.results.NS_ERROR_INVALID_ARG;
|
|
|
|
return new JSDContentHandler();
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
var Module = new Object();
|
|
|
|
Module.registerSelf =
|
|
function (compMgr, fileSpec, location, type)
|
|
{
|
|
debug("*** Registering -venkman handler.\n");
|
|
|
|
compMgr = compMgr.QueryInterface(nsIComponentRegistrar);
|
|
|
|
compMgr.registerFactoryLocation(CLINE_SERVICE_CID,
|
|
"Venkman CommandLine Service",
|
|
CLINE_SERVICE_CTRID,
|
|
fileSpec,
|
|
location,
|
|
type);
|
|
|
|
catman = Components.classes[CATMAN_CTRID].getService(nsICategoryManager);
|
|
catman.addCategoryEntry("command-line-argument-handlers",
|
|
"venkman command line handler",
|
|
CLINE_SERVICE_CTRID, true, true);
|
|
|
|
catman.addCategoryEntry("command-line-handler",
|
|
"venkman command line handler",
|
|
CLINE_SERVICE_CTRID, true, true);
|
|
|
|
debug("*** Registering x-jsd protocol handler.\n");
|
|
compMgr.registerFactoryLocation(JSDPROT_HANDLER_CID,
|
|
"x-jsd protocol handler",
|
|
JSDPROT_HANDLER_CTRID,
|
|
fileSpec,
|
|
location,
|
|
type);
|
|
|
|
debug("*** Registering x-application-jsd content handler.\n");
|
|
compMgr.registerFactoryLocation(JSDCNT_HANDLER_CID,
|
|
"x-application-jsd content handler",
|
|
JSDCNT_HANDLER_CTRID,
|
|
fileSpec,
|
|
location,
|
|
type);
|
|
try
|
|
{
|
|
const JSD_CTRID = "@mozilla.org/js/jsd/debugger-service;1";
|
|
const jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
|
|
var jsds = Components.classes[JSD_CTRID].getService(jsdIDebuggerService);
|
|
jsds.initAtStartup = true;
|
|
}
|
|
catch (ex)
|
|
{
|
|
debug ("*** ERROR initializing debugger service");
|
|
debug (ex);
|
|
}
|
|
}
|
|
|
|
Module.unregisterSelf =
|
|
function(compMgr, fileSpec, location)
|
|
{
|
|
compMgr = compMgr.QueryInterface(nsIComponentRegistrar);
|
|
|
|
compMgr.unregisterFactoryLocation(CLINE_SERVICE_CID, fileSpec);
|
|
catman = Components.classes[CATMAN_CTRID].getService(nsICategoryManager);
|
|
catman.deleteCategoryEntry("command-line-argument-handlers",
|
|
CLINE_SERVICE_CTRID, true);
|
|
catman.deleteCategoryEntry("command-line-handler",
|
|
CLINE_SERVICE_CTRID, true);
|
|
}
|
|
|
|
Module.getClassObject =
|
|
function (compMgr, cid, iid) {
|
|
if (cid.equals(CLINE_SERVICE_CID))
|
|
return CLineFactory;
|
|
|
|
if (cid.equals(JSDPROT_HANDLER_CID))
|
|
return JSDProtocolHandlerFactory;
|
|
|
|
if (cid.equals(JSDCNT_HANDLER_CID))
|
|
return JSDContentHandlerFactory;
|
|
|
|
if (!iid.equals(Components.interfaces.nsIFactory))
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
Module.canUnload =
|
|
function(compMgr)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/* entrypoint */
|
|
function NSGetModule(compMgr, fileSpec) {
|
|
return Module;
|
|
}
|