/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape 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/NPL/ * * 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 Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1999 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include "nsString.h" #include "nsVoidArray.h" #include "rdf.h" #include "nsIRDFService.h" #include "nsIRDFDataSource.h" #include "nsIRDFNode.h" #include "nsIRDFObserver.h" #include "nsRDFCID.h" #include "nsIRDFContainer.h" #include "nsIRDFContainerUtils.h" #include "nsXPIDLString.h" #include "nsIServiceManager.h" #include "nsIWindowMediator.h" #include "nsCOMPtr.h" #include "nsIWebShell.h" #include "nsXPComFactory.h" #include "nsIWebShellWindow.h" #include "nsIDOMWindow.h" #include "nsIDOMElement.h" #include "nsISimpleEnumerator.h" #include "nsIDocumentViewer.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID); static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID); static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID); static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); static NS_DEFINE_IID(kIWindowMediatorIID,NS_IWINDOWMEDIATOR_IID); static NS_DEFINE_IID(kISimpleEnumberatorIID, NS_ISIMPLEENUMERATOR_IID); static NS_DEFINE_CID(kRDFContainerCID, NS_RDFCONTAINER_CID); static NS_DEFINE_IID( kISimpleEnumerator, NS_ISIMPLEENUMERATOR_IID ); static const char kURINC_WindowMediatorRoot[] = "NC:WindowMediatorRoot"; DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, URL); static nsIRDFService* gRDFService = nsnull; nsresult NS_NewRDFContainer(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFContainer** aResult) { nsresult rv; rv = nsComponentManager::CreateInstance( kRDFContainerCID, NULL, nsIRDFContainer::GetIID(), (void**)aResult ); if (NS_FAILED(rv)) return rv; rv = (*aResult)->Init(aDataSource, aResource); if (NS_FAILED(rv)) { NS_RELEASE(*aResult); } return rv; } nsresult GetDOMWindow( nsIWebShellWindow* inWindow, nsCOMPtr< nsIDOMWindow>& outDOMWindow ) { nsCOMPtr webShell; inWindow->GetWebShell( *getter_AddRefs( webShell ) ); return inWindow->ConvertWebShellToDOMWindow( webShell, getter_AddRefs( outDOMWindow ) ); } nsCOMPtr GetDOMNodeFromWebShell(nsIWebShell *aShell) { nsCOMPtr node; nsCOMPtr cv; aShell->GetContentViewer(getter_AddRefs(cv)); if (cv) { nsCOMPtr docv(do_QueryInterface(cv)); if (docv) { nsCOMPtr doc; docv->GetDocument(*getter_AddRefs(doc)); if (doc) { nsCOMPtr domdoc(do_QueryInterface(doc)); if (domdoc) { nsCOMPtr element; domdoc->GetDocumentElement(getter_AddRefs(element)); if (element) node = do_QueryInterface(element); } } } } return node; } void GetWindowType( nsIWebShellWindow* inWindow, nsString& outType ) { nsIWebShell* shell = NULL; if ( inWindow && NS_SUCCEEDED(inWindow->GetWebShell( shell ) ) ) { nsCOMPtr node( GetDOMNodeFromWebShell ( shell ) ); if (node ) { nsCOMPtr webshellElement( do_QueryInterface(node)); if ( webshellElement.get() ) webshellElement->GetAttribute("windowtype", outType ); } NS_IF_RELEASE( shell ); } } class nsWindowMediator; struct nsWindowInfo { nsWindowInfo( nsIWebShellWindow* inWindow, PRInt32 inTimeStamp ): mTimeStamp( inTimeStamp ), mWindow( inWindow ) { } ~nsWindowInfo() { } nsCOMPtr mRDFID; PRInt32 mTimeStamp; nsCOMPtr mWindow; nsString GetType() { nsString rtnString; GetWindowType( mWindow, rtnString ); return rtnString; } }; class nsWindowEnumerator; class nsWindowMediator : public nsIWindowMediator { friend class nsWindowEnumerator; public: nsWindowMediator(); virtual ~nsWindowMediator(); nsresult Init(); NS_IMETHOD GetEnumerator( const PRUnichar* inType, nsISimpleEnumerator** outEnumerator ); NS_IMETHOD GetMostRecentWindow( const PRUnichar* inType, nsIDOMWindow** outWindow ); NS_IMETHOD RegisterWindow( nsIWebShellWindow* inWindow ); NS_IMETHOD UnregisterWindow( nsIWebShellWindow* inWindow ); NS_IMETHOD UpdateWindowTimeStamp( nsIWebShellWindow* inWindow ); NS_IMETHOD UpdateWindowTitle( nsIWebShellWindow* inWindow , const PRUnichar* inTitle ); NS_IMETHOD GetWindowForResource( const PRUnichar* inResource, nsIDOMWindow** outWindow ); NS_IMETHOD ConvertISupportsToDOMWindow( nsISupports* inInterface, nsIDOMWindow** outWindow ) { return inInterface->QueryInterface(nsIDOMWindow::GetIID() , (void**) outWindow ); } // COM and RDF NS_DECL_ISUPPORTS // RDF // nsIRDFDataSource NS_IMETHOD GetURI(char* *uri) { NS_PRECONDITION(uri != nsnull, "null ptr"); if (! uri) return NS_ERROR_NULL_POINTER; *uri = nsXPIDLCString::Copy("rdf:window-mediator"); if (! *uri) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } NS_IMETHOD GetSource(nsIRDFResource* property, nsIRDFNode* target, PRBool tv, nsIRDFResource** source) { return mInner->GetSource(property, target, tv, source); } NS_IMETHOD GetSources(nsIRDFResource* property, nsIRDFNode* target, PRBool tv, nsISimpleEnumerator** sources) { return mInner->GetSources(property, target, tv, sources); } NS_IMETHOD GetTarget(nsIRDFResource* source, nsIRDFResource* property, PRBool tv, nsIRDFNode** target) { return mInner->GetTarget(source, property, tv, target); } NS_IMETHOD GetTargets(nsIRDFResource* source, nsIRDFResource* property, PRBool tv, nsISimpleEnumerator** targets) { return mInner->GetTargets(source, property, tv, targets); } NS_IMETHOD Assert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget, PRBool aTruthValue); NS_IMETHOD Unassert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget); NS_IMETHOD Change(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aOldTarget, nsIRDFNode* aNewTarget); NS_IMETHOD Move(nsIRDFResource* aOldSource, nsIRDFResource* aNewSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget); NS_IMETHOD HasAssertion(nsIRDFResource* source, nsIRDFResource* property, nsIRDFNode* target, PRBool tv, PRBool* hasAssertion) { return mInner->HasAssertion(source, property, target, tv, hasAssertion); } NS_IMETHOD AddObserver(nsIRDFObserver* n) { return mInner->AddObserver(n); } NS_IMETHOD RemoveObserver(nsIRDFObserver* n) { return mInner->RemoveObserver(n); } NS_IMETHOD ArcLabelsIn( nsIRDFNode* node, nsISimpleEnumerator** labels) { return mInner->ArcLabelsIn(node, labels); } NS_IMETHOD ArcLabelsOut(nsIRDFResource* source, nsISimpleEnumerator** labels) { return mInner->ArcLabelsOut(source, labels); } NS_IMETHOD GetAllResources(nsISimpleEnumerator** aCursor) { return mInner->GetAllResources(aCursor); } NS_IMETHOD GetAllCommands(nsIRDFResource* source, nsIEnumerator** commands); NS_IMETHOD GetAllCmds(nsIRDFResource* source, nsISimpleEnumerator** commands); NS_IMETHOD IsCommandEnabled(nsISupportsArray* aSources, nsIRDFResource* aCommand, nsISupportsArray* aArguments, PRBool* aResult); NS_IMETHOD DoCommand(nsISupportsArray* aSources, nsIRDFResource* aCommand, nsISupportsArray* aArguments); private: // Helper functions nsresult AddWindowToRDF( nsWindowInfo* ioWindowInfo ); PRInt32 AddEnumerator( nsWindowEnumerator* inEnumerator ); PRInt32 RemoveEnumerator( nsWindowEnumerator* inEnumerator); PRInt32 mTimeStamp; nsVoidArray mEnumeratorList; nsVoidArray mWindowList; // pseudo-constants for RDF static nsIRDFResource* kNC_WindowMediatorRoot; static nsIRDFResource* kNC_Name; static nsIRDFResource* kNC_URL; static PRInt32 gRefCnt; static nsIRDFDataSource* mInner; }; class nsWindowEnumerator : public nsISimpleEnumerator { public: nsWindowEnumerator ( const PRUnichar* inTypeString, nsWindowMediator& inMediator ); virtual ~nsWindowEnumerator(); NS_IMETHOD HasMoreElements(PRBool *retval); NS_IMETHOD GetNext(nsISupports **retval); NS_DECL_ISUPPORTS private: friend class nsWindowMediator; PRInt32 FindNext(); void WindowRemoved( PRInt32 inIndex); nsWindowMediator* mWindowMediator; nsString mType; PRInt32 mCurrentPosition; }; nsIRDFResource *nsWindowMediator::kNC_WindowMediatorRoot = NULL; nsIRDFResource *nsWindowMediator::kNC_Name = NULL; nsIRDFResource *nsWindowMediator::kNC_URL = NULL; PRInt32 nsWindowMediator::gRefCnt; nsIRDFDataSource *nsWindowMediator::mInner = NULL; nsWindowMediator::nsWindowMediator() : mTimeStamp( 0 ), mEnumeratorList(), mWindowList() { NS_INIT_REFCNT(); // This should really be done in the static constructor fn. nsresult rv; rv = Init(); NS_ASSERTION(NS_SUCCEEDED(rv), "uh oh, couldn't Init() for some reason"); } nsWindowMediator::~nsWindowMediator() { if (--gRefCnt == 0) { // Delete data PRInt32 count = mWindowList.Count(); for ( int32 i = 0; i< count; i++ ) { nsWindowInfo* windowInfo = ( nsWindowInfo*) mWindowList[i]; UnregisterWindow ( (windowInfo )->mWindow ); } // unregister this from the RDF service if ( gRDFService ) { gRDFService->UnregisterDataSource(this); nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); gRDFService = nsnull; } NS_IF_RELEASE(kNC_WindowMediatorRoot); NS_IF_RELEASE( kNC_Name ); NS_IF_RELEASE(kNC_URL); NS_IF_RELEASE(mInner); } } NS_IMETHODIMP nsWindowMediator::RegisterWindow( nsIWebShellWindow* inWindow ) { if ( inWindow == NULL ) return NS_ERROR_INVALID_ARG; mTimeStamp++; // Create window info struct and add to list of windows nsWindowInfo* windowInfo = new nsWindowInfo ( inWindow, mTimeStamp ); if ( windowInfo == NULL ) return NS_ERROR_OUT_OF_MEMORY; if ( !mWindowList.AppendElement( windowInfo ) ) { delete windowInfo; return NS_ERROR_OUT_OF_MEMORY; } nsresult returnValue; if ( NS_FAILED( returnValue = AddWindowToRDF( windowInfo ) )) { mWindowList.RemoveElementAt( mWindowList.Count() ); delete windowInfo; return returnValue; } return NS_OK; } NS_IMETHODIMP nsWindowMediator::UnregisterWindow( nsIWebShellWindow* inWindow ) { // Find Window info PRInt32 count = mWindowList.Count(); nsWindowInfo* windowInfo = NULL; PRInt32 windowIndex = 0; for ( windowIndex = 0; windowIndex< count; windowIndex++ ) { windowInfo = (nsWindowInfo*) mWindowList[windowIndex]; if ( ( windowInfo )->mWindow.get() == inWindow ) break; windowInfo = NULL; } if ( windowInfo == NULL ) return NS_ERROR_INVALID_ARG; // Inform the iterators PRInt32 index = -1; while (++index < mEnumeratorList.Count() ) { ((nsWindowEnumerator*)mEnumeratorList[ index ] )->WindowRemoved ( windowIndex ); } // Remove From RDF nsCOMPtr container; nsresult rv = NS_NewRDFContainer(mInner, kNC_WindowMediatorRoot, getter_AddRefs(container)); if (NS_SUCCEEDED(rv)) { container->RemoveElement( windowInfo->mRDFID, PR_TRUE ); } // Remove from the list and free up mWindowList.RemoveElement( windowInfo ); delete windowInfo; return NS_OK; } NS_METHOD nsWindowMediator::GetEnumerator( const PRUnichar* inType, nsISimpleEnumerator** outEnumerator ) { if ( outEnumerator == NULL ) return NS_ERROR_INVALID_ARG; nsWindowEnumerator* enumerator = new nsWindowEnumerator( inType, *this ); if (enumerator ) { return enumerator->QueryInterface( kISimpleEnumerator , (void**)outEnumerator ); } return NS_ERROR_OUT_OF_MEMORY; }; PRInt32 nsWindowMediator::AddEnumerator( nsWindowEnumerator* inEnumerator ) { return mEnumeratorList.AppendElement( inEnumerator ); } PRInt32 nsWindowMediator::RemoveEnumerator( nsWindowEnumerator* inEnumerator) { return mEnumeratorList.RemoveElement( inEnumerator ); } /* Returns the window of type inType ( if null return any window type ) which has the most recent time stamp */ NS_IMETHODIMP nsWindowMediator::GetMostRecentWindow( const PRUnichar* inType, nsIDOMWindow** outWindow ) { *outWindow = NULL; PRInt32 lastTimeStamp = -1; PRInt32 count = mWindowList.Count(); nsIWebShellWindow* mostRecentWindow = NULL; nsString typeString( inType ); // Find the most window with the highest time stamp that matches the requested type for ( int32 i = 0; i< count; i++ ) { nsWindowInfo* windowInfo = (nsWindowInfo*) mWindowList[i]; if ( ( inType == NULL || windowInfo->GetType() == typeString ) && windowInfo->mTimeStamp >= lastTimeStamp ) { mostRecentWindow = windowInfo->mWindow; lastTimeStamp = windowInfo->mTimeStamp; } } if( mostRecentWindow ) { nsCOMPtr DOMWindow; if( NS_SUCCEEDED ( GetDOMWindow( mostRecentWindow, DOMWindow ) ) ) { *outWindow = DOMWindow; (*outWindow)->AddRef(); return NS_OK; } else { return NS_ERROR_FAILURE; } } return NS_OK; } NS_IMETHODIMP nsWindowMediator::UpdateWindowTimeStamp( nsIWebShellWindow* inWindow ) { PRInt32 count = mWindowList.Count(); for ( int32 i = 0; i< count; i++ ) { nsWindowInfo* windowInfo = (nsWindowInfo*) mWindowList[i]; if ( windowInfo->mWindow.get() == inWindow ) { mTimeStamp++; windowInfo->mTimeStamp = mTimeStamp; return NS_OK; } } return NS_ERROR_FAILURE; } NS_IMETHODIMP nsWindowMediator::UpdateWindowTitle( nsIWebShellWindow* inWindow, const PRUnichar* inTitle ) { PRInt32 count = mWindowList.Count(); nsresult rv; for ( int32 i = 0; i< count; i++ ) { nsWindowInfo* windowInfo = (nsWindowInfo*) mWindowList[i]; if ( windowInfo->mWindow.get() == inWindow ) { nsIRDFResource* window = windowInfo->mRDFID; // Get rid of the old value nsIRDFNode* target = NULL; if ( NS_SUCCEEDED(mInner->GetTarget( window, kNC_Name, PR_TRUE, &target) ) ) { mInner->Unassert( window, kNC_Name, target ); NS_IF_RELEASE( target ); } // Add new title nsCOMPtr newTitle; if ( gRDFService && NS_FAILED(rv = gRDFService->GetLiteral( inTitle, getter_AddRefs(newTitle) ) ) ) { NS_ERROR("unable to create literal for window name"); return rv; } rv = Assert( window , kNC_Name, newTitle, PR_TRUE ); if (rv != NS_RDF_ASSERTION_ACCEPTED) { NS_ERROR("unable to set window name"); } return NS_OK; } } return NS_ERROR_FAILURE; } NS_IMETHODIMP nsWindowMediator::GetWindowForResource( const PRUnichar* inResource, nsIDOMWindow** outWindow ) { if ( outWindow == NULL ) return NS_ERROR_INVALID_ARG; *outWindow = NULL; PRInt32 count = mWindowList.Count(); // Find the window nsresult result = NS_ERROR_FAILURE; nsString temp( inResource ); char* resourceString = temp.ToNewCString(); for ( int32 i = 0; i< count; i++ ) { nsWindowInfo* windowInfo = (nsWindowInfo*) mWindowList[i]; PRBool isMatch = PR_FALSE; if ( NS_SUCCEEDED( windowInfo->mRDFID->EqualsString( resourceString, &isMatch) ) && isMatch ) { nsCOMPtr DOMWindow; if( NS_SUCCEEDED ( GetDOMWindow( windowInfo->mWindow, DOMWindow ) ) ) { *outWindow = DOMWindow; (*outWindow)->AddRef(); result = NS_OK; } break; } } delete resourceString; // Rather than returning an error when you pass in crap, return NS_OK // Doing this to avoid throwing a JS exception becasue event bubbling is not working as of 7/26/99 //return result; return NS_OK; } // COM NS_IMPL_ADDREF( nsWindowMediator ); NS_IMPL_RELEASE( nsWindowMediator ); NS_IMETHODIMP nsWindowMediator::QueryInterface(REFNSIID iid, void **result) { if (! result) return NS_ERROR_NULL_POINTER; *result = nsnull; if (iid.Equals(kIRDFDataSourceIID) || iid.Equals(kIWindowMediatorIID) || iid.Equals(kISupportsIID) ) { *result = NS_STATIC_CAST(nsIWindowMediator *, this); AddRef(); return NS_OK; } return(NS_NOINTERFACE); } // RDF nsresult nsWindowMediator::Init() { nsresult rv; if (gRefCnt++ == 0) { rv = nsServiceManager::GetService( kRDFServiceCID, kIRDFServiceIID, (nsISupports**) &gRDFService ); if (NS_FAILED(rv)) return rv; gRDFService->GetResource( kURINC_WindowMediatorRoot, &kNC_WindowMediatorRoot ); gRDFService->GetResource (kURINC_Name, &kNC_Name ); gRDFService->GetResource( kURINC_URL, &kNC_URL ); } if (NS_FAILED(rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, nsnull, kIRDFDataSourceIID, (void**) &mInner))) { return rv; } NS_WITH_SERVICE(nsIRDFContainerUtils, rdfc, kRDFContainerUtilsCID, &rv); if (NS_FAILED(rv)) return rv; rv = rdfc->MakeSeq(mInner, kNC_WindowMediatorRoot, NULL ); NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to make NC:WindowMediatorRoot a sequence"); if (NS_FAILED(rv)) return rv; if ( gRDFService == NULL ) return NS_ERROR_NULL_POINTER; // register this as a named data source with the RDF service return gRDFService->RegisterDataSource(this, PR_FALSE); } NS_IMETHODIMP nsWindowMediator::Assert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget, PRBool aTruthValue) { // XXX TODO: filter out asserts we don't care about return mInner->Assert(aSource, aProperty, aTarget, aTruthValue); } NS_IMETHODIMP nsWindowMediator::Unassert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget) { // XXX TODO: filter out unasserts we don't care about return mInner->Unassert(aSource, aProperty, aTarget); } NS_IMETHODIMP nsWindowMediator::Change(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aOldTarget, nsIRDFNode* aNewTarget) { // XXX TODO: filter out changes we don't care about return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget); } NS_IMETHODIMP nsWindowMediator::Move(nsIRDFResource* aOldSource, nsIRDFResource* aNewSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget) { // XXX TODO: filter out changes we don't care about return mInner->Move(aOldSource, aNewSource, aProperty, aTarget); } NS_IMETHODIMP nsWindowMediator::GetAllCommands(nsIRDFResource* source, nsIEnumerator/**/** commands) { NS_NOTYETIMPLEMENTED("write me!"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP nsWindowMediator::GetAllCmds(nsIRDFResource* source, nsISimpleEnumerator/**/** commands) { NS_NOTYETIMPLEMENTED("write me!"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP nsWindowMediator::IsCommandEnabled(nsISupportsArray/**/* aSources, nsIRDFResource* aCommand, nsISupportsArray/**/* aArguments, PRBool* aResult) { NS_NOTYETIMPLEMENTED("write me!"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP nsWindowMediator::DoCommand(nsISupportsArray* aSources, nsIRDFResource* aCommand, nsISupportsArray* aArguments) { NS_NOTYETIMPLEMENTED("write me!"); return NS_ERROR_NOT_IMPLEMENTED; } // Private helpers nsresult nsWindowMediator::AddWindowToRDF( nsWindowInfo* ioWindowInfo ) { if ( !ioWindowInfo || !(ioWindowInfo->mWindow) || !gRDFService ) return NS_ERROR_NULL_POINTER; nsCOMPtr window; nsresult rv; nsString windowTitle; // Make up a unique ID and create the RDF NODE nsString uniqueID = "window-"; uniqueID.Append(windowTitle ); uniqueID.Append( mTimeStamp, 10 ); char cID[ 256]; uniqueID.ToCString( cID, 256); if (NS_FAILED(rv = gRDFService->GetResource(cID, getter_AddRefs(window) ))) { NS_ERROR("unable to get window resource"); return rv; } ioWindowInfo->mRDFID = window ; // Get the RDF literal and add it to our node nsCOMPtr windowTitleLiteral; if (NS_FAILED(rv = gRDFService->GetLiteral( windowTitle.GetUnicode(), getter_AddRefs(windowTitleLiteral)))) { NS_ERROR("unable to create literal for window name"); return rv; } rv = Assert(window, kNC_Name, windowTitleLiteral, PR_TRUE); if (rv != NS_RDF_ASSERTION_ACCEPTED) { NS_ERROR("unable to set window name"); return rv; } // Add the element to the container nsCOMPtr container; rv = NS_NewRDFContainer(mInner, kNC_WindowMediatorRoot, getter_AddRefs(container)); if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv = container->AppendElement( window ) ) /* rdf_ContainerAppendElement(mInner, kNC_WindowMediatorRoot, window) */ ) { NS_ERROR("unable to add window to container"); return rv; } return NS_OK; } //---------------------------------------------------------------------- // Entry point to create nsAppShellService factory instances... NS_DEF_FACTORY(WindowMediator, nsWindowMediator) nsresult NS_NewWindowMediatorFactory(nsIFactory** aResult) { nsresult rv = NS_OK; nsIFactory* inst; inst = new nsWindowMediatorFactory; if (nsnull == inst) { rv = NS_ERROR_OUT_OF_MEMORY; } else { NS_ADDREF(inst); } *aResult = inst; return rv; } // window Enumerator nsWindowEnumerator::nsWindowEnumerator ( const PRUnichar* inTypeString, nsWindowMediator& inMediator ) : mWindowMediator( &inMediator ), mType( inTypeString ), mCurrentPosition( -1 ) { NS_INIT_REFCNT(); mWindowMediator->AddEnumerator( this ); mWindowMediator->AddRef(); } nsWindowEnumerator::~nsWindowEnumerator() { mWindowMediator->RemoveEnumerator( this ); mWindowMediator->Release(); } NS_IMETHODIMP nsWindowEnumerator::HasMoreElements(PRBool *retval) { if ( !retval ) return NS_ERROR_INVALID_ARG; *retval = PR_FALSE; if ( FindNext() != -1 ) *retval = PR_TRUE; return NS_OK; } NS_IMETHODIMP nsWindowEnumerator::GetNext(nsISupports **retval) { if ( !retval ) return NS_ERROR_INVALID_ARG; *retval = NULL; PRInt32 index = FindNext(); if ( index >= 0 ) { nsWindowInfo* windowInfo = (nsWindowInfo*) mWindowMediator->mWindowList[index]; nsCOMPtr domWindow; GetDOMWindow( windowInfo->mWindow, domWindow ); domWindow->QueryInterface( kISupportsIID ,(void**)retval ); mCurrentPosition++; } return NS_OK; } PRInt32 nsWindowEnumerator::FindNext() { PRInt32 numWindows = mWindowMediator->mWindowList.Count(); PRBool allWindows = (mType.Length() == 0); for ( PRInt32 i = mCurrentPosition+1; i < numWindows; i++ ) { nsWindowInfo* windowInfo = (nsWindowInfo*) mWindowMediator->mWindowList[i]; if ( allWindows || ( windowInfo->GetType() == mType ) ) { return i; } } return -1; } // if a window is being removed adjust the iterator's current position void nsWindowEnumerator::WindowRemoved( PRInt32 inIndex) { if ( inIndex <= mCurrentPosition ) { mCurrentPosition--; } } /* * Implementations of nsISupports interface methods... */ NS_IMPL_ADDREF(nsWindowEnumerator); NS_IMPL_RELEASE(nsWindowEnumerator); NS_IMPL_QUERY_INTERFACE(nsWindowEnumerator, kISimpleEnumberatorIID);