1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=2 sw=2 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is mozilla.org code.
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.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK *****
41 * This Original Code has been modified by IBM Corporation.
42 * Modifications made by IBM described herein are
43 * Copyright (c) International Business Machines
46 * Modifications to Mozilla code or documentation
47 * identified per MPL Section 3.3
49 * Date Modified by Description of modification
50 * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
54 #include "nsDOMScriptObjectFactory.h"
55 #include "xpcexception.h"
56 #include "nsScriptNameSpaceManager.h"
57 #include "nsIObserverService.h"
58 #include "nsJSEnvironment.h"
59 #include "nsJSEventListener.h"
60 #include "nsGlobalWindow.h"
61 #include "nsIJSContextStack.h"
62 #include "nsISupportsPrimitives.h"
63 #include "nsDOMException.h"
66 #include "nsXULPrototypeCache.h"
69 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID
, NS_DOM_SCRIPT_OBJECT_FACTORY_CID
);
71 nsDOMScriptObjectFactory::nsDOMScriptObjectFactory() :
72 mLoadedAllLanguages(PR_FALSE
)
74 nsCOMPtr
<nsIObserverService
> observerService
=
75 do_GetService("@mozilla.org/observer-service;1");
77 if (observerService
) {
78 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, PR_FALSE
);
81 nsCOMPtr
<nsIExceptionService
> xs
=
82 do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID
);
85 xs
->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM
);
86 xs
->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM_RANGE
);
88 xs
->RegisterExceptionProvider(this, NS_ERROR_MODULE_SVG
);
90 xs
->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM_XPATH
);
91 xs
->RegisterExceptionProvider(this, NS_ERROR_MODULE_XPCONNECT
);
93 // And pre-create the javascript language.
94 NS_CreateJSRuntime(getter_AddRefs(mLanguageArray
[NS_STID_INDEX(nsIProgrammingLanguage::JAVASCRIPT
)]));
97 NS_INTERFACE_MAP_BEGIN(nsDOMScriptObjectFactory
)
98 NS_INTERFACE_MAP_ENTRY(nsIDOMScriptObjectFactory
)
99 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
100 NS_INTERFACE_MAP_ENTRY(nsIExceptionProvider
)
101 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMScriptObjectFactory
)
105 NS_IMPL_ADDREF(nsDOMScriptObjectFactory
)
106 NS_IMPL_RELEASE(nsDOMScriptObjectFactory
)
109 * Notes about language registration (for language other than js):
110 * - All language are expected to register (at least) 2 contract IDs
111 * @mozilla.org/script-language;1?id=%d
112 * using the language ID as defined in nsIProgrammingLanguage, and
113 * @mozilla.org/script-language;1?script-type=%s
114 * using the "mime-type" of the script language
116 * Theoretically, a language could register multiple script-type
117 * names, although this is discouraged - each language should have one,
120 * The most common case is that languages are looked up by ID. For this
121 * reason, we keep an array of languages indexed by this ID - the registry
122 * is only looked the first request for a language ID.
124 * The registry is looked up and getService called for each query by name.
125 * (As services are cached by CID, multiple contractIDs will still work
130 nsDOMScriptObjectFactory::GetScriptRuntime(const nsAString
&aLanguageName
,
131 nsIScriptRuntime
**aLanguage
)
133 // Note that many callers have optimized detection for JS (along with
134 // supporting various alternate names for JS), so don't call this.
135 // One exception is for the new "script-type" attribute on a node - and
136 // there is no need to support backwards compatible names.
137 // As JS is the default language, this is still rarely called for JS -
138 // only when a node explicitly sets JS - so that is done last.
139 nsCAutoString
contractid(NS_LITERAL_CSTRING(
140 "@mozilla.org/script-language;1?script-type="));
141 // Arbitrarily use utf8 encoding should the name have extended chars
142 AppendUTF16toUTF8(aLanguageName
, contractid
);
144 nsCOMPtr
<nsIScriptRuntime
> lang
=
145 do_GetService(contractid
.get(), &rv
);
148 if (aLanguageName
.Equals(NS_LITERAL_STRING("application/javascript")))
149 return GetScriptRuntimeByID(nsIProgrammingLanguage::JAVASCRIPT
, aLanguage
);
150 // Not JS and nothing else we know about.
151 NS_WARNING("No script language registered for this mime-type");
152 return NS_ERROR_FACTORY_NOT_REGISTERED
;
154 // And stash it away in our array for fast lookup by ID.
155 PRUint32 lang_ndx
= NS_STID_INDEX(lang
->GetScriptTypeID());
156 if (mLanguageArray
[lang_ndx
] == nsnull
) {
157 mLanguageArray
[lang_ndx
] = lang
;
159 // All languages are services - we should have an identical object!
160 NS_ASSERTION(mLanguageArray
[lang_ndx
] == lang
,
161 "Got a different language for this ID???");
164 NS_IF_ADDREF(*aLanguage
);
169 nsDOMScriptObjectFactory::GetScriptRuntimeByID(PRUint32 aLanguageID
,
170 nsIScriptRuntime
**aLanguage
)
172 if (!NS_STID_VALID(aLanguageID
)) {
173 NS_WARNING("Unknown script language");
174 return NS_ERROR_UNEXPECTED
;
176 *aLanguage
= mLanguageArray
[NS_STID_INDEX(aLanguageID
)];
178 nsCAutoString
contractid(NS_LITERAL_CSTRING(
179 "@mozilla.org/script-language;1?id="));
180 char langIdStr
[25]; // space for an int.
181 sprintf(langIdStr
, "%d", aLanguageID
);
182 contractid
+= langIdStr
;
184 nsCOMPtr
<nsIScriptRuntime
> lang
= do_GetService(contractid
.get(), &rv
);
187 NS_ERROR("Failed to get the script language");
191 // Stash it away in our array for fast lookup by ID.
192 mLanguageArray
[NS_STID_INDEX(aLanguageID
)] = lang
;
195 NS_IF_ADDREF(*aLanguage
);
200 nsDOMScriptObjectFactory::GetIDForScriptType(const nsAString
&aLanguageName
,
201 PRUint32
*aScriptTypeID
)
203 nsCOMPtr
<nsIScriptRuntime
> languageRuntime
;
205 rv
= GetScriptRuntime(aLanguageName
, getter_AddRefs(languageRuntime
));
209 *aScriptTypeID
= languageRuntime
->GetScriptTypeID();
214 nsDOMScriptObjectFactory::NewScriptGlobalObject(PRBool aIsChrome
,
215 PRBool aIsModalContentWindow
,
216 nsIScriptGlobalObject
**aGlobal
)
218 return NS_NewScriptGlobalObject(aIsChrome
, aIsModalContentWindow
, aGlobal
);
221 NS_IMETHODIMP_(nsISupports
*)
222 nsDOMScriptObjectFactory::GetClassInfoInstance(nsDOMClassInfoID aID
)
224 return NS_GetDOMClassInfoInstance(aID
);
227 NS_IMETHODIMP_(nsISupports
*)
228 nsDOMScriptObjectFactory::GetExternalClassInfoInstance(const nsAString
& aName
)
230 nsScriptNameSpaceManager
*nameSpaceManager
= nsJSRuntime::GetNameSpaceManager();
231 NS_ENSURE_TRUE(nameSpaceManager
, nsnull
);
233 const nsGlobalNameStruct
*globalStruct
;
234 nameSpaceManager
->LookupName(aName
, &globalStruct
);
236 if (globalStruct
->mType
== nsGlobalNameStruct::eTypeExternalClassInfoCreator
) {
238 nsCOMPtr
<nsIDOMCIExtension
> creator(do_CreateInstance(globalStruct
->mCID
, &rv
));
239 NS_ENSURE_SUCCESS(rv
, nsnull
);
241 rv
= creator
->RegisterDOMCI(NS_ConvertUTF16toUTF8(aName
).get(), this);
242 NS_ENSURE_SUCCESS(rv
, nsnull
);
244 rv
= nameSpaceManager
->LookupName(aName
, &globalStruct
);
245 NS_ENSURE_TRUE(NS_SUCCEEDED(rv
) && globalStruct
, nsnull
);
247 NS_ASSERTION(globalStruct
->mType
== nsGlobalNameStruct::eTypeExternalClassInfo
,
248 "The classinfo data for this class didn't get registered.");
250 if (globalStruct
->mType
== nsGlobalNameStruct::eTypeExternalClassInfo
) {
251 return nsDOMClassInfo::GetClassInfoInstance(globalStruct
->mData
);
258 nsDOMScriptObjectFactory::Observe(nsISupports
*aSubject
,
260 const PRUnichar
*someData
)
262 if (!nsCRT::strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
264 // Flush the XUL cache since it holds JS roots, and we're about to
265 // start the final GC.
266 nsXULPrototypeCache
* cache
= nsXULPrototypeCache::GetInstance();
272 nsCOMPtr
<nsIThreadJSContextStack
> stack
=
273 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
276 JSContext
*cx
= nsnull
;
278 stack
->GetSafeJSContext(&cx
);
281 // Do one final GC to clean things up before shutdown.
287 nsGlobalWindow::ShutDown();
288 nsDOMClassInfo::ShutDown();
291 NS_STID_FOR_INDEX(i
) {
292 if (mLanguageArray
[i
] != nsnull
) {
293 mLanguageArray
[i
]->ShutDown();
294 mLanguageArray
[i
] = nsnull
;
298 nsCOMPtr
<nsIExceptionService
> xs
=
299 do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID
);
302 xs
->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM
);
303 xs
->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM_RANGE
);
305 xs
->UnregisterExceptionProvider(this, NS_ERROR_MODULE_SVG
);
307 xs
->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM_XPATH
);
308 xs
->UnregisterExceptionProvider(this, NS_ERROR_MODULE_XPCONNECT
);
316 CreateXPConnectException(nsresult aResult
, nsIException
*aDefaultException
,
317 nsIException
**_retval
)
319 // See whether we already have a useful XPConnect exception. If we
320 // do, let's not create one with _less_ information!
321 nsCOMPtr
<nsIXPCException
> exception(do_QueryInterface(aDefaultException
));
324 exception
= do_CreateInstance("@mozilla.org/js/xpc/Exception;1", &rv
);
325 NS_ENSURE_SUCCESS(rv
, rv
);
327 rv
= exception
->Initialize(nsnull
, aResult
, nsnull
, nsnull
, nsnull
,
329 NS_ENSURE_SUCCESS(rv
, rv
);
332 NS_ADDREF(*_retval
= exception
);
337 nsDOMScriptObjectFactory::GetException(nsresult result
,
338 nsIException
*aDefaultException
,
339 nsIException
**_retval
)
341 switch (NS_ERROR_GET_MODULE(result
))
343 case NS_ERROR_MODULE_DOM_RANGE
:
344 return NS_NewRangeException(result
, aDefaultException
, _retval
);
346 case NS_ERROR_MODULE_SVG
:
347 return NS_NewSVGException(result
, aDefaultException
, _retval
);
349 case NS_ERROR_MODULE_DOM_XPATH
:
350 return NS_NewXPathException(result
, aDefaultException
, _retval
);
351 case NS_ERROR_MODULE_XPCONNECT
:
352 return CreateXPConnectException(result
, aDefaultException
, _retval
);
353 case NS_ERROR_MODULE_DOM_FILE
:
354 return NS_NewFileException(result
, aDefaultException
, _retval
);
356 return NS_NewDOMException(result
, aDefaultException
, _retval
);
361 nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName
,
362 nsDOMClassInfoExternalConstructorFnc aConstructorFptr
,
363 const nsIID
*aProtoChainInterface
,
364 const nsIID
**aInterfaces
,
365 PRUint32 aScriptableFlags
,
366 PRBool aHasClassInterface
,
367 const nsCID
*aConstructorCID
)
369 nsScriptNameSpaceManager
*nameSpaceManager
= nsJSRuntime::GetNameSpaceManager();
370 NS_ENSURE_TRUE(nameSpaceManager
, NS_ERROR_NOT_INITIALIZED
);
372 return nameSpaceManager
->RegisterDOMCIData(aName
,
374 aProtoChainInterface
,
381 /* static */ nsresult
382 nsDOMScriptObjectFactory::Startup()
384 nsJSRuntime::Startup();
385 // nsDOMScriptObjectFactory is a service - assuming that reinitialzing
386 // xpcom also recreates all services, then everything else should
387 // reinitialize correctly.
392 nsresult
NS_GetScriptRuntime(const nsAString
&aLanguageName
,
393 nsIScriptRuntime
**aLanguage
)
397 nsCOMPtr
<nsIDOMScriptObjectFactory
> factory
= \
398 do_GetService(kDOMScriptObjectFactoryCID
, &rv
);
401 return factory
->GetScriptRuntime(aLanguageName
, aLanguage
);
404 nsresult
NS_GetScriptRuntimeByID(PRUint32 aScriptTypeID
,
405 nsIScriptRuntime
**aLanguage
)
409 nsCOMPtr
<nsIDOMScriptObjectFactory
> factory
= \
410 do_GetService(kDOMScriptObjectFactoryCID
, &rv
);
413 return factory
->GetScriptRuntimeByID(aScriptTypeID
, aLanguage
);