Bug 441233 Missing focus events in Thunderbird account wizard dialog r=surkov.alexander
[wine-gecko.git] / dom / src / base / nsDOMScriptObjectFactory.cpp
blobbbab07bff6c1ee6ad8fd408d5f7a84ac9a969091
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
15 * License.
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.
24 * Contributor(s):
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
44 * Corporation, 2000
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
51 * use in OS2
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"
64 #include "nsCRT.h"
65 #ifdef MOZ_XUL
66 #include "nsXULPrototypeCache.h"
67 #endif
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);
84 if (xs) {
85 xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM);
86 xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM_RANGE);
87 #ifdef MOZ_SVG
88 xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_SVG);
89 #endif
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)
102 NS_INTERFACE_MAP_END
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,
118 * canonical name.
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
126 * correctly)
129 NS_IMETHODIMP
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);
143 nsresult rv;
144 nsCOMPtr<nsIScriptRuntime> lang =
145 do_GetService(contractid.get(), &rv);
147 if (NS_FAILED(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;
158 } else {
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???");
163 *aLanguage = lang;
164 NS_IF_ADDREF(*aLanguage);
165 return NS_OK;
168 NS_IMETHODIMP
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)];
177 if (!*aLanguage) {
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;
183 nsresult rv;
184 nsCOMPtr<nsIScriptRuntime> lang = do_GetService(contractid.get(), &rv);
186 if (NS_FAILED(rv)) {
187 NS_ERROR("Failed to get the script language");
188 return rv;
191 // Stash it away in our array for fast lookup by ID.
192 mLanguageArray[NS_STID_INDEX(aLanguageID)] = lang;
193 *aLanguage = lang;
195 NS_IF_ADDREF(*aLanguage);
196 return NS_OK;
199 NS_IMETHODIMP
200 nsDOMScriptObjectFactory::GetIDForScriptType(const nsAString &aLanguageName,
201 PRUint32 *aScriptTypeID)
203 nsCOMPtr<nsIScriptRuntime> languageRuntime;
204 nsresult rv;
205 rv = GetScriptRuntime(aLanguageName, getter_AddRefs(languageRuntime));
206 if (NS_FAILED(rv))
207 return rv;
209 *aScriptTypeID = languageRuntime->GetScriptTypeID();
210 return NS_OK;
213 NS_IMETHODIMP
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);
235 if (globalStruct) {
236 if (globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
237 nsresult rv;
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);
254 return nsnull;
257 NS_IMETHODIMP
258 nsDOMScriptObjectFactory::Observe(nsISupports *aSubject,
259 const char *aTopic,
260 const PRUnichar *someData)
262 if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
263 #ifdef MOZ_XUL
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();
268 if (cache)
269 cache->Flush();
270 #endif
272 nsCOMPtr<nsIThreadJSContextStack> stack =
273 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
275 if (stack) {
276 JSContext *cx = nsnull;
278 stack->GetSafeJSContext(&cx);
280 if (cx) {
281 // Do one final GC to clean things up before shutdown.
283 ::JS_GC(cx);
287 nsGlobalWindow::ShutDown();
288 nsDOMClassInfo::ShutDown();
290 PRUint32 i;
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);
301 if (xs) {
302 xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM);
303 xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM_RANGE);
304 #ifdef MOZ_SVG
305 xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_SVG);
306 #endif
307 xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM_XPATH);
308 xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_XPCONNECT);
312 return NS_OK;
315 static nsresult
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));
322 if (!exception) {
323 nsresult rv = NS_OK;
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,
328 nsnull);
329 NS_ENSURE_SUCCESS(rv, rv);
332 NS_ADDREF(*_retval = exception);
333 return NS_OK;
336 NS_IMETHODIMP
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);
345 #ifdef MOZ_SVG
346 case NS_ERROR_MODULE_SVG:
347 return NS_NewSVGException(result, aDefaultException, _retval);
348 #endif
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);
355 default:
356 return NS_NewDOMException(result, aDefaultException, _retval);
360 NS_IMETHODIMP
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,
373 aConstructorFptr,
374 aProtoChainInterface,
375 aInterfaces,
376 aScriptableFlags,
377 aHasClassInterface,
378 aConstructorCID);
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.
388 return NS_OK;
391 // Factories
392 nsresult NS_GetScriptRuntime(const nsAString &aLanguageName,
393 nsIScriptRuntime **aLanguage)
395 nsresult rv;
396 *aLanguage = nsnull;
397 nsCOMPtr<nsIDOMScriptObjectFactory> factory = \
398 do_GetService(kDOMScriptObjectFactoryCID, &rv);
399 if (NS_FAILED(rv))
400 return rv;
401 return factory->GetScriptRuntime(aLanguageName, aLanguage);
404 nsresult NS_GetScriptRuntimeByID(PRUint32 aScriptTypeID,
405 nsIScriptRuntime **aLanguage)
407 nsresult rv;
408 *aLanguage = nsnull;
409 nsCOMPtr<nsIDOMScriptObjectFactory> factory = \
410 do_GetService(kDOMScriptObjectFactoryCID, &rv);
411 if (NS_FAILED(rv))
412 return rv;
413 return factory->GetScriptRuntimeByID(aScriptTypeID, aLanguage);