/* -*- 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 Communicator client code. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * Pierre Phaneuf */ #include "nsDocShell.h" #include "nsIWebShell.h" #include "nsIInterfaceRequestor.h" #include "nsIDocumentLoader.h" #include "nsIContentViewer.h" #include "nsIDocumentViewer.h" #include "nsIMarkupDocumentViewer.h" #include "nsIClipboardCommands.h" #include "nsIDeviceContext.h" #include "nsILinkHandler.h" #include "nsIStreamListener.h" #include "nsIPrompt.h" #include "nsNetUtil.h" #include "nsIProtocolHandler.h" #include "nsIDNSService.h" #include "nsIRefreshURI.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObjectOwner.h" #include "nsIDocumentLoaderObserver.h" #include "nsIProgressEventSink.h" #include "nsDOMEvent.h" #include "nsIPresContext.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsIEventQueueService.h" #include "nsCRT.h" #include "nsVoidArray.h" #include "nsString.h" #include "nsWidgetsCID.h" #include "nsGfxCIID.h" #include "plevent.h" #include "prprf.h" #include "nsIPluginHost.h" #include "nsplugin.h" #include "nsIFrame.h" //#include "nsPluginsCID.h" #include "nsIPluginManager.h" #include "nsIPref.h" #include "nsITimer.h" #include "nsITimerCallback.h" #include "nsIBrowserWindow.h" #include "nsIContent.h" #include "prlog.h" #include "nsCOMPtr.h" #include "nsIPresShell.h" #include "nsIWebShellServices.h" #include "nsIGlobalHistory.h" #include "prmem.h" #include "nsXPIDLString.h" #include "nsIDOMHTMLElement.h" #include "nsIDOMHTMLDocument.h" #include "nsLayoutCID.h" #include "nsIDOMRange.h" #include "nsIURIContentListener.h" #include "nsIDOMDocument.h" #include "nsTimer.h" #include "nsIBaseWindow.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeNode.h" #include "nsIDocShellTreeOwner.h" #include "nsCURILoader.h" #include "nsILocaleService.h" #include "nsIStringBundle.h" static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); #ifdef XP_PC #include #endif #include "nsIIOService.h" #include "nsIURL.h" #include "nsIProtocolHandler.h" //XXX for nsIPostData; this is wrong; we shouldn't see the nsIDocument type #include "nsIDocument.h" #ifdef DEBUG #undef NOISY_LINKS #undef NOISY_WEBSHELL_LEAKS #else #undef NOISY_LINKS #undef NOISY_WEBSHELL_LEAKS #endif #define NOISY_WEBSHELL_LEAKS #ifdef NOISY_WEBSHELL_LEAKS #undef DETECT_WEBSHELL_LEAKS #define DETECT_WEBSHELL_LEAKS #endif #ifdef NS_DEBUG /** * Note: the log module is created during initialization which * means that you cannot perform logging before then. */ static PRLogModuleInfo* gLogModule = PR_NewLogModule("webshell"); #endif #define WEB_TRACE_CALLS 0x1 #define WEB_TRACE_HISTORY 0x2 #define WEB_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit)) #ifdef NS_DEBUG #define WEB_TRACE(_bit,_args) \ PR_BEGIN_MACRO \ if (WEB_LOG_TEST(gLogModule,_bit)) { \ PR_LogPrint _args; \ } \ PR_END_MACRO #else #define WEB_TRACE(_bit,_args) #endif #if OLD_EVENT_QUEUE /* The following is not used for the GTK version of the browser. * It is still lurking around for Motif */ PLEventQueue* gWebShell_UnixEventQueue; void nsWebShell_SetUnixEventQueue(PLEventQueue* aEventQueue) { gWebShell_UnixEventQueue = aEventQueue; } #endif /* OLD_EVENT_QUEUE */ static NS_DEFINE_CID(kGlobalHistoryCID, NS_GLOBALHISTORY_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); //---------------------------------------------------------------------- typedef enum { eCharsetReloadInit, eCharsetReloadRequested, eCharsetReloadStopOrigional } eCharsetReloadState; class nsWebShell : public nsDocShell, public nsIWebShell, public nsIWebShellContainer, public nsIWebShellServices, public nsILinkHandler, public nsIDocumentLoaderObserver, public nsIProgressEventSink, // should go away (nsIDocLoaderObs) public nsIRefreshURI, public nsIURIContentListener, public nsIClipboardCommands { public: nsWebShell(); virtual ~nsWebShell(); NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW // nsISupports NS_DECL_ISUPPORTS NS_DECL_NSIURICONTENTLISTENER // nsIInterfaceRequestor NS_DECL_NSIINTERFACEREQUESTOR // nsIContentViewerContainer NS_IMETHOD Embed(nsIContentViewer* aDocViewer, const char* aCommand, nsISupports* aExtraInfo); // nsIWebShell NS_IMETHOD Init(nsNativeWidget aNativeParent, PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsScrollPreference aScrolling = nsScrollPreference_kAuto, PRBool aAllowPlugins = PR_TRUE, PRBool aIsSunkenBorder = PR_FALSE); NS_IMETHOD SizeToContent(); NS_IMETHOD RemoveFocus(); NS_IMETHOD SetContentViewer(nsIContentViewer* aViewer); NS_IMETHOD SetContainer(nsIWebShellContainer* aContainer); NS_IMETHOD GetContainer(nsIWebShellContainer*& aResult); NS_IMETHOD GetTopLevelWindow(nsIWebShellContainer** aWebShellWindow); NS_IMETHOD GetPrefs(nsIPref*& aPrefs); NS_IMETHOD GetRootWebShell(nsIWebShell*& aResult); NS_IMETHOD SetParent(nsIWebShell* aParent); NS_IMETHOD GetParent(nsIWebShell*& aParent); NS_IMETHOD GetReferrer(nsIURI **aReferrer); NS_IMETHOD GetChildCount(PRInt32& aResult); NS_IMETHOD AddChild(nsIWebShell* aChild); NS_IMETHOD RemoveChild(nsIWebShell* aChild); NS_IMETHOD ChildAt(PRInt32 aIndex, nsIWebShell*& aResult); NS_IMETHOD GetName(const PRUnichar** aName); NS_IMETHOD SetName(const PRUnichar* aName); NS_IMETHOD FindChildWithName(const PRUnichar* aName, nsIWebShell*& aResult); NS_IMETHOD SetWebShellType(nsWebShellType aWebShellType); NS_IMETHOD GetScrolling(PRInt32& aScrolling); NS_IMETHOD SetScrolling(PRInt32 aScrolling, PRBool aSetCurrentAndInitial = PR_TRUE); // Document load api's NS_IMETHOD GetDocumentLoader(nsIDocumentLoader*& aResult); NS_IMETHOD LoadURL(const PRUnichar *aURLSpec, nsIInputStream* aPostDataStream=nsnull, PRBool aModifyHistory=PR_TRUE, nsLoadFlags aType = nsIChannel::LOAD_NORMAL, const PRUint32 localIP = 0, nsISupports * aHistoryState = nsnull, const PRUnichar* aReferrer=nsnull); NS_IMETHOD LoadURL(const PRUnichar *aURLSpec, const char* aCommand, nsIInputStream* aPostDataStream=nsnull, PRBool aModifyHistory=PR_TRUE, nsLoadFlags aType = nsIChannel::LOAD_NORMAL, const PRUint32 localIP = 0, nsISupports * aHistoryState=nsnull, const PRUnichar* aReferrer=nsnull); NS_IMETHOD LoadURI(nsIURI * aUri, const char * aCommand, nsIInputStream* aPostDataStream=nsnull, PRBool aModifyHistory=PR_TRUE, nsLoadFlags aType = nsIChannel::LOAD_NORMAL, const PRUint32 aLocalIP=0, nsISupports * aHistoryState=nsnull, const PRUnichar* aReferrer=nsnull); NS_IMETHOD Stop(void); NS_IMETHOD StopBeforeRequestingURL(); NS_IMETHOD StopAfterURLAvailable(); NS_IMETHOD Reload(nsLoadFlags aType); // History api's NS_IMETHOD Back(void); NS_IMETHOD CanBack(void); NS_IMETHOD Forward(void); NS_IMETHOD CanForward(void); NS_IMETHOD GoTo(PRInt32 aHistoryIndex); NS_IMETHOD GetHistoryLength(PRInt32& aResult); NS_IMETHOD GetHistoryIndex(PRInt32& aResult); NS_IMETHOD GetURL(PRInt32 aHistoryIndex, const PRUnichar** aURLResult); // nsIWebShellContainer NS_IMETHOD WillLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, nsLoadType aReason); NS_IMETHOD BeginLoadURL(nsIWebShell* aShell, const PRUnichar* aURL); NS_IMETHOD ProgressLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, PRInt32 aProgress, PRInt32 aProgressMax); NS_IMETHOD EndLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, nsresult aStatus); NS_IMETHOD NewWebShell(PRUint32 aChromeMask, PRBool aVisible, nsIWebShell *&aNewWebShell); NS_IMETHOD ContentShellAdded(nsIWebShell* aChildShell, nsIContent* frameNode); NS_IMETHOD FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult); NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken); NS_IMETHOD GetHistoryState(nsISupports** aLayoutHistoryState); NS_IMETHOD SetHistoryState(nsISupports* aLayoutHistoryState); // nsIWebShellServices NS_IMETHOD LoadDocument(const char* aURL, const char* aCharset= nsnull , nsCharsetSource aSource = kCharsetUninitialized); NS_IMETHOD ReloadDocument(const char* aCharset= nsnull , nsCharsetSource aSource = kCharsetUninitialized, const char* aCmd=nsnull); NS_IMETHOD StopDocumentLoad(void); NS_IMETHOD SetRendering(PRBool aRender); // nsILinkHandler NS_IMETHOD OnLinkClick(nsIContent* aContent, nsLinkVerb aVerb, const PRUnichar* aURLSpec, const PRUnichar* aTargetSpec, nsIInputStream* aPostDataStream = 0); NS_IMETHOD OnOverLink(nsIContent* aContent, const PRUnichar* aURLSpec, const PRUnichar* aTargetSpec); NS_IMETHOD GetLinkState(const PRUnichar* aURLSpec, nsLinkState& aState); // nsIScriptGlobalObjectOwner NS_DECL_NSISCRIPTGLOBALOBJECTOWNER // nsIDocumentLoaderObserver NS_IMETHOD OnStartDocumentLoad(nsIDocumentLoader* loader, nsIURI* aURL, const char* aCommand); NS_IMETHOD OnEndDocumentLoad(nsIDocumentLoader* loader, nsIChannel* channel, nsresult aStatus); NS_IMETHOD OnStartURLLoad(nsIDocumentLoader* loader, nsIChannel* channel); NS_IMETHOD OnProgressURLLoad(nsIDocumentLoader* loader, nsIChannel* channel, PRUint32 aProgress, PRUint32 aProgressMax); NS_IMETHOD OnStatusURLLoad(nsIDocumentLoader* loader, nsIChannel* channel, nsString& aMsg); NS_IMETHOD OnEndURLLoad(nsIDocumentLoader* loader, nsIChannel* channel, nsresult aStatus); NS_IMETHOD HandleUnknownContentType(nsIDocumentLoader* loader, nsIChannel* channel, const char *aContentType, const char *aCommand ); NS_IMETHOD RefreshURL(const char* aURL, PRInt32 millis, PRBool repeat); // nsIRefreshURL interface methods... NS_IMETHOD RefreshURI(nsIURI* aURI, PRInt32 aMillis, PRBool aRepeat); NS_IMETHOD CancelRefreshURITimers(void); // nsIProgressEventSink NS_DECL_NSIPROGRESSEVENTSINK // nsIClipboardCommands NS_IMETHOD CanCutSelection (PRBool* aResult); NS_IMETHOD CanCopySelection (PRBool* aResult); NS_IMETHOD CanPasteSelection(PRBool* aResult); NS_IMETHOD CutSelection (void); NS_IMETHOD CopySelection (void); NS_IMETHOD PasteSelection(void); NS_IMETHOD SelectAll(void); NS_IMETHOD SelectNone(void); NS_IMETHOD FindNext(const PRUnichar * aSearchStr, PRBool aMatchCase, PRBool aSearchDown, PRBool &aIsFound); // nsIBaseWindow NS_DECL_NSIBASEWINDOW // nsIDocShell NS_DECL_NSIDOCSHELL // nsWebShell nsIEventQueue* GetEventQueue(void); void HandleLinkClickEvent(nsIContent *aContent, nsLinkVerb aVerb, const PRUnichar* aURLSpec, const PRUnichar* aTargetSpec, nsIInputStream* aPostDataStream = 0); void ShowHistory(); nsIWebShell* GetTarget(const PRUnichar* aName); nsIBrowserWindow* GetBrowserWindow(void); static void RefreshURLCallback(nsITimer* aTimer, void* aClosure); static nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent); nsresult CreatePluginHost(PRBool aAllowPlugins); nsresult DestroyPluginHost(void); NS_IMETHOD IsBusy(PRBool& aResult); NS_IMETHOD SetSessionHistory(nsISessionHistory * aSHist); NS_IMETHOD GetSessionHistory(nsISessionHistory *& aResult); NS_IMETHOD SetIsInSHist(PRBool aIsFrame); NS_IMETHOD GetIsInSHist(PRBool& aIsFrame); NS_IMETHOD GetURL(const PRUnichar** aURL); NS_IMETHOD SetURL(const PRUnichar* aURL); protected: void GetRootWebShellEvenIfChrome(nsIWebShell** aResult); void InitFrameData(PRBool aCompleteInitScrolling); nsresult CheckForTrailingSlash(nsIURI* aURL); nsresult GetViewManager(nsIViewManager* *viewManager); nsresult InitDialogVars(void); nsIEventQueue* mThreadEventQueue; nsIScriptGlobalObject *mScriptGlobal; nsIScriptContext* mScriptContext; nsIWebShellContainer* mContainer; nsIDeviceContext* mDeviceContext; nsIPref* mPrefs; nsIWidget* mWindow; nsIDocumentLoader* mDocLoader; nsCOMPtr mPrompter; nsCOMPtr mStringBundle; nsString mDefaultCharacterSet; nsVoidArray mHistory; PRInt32 mHistoryIndex; nsIGlobalHistory* mHistoryService; nsISessionHistory * mSHist; nsString mURL; nsString mReferrer; nsString mOverURL; nsString mOverTarget; PRPackedBool mIsInSHist; PRPackedBool mFailedToLoadHistoryService; nsScrollPreference mScrollPref; PRInt32 mScrolling[2]; nsVoidArray mRefreshments; eCharsetReloadState mCharsetReloadState; nsISupports* mHistoryState; // Weak reference. Session history owns this. void ReleaseChildren(); NS_IMETHOD DestroyChildren(); nsresult CreateScriptEnvironment(); nsresult DoLoadURL(nsIURI * aUri, const char* aCommand, nsIInputStream* aPostDataStream, nsLoadFlags aType, const PRUint32 aLocalIP, const PRUnichar* aReferrer, PRBool aKickOffLoad = PR_TRUE); nsresult PrepareToLoadURI(nsIURI * aUri, const char * aCommand, nsIInputStream * aPostStream, PRBool aModifyHistory, nsLoadFlags aType, const PRUint32 aLocalIP, nsISupports * aHistoryState, const PRUnichar * aReferrer); nsresult CreateViewer(nsIChannel* aChannel, const char* aContentType, const char* aCommand, nsIStreamListener** aResult); float mZoom; static nsIPluginHost *mPluginHost; static nsIPluginManager *mPluginManager; static PRUint32 mPluginInitCnt; PRBool mProcessedEndDocumentLoad; PRBool mViewSource; // if there is no mWindow, this will keep track of the bounds --dwc0001 nsRect mBounds; MOZ_TIMER_DECLARE(mTotalTime) #ifdef DETECT_WEBSHELL_LEAKS private: // We're counting the number of |nsWebShells| to help find leaks static unsigned long gNumberOfWebShells; public: static unsigned long TotalWebShellsInExistence() { return gNumberOfWebShells; } #endif }; #ifdef DETECT_WEBSHELL_LEAKS unsigned long nsWebShell::gNumberOfWebShells = 0; extern "C" NS_WEB unsigned long NS_TotalWebShellsInExistence() { return nsWebShell::TotalWebShellsInExistence(); } #endif //---------------------------------------------------------------------- // Class IID's static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_IID(kChildCID, NS_CHILD_CID); static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID); static NS_DEFINE_IID(kDocLoaderServiceCID, NS_DOCUMENTLOADER_SERVICE_CID); static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID); // IID's static NS_DEFINE_IID(kIContentViewerContainerIID, NS_ICONTENT_VIEWER_CONTAINER_IID); static NS_DEFINE_IID(kIDocumentLoaderObserverIID, NS_IDOCUMENT_LOADER_OBSERVER_IID); static NS_DEFINE_IID(kIProgressEventSinkIID, NS_IPROGRESSEVENTSINK_IID); static NS_DEFINE_IID(kIDeviceContextIID, NS_IDEVICE_CONTEXT_IID); static NS_DEFINE_IID(kIDocumentLoaderIID, NS_IDOCUMENTLOADER_IID); static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kRefreshURIIID, NS_IREFRESHURI_IID); static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID); static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID); static NS_DEFINE_IID(kITimerCallbackIID, NS_ITIMERCALLBACK_IID); static NS_DEFINE_IID(kIWebShellContainerIID, NS_IWEB_SHELL_CONTAINER_IID); static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_IID); static NS_DEFINE_IID(kIClipboardCommandsIID, NS_ICLIPBOARDCOMMANDS_IID); static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); static NS_DEFINE_IID(kISessionHistoryIID, NS_ISESSIONHISTORY_IID); static NS_DEFINE_IID(kIDOMHTMLDocumentIID, NS_IDOMHTMLDOCUMENT_IID); static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID); // XXX not sure static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID); nsIPluginHost *nsWebShell::mPluginHost = nsnull; nsIPluginManager *nsWebShell::mPluginManager = nsnull; PRUint32 nsWebShell::mPluginInitCnt = 0; nsresult nsWebShell::CreatePluginHost(PRBool aAllowPlugins) { nsresult rv = NS_OK; if ((PR_TRUE == aAllowPlugins) && (0 == mPluginInitCnt)) { if (nsnull == mPluginManager) { // use the service manager to obtain the plugin manager. rv = nsServiceManager::GetService(kCPluginManagerCID, kIPluginManagerIID, (nsISupports**)&mPluginManager); if (NS_OK == rv) { if (NS_OK == mPluginManager->QueryInterface(kIPluginHostIID, (void **)&mPluginHost)) { mPluginHost->Init(); } } } } mPluginInitCnt++; return rv; } nsresult nsWebShell::DestroyPluginHost(void) { mPluginInitCnt--; NS_ASSERTION(!(mPluginInitCnt < 0), "underflow in plugin host destruction"); if (0 == mPluginInitCnt) { if (nsnull != mPluginHost) { mPluginHost->Destroy(); mPluginHost->Release(); mPluginHost = NULL; } // use the service manager to release the plugin manager. if (nsnull != mPluginManager) { nsServiceManager::ReleaseService(kCPluginManagerCID, mPluginManager); mPluginManager = NULL; } } return NS_OK; } //---------------------------------------------------------------------- // Note: operator new zeros our memory nsWebShell::nsWebShell() : nsDocShell() { #ifdef DETECT_WEBSHELL_LEAKS // We're counting the number of |nsWebShells| to help find leaks ++gNumberOfWebShells; #endif #ifdef NOISY_WEBSHELL_LEAKS printf("WEBSHELL+ = %ld\n", gNumberOfWebShells); #endif NS_INIT_REFCNT(); mHistoryIndex = -1; mScrollPref = nsScrollPreference_kAuto; mScriptGlobal = nsnull; mScriptContext = nsnull; mThreadEventQueue = nsnull; InitFrameData(PR_TRUE); mItemType = typeContent; mSHist = nsnull; mIsInSHist = PR_FALSE; mFailedToLoadHistoryService = PR_FALSE; mDefaultCharacterSet = ""; mProcessedEndDocumentLoad = PR_FALSE; mCharsetReloadState = eCharsetReloadInit; mViewSource=PR_FALSE; mHistoryService = nsnull; mHistoryState = nsnull; } nsWebShell::~nsWebShell() { if (nsnull != mHistoryService) { nsServiceManager::ReleaseService(kGlobalHistoryCID, mHistoryService); mHistoryService = nsnull; } // Stop any pending document loads and destroy the loader... if (nsnull != mDocLoader) { mDocLoader->Stop(); mDocLoader->RemoveObserver((nsIDocumentLoaderObserver*)this); mDocLoader->SetContainer(nsnull); NS_RELEASE(mDocLoader); } // Cancel any timers that were set for this loader. CancelRefreshURITimers(); ++mRefCnt; // following releases can cause this destructor to be called // recursively if the refcount is allowed to remain 0 NS_IF_RELEASE(mSHist); NS_IF_RELEASE(mWindow); NS_IF_RELEASE(mThreadEventQueue); mContentViewer=nsnull; NS_IF_RELEASE(mDeviceContext); NS_IF_RELEASE(mPrefs); NS_IF_RELEASE(mContainer); if (nsnull != mScriptGlobal) { mScriptGlobal->SetWebShell(nsnull); NS_RELEASE(mScriptGlobal); } if (nsnull != mScriptContext) { mScriptContext->SetOwner(nsnull); NS_RELEASE(mScriptContext); } InitFrameData(PR_TRUE); // XXX Because we hold references to the children and they hold references // to us we never get destroyed. See Destroy() instead... #if 0 // Release references on our children ReleaseChildren(); #endif // Free up history memory PRInt32 i, n = mHistory.Count(); for (i = 0; i < n; i++) { nsString* s = (nsString*) mHistory.ElementAt(i); delete s; } DestroyPluginHost(); #ifdef DETECT_WEBSHELL_LEAKS // We're counting the number of |nsWebShells| to help find leaks --gNumberOfWebShells; #endif #ifdef NOISY_WEBSHELL_LEAKS printf("WEBSHELL- = %ld\n", gNumberOfWebShells); #endif } void nsWebShell::InitFrameData(PRBool aCompleteInitScrolling) { if (aCompleteInitScrolling) { mScrolling[0] = -1; mScrolling[1] = -1; SetMarginWidth(-1); SetMarginHeight(-1); } else { mScrolling[1] = mScrolling[0]; } } void nsWebShell::ReleaseChildren() { PRInt32 i, n = mChildren.Count(); for (i = 0; i < n; i++) { nsCOMPtr shell = dont_AddRef((nsIDocShellTreeItem*)mChildren.ElementAt(i)); shell->SetParent(nsnull); //Break circular reference of webshell to contentviewer nsCOMPtr webShell(do_QueryInterface(shell)); webShell->SetContentViewer(nsnull); } mChildren.Clear(); } NS_IMETHODIMP nsWebShell::DestroyChildren() { PRInt32 i, n = mChildren.Count(); for (i = 0; i < n; i++) { nsIDocShellTreeItem * shell = (nsIDocShellTreeItem*) mChildren.ElementAt(i); shell->SetParent(nsnull); nsCOMPtr shellWin(do_QueryInterface(shell)); shellWin->Destroy(); NS_RELEASE(shell); } mChildren.Clear(); return NS_OK; } NS_IMPL_ADDREF(nsWebShell) NS_IMPL_RELEASE(nsWebShell) NS_INTERFACE_MAP_BEGIN(nsWebShell) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebShell) NS_INTERFACE_MAP_ENTRY(nsIWebShell) NS_INTERFACE_MAP_ENTRY(nsIWebShellServices) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIContentViewerContainer, nsIWebShell) NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner) NS_INTERFACE_MAP_ENTRY(nsIDocumentLoaderObserver) NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink) NS_INTERFACE_MAP_ENTRY(nsIWebShellContainer) NS_INTERFACE_MAP_ENTRY(nsILinkHandler) NS_INTERFACE_MAP_ENTRY(nsIRefreshURI) NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIURIContentListener) NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) NS_INTERFACE_MAP_ENTRY(nsIDocShell) NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem) NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeNode) NS_INTERFACE_MAP_END NS_IMETHODIMP nsWebShell::GetInterface(const nsIID &aIID, void** aInstancePtr) { NS_ENSURE_ARG_POINTER(aInstancePtr); nsresult rv = NS_OK; if(aIID.Equals(NS_GET_IID(nsILinkHandler))) { *aInstancePtr = NS_STATIC_CAST(nsILinkHandler*, this); NS_ADDREF((nsISupports*)*aInstancePtr); return NS_OK; } else if(aIID.Equals(NS_GET_IID(nsIScriptGlobalObjectOwner))) { *aInstancePtr = NS_STATIC_CAST(nsIScriptGlobalObjectOwner*, this); NS_ADDREF((nsISupports*)*aInstancePtr); return NS_OK; } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) { *aInstancePtr = NS_STATIC_CAST(nsIURIContentListener*, this); NS_ADDREF((nsISupports*)*aInstancePtr); return NS_OK; } else if(aIID.Equals(NS_GET_IID(nsIScriptGlobalObject))) { NS_ENSURE_SUCCESS(CreateScriptEnvironment(), NS_ERROR_FAILURE); *aInstancePtr = mScriptGlobal; NS_ADDREF((nsISupports*)*aInstancePtr); return NS_OK; } else if(mPluginManager) //XXX this seems a little wrong. MMP rv = mPluginManager->QueryInterface(aIID, aInstancePtr); if (!*aInstancePtr || NS_FAILED(rv)) return QueryInterface(aIID, aInstancePtr); else return rv; } NS_IMETHODIMP nsWebShell::Embed(nsIContentViewer* aContentViewer, const char* aCommand, nsISupports* aExtraInfo) { nsresult rv; nsRect bounds; WEB_TRACE(WEB_TRACE_CALLS, ("nsWebShell::Embed: this=%p aDocViewer=%p aCommand=%s aExtraInfo=%p", this, aContentViewer, aCommand ? aCommand : "", aExtraInfo)); // // Copy content viewer state from previous or parent content viewer. // // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad! // // Do NOT to maintain a reference to the old content viewer outside // of this "copying" block, or it will not be destroyed until the end of // this routine and all