/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Christopher Blizzard. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Christopher Blizzard * Chris Lord * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsIDocShell.h" #include "nsIWebProgress.h" #include "nsIDOMNSEventTarget.h" #include "nsIWidget.h" #include "nsCRT.h" #include "nsNetUtil.h" #include "nsIDocumentViewer.h" #include "nsIDocument.h" #include "nsIDOMEventTarget.h" #include "nsIDOMDocumentEvent.h" #include "nsIPrivateDOMEvent.h" #include "nsIWebBrowserStream.h" #include "nsIWebBrowserFocus.h" #include "nsIDirectoryService.h" #include "nsAppDirectoryServiceDefs.h" #include "nsIDocShellTreeItem.h" #include "nsDirectoryServiceDefs.h" #include "nsIToolkitChromeRegistry.h" #include "nsEnumeratorUtils.h" #include "nsIMutableArray.h" // for do_GetInterface #include "nsIInterfaceRequestor.h" // for do_CreateInstance #include "nsIComponentManager.h" #include "nsComponentManagerUtils.h" // for initializing our window watcher service #include "nsIWindowWatcher.h" #include "nsILocalFile.h" #include "nsXULAppAPI.h" // all of the crap that we need for event listeners // and when chrome windows finish loading #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" #include "nsIDOMWindowInternal.h" // For seting scrollbar visibilty #include "nsIDOMBarProp.h" // for the focus hacking we need to do #include "nsIFocusController.h" // app component registration #include "nsIGenericFactory.h" #include "nsIComponentRegistrar.h" // all of our local includes #include "HeadlessPrivate.h" #include "HeadlessWindow.h" #include "HeadlessProgress.h" #include "HeadlessHistory.h" #include "HeadlessAppInfo.h" #include "HeadlessContentListener.h" #include "HeadlessEventListener.h" #include "HeadlessWindowCreator.h" #include "HeadlessPromptService.h" PRUint32 HeadlessPrivate::sWidgetCount = 0; char *HeadlessPrivate::sPath = nsnull; char *HeadlessPrivate::sCompPath = nsnull; nsVoidArray *HeadlessPrivate::sWindowList = nsnull; nsILocalFile *HeadlessPrivate::sProfileDir = nsnull; nsISupports *HeadlessPrivate::sProfileLock = nsnull; GSList *HeadlessPrivate::sCompPaths = NULL; GSList *HeadlessPrivate::sChromePaths = NULL; nsIDirectoryServiceProvider *HeadlessPrivate::sAppFileLocProvider = nsnull; GHashTable *HeadlessPrivate::sDirectoryHash = NULL; class HeadlessDirectoryProvider : public nsIDirectoryServiceProvider2 { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDIRECTORYSERVICEPROVIDER NS_DECL_NSIDIRECTORYSERVICEPROVIDER2 }; static const HeadlessDirectoryProvider kDirectoryProvider; NS_IMPL_QUERY_INTERFACE2(HeadlessDirectoryProvider, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2) NS_IMETHODIMP_(nsrefcnt) HeadlessDirectoryProvider::AddRef() { return 1; } NS_IMETHODIMP_(nsrefcnt) HeadlessDirectoryProvider::Release() { return 1; } NS_IMETHODIMP HeadlessDirectoryProvider::GetFile(const char *aKey, PRBool *aPersist, nsIFile* *aResult) { if (HeadlessPrivate::sAppFileLocProvider) { nsresult rv = HeadlessPrivate::sAppFileLocProvider->GetFile(aKey, aPersist, aResult); if (NS_SUCCEEDED(rv)) return rv; } if (HeadlessPrivate::sDirectoryHash) { const char *path = (const char *) g_hash_table_lookup (HeadlessPrivate::sDirectoryHash, aKey); if (path) { nsILocalFile *localFile; nsresult rv = NS_NewNativeLocalFile (nsDependentCString (path), 1, &localFile); if (NS_SUCCEEDED (rv)) { *aResult = (nsIFile *)localFile; return rv; } } } if (HeadlessPrivate::sProfileDir && (!strcmp(aKey, NS_APP_USER_PROFILE_50_DIR) || !strcmp(aKey, NS_APP_PROFILE_DIR_STARTUP))) { *aPersist = PR_TRUE; return HeadlessPrivate::sProfileDir->Clone(aResult); } return NS_ERROR_FAILURE; } NS_IMETHODIMP HeadlessDirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult) { nsresult rv; nsCOMPtr dp2(do_QueryInterface(HeadlessPrivate::sAppFileLocProvider)); nsCOMPtr result; if (dp2) { rv = dp2->GetFiles(aKey, getter_AddRefs(result)); if (NS_FAILED(rv) && rv != NS_ERROR_FAILURE) return rv; } // If this is the chrome or components directly list then add any // extra paths specified by the app GSList *extraPaths = NULL; if (!strcmp(aKey, NS_XPCOM_COMPONENT_DIR_LIST)) extraPaths = HeadlessPrivate::sCompPaths; else if (!strcmp(aKey, NS_CHROME_MANIFESTS_FILE_LIST)) extraPaths = HeadlessPrivate::sChromePaths; if (extraPaths) { // Copy the paths to an array nsCOMPtr array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; for (GSList *l = extraPaths; l; l = l->next) { nsCOMPtr file; rv = NS_NewNativeLocalFile(nsDependentCString((gchar *) l->data), 1, getter_AddRefs (file)); if (NS_FAILED(rv)) return rv; array->AppendElement(file, PR_FALSE); } nsCOMPtr arrayEnumerator; rv = array->Enumerate(getter_AddRefs(arrayEnumerator)); if (NS_FAILED(rv)) return rv; if (result) { nsCOMPtr unionEnumerator; rv = NS_NewUnionEnumerator(getter_AddRefs(unionEnumerator), arrayEnumerator, result); if (NS_FAILED(rv)) return rv; result = unionEnumerator; } else result = arrayEnumerator; } if (result) { result.forget(aResult); return NS_SUCCESS_AGGREGATE_RESULT; } else return NS_ERROR_FAILURE; } #define HEADLESS_APPINFO_CID \ {0x066aa9a8, 0xaae7, 0x42a3, {0x91, 0x7c, 0x77, 0xb2, 0xf9, 0x7e, 0x99, 0xa9}} NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(HeadlessAppInfo, HeadlessAppInfo::GetSingleton) static const nsModuleComponentInfo appInfoComp = { "App info", HEADLESS_APPINFO_CID, "@mozilla.org/xre/app-info;1", HeadlessAppInfoConstructor }; HeadlessPrivate::HeadlessPrivate(void) { mOwningObject = nsnull; mWindow = nsnull; mProgress = nsnull; mHistory = nsnull; mContentListener = nsnull; mEventListener = nsnull; mChromeMask = nsIWebBrowserChrome::CHROME_ALL; mIsChrome = PR_FALSE; mChromeLoaded = PR_FALSE; mListenersAttached = PR_FALSE; mIsDestroyed = PR_FALSE; PushStartup(); if (!sWindowList) { sWindowList = new nsVoidArray(); } sWindowList->AppendElement(this); } HeadlessPrivate::~HeadlessPrivate() { sWindowList->RemoveElement(this); PopStartup(); } nsresult HeadlessPrivate::Init(MozHeadless *aOwningObject, PRUint32 aChromeFlags) { // are we being re-initialized? if (mOwningObject) return NS_OK; // hang on with a reference to the owning widget mOwningObject = aOwningObject; if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) mIsChrome = PR_TRUE; else mIsChrome = PR_FALSE; // Create our embed window, and create an owning reference to it and // initialize it. It is assumed that this window will be destroyed // when we go out of scope. mWindow = new HeadlessWindow(); mWindowGuard = static_cast(mWindow); mWindow->Init(this, mIsChrome ? (long)nsIDocShellTreeItem::typeChromeWrapper : (long)nsIDocShellTreeItem::typeContentWrapper); // Create our progress listener object, make an owning reference, // and initialize it. It is assumed that this progress listener // will be destroyed when we go out of scope. mProgress = new HeadlessProgress(); mProgressGuard = static_cast (mProgress); mProgress->Init(this); // Create our session history listener object, make an owning reference, // and initialise it. It is assumed that this session history listener // will be destroyed when we go out of scope. mHistory = new HeadlessHistory(); mHistoryGuard = static_cast(mHistory); mHistory->Init(this); // Create our content listener object, initialize it and attach it. // It is assumed that this will be destroyed when we go out of // scope. mContentListener = new HeadlessContentListener(); mContentListenerGuard = static_cast(static_cast(mContentListener)); mContentListener->Init(this); // Create our key listener object and initialize it. It is assumed // that this will be destroyed before we go out of scope. mEventListener = new HeadlessEventListener(); mEventListenerGuard = static_cast(static_cast(mEventListener)); mEventListener->Init(this); // has the window creator service been set up? static int initialized = PR_FALSE; // Set up our window creator ( only once ) if (!initialized) { // We set this flag here instead of on success. If it failed we // don't want to keep trying and leaking window creator objects. initialized = PR_TRUE; // create our local object HeadlessWindowCreator *creator = new HeadlessWindowCreator(); nsCOMPtr windowCreator; windowCreator = static_cast(creator); // Attach it via the watcher service nsCOMPtr watcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID); if (watcher) watcher->SetWindowCreator(windowCreator); } // Realize... // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // get a handle on the navigation object mNavigation = do_QueryInterface(webBrowser); // Create our session history object and tell the navigation object // to use it. We need to do this before we create the web browser // window. mSessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID); mNavigation->SetSessionHistory(mSessionHistory); // Set the chrome mask SetChromeMask(aChromeFlags); // create the window mWindow->CreateWindow(); // bind the progress listener to the browser object nsCOMPtr supportsWeak; supportsWeak = do_QueryInterface(mProgressGuard); nsCOMPtr weakRef; supportsWeak->GetWeakReference(getter_AddRefs(weakRef)); webBrowser->AddWebBrowserListener(weakRef, NS_GET_IID(nsIWebProgressListener)); // bind the session history listener to the browser object supportsWeak = do_QueryInterface(mHistoryGuard); supportsWeak->GetWeakReference(getter_AddRefs(weakRef)); webBrowser->AddWebBrowserListener(weakRef, NS_GET_IID(nsISHistoryListener)); // set ourselves as the parent uri content listener nsCOMPtr uriListener; uriListener = do_QueryInterface(mContentListenerGuard); webBrowser->SetParentURIContentListener(uriListener); // Focus ChildFocusIn (); return NS_OK; } void HeadlessPrivate::Show(void) { // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // and set the visibility on the thing nsCOMPtr baseWindow = do_QueryInterface(webBrowser); baseWindow->SetVisibility(PR_TRUE); } void HeadlessPrivate::Hide(void) { // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // and set the visibility on the thing nsCOMPtr baseWindow = do_QueryInterface(webBrowser); baseWindow->SetVisibility(PR_FALSE); } void HeadlessPrivate::Resize(PRUint32 aWidth, PRUint32 aHeight) { mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION | nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER, 0, 0, aWidth, aHeight); } void HeadlessPrivate::Destroy(void) { // This flag might have been set from // HeadlessWindow::DestroyBrowserWindow() as well if someone used a // window.close() or something or some other script action to close // the window. No harm setting it again. mIsDestroyed = PR_TRUE; // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // Release our progress listener nsCOMPtr supportsWeak; supportsWeak = do_QueryInterface(mProgressGuard); nsCOMPtr weakRef; supportsWeak->GetWeakReference(getter_AddRefs(weakRef)); webBrowser->RemoveWebBrowserListener(weakRef, NS_GET_IID(nsIWebProgressListener)); weakRef = nsnull; supportsWeak = nsnull; // Release our history listener supportsWeak = do_QueryInterface(mHistoryGuard); supportsWeak->GetWeakReference(getter_AddRefs(weakRef)); webBrowser->RemoveWebBrowserListener(weakRef, NS_GET_IID(nsISHistoryListener)); weakRef = nsnull; supportsWeak = nsnull; // Release our content listener webBrowser->SetParentURIContentListener(nsnull); mContentListenerGuard = nsnull; mContentListener = nsnull; // Now that we have removed the listener, release our progress // object mProgressGuard = nsnull; mProgress = nsnull; mHistoryGuard = nsnull; mHistory = nsnull; // detach our event listeners and release the event receiver DetachListeners(); if (mEventTarget) mEventTarget = nsnull; // destroy our child window mWindow->ReleaseChildren(); // release navigation mNavigation = nsnull; // release session history mSessionHistory = nsnull; mOwningObject = nsnull; } void HeadlessPrivate::SetURI(const char *aURI) { mURI.Assign(aURI); } void HeadlessPrivate::SetIcon(const char *aURI) { mIcon.Assign(aURI); } void HeadlessPrivate::LoadCurrentURI(void) { if (mURI.Length()) { nsCOMPtr piWin; GetPIDOMWindow(getter_AddRefs(piWin)); nsAutoPopupStatePusher popupStatePusher(piWin, openAllowed); mNavigation->LoadURI(NS_ConvertUTF8toUTF16(mURI).get(), // URI string nsIWebNavigation::LOAD_FLAGS_NONE, // Load flags nsnull, // Referring URI nsnull, // Post data nsnull); // extra headers } } void HeadlessPrivate::Reload(PRUint32 reloadFlags) { /* Use the session history if it is available, this * allows framesets to reload correctly */ nsCOMPtr wn; if (mSessionHistory) { wn = do_QueryInterface(mSessionHistory); } if (!wn) wn = mNavigation; if (wn) wn->Reload(reloadFlags); } void HeadlessPrivate::ApplyChromeMask() { if (mWindow) { nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); nsCOMPtr domWindow; webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); if (domWindow) { nsCOMPtr scrollbars; domWindow->GetScrollbars(getter_AddRefs(scrollbars)); if (scrollbars) { scrollbars->SetVisible (mChromeMask & nsIWebBrowserChrome::CHROME_SCROLLBARS ? PR_TRUE : PR_FALSE); } } } } void HeadlessPrivate::SetChromeMask(PRUint32 aChromeMask) { mChromeMask = aChromeMask; ApplyChromeMask(); } /* static */ void HeadlessPrivate::PushStartup(void) { // increment the number of widgets sWidgetCount++; // if this is the first widget, fire up xpcom if (sWidgetCount == 1) { nsresult rv; nsCOMPtr binDir; if (sCompPath) { rv = NS_NewNativeLocalFile(nsDependentCString(sCompPath), 1, getter_AddRefs(binDir)); if (NS_FAILED(rv)) return; } const char *grePath = sPath; if (!grePath) grePath = getenv("MOZILLA_FIVE_HOME"); if (!grePath) return; nsCOMPtr greDir; rv = NS_NewNativeLocalFile(nsDependentCString(grePath), PR_TRUE, getter_AddRefs(greDir)); if (NS_FAILED(rv)) return; if (sProfileDir && !sProfileLock) { rv = XRE_LockProfileDirectory(sProfileDir, &sProfileLock); if (NS_FAILED(rv)) return; } rv = XRE_InitEmbedding(greDir, binDir, const_cast(&kDirectoryProvider), nsnull, nsnull); if (NS_FAILED(rv)) return; if (sProfileDir) XRE_NotifyProfile(); rv = RegisterAppComponents(); NS_ASSERTION(NS_SUCCEEDED(rv), "Warning: Failed to register app components.\n"); } } /* static */ void HeadlessPrivate::PopStartup(void) { sWidgetCount--; if (sWidgetCount == 0) { // we no longer need a reference to the DirectoryServiceProvider if (sAppFileLocProvider) { NS_RELEASE(sAppFileLocProvider); sAppFileLocProvider = nsnull; } // We also no longer need the directory hash if (sDirectoryHash) { g_hash_table_destroy (sDirectoryHash); sDirectoryHash = NULL; } // We no longer need the extra path lists g_slist_foreach (sCompPaths, (GFunc) g_free, NULL); g_slist_free (sCompPaths); sCompPaths = NULL; g_slist_foreach (sChromePaths, (GFunc) g_free, NULL); g_slist_free (sChromePaths); sChromePaths = NULL; // shut down XPCOM/Embedding XRE_TermEmbedding(); NS_IF_RELEASE(sProfileLock); NS_IF_RELEASE(sProfileDir); } } /* static */ void HeadlessPrivate::SetPath(const char *aPath) { if (sPath) free(sPath); if (aPath) sPath = strdup(aPath); else sPath = nsnull; } /* static */ void HeadlessPrivate::SetCompPath(const char *aPath) { if (sCompPath) free(sCompPath); if (aPath) sCompPath = strdup(aPath); else sCompPath = nsnull; } /* static */ void HeadlessPrivate::AddCompPath(const char *aPath) { sCompPaths = g_slist_append(sCompPaths, g_strdup(aPath)); } /* static */ void HeadlessPrivate::AddChromePath(const char *aPath) { sChromePaths = g_slist_append(sChromePaths, g_strdup(aPath)); } /* static */ void HeadlessPrivate::SetProfilePath(const char *aDir, const char *aName) { if (sProfileDir) { if (sWidgetCount) { NS_ERROR("Cannot change profile directory during run."); return; } NS_RELEASE(sProfileDir); NS_RELEASE(sProfileLock); } nsresult rv = NS_NewNativeLocalFile(nsDependentCString(aDir), PR_TRUE, &sProfileDir); if (NS_SUCCEEDED(rv) && aName) rv = sProfileDir->AppendNative(nsDependentCString(aName)); if (NS_SUCCEEDED(rv)) { PRBool exists = PR_FALSE; rv = sProfileDir->Exists(&exists); if (!exists) rv = sProfileDir->Create(nsIFile::DIRECTORY_TYPE, 0700); rv = XRE_LockProfileDirectory(sProfileDir, &sProfileLock); } if (NS_SUCCEEDED(rv)) { if (sWidgetCount) XRE_NotifyProfile(); return; } NS_WARNING("Failed to lock profile."); // Failed NS_IF_RELEASE(sProfileDir); NS_IF_RELEASE(sProfileLock); } void HeadlessPrivate::SetDirectoryServiceProvider(nsIDirectoryServiceProvider * appFileLocProvider) { if (sAppFileLocProvider) NS_RELEASE(sAppFileLocProvider); if (appFileLocProvider) { sAppFileLocProvider = appFileLocProvider; NS_ADDREF(sAppFileLocProvider); } } void HeadlessPrivate::SetDirectory(const gchar *aKey, const gchar *aPath) { if (!aKey) return; if (!HeadlessPrivate::sDirectoryHash) { if (!aPath) return; else HeadlessPrivate::sDirectoryHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } if (!aPath) { g_hash_table_remove (HeadlessPrivate::sDirectoryHash, aKey); return; } g_hash_table_replace (HeadlessPrivate::sDirectoryHash, g_strdup (aKey), g_strdup (aPath)); } nsresult HeadlessPrivate::OpenStream(const char *aBaseURI, const char *aContentType) { nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); nsCOMPtr wbStream = do_QueryInterface(webBrowser); if (!wbStream) return NS_ERROR_FAILURE; nsCOMPtr uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aBaseURI); if (NS_FAILED(rv)) return rv; rv = wbStream->OpenStream(uri, nsDependentCString(aContentType)); return rv; } nsresult HeadlessPrivate::AppendToStream(const PRUint8 *aData, PRUint32 aLen) { // Attach listeners to this document since in some cases we don't // get updates for content added this way. ContentStateChange(); nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); nsCOMPtr wbStream = do_QueryInterface(webBrowser); if (!wbStream) return NS_ERROR_FAILURE; return wbStream->AppendToStream(aData, aLen); } nsresult HeadlessPrivate::CloseStream(void) { nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); nsCOMPtr wbStream = do_QueryInterface(webBrowser); if (!wbStream) return NS_ERROR_FAILURE; return wbStream->CloseStream(); } /* static */ HeadlessPrivate * HeadlessPrivate::FindPrivateForBrowser(nsIWebBrowserChrome *aBrowser) { if (!sWindowList) return nsnull; // Get the number of browser windows. PRInt32 count = sWindowList->Count(); // This function doesn't get called very often at all ( only when // creating a new window ) so it's OK to walk the list of open // windows. for (int i = 0; i < count; i++) { HeadlessPrivate *tmpPrivate = static_cast( sWindowList->ElementAt(i)); // get the browser object for that window nsIWebBrowserChrome *chrome = static_cast( tmpPrivate->mWindow); if (chrome == aBrowser) return tmpPrivate; } return nsnull; } void HeadlessPrivate::ContentStateChange(void) { // we don't attach listeners to chrome if (mListenersAttached && !mIsChrome) return; GetListener(); if (!mEventTarget) return; AttachListeners(); } void HeadlessPrivate::ContentFinishedLoading(void) { if (mIsChrome) { // We're done loading. mChromeLoaded = PR_TRUE; // get the web browser nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // get the content DOM window for that web browser nsCOMPtr domWindow; webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); if (!domWindow) { NS_WARNING("no dom window in content finished loading\n"); return; } // resize the content domWindow->SizeToContent(); // and since we're done loading show the window, assuming that the // visibility flag has been set. PRBool visibility; mWindow->GetVisibility(&visibility); if (visibility) mWindow->SetVisibility(PR_TRUE); } } void HeadlessPrivate::ChildFocusIn(void) { if (mIsDestroyed) return; nsresult rv; nsCOMPtr webBrowser; rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); if (NS_FAILED(rv)) return; nsCOMPtr webBrowserFocus(do_QueryInterface(webBrowser)); if (!webBrowserFocus) return; webBrowserFocus->Activate(); } void HeadlessPrivate::ChildFocusOut(void) { if (mIsDestroyed) return; nsresult rv; nsCOMPtr webBrowser; rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); if (NS_FAILED(rv)) return; nsCOMPtr webBrowserFocus(do_QueryInterface(webBrowser)); if (!webBrowserFocus) return; webBrowserFocus->Deactivate(); } // Get the event listener for the chrome event handler. void HeadlessPrivate::GetListener(void) { if (mEventTarget) return; nsCOMPtr piWin; GetPIDOMWindow(getter_AddRefs(piWin)); if (!piWin) return; mEventTarget = do_QueryInterface(piWin->GetChromeEventHandler()); } // attach key and mouse event listeners void HeadlessPrivate::AttachListeners(void) { if (!mEventTarget || mListenersAttached) return; nsIDOMEventListener *eventListener = static_cast(static_cast(mEventListener)); nsresult rv; /*nsCOMPtr eventTarget = do_QueryInterface(mEventTarget); eventTarget->AddEventListener(NS_LITERAL_STRING("overflow"), eventListener, PR_TRUE, PR_FALSE);*/ nsCOMPtr eventTarget = do_QueryInterface(mEventTarget); rv = eventTarget->AddEventListener(NS_LITERAL_STRING("DOMLinkAdded"), eventListener, PR_TRUE, PR_FALSE); if (NS_FAILED(rv)) { NS_WARNING("Failed to add DOM link listener\n"); return; } rv = mEventTarget->AddEventListenerByIID(eventListener, NS_GET_IID(nsIDOMKeyListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to add key listener\n"); return; } rv = mEventTarget->AddEventListenerByIID(eventListener, NS_GET_IID(nsIDOMMouseListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to add mouse listener\n"); return; } rv = mEventTarget->AddEventListenerByIID(eventListener, NS_GET_IID(nsIDOMUIListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to add UI listener\n"); return; } // ok, all set. mListenersAttached = PR_TRUE; } void HeadlessPrivate::DetachListeners(void) { if (!mListenersAttached || !mEventTarget) return; nsIDOMEventListener *eventListener = static_cast(static_cast(mEventListener)); nsresult rv; nsCOMPtr eventTarget = do_QueryInterface(mEventTarget); rv = eventTarget->RemoveEventListener(NS_LITERAL_STRING("DOMLinkAdded"), eventListener, PR_TRUE); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove DOMLinkAdded listener\n"); return; } rv = mEventTarget->RemoveEventListenerByIID(eventListener, NS_GET_IID(nsIDOMKeyListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove key listener\n"); return; } rv = mEventTarget->RemoveEventListenerByIID(eventListener, NS_GET_IID(nsIDOMMouseListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove mouse listener\n"); return; } rv = mEventTarget->RemoveEventListenerByIID(eventListener, NS_GET_IID(nsIDOMUIListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove UI listener\n"); return; } mListenersAttached = PR_FALSE; } nsresult HeadlessPrivate::GetPIDOMWindow(nsPIDOMWindow **aPIWin) { *aPIWin = nsnull; // get the web browser nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // get the content DOM window for that web browser nsCOMPtr domWindow; webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); if (!domWindow) return NS_ERROR_FAILURE; // get the private DOM window nsCOMPtr domWindowPrivate = do_QueryInterface(domWindow); // and the root window for that DOM window *aPIWin = domWindowPrivate->GetPrivateRoot(); if (*aPIWin) { NS_ADDREF(*aPIWin); return NS_OK; } return NS_ERROR_FAILURE; } /* static */ nsresult HeadlessPrivate::RegisterAppComponent(const nsModuleComponentInfo *aComponentInfo) { nsCOMPtr cr; nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(cr)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr cm; rv = NS_GetComponentManager (getter_AddRefs (cm)); NS_ENSURE_SUCCESS (rv, rv); nsCOMPtr componentFactory; rv = NS_NewGenericFactory(getter_AddRefs(componentFactory), aComponentInfo); if (NS_FAILED(rv)) { NS_WARNING("Unable to create factory for component"); return rv; } rv = cr->RegisterFactory(aComponentInfo->mCID, aComponentInfo->mDescription, aComponentInfo->mContractID, componentFactory); NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to register factory for component"); // Call the registration hook of the component, if any if (aComponentInfo->mRegisterSelfProc) { rv = aComponentInfo->mRegisterSelfProc(cm, nsnull, nsnull, nsnull, aComponentInfo); NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to self-register component"); } return rv; } /* static */ nsresult HeadlessPrivate::RegisterAppComponents(void) { nsresult rv = NS_OK; if (!NS_FAILED(rv)) rv = RegisterAppComponent (&appInfoComp); return rv; }