From 39c808b9889858835f7543baf6df8c59c857064f Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Wed, 14 Jun 2000 04:57:49 +0000 Subject: [PATCH] Restore "javascript:\n"-in-location-brings-up-console compatibility (r=mccabe@netscape.com). git-svn-id: svn://10.0.0.236/trunk@72188 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/dom/src/jsurl/makefile.win | 1 + .../dom/src/jsurl/nsIEvaluateStringProxy.idl | 31 ++-- mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp | 172 +++++++++++++----- 3 files changed, 142 insertions(+), 62 deletions(-) diff --git a/mozilla/dom/src/jsurl/makefile.win b/mozilla/dom/src/jsurl/makefile.win index 65d718b3ba1..1fae09f070e 100644 --- a/mozilla/dom/src/jsurl/makefile.win +++ b/mozilla/dom/src/jsurl/makefile.win @@ -46,6 +46,7 @@ LCFLAGS = $(LCFLAGS) -DDEBUG_GC LLIBS= \ $(LIBNSPR) \ + $(DIST)\lib\js32$(VERSION_NUMBER).lib \ $(DIST)\lib\xpcom.lib \ $(NULL) diff --git a/mozilla/dom/src/jsurl/nsIEvaluateStringProxy.idl b/mozilla/dom/src/jsurl/nsIEvaluateStringProxy.idl index 6fceef71733..c7a81505280 100644 --- a/mozilla/dom/src/jsurl/nsIEvaluateStringProxy.idl +++ b/mozilla/dom/src/jsurl/nsIEvaluateStringProxy.idl @@ -17,28 +17,29 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): */ #include "nsISupports.idl" interface nsIChannel; -interface nsIURI; -interface nsIPrincipal; -interface nsIScriptContext; [uuid(67411da0-7c2e-11d3-8c67-00609792278c)] -interface nsIEvaluateStringProxy: nsISupports +interface nsIEvaluateStringProxy : nsISupports { - /** - * Channel of the javascript: url to evaluate: - */ - void init(in nsIChannel channel); + /** + * Channel of the javascript: url to evaluate: + */ + void init(in nsIChannel channel); - /** - * Cause the evaluation to happen: - */ - void evaluateString(out string aRetValue, - out boolean aIsUndefined); + /** + * Cause the evaluation to happen: + */ + void evaluateString(out string aRetValue, + out boolean aIsUndefined); + + /** + * Create or focus the JavaScript console. + */ + void bringUpConsole(); }; - diff --git a/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp b/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp index 7479f8bb0c1..64f802657d1 100644 --- a/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp +++ b/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp @@ -17,7 +17,7 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): * Pierre Phaneuf */ #include "nsCOMPtr.h" @@ -44,17 +44,23 @@ #include "nsIEvaluateStringProxy.h" #include "nsXPIDLString.h" #include "nsIByteArrayInputStream.h" +#include "nsIWindowMediator.h" +#include "nsIDOMWindow.h" static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID); static NS_DEFINE_CID(kJSProtocolHandlerCID, NS_JSPROTOCOLHANDLER_CID); +static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); + +static const char console_chrome_url[] = "chrome://global/content/console.xul"; +static const char console_window_options[] = "chrome,menubar,toolbar,resizable"; class nsJSThunk; -/***************************************************************************/ -/* nsEvaluateStringProxy */ -/* This private class will allow us to evaluate js on another thread */ -/***************************************************************************/ +//////////////////////////////////////////////////////////////////////////////// +// nsEvaluateStringProxy +// This private class will allow us to evaluate DOM JS on the main thread + class nsEvaluateStringProxy : public nsIEvaluateStringProxy { public: NS_DECL_ISUPPORTS @@ -63,10 +69,9 @@ public: nsEvaluateStringProxy(); virtual ~nsEvaluateStringProxy(); protected: - nsCOMPtr mChannel; + nsCOMPtr mChannel; }; - nsEvaluateStringProxy::nsEvaluateStringProxy() { NS_INIT_REFCNT(); @@ -93,13 +98,14 @@ nsEvaluateStringProxy::EvaluateString(char **aRetValue, PRBool *aIsUndefined) NS_ENSURE_ARG_POINTER(aIsUndefined); nsresult rv; - + + // Get an interface requestor from the channel callbacks. nsCOMPtr callbacks; rv = mChannel->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (NS_FAILED(rv)) return rv; NS_ENSURE_TRUE(callbacks, NS_ERROR_FAILURE); - // The event sink must be a script global Object Owner or we fail. + // The requestor must be able to get a script global object owner. nsCOMPtr globalOwner; callbacks->GetInterface(NS_GET_IID(nsIScriptGlobalObjectOwner), getter_AddRefs(globalOwner)); @@ -118,21 +124,20 @@ nsEvaluateStringProxy::EvaluateString(char **aRetValue, PRBool *aIsUndefined) nsCOMPtr owner; rv = mChannel->GetOwner(getter_AddRefs(owner)); nsCOMPtr principal; - if (owner) - { + if (owner) { principal = do_QueryInterface(owner, &rv); NS_ASSERTION(principal, "Channel's owner is not a principal"); if (!principal) return NS_ERROR_FAILURE; } - else // No owner from channel, use the current URI to generate a principal - { + else { + // No owner from channel, use the current URI to generate a principal nsCOMPtr uri; rv = mChannel->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv) || !uri) return NS_ERROR_FAILURE; NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_FAILED(rv)) return rv; - rv =securityManager->GetCodebasePrincipal(uri, getter_AddRefs(principal)); + rv = securityManager->GetCodebasePrincipal(uri, getter_AddRefs(principal)); if (NS_FAILED(rv) || !principal) return NS_ERROR_FAILURE; } @@ -148,22 +153,84 @@ nsEvaluateStringProxy::EvaluateString(char **aRetValue, PRBool *aIsUndefined) nsString result; { - nsAutoString scriptString; - scriptString.AssignWithConversion(script); - rv = scriptContext->EvaluateString(scriptString, - nsnull, // obj - principal, - nsnull, // url - 0, // line no - nsnull, - result, - aIsUndefined); + nsAutoString scriptString; + scriptString.AssignWithConversion(script); + rv = scriptContext->EvaluateString(scriptString, + nsnull, // obj + principal, + nsnull, // url + 0, // line no + nsnull, + result, + aIsUndefined); } + // XXXbe this should not decimate! pass back UCS-2 to necko *aRetValue = result.ToNewCString(); return rv; } +// Gasp. This is so much easier to write in JS.... +NS_IMETHODIMP +nsEvaluateStringProxy::BringUpConsole() +{ + nsresult rv; + + // First, get the Window Mediator service. + NS_WITH_SERVICE(nsIWindowMediator, windowMediator, kWindowMediatorCID, &rv); + if (NS_FAILED(rv)) return rv; + + // Next, find out whether there's a console already open. + nsCOMPtr console; + nsAutoString windowType = NS_LITERAL_STRING("global:console"); + rv = windowMediator->GetMostRecentWindow(windowType.GetUnicode(), + getter_AddRefs(console)); + if (NS_FAILED(rv)) return rv; + + if (console) { + // If the console is already open, bring it to the top. + rv = console->Focus(); + } else { + // Get an interface requestor from the channel callbacks. + nsCOMPtr callbacks; + rv = mChannel->GetNotificationCallbacks(getter_AddRefs(callbacks)); + if (NS_FAILED(rv)) return rv; + NS_ENSURE_TRUE(callbacks, NS_ERROR_FAILURE); + + // The requestor must be able to get a script global object owner. + nsCOMPtr globalOwner; + callbacks->GetInterface(NS_GET_IID(nsIScriptGlobalObjectOwner), + getter_AddRefs(globalOwner)); + NS_ENSURE_TRUE(globalOwner, NS_ERROR_FAILURE); + + // So far so good: get the script global and its context. + nsCOMPtr global; + globalOwner->GetScriptGlobalObject(getter_AddRefs(global)); + NS_ENSURE_TRUE(global, NS_ERROR_FAILURE); + + nsCOMPtr scriptContext; + rv = global->GetContext(getter_AddRefs(scriptContext)); + if (NS_FAILED(rv)) return rv; + + // Finally, QI global to nsIDOMWindow and open the console. + nsCOMPtr window = do_QueryInterface(global, &rv); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + + JSContext *cx = (JSContext*) scriptContext->GetNativeContext(); + void *mark; + jsval *argv = JS_PushArguments(cx, &mark, "sss", + console_chrome_url, + "_blank", + console_window_options); + if (!argv) return NS_ERROR_OUT_OF_MEMORY; + + rv = window->Open(cx, argv, 3, getter_AddRefs(console)); + + JS_PopArguments(cx, mark); + } + return rv; +} + //////////////////////////////////////////////////////////////////////////////// class nsJSThunk : public nsIStreamIO @@ -172,7 +239,7 @@ public: NS_DECL_ISUPPORTS nsJSThunk() - : mChannel(nsnull), mResult(nsnull), mLength(0), mReadCursor(0) { + : mChannel(nsnull), mResult(nsnull), mLength(0), mReadCursor(0) { NS_INIT_REFCNT(); } @@ -189,14 +256,16 @@ public: } NS_IMETHOD Open(char* *contentType, PRInt32 *contentLength) { - // IMPORTANT CHANGE: We used to just implement nsIInputStream and use an - // input stream channel in the js protocol, but that had the nasty side effect - // of doing the evaluation after the window content was already torn down (in - // the webshell's OnStartRequest callback). By using an nsIStreamIO instead, - // we now get more control over when the evaluation occurs. By evaluating in the - // Open method, we can can get the status of the channel in the OnStartRequest - // callback and detect NS_ERROR_DOM_RETVAL_UNDEFINED, thereby avoiding tearing - // down the current document. + // IMPORTANT CHANGE: We used to just implement nsIInputStream and use + // an input stream channel in the js protocol, but that had the nasty + // side effect of doing the evaluation after the window content was + // already torn down (in the webshell's OnStartRequest callback). + // + // By using an nsIStreamIO instead, we now get more control over when + // the evaluation occurs. By evaluating in the Open method, we can + // get the status of the channel in the OnStartRequest callback and + // detect NS_ERROR_DOM_RETVAL_UNDEFINED, thereby avoiding tear-down of + // the current document. nsresult rv; @@ -205,10 +274,9 @@ public: nsIProxyObjectManager::GetCID(), &rv); if (NS_FAILED(rv)) return rv; - nsEvaluateStringProxy* eval = new nsEvaluateStringProxy(); - if (eval == nsnull) + nsCOMPtr eval = new nsEvaluateStringProxy(); + if (!eval) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(eval); rv = eval->Init(mChannel); if (NS_FAILED(rv)) return rv; @@ -219,31 +287,40 @@ public: PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(evalProxy)); - if (NS_FAILED(rv)) { - NS_RELEASE(eval); - return rv; + if (NS_FAILED(rv)) return rv; + + // If mURI is just "javascript:", we bring up the JavaScript console + // and return NS_ERROR_DOM_RETVAL_UNDEFINED. + nsXPIDLCString spec; + rv = mURI->GetSpec(getter_Copies(spec)); + if (NS_FAILED(rv)) return rv; + + if (PL_strcasecmp(spec, "javascript:") == 0) { + rv = evalProxy->BringUpConsole(); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + return NS_ERROR_DOM_RETVAL_UNDEFINED; } char* retString; PRBool isUndefined; rv = evalProxy->EvaluateString(&retString, &isUndefined); - NS_RELEASE(eval); - if (NS_FAILED(rv)) { rv = NS_ERROR_MALFORMED_URI; return rv; } if (isUndefined) { - if (retString) + if (retString) Recycle(retString); rv = NS_ERROR_DOM_RETVAL_UNDEFINED; return rv; } #if 0 - else { - // This is from the old code which need to be hack on a bit more: + { + // This is from the old code which need to be hack on a bit more. + // XXXbe maybe we should just drop this, and take the compatibility + // hit here -- does anyone care? // plaintext is apparently busted if (ret[0] != PRUnichar('<')) @@ -408,8 +485,9 @@ nsJSProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result) nsCOMPtr channel; rv = NS_NewStreamIOChannel(getter_AddRefs(channel), uri, thunk); - // If the resultant script evaluation actually does return a - // value, we treat it as html. + + // If the resultant script evaluation actually does return a value, we + // treat it as html. XXXbe see comment above if (NS_SUCCEEDED(rv)) { rv = channel->SetContentType("text/html"); } @@ -427,7 +505,7 @@ nsJSProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result) //////////////////////////////////////////////////////////////////////////////// static nsModuleComponentInfo gJSModuleInfo[] = { - { "JavaScript Protocol Handler", + { "JavaScript Protocol Handler", NS_JSPROTOCOLHANDLER_CID, NS_NETWORK_PROTOCOL_PROGID_PREFIX "javascript", nsJSProtocolHandler::Create }