1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3
* ***** BEGIN LICENSE BLOCK *****
4
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 1.1 (the "License"); you may not use this file except in compliance with
8
* the License. You may obtain a copy of the License at
9
* http://www.mozilla.org/MPL/
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
16
* The Original Code is Mozilla Communicator client code, released
19
* The Initial Developer of the Original Code is
20
* Netscape Communications Corporation.
21
* Portions created by the Initial Developer are Copyright (C) 1998
22
* the Initial Developer. All Rights Reserved.
25
* Robert Ginda <rginda@netscape.com>
27
* Alternatively, the contents of this file may be used under the terms of
28
* either of the GNU General Public License Version 2 or later (the "GPL"),
29
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
* in which case the provisions of the GPL or the LGPL are applicable instead
31
* of those above. If you wish to allow use of your version of this file only
32
* under the terms of either the GPL or the LGPL, and not to allow others to
33
* use your version of this file under the terms of the MPL, indicate your
34
* decision by deleting the provisions above and replace them with the notice
35
* and other provisions required by the GPL or the LGPL. If you do not delete
36
* the provisions above, a recipient may use your version of this file under
37
* the terms of any one of the MPL, the GPL or the LGPL.
39
* ***** END LICENSE BLOCK ***** */
41
#if !defined(XPCONNECT_STANDALONE) && !defined(NO_SUBSCRIPT_LOADER)
43
#include "mozJSSubScriptLoader.h"
45
#include "nsIServiceManager.h"
46
#include "nsIXPConnect.h"
49
#include "nsIIOService.h"
50
#include "nsIChannel.h"
51
#include "nsIInputStream.h"
53
#include "nsDependentString.h"
57
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
59
/* load() error msgs, XXX localize? */
60
#define LOAD_ERROR_NOSERVICE "Error creating IO Service."
61
#define LOAD_ERROR_NOCHANNEL "Error creating channel (invalid URL scheme?)"
62
#define LOAD_ERROR_NOSTREAM "Error opening input stream (invalid filename?)"
63
#define LOAD_ERROR_NOCONTENT "ContentLength not available (not a local URL?)"
64
#define LOAD_ERROR_BADREAD "File Read Error."
65
#define LOAD_ERROR_READUNDERFLOW "File Read Error (underflow.)"
67
/* turn ALL JS Runtime errors into exceptions */
68
JS_STATIC_DLL_CALLBACK(void)
69
ExceptionalErrorReporter (JSContext *cx, const char *message,
70
JSErrorReport *report)
76
if (report && JSREPORT_IS_EXCEPTION (report->flags))
77
/* if it's already an exception, our job is done. */
80
ex = JS_NewObject (cx, nsnull, nsnull, nsnull);
81
/* create a jsobject to throw */
85
/* decorate the exception */
88
jstr = JS_NewStringCopyZ (cx, message);
91
ok = JS_DefineProperty (cx, ex, "message", STRING_TO_JSVAL(jstr),
92
nsnull, nsnull, JSPROP_ENUMERATE);
99
jstr = JS_NewStringCopyZ (cx, report->filename);
102
ok = JS_DefineProperty (cx, ex, "fileName", STRING_TO_JSVAL(jstr),
103
nsnull, nsnull, JSPROP_ENUMERATE);
107
ok = JS_DefineProperty (cx, ex, "lineNumber",
108
INT_TO_JSVAL(NS_STATIC_CAST(uintN,
110
nsnull, nsnull, JSPROP_ENUMERATE);
115
JS_SetPendingException (cx, OBJECT_TO_JSVAL(ex));
122
"mozJSSubScriptLoader: Error occurred while reporting error :/\n")
127
mozJSSubScriptLoader::mozJSSubScriptLoader() : mSystemPrincipal(nsnull)
131
mozJSSubScriptLoader::~mozJSSubScriptLoader()
136
NS_IMPL_THREADSAFE_ISUPPORTS1(mozJSSubScriptLoader, mozIJSSubScriptLoader)
138
NS_IMETHODIMP /* args and return value are delt with using XPConnect and JSAPI */
139
mozJSSubScriptLoader::LoadSubScript (const PRUnichar * /*url*/
140
/* [, JSObject *target_obj] */)
143
* Loads a local url and evals it into the current cx
144
* Synchronous (an async version would be cool too.)
145
* url: The url to load. Must be local so that it can be loaded
147
* target_obj: Optional object to eval the script onto (defaults to context
149
* returns: Whatever jsval the script pointed to by the url returns.
150
* Should ONLY (O N L Y !) be called from JavaScript code.
153
/* gotta define most of this stuff up here because of all the gotos,
154
* defined the rest up here to be consistent */
158
/* get JS things from the CallContext */
159
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
160
if (!xpc) return NS_ERROR_FAILURE;
162
nsCOMPtr<nsIXPCNativeCallContext> cc;
163
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
164
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
167
rv = cc->GetJSContext (&cx);
168
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
171
rv = cc->GetArgc (&argc);
172
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
175
rv = cc->GetArgvPtr (&argv);
176
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
179
rv = cc->GetRetValPtr (&rval);
180
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
182
/* set mJSPrincipals if it's not here already */
183
if (!mSystemPrincipal)
185
nsCOMPtr<nsIScriptSecurityManager> secman =
186
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
190
rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal));
191
if (NS_FAILED(rv) || !mSystemPrincipal)
197
JSObject *target_obj = nsnull;
198
ok = JS_ConvertArguments (cx, argc, argv, "s / o", &url, &target_obj);
201
cc->SetExceptionWasThrown (JS_TRUE);
202
/* let the exception raised by JS_ConvertArguments show through */
208
/* if the user didn't provide an object to eval onto, find the global
209
* object by walking the parent chain of the calling object */
212
JSObject *got_glob = JS_GetGlobalObject (cx);
213
fprintf (stderr, "JS_GetGlobalObject says glob is %p.\n", got_glob);
214
target_obj = JS_GetPrototype (cx, got_glob);
215
fprintf (stderr, "That glob's prototype is %p.\n", target_obj);
216
target_obj = JS_GetParent (cx, got_glob);
217
fprintf (stderr, "That glob's parent is %p.\n", target_obj);
220
nsCOMPtr<nsIXPConnectWrappedNative> wn;
221
rv = cc->GetCalleeWrapper (getter_AddRefs(wn));
222
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
224
rv = wn->GetJSObject (&target_obj);
225
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
228
fprintf (stderr, "Parent chain: %p", target_obj);
230
JSObject *maybe_glob = JS_GetParent (cx, target_obj);
231
while (maybe_glob != nsnull)
234
fprintf (stderr, ", %p", maybe_glob);
236
target_obj = maybe_glob;
237
maybe_glob = JS_GetParent (cx, maybe_glob);
240
fprintf (stderr, "\n");
245
/* load up the url. From here on, failures are reflected as ``custom''
253
JSPrincipals *jsPrincipals;
255
nsCOMPtr<nsIChannel> chan;
256
nsCOMPtr<nsIInputStream> instream;
258
nsCOMPtr<nsIIOService> serv = do_GetService(kIOServiceCID);
261
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOSERVICE);
262
goto return_exception;
265
rv = serv->NewChannel(nsDependentCString(url), nsnull, NS_STATIC_CAST(nsIURI *, nsnull),
266
getter_AddRefs(chan));
269
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOCHANNEL);
270
goto return_exception;
273
rv = chan->Open (getter_AddRefs(instream));
276
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOSTREAM);
277
goto return_exception;
280
rv = chan->GetContentLength (&len);
281
if (NS_FAILED(rv) || len == -1)
283
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOCONTENT);
284
goto return_exception;
287
buf = new char[len + 1];
289
return NS_ERROR_OUT_OF_MEMORY;
291
rv = instream->Read (buf, len, &readcount);
294
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_BADREAD);
295
goto return_exception;
298
if (NS_STATIC_CAST(PRUint32, len) != readcount)
300
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_READUNDERFLOW);
301
goto return_exception;
304
/* we can't hold onto jsPrincipals as a module var because the
305
* JSPRINCIPALS_DROP macro takes a JSContext, which we won't have in the
307
rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals);
308
if (NS_FAILED(rv) || !jsPrincipals) {
313
/* set our own error reporter so we can report any bad things as catchable
314
* exceptions, including the source/line number */
315
er = JS_SetErrorReporter (cx, ExceptionalErrorReporter);
317
ok = JS_EvaluateScriptForPrincipals (cx, target_obj, jsPrincipals,
318
buf, len, url, 1, rval);
319
/* repent for our evil deeds */
320
JS_SetErrorReporter (cx, er);
322
cc->SetExceptionWasThrown (!ok);
323
cc->SetReturnValueWasSet (ok);
326
JSPRINCIPALS_DROP(cx, jsPrincipals);
333
JS_SetPendingException (cx, STRING_TO_JSVAL(errmsg));
334
cc->SetExceptionWasThrown (JS_TRUE);
339
#endif /* NO_SUBSCRIPT_LOADER */