|  | /* | 
|  | * Copyright 2005 Jacek Caban | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdarg.h> | 
|  |  | 
|  | #define COBJMACROS | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "winuser.h" | 
|  | #include "winreg.h" | 
|  | #include "ole2.h" | 
|  |  | 
|  | #include "wine/debug.h" | 
|  | #include "wine/unicode.h" | 
|  |  | 
|  | #include "mshtml_private.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(mshtml); | 
|  |  | 
|  | #define NS_PROMPTSERVICE_CONTRACTID "@mozilla.org/embedcomp/prompt-service;1" | 
|  | #define NS_WINDOWWATCHER_CONTRACTID "@mozilla.org/embedcomp/window-watcher;1" | 
|  | #define NS_TOOLTIPTEXTPROVIDER_CONTRACTID "@mozilla.org/embedcomp/tooltiptextprovider;1" | 
|  |  | 
|  | #define NS_TOOLTIPTEXTPROVIDER_CLASSNAME "nsTooltipTextProvider" | 
|  |  | 
|  | static const nsIID NS_PROMPTSERVICE_CID = | 
|  | {0xa2112d6a,0x0e28,0x421f,{0xb4,0x6a,0x25,0xc0,0xb3,0x8,0xcb,0xd0}}; | 
|  | static const nsIID NS_TOOLTIPTEXTPROVIDER_CID = | 
|  | {0x0b666e3e,0x569a,0x462c,{0xa7,0xf0,0xb1,0x6b,0xb1,0x5d,0x42,0xff}}; | 
|  |  | 
|  | static nsresult NSAPI nsWindowCreator_QueryInterface(nsIWindowCreator2 *iface, nsIIDRef riid, | 
|  | nsQIResult result) | 
|  | { | 
|  | *result = NULL; | 
|  |  | 
|  | if(IsEqualGUID(&IID_nsISupports, riid)) { | 
|  | TRACE("(IID_nsISupports %p)\n", result); | 
|  | *result = iface; | 
|  | }else if(IsEqualGUID(&IID_nsIWindowCreator, riid)) { | 
|  | TRACE("(IID_nsIWindowCreator %p)\n", result); | 
|  | *result = iface; | 
|  | }else if(IsEqualGUID(&IID_nsIWindowCreator2, riid)) { | 
|  | TRACE("(IID_nsIWindowCreator2 %p)\n", result); | 
|  | *result = iface; | 
|  | } | 
|  |  | 
|  | if(*result) { | 
|  | nsIWindowCreator_AddRef(iface); | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | WARN("(%s %p)\n", debugstr_guid(riid), result); | 
|  | return NS_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsWindowCreator_AddRef(nsIWindowCreator2 *iface) | 
|  | { | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsWindowCreator_Release(nsIWindowCreator2 *iface) | 
|  | { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWindowCreator_CreateChromeWindow(nsIWindowCreator2 *iface, | 
|  | nsIWebBrowserChrome *parent, PRUint32 chromeFlags, nsIWebBrowserChrome **_retval) | 
|  | { | 
|  | TRACE("(%p %08x %p)\n", parent, chromeFlags, _retval); | 
|  | return nsIWindowCreator2_CreateChromeWindow2(iface, parent, chromeFlags, 0, NULL, | 
|  | NULL, _retval); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWindowCreator_CreateChromeWindow2(nsIWindowCreator2 *iface, | 
|  | nsIWebBrowserChrome *parent, PRUint32 chromeFlags, PRUint32 contextFlags, | 
|  | nsIURI *uri, PRBool *cancel, nsIWebBrowserChrome **_retval) | 
|  | { | 
|  | TRACE("(%p %08x %08x %p %p %p)\n", parent, chromeFlags, contextFlags, uri, | 
|  | cancel, _retval); | 
|  |  | 
|  | if(cancel) | 
|  | *cancel = FALSE; | 
|  |  | 
|  | *_retval = NSWBCHROME(NSContainer_Create(NULL, (NSContainer*)parent)); | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static const nsIWindowCreator2Vtbl nsWindowCreatorVtbl = { | 
|  | nsWindowCreator_QueryInterface, | 
|  | nsWindowCreator_AddRef, | 
|  | nsWindowCreator_Release, | 
|  | nsWindowCreator_CreateChromeWindow, | 
|  | nsWindowCreator_CreateChromeWindow2 | 
|  | }; | 
|  |  | 
|  | static nsIWindowCreator2 nsWindowCreator = { &nsWindowCreatorVtbl }; | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_QueryInterface(nsIPromptService *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | *result = NULL; | 
|  |  | 
|  | if(IsEqualGUID(&IID_nsISupports, riid)) { | 
|  | TRACE("(IID_nsISupports %p)\n", result); | 
|  | *result = iface; | 
|  | }else if(IsEqualGUID(&IID_nsIPromptService, riid)) { | 
|  | TRACE("(IID_nsIPromptService %p)\n", result); | 
|  | *result = iface; | 
|  | } | 
|  |  | 
|  | if(*result) | 
|  | return NS_OK; | 
|  |  | 
|  | TRACE("(%s %p)\n", debugstr_guid(riid), result); | 
|  | return NS_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsPromptService_AddRef(nsIPromptService *iface) | 
|  | { | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsPromptService_Release(nsIPromptService *iface) | 
|  | { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_Alert(nsIPromptService *iface, nsIDOMWindow *aParent, | 
|  | const PRUnichar *aDialogTitle, const PRUnichar *aText) | 
|  | { | 
|  | HTMLWindow *window; | 
|  | BSTR text; | 
|  |  | 
|  | TRACE("(%p %s %s)\n", aParent, debugstr_w(aDialogTitle), debugstr_w(aText)); | 
|  |  | 
|  | window = nswindow_to_window(aParent); | 
|  | if(!window) { | 
|  | WARN("Could not find HTMLWindow for nsIDOMWindow %p\n", aParent); | 
|  | return NS_ERROR_UNEXPECTED; | 
|  | } | 
|  |  | 
|  | text = SysAllocString(aText); | 
|  | IHTMLWindow2_alert(HTMLWINDOW2(window), text); | 
|  | SysFreeString(text); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_AlertCheck(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, const PRUnichar *aCheckMsg, PRBool *aCheckState) | 
|  | { | 
|  | FIXME("(%p %s %s %s %p)\n", aParent, debugstr_w(aDialogTitle), debugstr_w(aText), | 
|  | debugstr_w(aCheckMsg), aCheckState); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_Confirm(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, const PRUnichar *aText, | 
|  | PRBool *_retval) | 
|  | { | 
|  | FIXME("(%p %s %s %p)\n", aParent, debugstr_w(aDialogTitle), debugstr_w(aText), _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_ConfirmCheck(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, const PRUnichar *aCheckMsg, PRBool *aCheckState, | 
|  | PRBool *_retval) | 
|  | { | 
|  | FIXME("(%p %s %s %s %p %p)\n", aParent, debugstr_w(aDialogTitle), debugstr_w(aText), | 
|  | debugstr_w(aCheckMsg), aCheckState, _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_ConfirmEx(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, PRUint32 aButtonFlags, const PRUnichar *aButton0Title, | 
|  | const PRUnichar *aButton1Title, const PRUnichar *aButton2Title, | 
|  | const PRUnichar *aCheckMsg, PRBool *aCheckState, PRInt32 *_retval) | 
|  | { | 
|  | static const PRUnichar wszContinue[] = {'C','o','n','t','i','n','u','e',0}; | 
|  |  | 
|  | FIXME("(%p %s %s %08x %s %s %s %s %p %p) hack!\n", aParent, debugstr_w(aDialogTitle), | 
|  | debugstr_w(aText), aButtonFlags, debugstr_w(aButton0Title), | 
|  | debugstr_w(aButton1Title), debugstr_w(aButton2Title), debugstr_w(aCheckMsg), | 
|  | aCheckState, _retval); | 
|  |  | 
|  | /* | 
|  | * FIXME: | 
|  | * This is really very very ugly hack!!! | 
|  | */ | 
|  |  | 
|  | if(aButton0Title && !memcmp(aButton0Title, wszContinue, sizeof(wszContinue))) | 
|  | *_retval = 0; | 
|  | else if(aButton1Title && !memcmp(aButton1Title, wszContinue, sizeof(wszContinue))) | 
|  | *_retval = 1; | 
|  | else if(aButton2Title && !memcmp(aButton2Title, wszContinue, sizeof(wszContinue))) | 
|  | *_retval = 2; | 
|  | /* else | 
|  | *     let's hope that _retval is set to the default value */ | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_Prompt(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, PRUnichar **aValue, const PRUnichar *aCheckMsg, | 
|  | PRBool *aCheckState, PRBool *_retval) | 
|  | { | 
|  | FIXME("(%p %s %s %p %s %p %p)\n", aParent, debugstr_w(aDialogTitle), debugstr_w(aText), | 
|  | aValue, debugstr_w(aCheckMsg), aCheckState, _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_PromptUsernameAndPassword(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, PRUnichar **aUsername, PRUnichar **aPassword, | 
|  | const PRUnichar *aCheckMsg, PRBool *aCheckState, PRBool *_retval) | 
|  | { | 
|  | FIXME("(%p %s %s %p %p %s %p %p)\n", aParent, debugstr_w(aDialogTitle), | 
|  | debugstr_w(aText), aUsername, aPassword, debugstr_w(aCheckMsg), aCheckState, | 
|  | _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_PromptPassword(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, PRUnichar **aPassword, const PRUnichar *aCheckMsg, | 
|  | PRBool *aCheckState, PRBool *_retval) | 
|  | { | 
|  | FIXME("(%p %s %s %p %s %p %p)\n", aParent, debugstr_w(aDialogTitle), | 
|  | debugstr_w(aText), aPassword, debugstr_w(aCheckMsg), aCheckState, _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsPromptService_Select(nsIPromptService *iface, | 
|  | nsIDOMWindow *aParent, const PRUnichar *aDialogTitle, | 
|  | const PRUnichar *aText, PRUint32 aCount, const PRUnichar **aSelectList, | 
|  | PRInt32 *aOutSelection, PRBool *_retval) | 
|  | { | 
|  | FIXME("(%p %s %s %d %p %p %p)\n", aParent, debugstr_w(aDialogTitle), | 
|  | debugstr_w(aText), aCount, aSelectList, aOutSelection, _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static const nsIPromptServiceVtbl PromptServiceVtbl = { | 
|  | nsPromptService_QueryInterface, | 
|  | nsPromptService_AddRef, | 
|  | nsPromptService_Release, | 
|  | nsPromptService_Alert, | 
|  | nsPromptService_AlertCheck, | 
|  | nsPromptService_Confirm, | 
|  | nsPromptService_ConfirmCheck, | 
|  | nsPromptService_ConfirmEx, | 
|  | nsPromptService_Prompt, | 
|  | nsPromptService_PromptUsernameAndPassword, | 
|  | nsPromptService_PromptPassword, | 
|  | nsPromptService_Select | 
|  | }; | 
|  |  | 
|  | static nsIPromptService nsPromptService = { &PromptServiceVtbl }; | 
|  |  | 
|  | static nsresult NSAPI nsTooltipTextProvider_QueryInterface(nsITooltipTextProvider *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | *result = NULL; | 
|  |  | 
|  | if(IsEqualGUID(&IID_nsISupports, riid)) { | 
|  | TRACE("(IID_nsISupports %p)\n", result); | 
|  | *result = iface; | 
|  | }else if(IsEqualGUID(&IID_nsITooltipTextProvider, riid)) { | 
|  | TRACE("(IID_nsITooltipTextProvider %p)\n", result); | 
|  | *result = iface; | 
|  | } | 
|  |  | 
|  | if(*result) { | 
|  | nsITooltipTextProvider_AddRef(iface); | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | WARN("(%s %p)\n", debugstr_guid(riid), result); | 
|  | return NS_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsTooltipTextProvider_AddRef(nsITooltipTextProvider *iface) | 
|  | { | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsTooltipTextProvider_Release(nsITooltipTextProvider *iface) | 
|  | { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsTooltipTextProvider_GetNodeText(nsITooltipTextProvider *iface, | 
|  | nsIDOMNode *aNode, PRUnichar **aText, PRBool *_retval) | 
|  | { | 
|  | nsIDOMHTMLElement *nselem; | 
|  | nsIDOMNode *node = aNode, *parent; | 
|  | nsAString title_str; | 
|  | const PRUnichar *title = NULL; | 
|  | nsresult nsres; | 
|  |  | 
|  | TRACE("(%p %p %p)\n", aNode, aText, _retval); | 
|  |  | 
|  | *aText = NULL; | 
|  |  | 
|  | nsAString_Init(&title_str, NULL); | 
|  |  | 
|  | do { | 
|  | nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMHTMLElement, (void**)&nselem); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | title = NULL; | 
|  |  | 
|  | nsIDOMHTMLElement_GetTitle(nselem, &title_str); | 
|  | nsIDOMHTMLElement_Release(nselem); | 
|  |  | 
|  | nsAString_GetData(&title_str, &title); | 
|  | if(title && *title) { | 
|  | if(node != aNode) | 
|  | nsIDOMNode_Release(node); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | nsres = nsIDOMNode_GetParentNode(node, &parent); | 
|  | if(NS_FAILED(nsres)) | 
|  | parent = NULL; | 
|  |  | 
|  | if(node != aNode) | 
|  | nsIDOMNode_Release(node); | 
|  | node = parent; | 
|  | } while(node); | 
|  |  | 
|  | if(title && *title) { | 
|  | int size = (strlenW(title)+1)*sizeof(PRUnichar); | 
|  |  | 
|  | *aText = nsalloc(size); | 
|  | memcpy(*aText, title, size); | 
|  | TRACE("aText = %s\n", debugstr_w(*aText)); | 
|  |  | 
|  | *_retval = TRUE; | 
|  | }else { | 
|  | *_retval = FALSE; | 
|  | } | 
|  |  | 
|  | nsAString_Finish(&title_str); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static const nsITooltipTextProviderVtbl nsTooltipTextProviderVtbl = { | 
|  | nsTooltipTextProvider_QueryInterface, | 
|  | nsTooltipTextProvider_AddRef, | 
|  | nsTooltipTextProvider_Release, | 
|  | nsTooltipTextProvider_GetNodeText | 
|  | }; | 
|  |  | 
|  | static nsITooltipTextProvider nsTooltipTextProvider = { &nsTooltipTextProviderVtbl }; | 
|  |  | 
|  | typedef struct { | 
|  | const nsIFactoryVtbl *lpFactoryVtbl; | 
|  | nsISupports *service; | 
|  | } nsServiceFactory; | 
|  |  | 
|  | #define NSFACTORY(x)  ((nsIFactory*)  &(x)->lpFactoryVtbl) | 
|  |  | 
|  | #define NSFACTORY_THIS(iface) DEFINE_THIS(nsServiceFactory, Factory, iface) | 
|  |  | 
|  | static nsresult NSAPI nsServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid, | 
|  | nsQIResult result) | 
|  | { | 
|  | nsServiceFactory *This = NSFACTORY_THIS(iface); | 
|  |  | 
|  | *result = NULL; | 
|  |  | 
|  | if(IsEqualGUID(&IID_nsISupports, riid)) { | 
|  | TRACE("(%p)->(IID_nsISupports %p)\n", This, result); | 
|  | *result = NSFACTORY(This); | 
|  | }else if(IsEqualGUID(&IID_nsIFactory, riid)) { | 
|  | TRACE("(%p)->(IID_nsIFactory %p)\n", This, result); | 
|  | *result = NSFACTORY(This); | 
|  | } | 
|  |  | 
|  | if(*result) | 
|  | return NS_OK; | 
|  |  | 
|  | WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); | 
|  | return NS_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsServiceFactory_AddRef(nsIFactory *iface) | 
|  | { | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsServiceFactory_Release(nsIFactory *iface) | 
|  | { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsServiceFactory_CreateInstance(nsIFactory *iface, | 
|  | nsISupports *aOuter, const nsIID *iid, void **result) | 
|  | { | 
|  | nsServiceFactory *This = NSFACTORY_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p %s %p)\n", This, aOuter, debugstr_guid(iid), result); | 
|  |  | 
|  | return nsISupports_QueryInterface(This->service, iid, result); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsServiceFactory_LockFactory(nsIFactory *iface, PRBool lock) | 
|  | { | 
|  | nsServiceFactory *This = NSFACTORY_THIS(iface); | 
|  | WARN("(%p)->(%x)\n", This, lock); | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | #undef NSFACTORY_THIS | 
|  |  | 
|  | static const nsIFactoryVtbl nsServiceFactoryVtbl = { | 
|  | nsServiceFactory_QueryInterface, | 
|  | nsServiceFactory_AddRef, | 
|  | nsServiceFactory_Release, | 
|  | nsServiceFactory_CreateInstance, | 
|  | nsServiceFactory_LockFactory | 
|  | }; | 
|  |  | 
|  | static nsServiceFactory nsPromptServiceFactory = { | 
|  | &nsServiceFactoryVtbl, | 
|  | (nsISupports*)&nsPromptService | 
|  | }; | 
|  |  | 
|  | static nsServiceFactory nsTooltipTextFactory = { | 
|  | &nsServiceFactoryVtbl, | 
|  | (nsISupports*)&nsTooltipTextProvider | 
|  | }; | 
|  |  | 
|  | void register_nsservice(nsIComponentRegistrar *registrar, nsIServiceManager *service_manager) | 
|  | { | 
|  | nsIWindowWatcher *window_watcher; | 
|  | nsresult nsres; | 
|  |  | 
|  | nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_PROMPTSERVICE_CID, | 
|  | "Prompt Service", NS_PROMPTSERVICE_CONTRACTID, NSFACTORY(&nsPromptServiceFactory)); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("RegisterFactory failed: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIServiceManager_GetServiceByContractID(service_manager, NS_WINDOWWATCHER_CONTRACTID, | 
|  | &IID_nsIWindowWatcher, (void**)&window_watcher); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsres = nsIWindowWatcher_SetWindowCreator(window_watcher, | 
|  | (nsIWindowCreator*)&nsWindowCreator); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("SetWindowCreator failed: %08x\n", nsres); | 
|  | nsIWindowWatcher_Release(window_watcher); | 
|  | }else { | 
|  | ERR("Could not get WindowWatcher object: %08x\n", nsres); | 
|  | } | 
|  |  | 
|  | nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_TOOLTIPTEXTPROVIDER_CID, | 
|  | NS_TOOLTIPTEXTPROVIDER_CLASSNAME, NS_TOOLTIPTEXTPROVIDER_CONTRACTID, | 
|  | NSFACTORY(&nsTooltipTextFactory)); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("RegisterFactory failed: %08x\n", nsres); | 
|  | } |