forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			4485 lines
		
	
	
	
		
			131 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			4485 lines
		
	
	
	
		
			131 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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 <pp@ludusdesign.com>
 | |
|  */
 | |
| #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 <windows.h>
 | |
| #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<nsIPrompt> mPrompter;
 | |
|   nsCOMPtr<nsIStringBundle> 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<nsIDocShellTreeItem> shell = dont_AddRef((nsIDocShellTreeItem*)mChildren.ElementAt(i));
 | |
|     shell->SetParent(nsnull);
 | |
| 
 | |
|     //Break circular reference of webshell to contentviewer
 | |
|     nsCOMPtr<nsIWebShell> 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<nsIBaseWindow> 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 <SCRIPT>s and event handlers fail! (bug 20315)
 | |
|   //
 | |
|   // In this block of code, if we get an error result, we return it
 | |
|   // but if we get a null pointer, that's perfectly legal for parent
 | |
|   // and parentContentViewer.
 | |
|   //
 | |
|   nsCOMPtr<nsIWebShell> parent;
 | |
|   rv = GetParent(*getter_AddRefs(parent));
 | |
|   if (NS_FAILED(rv)) { return rv; }
 | |
|   
 | |
|   if (mContentViewer || parent) 
 | |
|   {
 | |
|     nsCOMPtr<nsIMarkupDocumentViewer> oldMUDV;
 | |
|     if (mContentViewer) { // Get any interesting state from old content viewer
 | |
|       // XXX: it would be far better to just reuse the document viewer ,
 | |
|       //      since we know we're just displaying the same document as before
 | |
|       oldMUDV = do_QueryInterface(mContentViewer);
 | |
|     }
 | |
|     else
 | |
|     { // No old content viewer, so get state from parent's content viewer
 | |
|       nsCOMPtr<nsIContentViewer> parentContentViewer;
 | |
|       rv = parent->GetContentViewer(getter_AddRefs(parentContentViewer));
 | |
|       if (NS_FAILED(rv)) { return rv; }
 | |
|       if (parentContentViewer) {
 | |
|         oldMUDV = do_QueryInterface(parentContentViewer);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     PRUnichar *defaultCharset=nsnull;
 | |
|     PRUnichar *forceCharset=nsnull;
 | |
|     PRUnichar *hintCharset=nsnull;
 | |
|     PRInt32 hintCharsetSource;
 | |
| 
 | |
|     nsCOMPtr<nsIMarkupDocumentViewer> newMUDV = do_QueryInterface(aContentViewer);
 | |
|     if (oldMUDV && newMUDV)
 | |
|     {
 | |
|       NS_ENSURE_SUCCESS(oldMUDV->GetDefaultCharacterSet (&defaultCharset), NS_ERROR_FAILURE);
 | |
|       NS_ENSURE_SUCCESS(oldMUDV->GetForceCharacterSet (&forceCharset), NS_ERROR_FAILURE);
 | |
|       NS_ENSURE_SUCCESS(oldMUDV->GetHintCharacterSet (&hintCharset), NS_ERROR_FAILURE);
 | |
|       NS_ENSURE_SUCCESS(oldMUDV->GetHintCharacterSetSource (&hintCharsetSource), NS_ERROR_FAILURE);
 | |
| 
 | |
|       // set the old state onto the new content viewer
 | |
|       NS_ENSURE_SUCCESS(newMUDV->SetDefaultCharacterSet (defaultCharset), NS_ERROR_FAILURE);
 | |
|       NS_ENSURE_SUCCESS(newMUDV->SetForceCharacterSet (forceCharset), NS_ERROR_FAILURE);
 | |
|       NS_ENSURE_SUCCESS(newMUDV->SetHintCharacterSet (hintCharset), NS_ERROR_FAILURE);
 | |
|       NS_ENSURE_SUCCESS(newMUDV->SetHintCharacterSetSource (hintCharsetSource), NS_ERROR_FAILURE);
 | |
| 
 | |
|       if (defaultCharset) {
 | |
|         Recycle(defaultCharset);
 | |
|       }
 | |
|       if (forceCharset) {
 | |
|         Recycle(forceCharset);
 | |
|       }
 | |
|       if (hintCharset) {
 | |
|         Recycle(hintCharset);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   // End copying block (Don't hold content/document viewer ref beyond here!!)
 | |
| 
 | |
|   mContentViewer = nsnull;
 | |
|   if (nsnull != mScriptContext) {
 | |
|     mScriptContext->GC();
 | |
|   }
 | |
|   mContentViewer = aContentViewer;
 | |
| 
 | |
|   // check to see if we have a window to embed into --dwc0001
 | |
|   /* Note we also need to check for the presence of a native widget. If the
 | |
|      webshell is hidden before it's embedded, which can happen in an onload
 | |
|      handler, the native widget is destroyed before this code is run.  This
 | |
|      appears to be mostly harmless except on Windows, where the subsequent
 | |
|      attempt to create a child window without a parent is met with disdain
 | |
|      by the OS. It's handy, then, that GetNativeData on Windows returns
 | |
|      null in this case. */
 | |
|   if(mWindow && mWindow->GetNativeData(NS_NATIVE_WIDGET)) {
 | |
|     mWindow->GetClientBounds(bounds);
 | |
|     bounds.x = bounds.y = 0;
 | |
|     rv = mContentViewer->Init(mWindow->GetNativeData(NS_NATIVE_WIDGET),
 | |
|                               mDeviceContext,
 | |
|                               mPrefs,
 | |
|                               bounds,
 | |
|                               mScrollPref);
 | |
| 
 | |
|     // If the history state has been set by session history,
 | |
|     // set it on the pres shell now that we have a content
 | |
|     // viewer.
 | |
|     if (mContentViewer && mHistoryState) {
 | |
|       nsCOMPtr<nsIDocumentViewer> docv = do_QueryInterface(mContentViewer);
 | |
|       if (nsnull != docv) {
 | |
|         nsCOMPtr<nsIPresShell> shell;
 | |
|         rv = docv->GetPresShell(*getter_AddRefs(shell));
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|           rv = shell->SetHistoryState((nsILayoutHistoryState*) mHistoryState);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|       mContentViewer->Show();
 | |
|     }
 | |
|   } else {
 | |
|     mContentViewer = nsnull;
 | |
|   }
 | |
| 
 | |
|   // Now that we have switched documents, forget all of our children
 | |
|   DestroyChildren();
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::HandleUnknownContentType(nsIDocumentLoader* loader,
 | |
|                                      nsIChannel* channel,
 | |
|                                      const char *aContentType,
 | |
|                                      const char *aCommand ) {
 | |
|     // If we have a doc loader observer, let it respond to this. 
 | |
|     // if we don't have a doc loader observer...we still need to reach the unknown content handler
 | |
|     // somehow...we must be a frame so try asking our parent for a doc loader observer...
 | |
|     if (!mDocLoaderObserver && mParent) {
 | |
|       nsCOMPtr<nsIWebShell> root;
 | |
|       nsCOMPtr<nsIDocumentLoaderObserver> observer;
 | |
|       nsresult res = GetRootWebShell(*getter_AddRefs(root));
 | |
| 
 | |
|       if (NS_SUCCEEDED(res) && root)
 | |
|         root->GetDocLoaderObserver(getter_AddRefs(observer));
 | |
|       if (observer)
 | |
|         return observer->HandleUnknownContentType(mDocLoader, channel, aContentType, aCommand);
 | |
|     }
 | |
|     
 | |
|     return mDocLoaderObserver ? mDocLoaderObserver->HandleUnknownContentType( mDocLoader, channel, aContentType, aCommand )
 | |
|                               : NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::Init(nsNativeWidget aNativeParent,
 | |
|                  PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
 | |
|                  nsScrollPreference aScrolling,
 | |
|                  PRBool aAllowPlugins,
 | |
|                  PRBool aIsSunkenBorder)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   // Cache the PL_EventQueue of the current UI thread...
 | |
|   //
 | |
|   // Since this call must be made on the UI thread, we know the Event Queue
 | |
|   // will be associated with the current thread...
 | |
|   //
 | |
|   NS_WITH_SERVICE(nsIEventQueueService, eventService, kEventQueueServiceCID, &rv);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD, &mThreadEventQueue);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   //XXX make sure plugins have started up. this really needs to
 | |
|   //be associated with the nsIContentViewerContainer interfaces,
 | |
|   //not the nsIWebShell interfaces. this is a hack. MMP
 | |
|   nsRect aBounds(x,y,w,h);
 | |
|   mBounds.SetRect(x,y,w,h);     // initialize the webshells bounds --dwc0001
 | |
|   nsWidgetInitData  widgetInit;
 | |
| 
 | |
|   CreatePluginHost(aAllowPlugins);
 | |
| 
 | |
|   //mScrollPref = aScrolling;
 | |
| 
 | |
|   WEB_TRACE(WEB_TRACE_CALLS,
 | |
|             ("nsWebShell::Init: this=%p", this));
 | |
| 
 | |
| /*  it is ok to have a webshell without an aNativeParent (used later to create the mWindow --dwc0001
 | |
|   // Initial error checking...
 | |
|   NS_PRECONDITION(nsnull != aNativeParent, "null Parent Window");
 | |
|   if (nsnull == aNativeParent) {
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|     goto done;
 | |
|   }
 | |
| */
 | |
|   // Create a document loader...
 | |
|   nsCOMPtr<nsIWebShell> webShellParent(do_QueryInterface(mParent));
 | |
|   if (webShellParent) {
 | |
|     nsIDocumentLoader* parentLoader;
 | |
| 
 | |
|     // Create a child document loader...
 | |
|     rv = webShellParent->GetDocumentLoader(parentLoader);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|       rv = parentLoader->CreateDocumentLoader(&mDocLoader);
 | |
|       NS_RELEASE(parentLoader);
 | |
|     }
 | |
|   } else {
 | |
|     NS_WITH_SERVICE(nsIDocumentLoader, docLoaderService, kDocLoaderServiceCID, &rv);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
| 
 | |
|     rv = docLoaderService->CreateDocumentLoader(&mDocLoader);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
|   }
 | |
| 
 | |
|   // Set the webshell as the default IContentViewerContainer for the loader...
 | |
|   mDocLoader->SetContainer(NS_STATIC_CAST(nsIContentViewerContainer*, (nsIWebShell*)this));
 | |
| 
 | |
|   //Register ourselves as an observer for the new doc loader
 | |
|   mDocLoader->AddObserver((nsIDocumentLoaderObserver*)this);
 | |
| 
 | |
| 
 | |
|   /* this is the old code, commented out for the new code below while I figure this out -- dwc0001
 | |
|   // Create device context
 | |
|   rv = nsComponentManager::CreateInstance(kDeviceContextCID, nsnull,
 | |
|                                     kIDeviceContextIID,
 | |
|                                     (void **)&mDeviceContext);
 | |
|   if (NS_FAILED(rv)) {
 | |
|     goto done;
 | |
|   }
 | |
|   mDeviceContext->Init(aNativeParent);
 | |
|   float dev2twip;
 | |
|   mDeviceContext->GetDevUnitsToTwips(dev2twip);
 | |
|   mDeviceContext->SetDevUnitsToAppUnits(dev2twip);
 | |
|   float twip2dev;
 | |
|   mDeviceContext->GetTwipsToDevUnits(twip2dev);
 | |
|   mDeviceContext->SetAppUnitsToDevUnits(twip2dev);
 | |
| //  mDeviceContext->SetGamma(1.7f);
 | |
|   mDeviceContext->SetGamma(1.0f);
 | |
| 
 | |
|   // Create a Native window for the shell container...
 | |
|   rv = nsComponentManager::CreateInstance(kChildCID, nsnull, kIWidgetIID, (void**)&mWindow);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   widgetInit.clipChildren = PR_FALSE;
 | |
|   widgetInit.mWindowType = eWindowType_child;
 | |
|   //widgetInit.mBorderStyle = aIsSunkenBorder ? eBorderStyle_3DChildWindow : eBorderStyle_none;
 | |
|   mWindow->Create(aNativeParent, aBounds, nsWebShell::HandleEvent,
 | |
|                   mDeviceContext, nsnull, nsnull, &widgetInit);
 | |
| */
 | |
| 
 | |
|   // Create device context
 | |
|   if (nsnull != aNativeParent) {
 | |
|     rv = nsComponentManager::CreateInstance(kDeviceContextCID, nsnull,
 | |
|                                             kIDeviceContextIID,
 | |
|                                             (void **)&mDeviceContext);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
|     mDeviceContext->Init(aNativeParent);
 | |
|     float dev2twip;
 | |
|     mDeviceContext->GetDevUnitsToTwips(dev2twip);
 | |
|     mDeviceContext->SetDevUnitsToAppUnits(dev2twip);
 | |
|     float twip2dev;
 | |
|     mDeviceContext->GetTwipsToDevUnits(twip2dev);
 | |
|     mDeviceContext->SetAppUnitsToDevUnits(twip2dev);
 | |
|     //  mDeviceContext->SetGamma(1.7f);
 | |
|     mDeviceContext->SetGamma(1.0f);
 | |
| 
 | |
|     // Create a Native window for the shell container...
 | |
|     rv = nsComponentManager::CreateInstance(kChildCID, nsnull, kIWidgetIID, (void**)&mWindow);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     widgetInit.clipChildren = PR_FALSE;
 | |
|     widgetInit.mWindowType = eWindowType_child;
 | |
|     //widgetInit.mBorderStyle = aIsSunkenBorder ? eBorderStyle_3DChildWindow : eBorderStyle_none;
 | |
|     mWindow->Create(aNativeParent, aBounds, nsWebShell::HandleEvent,
 | |
|                     mDeviceContext, nsnull, nsnull, &widgetInit);
 | |
|   } else {
 | |
|     // we need a deviceContext
 | |
| 
 | |
|     rv = nsComponentManager::CreateInstance(kDeviceContextCID, nsnull,kIDeviceContextIID,(void **)&mDeviceContext);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
|     mDeviceContext->Init(aNativeParent);
 | |
|     float dev2twip;
 | |
|     mDeviceContext->GetDevUnitsToTwips(dev2twip);
 | |
|     mDeviceContext->SetDevUnitsToAppUnits(dev2twip);
 | |
|     float twip2dev;
 | |
|     mDeviceContext->GetTwipsToDevUnits(twip2dev);
 | |
|     mDeviceContext->SetAppUnitsToDevUnits(twip2dev);
 | |
|     mDeviceContext->SetGamma(1.0f);
 | |
| 
 | |
|     widgetInit.clipChildren = PR_FALSE;
 | |
|     widgetInit.mWindowType = eWindowType_child;
 | |
|   }
 | |
| 
 | |
|   // Set the language portion of the user agent. :)
 | |
|   NS_WITH_SERVICE(nsILocaleService, localeServ, kLocaleServiceCID, &rv);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   PRUnichar *UALang;
 | |
|   rv = localeServ->GetLocaleComponentForUserAgent(&UALang);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   NS_WITH_SERVICE(nsIIOService, ioServ, kIOServiceCID, &rv);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   rv = ioServ->SetLanguage(UALang);
 | |
|   nsAllocator::Free(UALang);
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::IsBusy(PRBool& aResult)
 | |
| {
 | |
| 
 | |
|   if (mDocLoader!=nsnull) {
 | |
|     mDocLoader->IsBusy(aResult);
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SizeToContent()
 | |
| {
 | |
|   nsresult rv;
 | |
| 
 | |
|   // get the presentation shell
 | |
|   nsCOMPtr<nsIContentViewer> cv;
 | |
|   GetContentViewer(getter_AddRefs(cv));
 | |
|   if (cv) {
 | |
|     nsCOMPtr<nsIDocumentViewer> dv = do_QueryInterface(cv);
 | |
|     if (dv) {
 | |
|       nsCOMPtr<nsIPresContext> pcx;
 | |
|       dv->GetPresContext(*getter_AddRefs(pcx));
 | |
|       if (pcx) {
 | |
|         nsCOMPtr<nsIPresShell> pshell;
 | |
|         pcx->GetShell(getter_AddRefs(pshell));
 | |
| 
 | |
|         // whew! so resize the presentation shell
 | |
|         if (pshell) {
 | |
|           nsRect  shellArea;
 | |
|           PRInt32 width, height;
 | |
|           float   pixelScale;
 | |
| 
 | |
|           rv = pshell->ResizeReflow(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
 | |
| 
 | |
|           // so how big is it?
 | |
|           pcx->GetVisibleArea(shellArea);
 | |
|           pcx->GetTwipsToPixels(&pixelScale);
 | |
|           width = PRInt32((float)shellArea.width*pixelScale);
 | |
|           height = PRInt32((float)shellArea.height*pixelScale);
 | |
| 
 | |
|           // if we're the outermost webshell for this window, size the window
 | |
|           if (mContainer) {
 | |
|             nsCOMPtr<nsIBrowserWindow> browser = do_QueryInterface(mContainer);
 | |
|             if (browser) {
 | |
|               nsCOMPtr<nsIWebShell> browserWebShell;
 | |
|               PRInt32 oldX, oldY, oldWidth, oldHeight,
 | |
|                       widthDelta, heightDelta;
 | |
|               nsRect  windowBounds;
 | |
| 
 | |
|               GetPositionAndSize(&oldX, &oldY, &oldWidth, &oldHeight);
 | |
|               widthDelta = width - oldWidth;
 | |
|               heightDelta = height - oldHeight;
 | |
|               browser->GetWindowBounds(windowBounds);
 | |
|               browser->SizeWindowTo(windowBounds.width + widthDelta,
 | |
|                                     windowBounds.height + heightDelta,
 | |
|                                     PR_FALSE, PR_FALSE);
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::RemoveFocus()
 | |
| {
 | |
|   /*
 | |
|   --dwc0001
 | |
|   NS_PRECONDITION(nsnull != mWindow, "null window");
 | |
|   */
 | |
| 
 | |
|   if (nsnull != mWindow) {
 | |
|     nsIWidget *parentWidget = mWindow->GetParent();
 | |
|     if (nsnull != parentWidget) {
 | |
|       parentWidget->SetFocus();
 | |
|       NS_RELEASE(parentWidget);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetContentViewer(nsIContentViewer* aViewer)
 | |
| {
 | |
|   mContentViewer = aViewer;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetContainer(nsIWebShellContainer* aContainer)
 | |
| {
 | |
|   NS_IF_RELEASE(mContainer);
 | |
|   mContainer = aContainer;
 | |
|   NS_IF_ADDREF(mContainer);
 | |
| 
 | |
|   // uri dispatching change.....if you set a container for a webshell
 | |
|   // and that container is a content listener itself....then use
 | |
|   // it as our parent container. 
 | |
|   nsresult rv = NS_OK;
 | |
|   nsCOMPtr<nsIURIContentListener> contentListener = do_QueryInterface(mContainer, &rv);
 | |
|   if (NS_SUCCEEDED(rv) && contentListener)
 | |
|     SetParentURIContentListener(contentListener);
 | |
| 
 | |
|   // if the container is getting set to null, then our parent must be going away
 | |
|   // so clear out our knowledge of the content listener represented by the container
 | |
|   if (!aContainer)
 | |
|     SetParentURIContentListener(nsnull);
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetContainer(nsIWebShellContainer*& aResult)
 | |
| {
 | |
|   aResult = mContainer;
 | |
|   NS_IF_ADDREF(mContainer);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetTopLevelWindow(nsIWebShellContainer** aTopLevelWindow)
 | |
| {
 | |
|    NS_ENSURE_ARG_POINTER(aTopLevelWindow);
 | |
|    *aTopLevelWindow = nsnull;
 | |
| 
 | |
|    nsCOMPtr<nsIWebShell> rootWebShell;
 | |
| 
 | |
|    GetRootWebShellEvenIfChrome(getter_AddRefs(rootWebShell));
 | |
|    if(!rootWebShell)
 | |
|       return NS_OK;
 | |
|    
 | |
|    nsCOMPtr<nsIWebShellContainer> rootContainer;
 | |
|    rootWebShell->GetContainer(*aTopLevelWindow);
 | |
| 
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetSessionHistory(nsISessionHistory* aSHist)
 | |
| {
 | |
|   NS_IF_RELEASE(mSHist);
 | |
|   mSHist = aSHist;
 | |
|   NS_IF_ADDREF(aSHist);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetSessionHistory(nsISessionHistory *& aResult)
 | |
| {
 | |
|   aResult = mSHist;
 | |
|   NS_IF_ADDREF(mSHist);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| nsEventStatus PR_CALLBACK
 | |
| nsWebShell::HandleEvent(nsGUIEvent *aEvent)
 | |
| {
 | |
|   return nsEventStatus_eIgnore;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetPrefs(nsIPref*& aPrefs)
 | |
| {
 | |
|   aPrefs = mPrefs;
 | |
|   NS_IF_ADDREF(aPrefs);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetRootWebShell(nsIWebShell*& aResult)
 | |
| {
 | |
|    nsCOMPtr<nsIDocShellTreeItem> top;
 | |
|    GetSameTypeRootTreeItem(getter_AddRefs(top));
 | |
|    nsCOMPtr<nsIWebShell> topAsWebShell(do_QueryInterface(top));
 | |
|    aResult = topAsWebShell;
 | |
|    NS_IF_ADDREF(aResult);
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsWebShell::GetRootWebShellEvenIfChrome(nsIWebShell** aResult)
 | |
| {
 | |
|    nsCOMPtr<nsIDocShellTreeItem> top;
 | |
|    GetRootTreeItem(getter_AddRefs(top));
 | |
|    nsCOMPtr<nsIWebShell> topAsWebShell(do_QueryInterface(top));
 | |
|    *aResult = topAsWebShell;
 | |
|    NS_IF_ADDREF(*aResult);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetParent(nsIWebShell* aParent)
 | |
| {
 | |
|    nsCOMPtr<nsIDocShellTreeItem> parentAsTreeItem(do_QueryInterface(aParent));
 | |
| 
 | |
|    mParent = parentAsTreeItem.get();
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetParent(nsIWebShell*& aParent)
 | |
| {
 | |
|    nsCOMPtr<nsIDocShellTreeItem> parent;
 | |
|    NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parent)), NS_ERROR_FAILURE);
 | |
| 
 | |
|    if(parent)
 | |
|       parent->QueryInterface(NS_GET_IID(nsIWebShell), (void**)&aParent);
 | |
|    else
 | |
|       aParent = nsnull;
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetReferrer(nsIURI **aReferrer)
 | |
| {
 | |
|   return NS_NewURI(aReferrer, mReferrer, nsnull);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetChildCount(PRInt32& aResult)
 | |
| {
 | |
|    return nsDocShell::GetChildCount(&aResult);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::AddChild(nsIWebShell* aChild)
 | |
| {
 | |
|    NS_ENSURE_ARG(aChild);
 | |
| 
 | |
|    nsCOMPtr<nsIDocShellTreeItem> treeItemChild(do_QueryInterface(aChild));
 | |
|    return nsDocShell::AddChild(treeItemChild);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::RemoveChild(nsIWebShell* aChild)
 | |
| {
 | |
|    NS_ENSURE_ARG(aChild);
 | |
|    nsCOMPtr<nsIDocShellTreeItem> treeItemChild(do_QueryInterface(aChild));
 | |
|    return nsDocShell::RemoveChild(treeItemChild);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::ChildAt(PRInt32 aIndex, nsIWebShell*& aResult)
 | |
| {
 | |
|    nsCOMPtr<nsIDocShellTreeItem> child;
 | |
| 
 | |
|    NS_ENSURE_SUCCESS(GetChildAt(aIndex, getter_AddRefs(child)),
 | |
|       NS_ERROR_FAILURE);
 | |
| 
 | |
|    NS_ENSURE_SUCCESS(CallQueryInterface(child.get(), &aResult), 
 | |
|       NS_ERROR_FAILURE);
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetName(const PRUnichar** aName)
 | |
| {
 | |
|    *aName = mName.GetUnicode();
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetName(const PRUnichar* aName)
 | |
| {
 | |
|    return nsDocShell::SetName(aName);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetURL(const PRUnichar** aURL)
 | |
| {
 | |
|  // XXX This is wrong unless the parameter is marked "shared". 
 | |
|  // It should otherwise be copied and freed by the caller. 
 | |
|   *aURL = mURL.GetUnicode();
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetURL(const PRUnichar* aURL)
 | |
| {
 | |
|   mURL = aURL;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetIsInSHist(PRBool& aResult)
 | |
| {
 | |
|   aResult = mIsInSHist;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetIsInSHist(PRBool aIsInSHist)
 | |
| {
 | |
|   mIsInSHist = aIsInSHist;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::FindChildWithName(const PRUnichar* aName1,
 | |
|                               nsIWebShell*& aResult)
 | |
| {
 | |
|    nsCOMPtr<nsIDocShellTreeItem> treeItem;
 | |
| 
 | |
|    NS_ENSURE_SUCCESS(nsDocShell::FindChildWithName(aName1, PR_FALSE, nsnull, 
 | |
|       getter_AddRefs(treeItem)), NS_ERROR_FAILURE);
 | |
| 
 | |
|    if(treeItem)
 | |
|       CallQueryInterface(treeItem.get(), &aResult);
 | |
| 
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetWebShellType(nsWebShellType aWebShellType)
 | |
| {
 | |
|    PRInt32 treeItemType;
 | |
| 
 | |
|    switch(aWebShellType)
 | |
|       {
 | |
|       case nsWebShellChrome:
 | |
|          treeItemType = typeChrome;
 | |
|          break;
 | |
| 
 | |
|       case nsWebShellContent:
 | |
|          treeItemType = typeContent;
 | |
|          break;
 | |
| 
 | |
|       default:
 | |
|          NS_ERROR("Attempt to set bogus webshell type: values should be content or chrome.");
 | |
|          return NS_ERROR_FAILURE;
 | |
|       }
 | |
|    return SetItemType(treeItemType);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetScrolling(PRInt32& aScrolling)
 | |
| {
 | |
|   aScrolling = mScrolling[1];
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetScrolling(PRInt32 aScrolling, PRBool aSetCurrentAndInitial)
 | |
| {
 | |
|   mScrolling[1] = aScrolling;
 | |
|   if (aSetCurrentAndInitial) {
 | |
|     mScrolling[0] = aScrolling;
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Document Load methods
 | |
|  */
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetDocumentLoader(nsIDocumentLoader*& aResult)
 | |
| {
 | |
|   aResult = mDocLoader;
 | |
|   NS_IF_ADDREF(mDocLoader);
 | |
|   return (nsnull != mDocLoader) ? NS_OK : NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| #define FILE_PROTOCOL "file:///"
 | |
| 
 | |
| static void convertFileToURL(const nsString &aIn, nsString &aOut)
 | |
| {
 | |
| #ifdef XP_PC
 | |
|   char szFile[1000];
 | |
|   aIn.ToCString(szFile, sizeof(szFile));
 | |
|   if (PL_strchr(szFile, '\\')) {
 | |
|     PRInt32 len = strlen(szFile);
 | |
|     PRInt32 sum = len + sizeof(FILE_PROTOCOL);
 | |
|     char* lpszFileURL = (char *)PR_Malloc(sum + 1);
 | |
| 
 | |
|     // Translate '\' to '/'
 | |
|     for (PRInt32 i = 0; i < len; i++) {
 | |
|       if (szFile[i] == '\\') {
 | |
|         szFile[i] = '/';
 | |
|       }
 | |
|       if (szFile[i] == ':') {
 | |
|         szFile[i] = '|';
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // Build the file URL
 | |
|     PR_snprintf(lpszFileURL, sum, "%s%s", FILE_PROTOCOL, szFile);
 | |
|     aOut = lpszFileURL;
 | |
|     PR_Free((void *)lpszFileURL);
 | |
|   }
 | |
|   else
 | |
| #endif
 | |
|   {
 | |
|     aOut = aIn;
 | |
|   }
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::LoadURL(const PRUnichar *aURLSpec,
 | |
|                     nsIInputStream* aPostDataStream,
 | |
|                     PRBool aModifyHistory,
 | |
|                     nsLoadFlags aType,
 | |
|                     const PRUint32 aLocalIP,
 | |
|                     nsISupports * aHistoryState,
 | |
|                     const PRUnichar* aReferrer)
 | |
| {
 | |
|   // Initialize margnwidth, marginheight. Put scrolling back the way it was
 | |
|   // before the last document was loaded.
 | |
| 
 | |
| 	InitFrameData(PR_FALSE);
 | |
| 
 | |
|   const char *cmd = mViewSource ? "view-source" : "view" ;
 | |
|   mViewSource = PR_FALSE; // reset it
 | |
|   return LoadURL(aURLSpec, cmd, aPostDataStream,
 | |
|                  aModifyHistory,aType, aLocalIP, aHistoryState,
 | |
|                  aReferrer);
 | |
| }
 | |
| 
 | |
| 
 | |
| static PRBool EqualBaseURLs(nsIURI* url1, nsIURI* url2)
 | |
| {
 | |
|    nsXPIDLCString spec1;
 | |
|    nsXPIDLCString spec2;
 | |
|    char *  anchor1 = nsnull, * anchor2=nsnull;
 | |
|    PRBool rv = PR_FALSE;
 | |
|   
 | |
|    if (url1 && url2) {
 | |
|      // XXX We need to make these strcmps case insensitive.
 | |
|      url1->GetSpec(getter_Copies(spec1));
 | |
|      url2->GetSpec(getter_Copies(spec2));
 | |
|  
 | |
|      /* Don't look at the ref-part */
 | |
|      anchor1 = PL_strrchr(spec1, '#');
 | |
|      anchor2 = PL_strrchr(spec2, '#');
 | |
|  
 | |
|      if (anchor1)
 | |
|          *anchor1 = '\0';
 | |
|      if (anchor2)
 | |
|          *anchor2 = '\0';
 | |
|  
 | |
|      if (0 == PL_strcmp(spec1,spec2)) {
 | |
|        rv = PR_TRUE;
 | |
|      }
 | |
|    }   // url1 && url2
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsWebShell::DoLoadURL(nsIURI * aUri,
 | |
|                       const char* aCommand,
 | |
|                       nsIInputStream* aPostDataStream,
 | |
|                       nsLoadFlags aType,
 | |
|                       const PRUint32 aLocalIP,
 | |
|                       const PRUnichar* aReferrer,
 | |
|                       PRBool aKickOffLoad)
 | |
| {
 | |
|   if (!aUri)
 | |
|     return NS_ERROR_NULL_POINTER;
 | |
| 
 | |
|   // This should probably get saved in mHistoryService or something... 
 | |
|   // Ugh. It sucks that we have to hack webshell like this. Forgive me, Father.
 | |
|   do {
 | |
|     nsresult rv;
 | |
|     NS_WITH_SERVICE(nsIGlobalHistory, history, "component://netscape/browser/global-history", &rv);
 | |
|     if (NS_FAILED(rv)) break;
 | |
| 
 | |
|     nsXPIDLCString spec;
 | |
|     rv = aUri->GetSpec(getter_Copies(spec));
 | |
|     if (NS_FAILED(rv)) break;
 | |
| 
 | |
|     if (! spec)
 | |
|       break;
 | |
| 
 | |
|     rv = history->AddPage(spec, nsnull /* referrer */, PR_Now());
 | |
|     if (NS_FAILED(rv)) break;
 | |
|   } while (0);
 | |
| 
 | |
|   nsXPIDLCString urlSpec;
 | |
|   nsresult rv = NS_OK;
 | |
|   rv = aUri->GetSpec(getter_Copies(urlSpec));
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   // If it's a normal reload that uses the cache, look at the destination anchor
 | |
|   // and see if it's an element within the current document
 | |
|   // We don't have a reload loadtype yet in necko. So, check for just history
 | |
|   // loadtype
 | |
|   if ((aType == nsISessionHistory::LOAD_HISTORY || aType == nsIChannel::LOAD_NORMAL) && (nsnull != mContentViewer) &&
 | |
|       (nsnull == aPostDataStream))
 | |
|   {
 | |
|     nsCOMPtr<nsIDocumentViewer> docViewer;
 | |
|     if (NS_SUCCEEDED(mContentViewer->QueryInterface(kIDocumentViewerIID,
 | |
|                                                     getter_AddRefs(docViewer)))) {
 | |
|       // Get the document object
 | |
|       nsCOMPtr<nsIDocument> doc;
 | |
|       docViewer->GetDocument(*getter_AddRefs(doc));
 | |
| 
 | |
|       // Get the URL for the document
 | |
|       nsCOMPtr<nsIURI>  docURL = nsDontAddRef<nsIURI>(doc->GetDocumentURL());
 | |
| 
 | |
|       if (aUri && docURL && EqualBaseURLs(docURL, aUri)) {
 | |
|         // See if there's a destination anchor
 | |
|         nsXPIDLCString ref;
 | |
|         nsCOMPtr<nsIURL> aUrl = do_QueryInterface(aUri);
 | |
|         if (aUrl)
 | |
|           rv = aUrl->GetRef(getter_Copies(ref));
 | |
| 
 | |
|         nsCOMPtr<nsIPresShell> presShell;
 | |
|         rv = docViewer->GetPresShell(*getter_AddRefs(presShell));
 | |
| 
 | |
|         if (NS_SUCCEEDED(rv) && presShell) {
 | |
|            /* Pass OnStartDocument notifications to the docloaderobserver
 | |
|             * so that urlbar, forward/back buttons will
 | |
|             * behave properly when going to named anchors
 | |
|             */
 | |
|            nsIInterfaceRequestor * interfaceRequestor = NS_STATIC_CAST(nsIInterfaceRequestor *, this);
 | |
|            nsCOMPtr<nsIChannel> dummyChannel;
 | |
|            // creating a channel is expensive...don't create it unless we know we have to
 | |
|            // so move the creation down into each of the if clauses...
 | |
|            if (nsnull != (const char *) ref) {
 | |
|               rv = NS_OpenURI(getter_AddRefs(dummyChannel), aUri, nsnull, interfaceRequestor);
 | |
|               if (NS_FAILED(rv)) return rv;
 | |
|               rv = OnStartDocumentLoad(mDocLoader, aUri, "load");
 | |
|               // Go to the anchor in the current document
 | |
|               rv = presShell->GoToAnchor(nsAutoString(ref));            
 | |
| 		          mProcessedEndDocumentLoad = PR_FALSE;
 | |
|               // Set the URL & referrer if the anchor was successfully visited
 | |
|               if (NS_SUCCEEDED(rv)) {
 | |
|                   mURL = urlSpec;
 | |
|                   mReferrer = aReferrer;
 | |
|               }
 | |
| 		          // Pass on status of scrolling/anchor visit to docloaderobserver
 | |
|               rv = OnEndDocumentLoad(mDocLoader, dummyChannel, rv);
 | |
| 		          return rv;		   
 | |
|            }
 | |
|            else if (aType == nsISessionHistory::LOAD_HISTORY)
 | |
|            {
 | |
|               rv = NS_OpenURI(getter_AddRefs(dummyChannel), aUri, nsnull, interfaceRequestor);
 | |
|               if (NS_FAILED(rv)) return rv;
 | |
|               rv = OnStartDocumentLoad(mDocLoader, aUri, "load");
 | |
|               // Go to the top of the current document
 | |
|               nsCOMPtr<nsIViewManager> viewMgr;
 | |
|               rv = presShell->GetViewManager(getter_AddRefs(viewMgr));
 | |
|               if (NS_SUCCEEDED(rv) && viewMgr) {
 | |
|                 nsIScrollableView* view;
 | |
|                 rv = viewMgr->GetRootScrollableView(&view);
 | |
| 				        if (NS_SUCCEEDED(rv) && view)
 | |
|                 rv = view->ScrollTo(0, 0, NS_VMREFRESH_IMMEDIATE);
 | |
|                 if (NS_SUCCEEDED(rv)) {
 | |
|                      mURL = urlSpec;
 | |
|                      mReferrer = aReferrer;
 | |
|                 }
 | |
|                 mProcessedEndDocumentLoad = PR_FALSE;
 | |
| 		            // Pass on status of scrolling/anchor visit to docloaderobserver
 | |
|                 rv = OnEndDocumentLoad(mDocLoader, dummyChannel, rv);
 | |
| 		            return rv;		   
 | |
|               }
 | |
|            }
 | |
| #if 0        		   
 | |
| 		   mProcessedEndDocumentLoad = PR_FALSE;
 | |
| 		   // Pass on status of scrolling/anchor visit to docloaderobserver
 | |
|            rv = OnEndDocumentLoad(mDocLoader, dummyChannel, rv);
 | |
| 		   return rv;		   
 | |
| #endif /* 0 */
 | |
|         }  // NS_SUCCEEDED(rv) && presShell
 | |
|       } // EqualBaseURLs(docURL, url)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Stop loading the current document (if any...).  This call may result in
 | |
|   // firing an EndLoadURL notification for the old document...
 | |
|   if (aKickOffLoad)
 | |
|     StopBeforeRequestingURL();
 | |
|   
 | |
| 
 | |
|   // Tell web-shell-container we are loading a new url
 | |
|   if (nsnull != mContainer) {
 | |
|     nsAutoString uniSpec (urlSpec);
 | |
|     rv = mContainer->BeginLoadURL(this, uniSpec.GetUnicode());
 | |
|     if (NS_FAILED(rv)) {
 | |
|       return rv;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   mProcessedEndDocumentLoad = PR_FALSE;
 | |
| 
 | |
|  /* WebShell was primarily passing the buck when it came to streamObserver.
 | |
|   * So, pass on the observer which is already a streamObserver to DocLoder.
 | |
|   */
 | |
|   if (aKickOffLoad) {
 | |
| 
 | |
| #ifdef MOZ_PERF_METRICS
 | |
|     {
 | |
|        char* url;
 | |
|        nsresult rv = NS_OK;
 | |
|        rv = aUri->GetSpec(&url);
 | |
|        if (NS_SUCCEEDED(rv)) {
 | |
|          MOZ_TIMER_LOG(("*** Timing layout processes on url: '%s', webshell: %p\n", url, this));
 | |
|          delete [] url;
 | |
|        }
 | |
|     }
 | |
|   
 | |
|     MOZ_TIMER_DEBUGLOG(("Reset and start: nsWebShell::DoLoadURL(), this=%p\n", this));
 | |
|     MOZ_TIMER_RESET(mTotalTime);
 | |
|     MOZ_TIMER_START(mTotalTime);
 | |
| #endif
 | |
|         
 | |
|     rv = mDocLoader->LoadDocument(aUri,        // URL string
 | |
|                                   aCommand,        // Command
 | |
|                                   NS_STATIC_CAST(nsIContentViewerContainer*, (nsIWebShell*)this),// Container
 | |
|                                   aPostDataStream, // Post Data
 | |
|                                   nsnull,          // Extra Info...
 | |
|                                   aType,           // reload type
 | |
|                                   aLocalIP,        // load attributes.
 | |
|                                   aReferrer);      // referrer
 | |
| 
 | |
|   }
 | |
| 
 | |
|   // Fix for bug 1646.  Change the notion of current url and referrer only after
 | |
|   // the document load succeeds.
 | |
|   if (NS_SUCCEEDED(rv)) {
 | |
|     mURL = urlSpec;
 | |
|     mReferrer = aReferrer;
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| // nsIURIContentListener support
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetProtocolHandler(nsIURI *aURI, nsIProtocolHandler **aProtocolHandler)
 | |
| {
 | |
|    // Farm this off to our content listener
 | |
|    NS_ENSURE_SUCCESS(EnsureContentListener(), NS_ERROR_FAILURE);
 | |
|    return mContentListener->GetProtocolHandler(aURI, aProtocolHandler);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::CanHandleContent(const char * aContentType,
 | |
|                                            nsURILoadCommand aCommand,
 | |
|                                            const char * aWindowTarget,
 | |
|                                            char ** aDesiredContentType,
 | |
|                                            PRBool * aCanHandleContent)
 | |
| 
 | |
| {
 | |
|   // the webshell knows nothing about content policy....pass this
 | |
|   // up to our parent content handler...
 | |
|   nsCOMPtr<nsIURIContentListener> parentListener;
 | |
|   nsresult rv = GetParentURIContentListener(getter_AddRefs(parentListener));
 | |
|   if (parentListener)
 | |
|     rv = parentListener->CanHandleContent(aContentType, aCommand, aWindowTarget, aDesiredContentType, 
 | |
|                                           aCanHandleContent);
 | |
|   else
 | |
|     // i'm going to try something interesting...if we don't have a parent to dictate whether we
 | |
|     // can handle the content, let's say that we CAN handle the content instead of saying that we 
 | |
|     // can't. I was running into the scenario where we were running a chrome url to bring up the first window
 | |
|     // in the top level webshell. We didn't have a parent content listener yet because it was too early in
 | |
|     // the start up process...so we'd fail to load the url....
 | |
|     *aCanHandleContent = PR_TRUE;
 | |
|   return NS_OK;
 | |
| } 
 | |
| 
 | |
| NS_IMETHODIMP 
 | |
| nsWebShell::DoContent(const char * aContentType,
 | |
|                       nsURILoadCommand aCommand,
 | |
|                       const char * aWindowTarget,
 | |
|                       nsIChannel * aOpenedChannel,
 | |
|                       nsIStreamListener ** aContentHandler,
 | |
|                       PRBool * aAbortProcess)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   if (aAbortProcess)
 | |
|     *aAbortProcess = PR_FALSE;
 | |
| 
 | |
|   nsXPIDLCString strCommand;
 | |
|   // go to the uri loader and ask it to convert the uri load command into a old
 | |
|   // world style string
 | |
|   NS_WITH_SERVICE(nsIURILoader, pURILoader, NS_URI_LOADER_PROGID, &rv);
 | |
|   if (NS_SUCCEEDED(rv))
 | |
|     pURILoader->GetStringForCommand(aCommand, getter_Copies(strCommand));
 | |
| 
 | |
| 
 | |
|   // first, run any uri preparation stuff that we would have run normally
 | |
|   // had we gone through OpenURI
 | |
|   nsCOMPtr<nsIURI> aUri;
 | |
|   aOpenedChannel->GetURI(getter_AddRefs(aUri));
 | |
|   PrepareToLoadURI(aUri, strCommand, nsnull, PR_TRUE, nsIChannel::LOAD_NORMAL, 0, nsnull, nsnull);
 | |
|   // mscott: when I called DoLoadURL I found that we ran into problems because
 | |
|   // we currently don't have channel retargeting yet. Basically, what happens is that
 | |
|   // DoLoadURL calls StopBeforeRequestingURL and this cancels the current load group
 | |
|   // however since we can't retarget yet, we were basically canceling our very
 | |
|   // own load group!!! So the request would get canceled out from under us...
 | |
|   // after retargeting we may be able to safely call DoLoadURL. 
 | |
|   DoLoadURL(aUri, strCommand, nsnull, nsIChannel::LOAD_NORMAL, 0, nsnull, PR_FALSE);
 | |
| 
 | |
|   return CreateViewer(aOpenedChannel, 
 | |
|                       aContentType, 
 | |
|                       strCommand, 
 | |
|                       aContentHandler);
 | |
| }
 | |
| 
 | |
| static NS_DEFINE_IID(kIDocumentLoaderFactoryIID,   NS_IDOCUMENTLOADERFACTORY_IID);
 | |
| 
 | |
| nsresult nsWebShell::CreateViewer(nsIChannel* aChannel,
 | |
|                                   const char* aContentType,
 | |
|                                   const char* aCommand,
 | |
|                                   nsIStreamListener** aResult)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   nsIContentViewer* viewer = nsnull;
 | |
| 
 | |
|   nsCOMPtr<nsILoadGroup> loadGroup;
 | |
|   nsCOMPtr<nsILoadGroup> currentLoadGroup;
 | |
| 
 | |
|   /*
 | |
|    * Now that the content type is available, create a document
 | |
|    * (and viewer) of the appropriate type...
 | |
|    */
 | |
|   if (mDocLoader) {
 | |
|     mDocLoader->GetLoadGroup(getter_AddRefs(loadGroup));
 | |
| 
 | |
|     // Lookup class-id for the command plus content-type combination
 | |
|     nsCID cid;
 | |
|     char id[500];
 | |
|     PR_snprintf(id, sizeof(id),
 | |
|                 NS_DOCUMENT_LOADER_FACTORY_PROGID_PREFIX "%s/%s",
 | |
|                 aCommand ? aCommand : "view",/* XXX bug! shouldn't b needed!*/
 | |
|                 aContentType);
 | |
|     
 | |
|     rv = nsComponentManager::ProgIDToClassID(id, &cid);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|       // Create an instance of the document-loader-factory object
 | |
|       nsIDocumentLoaderFactory* factory;
 | |
|       rv = nsComponentManager::CreateInstance(cid, (nsISupports *)nsnull,
 | |
|                                             kIDocumentLoaderFactoryIID, 
 | |
|                                             (void **)&factory);
 | |
|       if (NS_SUCCEEDED(rv)) {
 | |
|         // Now create an instance of the content viewer
 | |
|         rv = factory->CreateInstance(aCommand, 
 | |
|                                      aChannel, 
 | |
|                                      loadGroup,
 | |
|                                      aContentType,
 | |
|                                      (nsIWebShell*)this,
 | |
|                                      nsnull,
 | |
|                                      aResult,
 | |
|                                      &viewer);
 | |
|         NS_RELEASE(factory);
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|   }
 | |
| 
 | |
|   if (NS_FAILED(rv)) {
 | |
|     printf("DocLoaderFactory: Unable to create ContentViewer for "
 | |
|            "command=%s, content-type=%s\n", 
 | |
|            aCommand ? aCommand : "(null)", aContentType);
 | |
|     // Give content container a chance to do something with this URL.
 | |
|     rv = HandleUnknownContentType(mDocLoader, 
 | |
|                                   aChannel, 
 | |
|                                   aContentType, 
 | |
|                                   aCommand );
 | |
|     // Stop the binding.
 | |
|     // This crashes on Unix/Mac... Stop();
 | |
|     goto done;
 | |
|   }
 | |
| 
 | |
|   // let's try resetting the load group if we need to...
 | |
|   rv = aChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup));
 | |
|   if (NS_SUCCEEDED(rv))
 | |
|   {
 | |
|     if (currentLoadGroup.get() != loadGroup.get()) {
 | |
|       nsLoadFlags loadAttribs = 0;
 | |
| 
 | |
|       //Cancel any URIs that are currently loading...
 | |
| /// XXX: Need to do this eventually      Stop();
 | |
|       //
 | |
|       // Retarget the document to this loadgroup...
 | |
|       //
 | |
|       if (currentLoadGroup) {
 | |
|         (void) currentLoadGroup->RemoveChannel(aChannel, nsnull, nsnull, nsnull);
 | |
|       }
 | |
|       aChannel->SetLoadGroup(loadGroup);
 | |
| 
 | |
|       // Mark the channel as being a document URI...
 | |
|       aChannel->GetLoadAttributes(&loadAttribs);
 | |
|       loadAttribs |= nsIChannel::LOAD_DOCUMENT_URI;
 | |
| 
 | |
|       aChannel->SetLoadAttributes(loadAttribs);
 | |
| 
 | |
|       loadGroup->AddChannel(aChannel, nsnull);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Give the document container the new viewer...
 | |
|    */
 | |
|   viewer->SetContainer((nsIWebShell*)this);
 | |
| 
 | |
|   rv = Embed(viewer, aCommand, nsnull);
 | |
|   if (NS_FAILED(rv)) {
 | |
|     goto done;
 | |
|   }
 | |
| 
 | |
| done:
 | |
|   NS_IF_RELEASE(viewer);
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| 
 | |
| nsresult nsWebShell::PrepareToLoadURI(nsIURI * aUri, 
 | |
|                                       const char * aCommand,
 | |
|                                       nsIInputStream * aPostStream,
 | |
|                                       PRBool aModifyHistory,
 | |
|                                       nsLoadFlags aType,
 | |
|                                       const PRUint32 aLocalIP,
 | |
|                                       nsISupports * aHistoryState,
 | |
|                                       const PRUnichar * aReferrer)
 | |
| {
 | |
|   nsresult rv;
 | |
|   CancelRefreshURITimers();
 | |
|   nsXPIDLCString scheme, CUriSpec;
 | |
| 
 | |
|   if (!aUri) return NS_ERROR_NULL_POINTER;
 | |
| 
 | |
|   rv = aUri->GetScheme(getter_Copies(scheme));
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
|   rv = aUri->GetSpec(getter_Copies(CUriSpec));
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   nsAutoString uriSpec(CUriSpec);
 | |
| 
 | |
|   nsXPIDLCString spec;
 | |
|   rv = aUri->GetSpec(getter_Copies(spec));
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   nsString* url = new nsString(uriSpec);
 | |
|   if (aModifyHistory) {
 | |
|     // Discard part of history that is no longer reachable
 | |
|     PRInt32 i, n = mHistory.Count();
 | |
|     i = mHistoryIndex + 1;
 | |
|     while (--n >= i) {
 | |
|       nsString* u = (nsString*) mHistory.ElementAt(n);
 | |
|       delete u;
 | |
|       mHistory.RemoveElementAt(n);
 | |
|     }
 | |
| 
 | |
|     // Tack on new url
 | |
|     mHistory.AppendElement(url);
 | |
|     mHistoryIndex++;
 | |
|   }
 | |
|   else {
 | |
| 	  
 | |
|     // Replace the current history index with this URL
 | |
|     nsString* u = (nsString*) mHistory.ElementAt(mHistoryIndex);
 | |
|     if (nsnull != u) {
 | |
|       delete u;
 | |
|     }
 | |
|     mHistory.ReplaceElementAt(url, mHistoryIndex);
 | |
|   }
 | |
|   ShowHistory();
 | |
| 
 | |
|   // Give web-shell-container right of refusal
 | |
|   if (nsnull != mContainer) {
 | |
|     nsAutoString str(spec);
 | |
|     rv = mContainer->WillLoadURL(this, str.GetUnicode(), nsLoadURL);
 | |
|     if (NS_FAILED(rv)) {
 | |
|       return rv;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP 
 | |
| nsWebShell::LoadURI(nsIURI * aUri,
 | |
|                     const char * aCommand,
 | |
|                     nsIInputStream* aPostDataStream,
 | |
|                     PRBool aModifyHistory,
 | |
|                     nsLoadFlags aType,
 | |
|                     const PRUint32 aLocalIP,
 | |
| 					          nsISupports * aHistoryState,
 | |
|                     const PRUnichar* aReferrer)
 | |
| {
 | |
|   nsresult rv = PrepareToLoadURI(aUri, aCommand, aPostDataStream,
 | |
|                                  aModifyHistory, aType, aLocalIP,
 | |
|                                  aHistoryState, aReferrer);
 | |
|   if (NS_SUCCEEDED(rv))
 | |
|     rv =  DoLoadURL(aUri, aCommand, aPostDataStream, aType, aLocalIP, aReferrer);
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::LoadURL(const PRUnichar *aURLSpec,
 | |
|                     const char* aCommand,
 | |
|                     nsIInputStream* aPostDataStream,
 | |
|                     PRBool aModifyHistory,
 | |
|                     nsLoadFlags aType,
 | |
|                     const PRUint32 aLocalIP,
 | |
|                     nsISupports * aHistoryState,
 | |
|                     const PRUnichar* aReferrer)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   PRBool isMail= PR_FALSE; // XXX mailto: hack
 | |
|   PRBool keywordsEnabled = PR_FALSE;
 | |
| 
 | |
|   /* 
 | |
|      TODO This doesnt belong here... The app should be doing all this
 | |
|      URL play. The webshell should not have a clue about whats "mailto" 
 | |
|      If you insist that this should be here, then put in URL parsing 
 | |
|      optimizations here. -Gagan
 | |
|   */
 | |
|   nsAutoString urlStr(aURLSpec);
 | |
|   // first things first. try to create a uri out of the string.
 | |
|   nsCOMPtr<nsIURI> uri;
 | |
|   nsXPIDLCString  spec;
 | |
|   rv = NS_NewURI(getter_AddRefs(uri), urlStr, nsnull);
 | |
|   if (NS_FAILED(rv)) {
 | |
|     // no dice.
 | |
|     nsAutoString urlSpec;
 | |
|     urlStr.Trim(" ");
 | |
| 
 | |
|     // see if we've got a file url.
 | |
|     convertFileToURL(urlStr, urlSpec);
 | |
|     rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nsnull);
 | |
|     if (NS_FAILED(rv)) {
 | |
|       NS_ASSERTION(mPrefs, "the webshell's pref service wasn't initialized");
 | |
| 
 | |
|       rv = mPrefs->GetBoolPref("keyword.enabled", &keywordsEnabled);
 | |
|       if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|       PRInt32 qMarkLoc = -1, spaceLoc = -1;
 | |
| 
 | |
|       if (keywordsEnabled) {
 | |
|           // These are keyword formatted strings
 | |
|           // "what is mozilla"
 | |
|           // "what is mozilla?"
 | |
|           // "?mozilla"
 | |
|           // "?What is mozilla"
 | |
| 
 | |
|           // These are not keyword formatted strings
 | |
|           // "www.blah.com" - anything with a dot in it 
 | |
|           // "nonQualifiedHost:80" - anything with a colon in it
 | |
|           // "nonQualifiedHost?"
 | |
|           // "nonQualifiedHost?args"
 | |
|           // "nonQualifiedHost?some args"
 | |
| 
 | |
|           if (urlStr.FindChar('.') == -1 && urlStr.FindChar(':') == -1) {
 | |
|               qMarkLoc = urlStr.FindChar('?');
 | |
|               spaceLoc = urlStr.FindChar(' ');
 | |
| 
 | |
|               PRBool keyword = PR_FALSE;
 | |
|               if ( (qMarkLoc == 0)
 | |
| #ifdef XP_PC
 | |
|                   // This is windows only because windows is the
 | |
|                   // only platform that utilizes WINS resolution 
 | |
|                   // (a DNS fallback) which can take several minutes to
 | |
|                   // fail a resolve call if the host does not exist. 
 | |
|                   // Thus, this forces us to bypass DNS/WINS altogether
 | |
|                   // on windows; for nonQualifiedHosts *only*.
 | |
| 
 | |
|                   // "nonQualifiedHost"
 | |
|                     || ( (qMarkLoc == -1) && (spaceLoc == -1) )
 | |
| #endif // XP_PC      
 | |
|                   ) {
 | |
|                   keyword = PR_TRUE;
 | |
|               } else if ( (spaceLoc > 0) && 
 | |
|                           ( (qMarkLoc == -1) || (spaceLoc < qMarkLoc) )) {
 | |
|                     keyword = PR_TRUE;
 | |
|               }
 | |
| 
 | |
|               if (keyword) {
 | |
|                   nsAutoString keywordSpec("keyword:");
 | |
|                   keywordSpec.Append(aURLSpec);
 | |
|                   rv = NS_NewURI(getter_AddRefs(uri), keywordSpec, nsnull);
 | |
|               } else {
 | |
|                   rv = NS_ERROR_FAILURE;
 | |
|               }
 | |
|           } else {
 | |
|               rv = NS_ERROR_FAILURE;
 | |
|           }
 | |
|       } else {
 | |
|           rv = NS_ERROR_FAILURE;
 | |
|       }
 | |
| 
 | |
|       PRInt32 colon = -1;
 | |
|       if (NS_FAILED(rv)) {
 | |
|           PRInt32 fSlash = urlSpec.FindChar('/');
 | |
|           PRUnichar port;
 | |
|           // if no scheme (protocol) is found, assume http.
 | |
|           if ( ((colon=urlSpec.FindChar(':')) == -1) // no colon at all
 | |
|                || ( (fSlash > -1) && (colon > fSlash) ) // the only colon comes after the first slash
 | |
|                || ( (colon < urlSpec.Length()-1) // the first char after the first colon is a digit (i.e. a port)
 | |
|                     && ((port=urlSpec.CharAt(colon+1)) <= '9')
 | |
|                     && (port > '0') )) {
 | |
|             // find host name
 | |
|             PRInt32 hostPos = urlSpec.FindCharInSet("./:");
 | |
|             if (hostPos == -1) {
 | |
|               hostPos = urlSpec.Length();
 | |
|             }
 | |
| 
 | |
|             // extract host name
 | |
|             nsAutoString hostSpec;
 | |
|             urlSpec.Left(hostSpec, hostPos);
 | |
| 
 | |
|             // insert url spec corresponding to host name
 | |
|             if (hostSpec.EqualsIgnoreCase("ftp")) {
 | |
|               urlSpec.Insert("ftp://", 0, 6);
 | |
|             } else {
 | |
|               urlSpec.Insert("http://", 0, 7);
 | |
|             }
 | |
|           } // end if colon
 | |
| 
 | |
|           // XXX mailto: hack
 | |
|           if ((urlSpec.Find("mailto:", PR_TRUE)) >= 0)
 | |
|               isMail = PR_TRUE;
 | |
| 
 | |
|           if (!isMail) {
 | |
|               rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nsnull);
 | |
|               if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
 | |
|                   // we weren't able to find a protocol handler
 | |
|                   rv = InitDialogVars();
 | |
|                   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|                   nsXPIDLString messageStr;
 | |
|                   nsAutoString name("protocolNotFound");
 | |
|                   rv = mStringBundle->GetStringFromName(name.GetUnicode(), getter_Copies(messageStr));
 | |
|                   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|                   NS_ASSERTION(colon != -1, "we shouldn't have gotten this far if we didn't have a colon");
 | |
| 
 | |
|                   // extract the scheme
 | |
|                   nsAutoString scheme;
 | |
|                   urlSpec.Left(scheme, colon);
 | |
| 
 | |
|                   nsAutoString dnsMsg(scheme);
 | |
|                   dnsMsg.Append(' ');
 | |
|                   dnsMsg.Append(messageStr);
 | |
| 
 | |
|                   (void)mPrompter->Alert(dnsMsg.GetUnicode());
 | |
|               } // end unknown protocol
 | |
|           } // end !isMail
 | |
|       }
 | |
|    }
 | |
|   }
 | |
| 
 | |
|   if (!uri) return rv;
 | |
| 
 | |
|    rv = uri->GetSpec(getter_Copies(spec));
 | |
|    if (NS_FAILED(rv)) return rv;
 | |
|   
 | |
|   // Get hold of Root webshell
 | |
|   nsCOMPtr<nsIWebShell>  root;
 | |
|   nsCOMPtr<nsISessionHistory> shist;
 | |
|   PRBool  isLoadingHistory=PR_FALSE; // Is SH currently loading an entry from history?
 | |
|   rv = GetRootWebShell(*getter_AddRefs(root));
 | |
|   // Get hold of session History
 | |
|   if (NS_SUCCEEDED(rv) && root) {    
 | |
|     root->GetSessionHistory(*getter_AddRefs(shist));
 | |
|   }
 | |
|   if (shist)
 | |
| 	  shist->GetLoadingFlag(&isLoadingHistory);
 | |
| 
 | |
| 
 | |
|   /* 
 | |
|    * Save the history state for the current index iff this loadurl() request
 | |
|    * is not from SH. When the request comes from SH, aModifyHistory will
 | |
|    * be false and nsSessionHistory.cpp takes of this.
 | |
|    */
 | |
|   if (shist) {
 | |
| 	 PRInt32  indix;
 | |
|      shist->GetCurrentIndex(&indix);
 | |
|      if (indix >= 0 && (aModifyHistory)) {
 | |
|        nsCOMPtr<nsISupports>  historyState;
 | |
|        rv = GetHistoryState(getter_AddRefs(historyState));
 | |
| 	   if (NS_SUCCEEDED(rv) && historyState)
 | |
|           shist->SetHistoryObjectForIndex(indix, historyState);
 | |
| 	 }
 | |
|   }
 | |
|   /* Set the History state object for the current page in the
 | |
|    * presentation shell. If it is a new page being visited,
 | |
|    * aHistoryState is null. If the load is coming from
 | |
|    * session History, it will be set to the cached history object by
 | |
|    * session History.
 | |
|    */
 | |
|    SetHistoryState(aHistoryState);
 | |
| 
 | |
|   /* Add the page to session history */
 | |
|   if (aModifyHistory && shist && (!isMail))  {
 | |
|         PRInt32  ret;
 | |
|         ret = shist->Add(spec, this);
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsIWebShell> parent;
 | |
|   nsresult res = GetParent(*getter_AddRefs(parent));
 | |
|   nsAutoString urlstr;
 | |
| 
 | |
|   if ((isLoadingHistory)) {
 | |
| 	/* if LoadURL() got called from SH, AND If we are going "Back/Forward" 
 | |
| 	 * to a frame page,SH  will change the mURL to the right value
 | |
|      * for smoother redraw. So, create a new nsIURI based on mURL,
 | |
|      * so that it will work right in such situations.
 | |
| 	 */
 | |
|      urlstr = mURL;
 | |
|   }
 | |
|   else{
 | |
| 	/* If the call is not from SH, use the url passed by the caller
 | |
| 	 * so that things like JS will work right. This is for bug # 1646.
 | |
| 	 * May regress in other situations.
 | |
| 	 * What a hack
 | |
| 	 */
 | |
|      urlstr=spec;
 | |
|   }
 | |
|   
 | |
|   nsCOMPtr<nsIURI>   newURI;
 | |
|   res = NS_NewURI(getter_AddRefs(newURI), urlstr, nsnull);
 | |
| 
 | |
|   if (NS_SUCCEEDED(res)) {
 | |
|     // now that we have a uri, call the REAL LoadURI method which requires a nsIURI.
 | |
|     return LoadURI(newURI, aCommand, aPostDataStream, aModifyHistory, aType, aLocalIP, aHistoryState, aReferrer);
 | |
|   }
 | |
|   return rv;
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::Stop(void)
 | |
| {
 | |
|   if (nsnull != mContentViewer) {
 | |
|     mContentViewer->Stop();
 | |
|   }
 | |
| 
 | |
|   // Cancel any timers that were set for this loader.
 | |
|   CancelRefreshURITimers();
 | |
| 
 | |
|   if (mDocLoader) {
 | |
|     // Stop any documents that are currently being loaded...
 | |
|     mDocLoader->Stop();
 | |
|   }
 | |
| 
 | |
|   // Stop the documents being loaded by children too...
 | |
|   PRInt32 i, n = mChildren.Count();
 | |
|   for (i = 0; i < n; i++) {
 | |
|     nsIDocShell* shell = (nsIDocShell*) mChildren.ElementAt(i);
 | |
|     nsCOMPtr<nsIWebShell> webShell(do_QueryInterface(shell));
 | |
|     webShell->Stop();
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| // This "stops" the current document load enough so that the document loader
 | |
| // can be used to load a new URL.
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::StopBeforeRequestingURL()
 | |
| {
 | |
|   if (mDocLoader) {
 | |
|     // Stop any documents that are currently being loaded...
 | |
|     mDocLoader->Stop();
 | |
|   }
 | |
| 
 | |
|   // Recurse down the webshell hierarchy.
 | |
|   PRInt32 i, n = mChildren.Count();
 | |
|   for (i = 0; i < n; i++) {
 | |
|     nsIDocShell* shell = (nsIDocShell*) mChildren.ElementAt(i);
 | |
|     nsCOMPtr<nsIWebShell> webShell(do_QueryInterface(shell));
 | |
|     webShell->StopBeforeRequestingURL();
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| // This "stops" the current document load completely and is called once
 | |
| // it has been determined that the new URL is valid and ready to be thrown
 | |
| // at us from netlib.
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::StopAfterURLAvailable()
 | |
| {
 | |
|   if (nsnull != mContentViewer) {
 | |
|     mContentViewer->Stop();
 | |
|   }
 | |
| 
 | |
|   // Cancel any timers that were set for this loader.
 | |
|   CancelRefreshURITimers();
 | |
| 
 | |
|   // Recurse down the webshell hierarchy.
 | |
|   PRInt32 i, n = mChildren.Count();
 | |
|   for (i = 0; i < n; i++) {
 | |
|     nsIDocShell* shell = (nsIDocShell*) mChildren.ElementAt(i);
 | |
|     nsCOMPtr<nsIWebShell> webShell(do_QueryInterface(shell));
 | |
|     webShell->StopAfterURLAvailable();
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::Reload(nsLoadFlags aType)
 | |
| {
 | |
|   nsString* s = (nsString*) mHistory.ElementAt(mHistoryIndex);
 | |
|   if (nsnull != s) {
 | |
|     // XXX What about the post data?
 | |
| 
 | |
|     // Allocate since mReferrer will change beneath us
 | |
|     PRUnichar* str = mReferrer.ToNewUnicode();
 | |
|     return LoadURL(s->GetUnicode(), nsnull, PR_FALSE, 
 | |
|                    aType, 0, nsnull, str);
 | |
|     Recycle(str);
 | |
|   }
 | |
| 
 | |
|   return NS_ERROR_FAILURE;
 | |
| 
 | |
| }
 | |
| 
 | |
| //----------------------------------------
 | |
| 
 | |
| // History methods
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::Back(void)
 | |
| {
 | |
|   return GoTo(mHistoryIndex - 1);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CanBack(void)
 | |
| {
 | |
|   return ((mHistoryIndex-1)  > - 1 ? NS_OK : NS_COMFALSE);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::Forward(void)
 | |
| {
 | |
|   return GoTo(mHistoryIndex + 1);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CanForward(void)
 | |
| {
 | |
|   return (mHistoryIndex  < mHistory.Count() - 1 ? NS_OK : NS_COMFALSE);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GoTo(PRInt32 aHistoryIndex)
 | |
| {
 | |
|   nsresult rv = NS_ERROR_ILLEGAL_VALUE;
 | |
|   if ((aHistoryIndex >= 0) &&
 | |
|       (aHistoryIndex < mHistory.Count())) {
 | |
|     nsString* s = (nsString*) mHistory.ElementAt(aHistoryIndex);
 | |
| 
 | |
|     // Give web-shell-container right of refusal
 | |
|     nsAutoString urlSpec(*s);
 | |
|     if (nsnull != mContainer) {
 | |
|       rv = mContainer->WillLoadURL(this, urlSpec.GetUnicode(), nsLoadHistory);
 | |
|       if (NS_FAILED(rv)) {
 | |
|         return rv;
 | |
|       }
 | |
|     }
 | |
| 
 | |
| #ifdef DEBUG
 | |
|     printf("Goto %d\n", aHistoryIndex);
 | |
| #endif
 | |
|     mHistoryIndex = aHistoryIndex;
 | |
|     ShowHistory();
 | |
| 
 | |
|     // convert the uri spec into a url and then pass it to DoLoadURL
 | |
|     nsCOMPtr<nsIURI> uri;
 | |
|     rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nsnull);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     rv = DoLoadURL(uri,       // URL string
 | |
|                    "view",        // Command
 | |
|                    nsnull,        // Post Data
 | |
| 				   nsISessionHistory::LOAD_HISTORY,  // the reload type
 | |
|                    0,            // load attributes
 | |
|                    nsnull);      // referrer
 | |
|   }
 | |
|   return rv;
 | |
| 
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetHistoryLength(PRInt32& aResult)
 | |
| {
 | |
|   aResult = mHistory.Count();
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetHistoryIndex(PRInt32& aResult)
 | |
| {
 | |
|   aResult = mHistoryIndex;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetURL(PRInt32 aHistoryIndex, const PRUnichar** aURLResult)
 | |
| {
 | |
|   nsresult rv = NS_ERROR_ILLEGAL_VALUE;
 | |
| 
 | |
|   // XXX Ownership rules for the string passed back from this
 | |
|   // method are not XPCOM compliant. If they were correct, 
 | |
|   // the caller would deallocate the string.
 | |
|   if ((aHistoryIndex >= 0) &&
 | |
|       (aHistoryIndex <= mHistory.Count() - 1)) {
 | |
|     nsString* s = (nsString*) mHistory.ElementAt(aHistoryIndex);
 | |
|     if (nsnull != s) {
 | |
|       *aURLResult = s->GetUnicode();
 | |
|     }
 | |
|     rv = NS_OK;
 | |
|   }
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsWebShell::ShowHistory()
 | |
| {
 | |
| #if defined(NS_DEBUG)
 | |
|   if (WEB_LOG_TEST(gLogModule, WEB_TRACE_HISTORY)) {
 | |
|     PRInt32 i, n = mHistory.Count();
 | |
|     for (i = 0; i < n; i++) {
 | |
|       if (i == mHistoryIndex) {
 | |
|         printf("**");
 | |
|       }
 | |
|       else {
 | |
|         printf("  ");
 | |
|       }
 | |
|       nsString* u = (nsString*) mHistory.ElementAt(i);
 | |
|       fputs(*u, stdout);
 | |
|       printf("\n");
 | |
|     }
 | |
|   }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| //----------------------------------------
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| // WebShell container implementation
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::WillLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, nsLoadType aReason)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   if (nsnull != mContainer) {
 | |
|     rv = mContainer->WillLoadURL(aShell, aURL, aReason);
 | |
|   }
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::BeginLoadURL(nsIWebShell* aShell, const PRUnichar* aURL)
 | |
| {
 | |
|   if (nsnull != mContainer) {
 | |
|     // XXX: do not propagate this notification up from any frames...
 | |
|     return mContainer->BeginLoadURL(aShell, aURL);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::ProgressLoadURL(nsIWebShell* aShell,
 | |
|                             const PRUnichar* aURL,
 | |
|                             PRInt32 aProgress,
 | |
|                             PRInt32 aProgressMax)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   if (nsnull != mContainer) {
 | |
|     rv = mContainer->ProgressLoadURL(aShell, aURL, aProgress, aProgressMax);
 | |
|   }
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::EndLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, nsresult aStatus)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   if (nsnull != mContainer) {
 | |
|     // XXX: do not propagate this notification up from any frames...
 | |
|     return mContainer->EndLoadURL(aShell, aURL, aStatus);
 | |
|   }
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::NewWebShell(PRUint32 aChromeMask,
 | |
|                         PRBool aVisible,
 | |
|                         nsIWebShell *&aNewWebShell)
 | |
| {
 | |
|   if (nsnull != mContainer) {
 | |
|     return mContainer->NewWebShell(aChromeMask, aVisible, aNewWebShell);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::ContentShellAdded(nsIWebShell* aChildShell, nsIContent* frameNode)
 | |
| {
 | |
|   if (nsnull != mContainer) {
 | |
|     return mContainer->ContentShellAdded(aChildShell, frameNode);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult)
 | |
| {
 | |
|    // First we try the new system
 | |
|    nsCOMPtr<nsIDocShellTreeItem> treeItem;
 | |
| 
 | |
|    NS_ENSURE_SUCCESS(FindItemWithName(aName, nsnull, 
 | |
|       getter_AddRefs(treeItem)), NS_ERROR_FAILURE);
 | |
| 
 | |
|    if(treeItem)
 | |
|       CallQueryInterface(treeItem.get(), &aResult);
 | |
|    else if(mContainer) // Then fall back to the old.
 | |
|       return mContainer->FindWebShellWithName(aName, aResult);
 | |
|   
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken)
 | |
| {
 | |
|    nsCOMPtr<nsIBaseWindow> webShellAsWin(do_QueryInterface(aFocusedWebShell));
 | |
|    return FocusAvailable(webShellAsWin, &aFocusTaken);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetHistoryState(nsISupports** aLayoutHistoryState)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   // XXX Need to think about what to do for framesets.
 | |
|   // For now, return an error if this webshell
 | |
|   // contains a frame or a frameset document.
 | |
|   // The main content area will always have a parent. It is
 | |
|   // enough to check the children count to verify frames.
 | |
|   if (mChildren.Count() > 0) {
 | |
|     return NS_ERROR_NOT_IMPLEMENTED;
 | |
|   }
 | |
| 
 | |
|   // Ask the pres shell for the history state
 | |
|   if (mContentViewer) {
 | |
|     nsCOMPtr<nsIDocumentViewer> docv = do_QueryInterface(mContentViewer);
 | |
|     if (nsnull != docv) {
 | |
|       nsCOMPtr<nsIPresShell> shell;
 | |
|       rv = docv->GetPresShell(*getter_AddRefs(shell));
 | |
|       if (NS_SUCCEEDED(rv)) {
 | |
|         rv = shell->GetHistoryState((nsILayoutHistoryState**) aLayoutHistoryState);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetHistoryState(nsISupports* aLayoutHistoryState)
 | |
| {
 | |
|   mHistoryState = aLayoutHistoryState;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| // Web Shell Services API
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::LoadDocument(const char* aURL,
 | |
|                          const char* aCharset,
 | |
|                          nsCharsetSource aSource)
 | |
| {
 | |
|   // XXX hack. kee the aCharset and aSource wait to pick it up
 | |
|   nsCOMPtr<nsIContentViewer> cv;
 | |
|   NS_ENSURE_SUCCESS(GetContentViewer(getter_AddRefs(cv)), NS_ERROR_FAILURE);
 | |
|   if (cv)
 | |
|   {
 | |
|     nsCOMPtr<nsIMarkupDocumentViewer> muDV = do_QueryInterface(cv);  
 | |
|     if (muDV)
 | |
|     {
 | |
|       nsCharsetSource hint;
 | |
|       muDV->GetHintCharacterSetSource((PRInt32 *)(&hint));
 | |
|       if( aSource > hint ) 
 | |
|       {
 | |
|         nsAutoString inputCharSet(aCharset);
 | |
|         muDV->SetHintCharacterSet(inputCharSet.GetUnicode());
 | |
|         muDV->SetHintCharacterSetSource((PRInt32)aSource);
 | |
|         if(eCharsetReloadRequested != mCharsetReloadState) 
 | |
|         {
 | |
|           mCharsetReloadState = eCharsetReloadRequested;
 | |
|           nsAutoString url(aURL);
 | |
|           LoadURL(url.GetUnicode());
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::ReloadDocument(const char* aCharset,
 | |
|                            nsCharsetSource aSource,
 | |
|                            const char* aCmd)
 | |
| {
 | |
| 
 | |
|   // XXX hack. kee the aCharset and aSource wait to pick it up
 | |
|   nsCOMPtr<nsIContentViewer> cv;
 | |
|   NS_ENSURE_SUCCESS(GetContentViewer(getter_AddRefs(cv)), NS_ERROR_FAILURE);
 | |
|   if (cv)
 | |
|   {
 | |
|     nsCOMPtr<nsIMarkupDocumentViewer> muDV = do_QueryInterface(cv);  
 | |
|     if (muDV)
 | |
|     {
 | |
|       nsCharsetSource hint;
 | |
|       muDV->GetHintCharacterSetSource((PRInt32 *)(&hint));
 | |
|       if( aSource > hint ) 
 | |
|       {
 | |
|         nsAutoString inputCharSet(aCharset);
 | |
|          muDV->SetHintCharacterSet(inputCharSet.GetUnicode());
 | |
|          muDV->SetHintCharacterSetSource((PRInt32)aSource);
 | |
|          mViewSource = (0==PL_strcmp("view-source", aCmd));
 | |
|          if(eCharsetReloadRequested != mCharsetReloadState) 
 | |
|          {
 | |
|             mCharsetReloadState = eCharsetReloadRequested;
 | |
|             return Reload(nsIChannel::LOAD_NORMAL);
 | |
|          }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::StopDocumentLoad(void)
 | |
| {
 | |
|   if(eCharsetReloadRequested != mCharsetReloadState) 
 | |
|   {
 | |
|      Stop();
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetRendering(PRBool aRender)
 | |
| {
 | |
|   if(eCharsetReloadRequested != mCharsetReloadState) 
 | |
|   {
 | |
|     if (mContentViewer) {
 | |
|        mContentViewer->SetEnableRendering(aRender);
 | |
|     }
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| // WebShell link handling
 | |
| 
 | |
| struct OnLinkClickEvent : public PLEvent {
 | |
|   OnLinkClickEvent(nsWebShell* aHandler, nsIContent* aContent,
 | |
|                    nsLinkVerb aVerb, const PRUnichar* aURLSpec,
 | |
|                    const PRUnichar* aTargetSpec, nsIInputStream* aPostDataStream = 0);
 | |
|   ~OnLinkClickEvent();
 | |
| 
 | |
|   void HandleEvent() {
 | |
|     mHandler->HandleLinkClickEvent(mContent, mVerb, mURLSpec->GetUnicode(),
 | |
|                                    mTargetSpec->GetUnicode(), mPostDataStream);
 | |
|   }
 | |
| 
 | |
|   nsWebShell*  mHandler;
 | |
|   nsString*    mURLSpec;
 | |
|   nsString*    mTargetSpec;
 | |
|   nsIInputStream* mPostDataStream;
 | |
|   nsIContent*     mContent;
 | |
|   nsLinkVerb      mVerb;
 | |
| };
 | |
| 
 | |
| static void PR_CALLBACK HandlePLEvent(OnLinkClickEvent* aEvent)
 | |
| {
 | |
|   aEvent->HandleEvent();
 | |
| }
 | |
| 
 | |
| static void PR_CALLBACK DestroyPLEvent(OnLinkClickEvent* aEvent)
 | |
| {
 | |
|   delete aEvent;
 | |
| }
 | |
| 
 | |
| OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
 | |
|                                    nsIContent *aContent,
 | |
|                                    nsLinkVerb aVerb,
 | |
|                                    const PRUnichar* aURLSpec,
 | |
|                                    const PRUnichar* aTargetSpec,
 | |
|                                    nsIInputStream* aPostDataStream)
 | |
| {
 | |
|   nsIEventQueue* eventQueue;
 | |
| 
 | |
|   mHandler = aHandler;
 | |
|   NS_ADDREF(aHandler);
 | |
|   mURLSpec = new nsString(aURLSpec);
 | |
|   mTargetSpec = new nsString(aTargetSpec);
 | |
|   mPostDataStream = aPostDataStream;
 | |
|   NS_IF_ADDREF(mPostDataStream);
 | |
|   mContent = aContent;
 | |
|   NS_IF_ADDREF(mContent);
 | |
|   mVerb = aVerb;
 | |
| 
 | |
|   PL_InitEvent(this, nsnull,
 | |
|                (PLHandleEventProc) ::HandlePLEvent,
 | |
|                (PLDestroyEventProc) ::DestroyPLEvent);
 | |
| 
 | |
|   eventQueue = aHandler->GetEventQueue();
 | |
|   eventQueue->PostEvent(this);
 | |
|   NS_RELEASE(eventQueue);
 | |
| }
 | |
| 
 | |
| OnLinkClickEvent::~OnLinkClickEvent()
 | |
| {
 | |
|   NS_IF_RELEASE(mContent);
 | |
|   NS_IF_RELEASE(mHandler);
 | |
|   NS_IF_RELEASE(mPostDataStream);
 | |
|   if (nsnull != mURLSpec) delete mURLSpec;
 | |
|   if (nsnull != mTargetSpec) delete mTargetSpec;
 | |
| 
 | |
| }
 | |
| 
 | |
| //----------------------------------------
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnLinkClick(nsIContent* aContent,
 | |
|                         nsLinkVerb aVerb,
 | |
|                         const PRUnichar* aURLSpec,
 | |
|                         const PRUnichar* aTargetSpec,
 | |
|                         nsIInputStream* aPostDataStream)
 | |
| {
 | |
|   OnLinkClickEvent* ev;
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   ev = new OnLinkClickEvent(this, aContent, aVerb, aURLSpec,
 | |
|                             aTargetSpec, aPostDataStream);
 | |
|   if (nsnull == ev) {
 | |
|     rv = NS_ERROR_OUT_OF_MEMORY;
 | |
|   }
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| // Find the web shell in the entire tree that we can reach that the
 | |
| // link click should go to.
 | |
| 
 | |
| // XXX This doesn't yet know how to target other windows with their
 | |
| // own tree
 | |
| nsIWebShell*
 | |
| nsWebShell::GetTarget(const PRUnichar* aName)
 | |
| {
 | |
|   nsAutoString name(aName);
 | |
|   nsIWebShell* target = nsnull;
 | |
| 
 | |
|   if (0 == name.Length()) {
 | |
|     NS_ADDREF_THIS();
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   if (name.EqualsIgnoreCase("_blank")) {
 | |
|     nsIWebShell *shell;
 | |
|     if (NS_OK == NewWebShell(NS_CHROME_ALL_CHROME, PR_TRUE, shell))
 | |
|       target = shell;
 | |
|     else
 | |
|     {
 | |
|       //don't know what to do here? MMP
 | |
|       NS_ASSERTION(PR_FALSE, "unable to get new webshell");
 | |
|     }
 | |
|   }
 | |
|   else if (name.EqualsIgnoreCase("_self")) {
 | |
|     target = this;
 | |
|     NS_ADDREF(target);
 | |
|   }
 | |
|   else if (name.EqualsIgnoreCase("_parent")) {
 | |
|     GetParent(target);
 | |
|     if (target == nsnull) {
 | |
|       target = this;
 | |
|       NS_ADDREF(target);
 | |
|     }
 | |
|   }
 | |
|   else if (name.EqualsIgnoreCase("_top")) {
 | |
|     GetRootWebShell(target);            // this addrefs, which is OK
 | |
|   }
 | |
|   else if (name.EqualsIgnoreCase("_content")) {
 | |
|     // a kind of special case: only the window can answer this question
 | |
|     NS_ASSERTION(mContainer, "null container in WebShell::GetTarget");
 | |
|     if (nsnull != mContainer)
 | |
|       mContainer->FindWebShellWithName(aName, target);
 | |
|       // (and don't SetName())
 | |
|     // else target remains nsnull, which would be bad
 | |
|   }
 | |
|   else {
 | |
|     // Look from the top of the tree downward
 | |
|     NS_ASSERTION(mContainer, "null container in WebShell::GetTarget");
 | |
|     if (nsnull != mContainer) {
 | |
|       mContainer->FindWebShellWithName(aName, target);
 | |
|       if (nsnull == target) {
 | |
|         mContainer->NewWebShell(NS_CHROME_ALL_CHROME, PR_TRUE, target);
 | |
|       }
 | |
|       if (nsnull != target) {
 | |
|         target->SetName(aName);
 | |
|       }
 | |
|       else {
 | |
|         target = this;
 | |
|         NS_ADDREF(target);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return target;
 | |
| }
 | |
| 
 | |
| nsIEventQueue* nsWebShell::GetEventQueue(void)
 | |
| {
 | |
|   NS_PRECONDITION(nsnull != mThreadEventQueue, "EventQueue for thread is null");
 | |
|   NS_ADDREF(mThreadEventQueue);
 | |
|   return mThreadEventQueue;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsWebShell::HandleLinkClickEvent(nsIContent *aContent,
 | |
|                                  nsLinkVerb aVerb,
 | |
|                                  const PRUnichar* aURLSpec,
 | |
|                                  const PRUnichar* aTargetSpec,
 | |
|                                  nsIInputStream* aPostDataStream)
 | |
| {
 | |
|   nsAutoString target(aTargetSpec);
 | |
| 
 | |
| 
 | |
|   switch(aVerb) {
 | |
|     case eLinkVerb_New:
 | |
|       target.SetString("_blank");
 | |
|       // Fall into replace case
 | |
|     case eLinkVerb_Replace:
 | |
|       {
 | |
|         nsIWebShell* shell = GetTarget(target.GetUnicode());
 | |
|         if (nsnull != shell) {
 | |
|           // Allocate since mURL may change beneath us
 | |
|           PRUnichar* str = mURL.ToNewUnicode();
 | |
|           nsresult rv = NS_OK;
 | |
| 
 | |
|           NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv); 
 | |
|           PRBool useURILoader = PR_FALSE;
 | |
|           if (NS_SUCCEEDED(rv))
 | |
|             prefs->GetBoolPref("browser.uriloader", &useURILoader);
 | |
|           if (useURILoader)
 | |
|           {
 | |
|               // for now, just hack the verb to be view-link-clicked
 | |
|               // and down in the load document code we'll detect this and
 | |
|               // set the correct uri loader command
 | |
|             (void)shell->LoadURL(aURLSpec, "view-link-click", aPostDataStream,
 | |
|                                 PR_TRUE, nsIChannel::LOAD_NORMAL, 
 | |
|                                 0, nsnull, str);
 | |
|           }
 | |
|           else
 | |
|           {
 | |
|             (void)shell->LoadURL(aURLSpec, aPostDataStream,
 | |
|                                  PR_TRUE, nsIChannel::LOAD_NORMAL,
 | |
|                                  0, nsnull, str);
 | |
|           }
 | |
|           Recycle(str);
 | |
|           NS_RELEASE(shell);
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case eLinkVerb_Embed:
 | |
|     default:
 | |
|       ;
 | |
|       // XXX Need to do this
 | |
|   }
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnOverLink(nsIContent* aContent,
 | |
|                        const PRUnichar* aURLSpec,
 | |
|                        const PRUnichar* aTargetSpec)
 | |
| {
 | |
|   if (!mOverURL.Equals(aURLSpec) || !mOverTarget.Equals(aTargetSpec)) {
 | |
| #ifdef NOISY_LINKS
 | |
|     fputs("Was '", stdout);
 | |
|     fputs(mOverURL, stdout);
 | |
|     fputs("' '", stdout);
 | |
|     fputs(mOverTarget, stdout);
 | |
|     fputs("'\n", stdout);
 | |
|     fputs("Over link '", stdout);
 | |
|     fputs(aURLSpec, stdout);
 | |
|     fputs("' '", stdout);
 | |
|     fputs(aTargetSpec, stdout);
 | |
|     fputs("'\n", stdout);
 | |
| #endif /* NS_DEBUG */
 | |
| 
 | |
|     mOverURL = aURLSpec;
 | |
|     mOverTarget = aTargetSpec;
 | |
| 
 | |
|     // Get the browser window and setStatus
 | |
|     nsIBrowserWindow *browserWindow;
 | |
| 
 | |
|     browserWindow = GetBrowserWindow();
 | |
|     if (nsnull != browserWindow) {
 | |
|       browserWindow->SetStatus(aURLSpec);
 | |
|       NS_RELEASE(browserWindow);
 | |
|     }
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetLinkState(const PRUnichar* aURLSpec, nsLinkState& aState)
 | |
| {
 | |
|   aState = eLinkState_Unvisited;
 | |
| 
 | |
|   nsresult rv;
 | |
| 
 | |
|   // XXX: GlobalHistory is going to be moved out of the webshell into a more appropriate place.
 | |
|   if ((nsnull == mHistoryService) && !mFailedToLoadHistoryService) {
 | |
|     rv = nsServiceManager::GetService(kGlobalHistoryCID,
 | |
|                                       NS_GET_IID(nsIGlobalHistory),
 | |
|                                       (nsISupports**) &mHistoryService);
 | |
| 
 | |
|     if (NS_FAILED(rv)) {
 | |
|       mFailedToLoadHistoryService = PR_TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (mHistoryService) {
 | |
|     // XXX aURLSpec should really be a char*, not a PRUnichar*.
 | |
|     nsAutoString urlStr(aURLSpec);
 | |
| 
 | |
|     char buf[256];
 | |
|     char* url = buf;
 | |
| 
 | |
|     if (urlStr.Length() >= PRInt32(sizeof buf)) {
 | |
|       url = new char[urlStr.Length() + 1];
 | |
|     }
 | |
| 
 | |
|     PRInt64 lastVisitDate;
 | |
| 
 | |
|     if (url) {
 | |
|       urlStr.ToCString(url, urlStr.Length() + 1);
 | |
| 
 | |
|       rv = mHistoryService->GetLastVisitDate(url, &lastVisitDate);
 | |
| 
 | |
|       if (url != buf)
 | |
|         delete[] url;
 | |
|     }
 | |
|     else {
 | |
|       rv = NS_ERROR_OUT_OF_MEMORY;
 | |
|     }
 | |
| 
 | |
|   //XXX: Moved to destructor  nsServiceManager::ReleaseService(kGlobalHistoryCID, mHistoryService);
 | |
| 
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     // a last-visit-date of zero means we've never seen it before; so
 | |
|     // if it's not zero, we must've seen it.
 | |
|     if (! LL_IS_ZERO(lastVisitDate))
 | |
|       aState = eLinkState_Visited;
 | |
| 
 | |
|     // XXX how to tell if eLinkState_OutOfDate?
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| nsIBrowserWindow* nsWebShell::GetBrowserWindow()
 | |
| {
 | |
|    nsCOMPtr<nsIWebShell> rootWebShell;
 | |
|   nsIBrowserWindow *browserWindow = nsnull;
 | |
| 
 | |
|   GetRootWebShellEvenIfChrome(getter_AddRefs(rootWebShell));
 | |
| 
 | |
|   if (rootWebShell) {
 | |
|     nsIWebShellContainer *rootContainer;
 | |
|     rootWebShell->GetContainer(rootContainer);
 | |
|     if (nsnull != rootContainer) {
 | |
|       rootContainer->QueryInterface(kIBrowserWindowIID, (void**)&browserWindow);
 | |
|       NS_RELEASE(rootContainer);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return browserWindow;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsWebShell::CreateScriptEnvironment()
 | |
| {
 | |
|   nsresult res = NS_OK;
 | |
| 
 | |
|   if (nsnull == mScriptGlobal) {
 | |
|     res = NS_NewScriptGlobalObject(&mScriptGlobal);
 | |
|     if (NS_FAILED(res)) {
 | |
|       return res;
 | |
|     }
 | |
|     mScriptGlobal->SetWebShell(this);
 | |
|     mScriptGlobal->SetGlobalObjectOwner(
 | |
|       NS_STATIC_CAST(nsIScriptGlobalObjectOwner*, this));
 | |
|   }
 | |
| 
 | |
|   if (nsnull == mScriptContext) {
 | |
|     res = NS_CreateScriptContext(mScriptGlobal, &mScriptContext);
 | |
|   }
 | |
| 
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnStartDocumentLoad(nsIDocumentLoader* loader,
 | |
|                                 nsIURI* aURL,
 | |
|                                 const char* aCommand)
 | |
| {
 | |
|   nsIDocumentViewer* docViewer;
 | |
|   nsresult rv = NS_ERROR_FAILURE;
 | |
| 
 | |
|   if ((nsnull != mScriptGlobal) &&
 | |
|       (loader == mDocLoader)) {
 | |
|     if (nsnull != mContentViewer &&
 | |
|         NS_OK == mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer)) {
 | |
|       nsIPresContext *presContext;
 | |
|       if (NS_OK == docViewer->GetPresContext(presContext)) {
 | |
|         nsEventStatus status = nsEventStatus_eIgnore;
 | |
|         nsMouseEvent event;
 | |
|         event.eventStructType = NS_EVENT;
 | |
|         event.message = NS_PAGE_UNLOAD;
 | |
|         rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
 | |
| 
 | |
|         NS_RELEASE(presContext);
 | |
|       }
 | |
|       NS_RELEASE(docViewer);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (loader == mDocLoader) {
 | |
|     nsCOMPtr<nsIDocumentLoaderObserver> dlObserver;
 | |
| 
 | |
|     if (!mDocLoaderObserver && mParent) {
 | |
|       /* If this is a frame (in which case it would have a parent && doesn't
 | |
|        * have a documentloaderObserver, get it from the rootWebShell
 | |
|        */
 | |
|       nsCOMPtr<nsIWebShell> root;
 | |
|       nsresult res = GetRootWebShell(*getter_AddRefs(root));
 | |
| 
 | |
|       if (NS_SUCCEEDED(res) && root)
 | |
|         root->GetDocLoaderObserver(getter_AddRefs(dlObserver));
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       dlObserver = do_QueryInterface(mDocLoaderObserver);  // we need this to addref
 | |
|     }
 | |
|     /*
 | |
|      * Fire the OnStartDocumentLoad of the webshell observer
 | |
|      */
 | |
|     if ((nsnull != mContainer) && (nsnull != dlObserver))
 | |
|     {
 | |
|        dlObserver->OnStartDocumentLoad(mDocLoader, aURL, aCommand);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnEndDocumentLoad(nsIDocumentLoader* loader,
 | |
|                               nsIChannel* channel,
 | |
|                               nsresult aStatus)
 | |
| {
 | |
| #ifdef MOZ_PERF_METRICS
 | |
|   MOZ_TIMER_DEBUGLOG(("Stop: nsWebShell::OnEndDocumentLoad(), this=%p\n", this));
 | |
|   MOZ_TIMER_STOP(mTotalTime);
 | |
|   MOZ_TIMER_LOG(("Total (Layout + Page Load) Time (webshell=%p): ", this));
 | |
|   MOZ_TIMER_PRINT(mTotalTime);
 | |
| #endif
 | |
| 
 | |
|   nsresult rv = NS_ERROR_FAILURE;
 | |
|   if (!channel) {
 | |
|     return NS_ERROR_NULL_POINTER;
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsIURI> aURL;
 | |
|   rv = channel->GetURI(getter_AddRefs(aURL));
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
|   
 | |
|   // clean up reload state for meta charset
 | |
|   if(eCharsetReloadRequested == mCharsetReloadState)
 | |
|       mCharsetReloadState = eCharsetReloadStopOrigional;
 | |
|   else 
 | |
|       mCharsetReloadState = eCharsetReloadInit;
 | |
| 
 | |
|   /* one of many safeguards that prevent death and destruction if
 | |
|      someone is so very very rude as to bring this window down
 | |
|      during this load handler. */
 | |
|   nsCOMPtr<nsIWebShell> kungFuDeathGrip(this);
 | |
| 
 | |
| //if (!mProcessedEndDocumentLoad) {
 | |
|   if (loader == mDocLoader) {
 | |
|     mProcessedEndDocumentLoad = PR_TRUE;
 | |
| 
 | |
|     if (nsnull != mScriptGlobal) {
 | |
|       nsIDocumentViewer* docViewer;
 | |
|       if (nsnull != mContentViewer &&
 | |
|           NS_OK == mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer)) {
 | |
|         nsIPresContext *presContext;
 | |
|         if (NS_OK == docViewer->GetPresContext(presContext)) {
 | |
|           nsEventStatus status = nsEventStatus_eIgnore;
 | |
|           nsMouseEvent event;
 | |
|           event.eventStructType = NS_EVENT;
 | |
|           event.message = NS_PAGE_LOAD;
 | |
|           rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
 | |
| 
 | |
|           NS_RELEASE(presContext);
 | |
|         }
 | |
|         NS_RELEASE(docViewer);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // Fire the EndLoadURL of the web shell container
 | |
|     if (nsnull != aURL) {
 | |
|        nsAutoString urlString;
 | |
|        char* spec;
 | |
|        rv = aURL->GetSpec(&spec);
 | |
|        if (NS_SUCCEEDED(rv)) {
 | |
|          urlString = spec;
 | |
|          if (nsnull != mContainer) {
 | |
|             rv = mContainer->EndLoadURL(this, urlString.GetUnicode(), 0);
 | |
|          }
 | |
|          nsCRT::free(spec);
 | |
|        }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     nsCOMPtr<nsIDocumentLoaderObserver> dlObserver;
 | |
| 
 | |
|     if (!mDocLoaderObserver && mParent) {
 | |
|       /* If this is a frame (in which case it would have a parent && doesn't
 | |
|        * have a documentloaderObserver, get it from the rootWebShell
 | |
|        */
 | |
|       nsCOMPtr<nsIWebShell> root;
 | |
|       nsresult res = GetRootWebShell(*getter_AddRefs(root));
 | |
| 
 | |
|       if (NS_SUCCEEDED(res) && root)
 | |
|         root->GetDocLoaderObserver(getter_AddRefs(dlObserver));
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       /* Take care of the Trailing slash situation */
 | |
|       if (mSHist)
 | |
|         CheckForTrailingSlash(aURL);
 | |
|       dlObserver = do_QueryInterface(mDocLoaderObserver);  // we need this to addref
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Fire the OnEndDocumentLoad of the DocLoaderobserver
 | |
|      */
 | |
|     if (dlObserver && (nsnull != aURL)) {
 | |
|        dlObserver->OnEndDocumentLoad(mDocLoader, channel, aStatus);
 | |
|     }
 | |
| 
 | |
|     if (mDocLoader == loader && NS_FAILED(aStatus)) {
 | |
|         nsAutoString errorMsg;
 | |
|         nsXPIDLCString host;
 | |
|         rv = aURL->GetHost(getter_Copies(host));
 | |
|         if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|         // Doc failed to load because the host was not found.
 | |
|         if (aStatus == NS_ERROR_UNKNOWN_HOST) {
 | |
|             CBufDescriptor buf((const char *)host, PR_TRUE, PL_strlen(host) + 1);
 | |
|             nsCAutoString hostStr(buf);
 | |
|             PRInt32 dotLoc = hostStr.FindChar('.');
 | |
| 
 | |
|             // First see if we should throw it to the keyword server.
 | |
|             NS_ASSERTION(mPrefs, "the webshell's pref service wasn't initialized");
 | |
|             PRBool keywordsEnabled = PR_FALSE;
 | |
|             rv = mPrefs->GetBoolPref("keyword.enabled", &keywordsEnabled);
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             if (keywordsEnabled && (-1 == dotLoc)) {
 | |
|                 // only send non-qualified hosts to the keyword server
 | |
|                 nsAutoString keywordSpec("keyword:");
 | |
|                 keywordSpec.Append(host);
 | |
|                 return LoadURL(keywordSpec.GetUnicode(), "view");
 | |
|             } // end keywordsEnabled
 | |
| 
 | |
|             // Try our www.*.com trick.
 | |
|             nsCAutoString retryHost;
 | |
|             if (-1 == dotLoc) {
 | |
|                 retryHost = "www.";
 | |
|                 retryHost += hostStr;
 | |
|                 retryHost += ".com";
 | |
|             } else {
 | |
|                 PRInt32 hostLen = hostStr.Length();
 | |
|                 if ( ((hostLen - dotLoc) == 3) || ((hostLen - dotLoc) == 4) ) {
 | |
|                     retryHost = "www.";
 | |
|                     retryHost += hostStr;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!retryHost.IsEmpty()) {
 | |
|                 rv = aURL->SetHost(retryHost.GetBuffer());
 | |
|                 if (NS_FAILED(rv)) return rv;
 | |
|                 nsXPIDLCString aSpec;
 | |
|                 rv = aURL->GetSpec(getter_Copies(aSpec));
 | |
|                 if (NS_FAILED(rv)) return rv;
 | |
|                 nsAutoString newURL(aSpec);
 | |
|                 // reload the url
 | |
|                 return LoadURL(newURL.GetUnicode(), "view");
 | |
|             } // retry
 | |
| 
 | |
|             // throw a DNS failure dialog
 | |
|             rv = InitDialogVars();
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             nsXPIDLString messageStr;
 | |
|             nsAutoString name("dnsNotFound");
 | |
|             rv = mStringBundle->GetStringFromName(name.GetUnicode(), getter_Copies(messageStr));
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             errorMsg = host;
 | |
|             errorMsg.Append(' ');
 | |
|             errorMsg.Append(messageStr);
 | |
| 
 | |
|             (void)mPrompter->Alert(errorMsg.GetUnicode());
 | |
|         } else // unknown host
 | |
| 
 | |
|         // Doc failed to load because we couldn't connect to the server.
 | |
|         if (aStatus == NS_ERROR_CONNECTION_REFUSED) {
 | |
|             // throw a connection failure dialog
 | |
|             PRInt32 port = -1;
 | |
|             rv = aURL->GetPort(&port);
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
|             
 | |
|             rv = InitDialogVars();
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             nsXPIDLString messageStr;
 | |
|             nsAutoString name("connectionFailure");
 | |
|             rv = mStringBundle->GetStringFromName(name.GetUnicode(), getter_Copies(messageStr));
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             errorMsg = messageStr;
 | |
|             errorMsg.Append(' ');
 | |
|             errorMsg.Append(host);
 | |
|             if (port > 0) {
 | |
|                 errorMsg.Append(':');
 | |
|                 errorMsg.Append(port);
 | |
|             }
 | |
|             errorMsg.Append('.');
 | |
| 
 | |
|             (void)mPrompter->Alert(errorMsg.GetUnicode());
 | |
|         } else // end NS_ERROR_CONNECTION_REFUSED
 | |
| 
 | |
|         // Doc failed to load because the socket function timed out.
 | |
|         if (aStatus == NS_ERROR_NET_TIMEOUT) {
 | |
|             // throw a timeout dialog
 | |
|             rv = InitDialogVars();
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             nsXPIDLString messageStr;
 | |
|             nsAutoString name("netTimeout");
 | |
|             rv = mStringBundle->GetStringFromName(name.GetUnicode(), getter_Copies(messageStr));
 | |
|             if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|             errorMsg = messageStr;
 | |
|             errorMsg.Append(' ');
 | |
|             errorMsg.Append(host);
 | |
|             errorMsg.Append('.');
 | |
| 
 | |
|             (void)mPrompter->Alert(errorMsg.GetUnicode());            
 | |
|         } // end NS_ERROR_NET_TIMEOUT
 | |
|     } // end mDocLoader == loader
 | |
|   } //!mProcessedEndDocumentLoad
 | |
|   else {
 | |
|     rv = NS_OK;
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnStartURLLoad(nsIDocumentLoader* loader,
 | |
|                            nsIChannel* channel)
 | |
| {
 | |
|   nsresult rv;
 | |
| 
 | |
|   nsCOMPtr<nsIURI> aURL;
 | |
|   rv = channel->GetURI(getter_AddRefs(aURL));
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
| 
 | |
|   // Stop loading of the earlier document completely when the document url
 | |
|   // load starts.  Now we know that this url is valid and available.
 | |
|   nsXPIDLCString url;
 | |
|   aURL->GetSpec(getter_Copies(url));
 | |
|   if (0 == PL_strcmp(url, mURL.GetBuffer()))
 | |
|     StopAfterURLAvailable();
 | |
| 
 | |
|   /*
 | |
|    *Fire the OnStartDocumentLoad of the webshell observer
 | |
|    */
 | |
|   if ((nsnull != mContainer) && (nsnull != mDocLoaderObserver))
 | |
|   {
 | |
|     mDocLoaderObserver->OnStartURLLoad(mDocLoader, channel);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnProgressURLLoad(nsIDocumentLoader* loader,
 | |
|                               nsIChannel* channel,
 | |
|                               PRUint32 aProgress,
 | |
|                               PRUint32 aProgressMax)
 | |
| {
 | |
|   /*
 | |
|    *Fire the OnStartDocumentLoad of the webshell observer and container...
 | |
|    */
 | |
|   if ((nsnull != mContainer) && (nsnull != mDocLoaderObserver))
 | |
|   {
 | |
|      mDocLoaderObserver->OnProgressURLLoad(mDocLoader, channel, aProgress, aProgressMax);
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnStatusURLLoad(nsIDocumentLoader* loader,
 | |
|                             nsIChannel* channel,
 | |
|                             nsString& aMsg)
 | |
| {
 | |
|   /*
 | |
|    *Fire the OnStartDocumentLoad of the webshell observer and container...
 | |
|    */
 | |
|   if ((nsnull != mContainer) && (nsnull != mDocLoaderObserver))
 | |
|   {
 | |
|      mDocLoaderObserver->OnStatusURLLoad(mDocLoader, channel, aMsg);
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnEndURLLoad(nsIDocumentLoader* loader,
 | |
|                          nsIChannel* channel,
 | |
|                          nsresult aStatus)
 | |
| {
 | |
| #if 0
 | |
|   const char* spec;
 | |
|   aURL->GetSpec(&spec);
 | |
|   printf("nsWebShell::OnEndURLLoad:%p: loader=%p url=%s status=%d\n", this, loader, spec, aStatus);
 | |
| #endif
 | |
|   /*
 | |
|    *Fire the OnEndDocumentLoad of the webshell observer
 | |
|    */
 | |
|   if ((nsnull != mContainer) && (nsnull != mDocLoaderObserver))
 | |
|   {
 | |
|       mDocLoaderObserver->OnEndURLLoad(mDocLoader, channel, aStatus);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| /* For use with redirect/refresh url api */
 | |
| class refreshData : public nsITimerCallback
 | |
| {
 | |
| public:
 | |
|   refreshData();
 | |
| 
 | |
|   NS_DECL_ISUPPORTS
 | |
| 
 | |
|   // nsITimerCallback interface
 | |
|   NS_IMETHOD_(void) Notify(nsITimer *timer);
 | |
| 
 | |
|   nsIWebShell* mShell;
 | |
|   nsString     mUrlSpec;
 | |
|   PRBool       mRepeat;
 | |
|   PRInt32      mDelay;
 | |
| 
 | |
| protected:
 | |
|   virtual ~refreshData();
 | |
| };
 | |
| 
 | |
| refreshData::refreshData()
 | |
| {
 | |
|   NS_INIT_REFCNT();
 | |
| 
 | |
|   mShell   = nsnull;
 | |
| }
 | |
| 
 | |
| refreshData::~refreshData()
 | |
| {
 | |
|   NS_IF_RELEASE(mShell);
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(refreshData, kITimerCallbackIID);
 | |
| 
 | |
| NS_IMETHODIMP_(void) refreshData::Notify(nsITimer *aTimer)
 | |
| {
 | |
|   NS_PRECONDITION((nsnull != mShell), "Null pointer...");
 | |
|   if (nsnull != mShell) {
 | |
|     mShell->LoadURL(mUrlSpec.GetUnicode(), nsnull, PR_TRUE, nsIChannel::LOAD_NORMAL);
 | |
|   }
 | |
|   /*
 | |
|    * LoadURL(...) will cancel all refresh timers... This causes the Timer and
 | |
|    * its refreshData instance to be released...
 | |
|    */
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::RefreshURI(nsIURI* aURI, PRInt32 millis, PRBool repeat)
 | |
| {
 | |
| 
 | |
|   nsresult rv = NS_OK;
 | |
|   if (nsnull == aURI) {
 | |
|     NS_PRECONDITION((aURI != nsnull), "Null pointer");
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|     goto done;
 | |
|   }
 | |
| 
 | |
|   char* spec;
 | |
|   aURI->GetSpec(&spec);
 | |
|   rv = RefreshURL(spec, millis, repeat);
 | |
|   nsCRT::free(spec);
 | |
| 
 | |
| done:
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::RefreshURL(const char* aURI, PRInt32 millis, PRBool repeat)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   nsITimer *timer=nsnull;
 | |
|   refreshData *data;
 | |
| 
 | |
|   if (nsnull == aURI) {
 | |
|     NS_PRECONDITION((aURI != nsnull), "Null pointer");
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|     goto done;
 | |
|   }
 | |
| 
 | |
|   NS_NEWXPCOM(data, refreshData);
 | |
|   if (nsnull == data) {
 | |
|     rv = NS_ERROR_OUT_OF_MEMORY;
 | |
|     goto done;
 | |
|   }
 | |
| 
 | |
|   // Set the reference count to one...
 | |
|   NS_ADDREF(data);
 | |
| 
 | |
|   data->mShell = this;
 | |
|   NS_ADDREF(data->mShell);
 | |
| 
 | |
|   data->mUrlSpec  = aURI;
 | |
|   data->mDelay    = millis;
 | |
|   data->mRepeat   = repeat;
 | |
| 
 | |
|   /* Create the timer. */
 | |
|   if (NS_OK == NS_NewTimer(&timer)) {
 | |
|       /* Add the timer to our array. */
 | |
|       NS_LOCK_INSTANCE();
 | |
|       mRefreshments.AppendElement(timer);
 | |
|       timer->Init(data, millis);
 | |
|       NS_UNLOCK_INSTANCE();
 | |
|   }
 | |
| 
 | |
|   NS_RELEASE(data);
 | |
| 
 | |
| done:
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CancelRefreshURITimers(void)
 | |
| {
 | |
|   PRInt32 i;
 | |
|   nsITimer* timer;
 | |
| 
 | |
|   /* Right now all we can do is cancel all the timers for this webshell. */
 | |
|   NS_LOCK_INSTANCE();
 | |
| 
 | |
|   /* Walk the list backwards to avoid copying the array as it shrinks.. */
 | |
|   for (i = mRefreshments.Count()-1; (0 <= i); i--) {
 | |
|     timer=(nsITimer*)mRefreshments.ElementAt(i);
 | |
|     /* Remove the entry from the list before releasing the timer.*/
 | |
|     mRefreshments.RemoveElementAt(i);
 | |
| 
 | |
|     if (timer) {
 | |
|       timer->Cancel();
 | |
|       NS_RELEASE(timer);
 | |
|     }
 | |
|   }
 | |
|   NS_UNLOCK_INSTANCE();
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| /*
 | |
|  * There are cases where netlib does things like add a trailing slash
 | |
|  * to the url being retrieved.  We need to watch out for such
 | |
|  * changes and update the currently loading url's entry in the history
 | |
|  * list. UpdateHistoryEntry() does this.
 | |
|  *
 | |
|  * Assumptions:
 | |
|  *
 | |
|  *   1) aURL is the URL that was inserted into the history list in LoadURL()
 | |
|  *   2) The load of aURL is in progress and this function is being called
 | |
|  *      from one of the functions in nsIStreamListener implemented by nsWebShell.
 | |
|  */
 | |
| nsresult nsWebShell::CheckForTrailingSlash(nsIURI* aURL)
 | |
| {
 | |
| 
 | |
|   PRInt32     curIndex=0;
 | |
|   nsresult rv;
 | |
| 
 | |
|   /* Get current history index and url for it */
 | |
|   rv = mSHist->GetCurrentIndex(&curIndex);
 | |
| 
 | |
|   /* Get the url that netlib passed us */
 | |
|   char* spec;
 | |
|   aURL->GetSpec(&spec);
 | |
|  
 | |
|   //Set it in session history
 | |
|   if (NS_SUCCEEDED(rv) && !mTitle.IsEmpty()) {
 | |
|     mSHist->SetTitleForIndex(curIndex, mTitle.GetUnicode());
 | |
|     // Replace the top most history entry with the new url
 | |
|     mSHist->SetURLForIndex(curIndex, spec);
 | |
|   }
 | |
|   nsCRT::free(spec);
 | |
| 
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CanCutSelection(PRBool* aResult)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   if (nsnull == aResult) {
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|   } else {
 | |
|     *aResult = PR_FALSE;
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CanCopySelection(PRBool* aResult)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   if (nsnull == aResult) {
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|   } else {
 | |
|     *aResult = PR_FALSE;
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CanPasteSelection(PRBool* aResult)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   if (nsnull == aResult) {
 | |
|     rv = NS_ERROR_NULL_POINTER;
 | |
|   } else {
 | |
|     *aResult = PR_FALSE;
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CutSelection(void)
 | |
| {
 | |
|   return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::CopySelection(void)
 | |
| {
 | |
|   return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::PasteSelection(void)
 | |
| {
 | |
|   return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SelectAll(void)
 | |
| {
 | |
|   nsresult rv;
 | |
| 
 | |
|   nsCOMPtr<nsIDocumentViewer> docViewer;
 | |
|   rv = mContentViewer->QueryInterface(kIDocumentViewerIID,
 | |
|                                       getter_AddRefs(docViewer));
 | |
|   if (NS_FAILED(rv) || !docViewer) return rv;
 | |
| 
 | |
|   nsCOMPtr<nsIPresShell> presShell;
 | |
|   rv = docViewer->GetPresShell(*getter_AddRefs(presShell));
 | |
|   if (NS_FAILED(rv) || !presShell) return rv;
 | |
| 
 | |
|   nsCOMPtr<nsIDOMSelection> selection;
 | |
|   rv = presShell->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection));
 | |
|   if (NS_FAILED(rv) || !selection) return rv;
 | |
| 
 | |
|   // Get the document object
 | |
|   nsCOMPtr<nsIDocument> doc;
 | |
|   rv = docViewer->GetDocument(*getter_AddRefs(doc));
 | |
|   if (NS_FAILED(rv) || !doc) return rv;
 | |
| 
 | |
| 
 | |
|   nsCOMPtr<nsIDOMHTMLDocument> htmldoc;
 | |
|   rv = doc->QueryInterface(kIDOMHTMLDocumentIID, (void**)&htmldoc);
 | |
|   if (NS_FAILED(rv) || !htmldoc) return rv;
 | |
| 
 | |
|   nsCOMPtr<nsIDOMHTMLElement>bodyElement;
 | |
|   rv = htmldoc->GetBody(getter_AddRefs(bodyElement));
 | |
|   if (NS_FAILED(rv) || !bodyElement) return rv;
 | |
| 
 | |
|   nsCOMPtr<nsIDOMNode>bodyNode = do_QueryInterface(bodyElement);
 | |
|   if (!bodyNode) return NS_ERROR_NO_INTERFACE;
 | |
| 
 | |
| #if 0
 | |
|   rv = selection->Collapse(bodyNode, 0);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   nsCOMPtr<nsIDOMRange>range;
 | |
|   rv = selection->GetRangeAt(0, getter_AddRefs(range));
 | |
|   if (NS_FAILED(rv) || !range) return rv;
 | |
| #endif
 | |
| 
 | |
|   rv = selection->ClearSelection();
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   nsCOMPtr<nsIDOMRange> range;
 | |
|   rv = nsComponentManager::CreateInstance(kCDOMRangeCID, nsnull,
 | |
|                                           NS_GET_IID(nsIDOMRange),
 | |
|                                           getter_AddRefs(range));
 | |
| 
 | |
|   rv = range->SelectNodeContents(bodyNode);
 | |
|   if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|   rv = selection->AddRange(range);
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SelectNone(void)
 | |
| {
 | |
|   return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| 
 | |
| //----------------------------------------------------
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::FindNext(const PRUnichar * aSearchStr, PRBool aMatchCase, PRBool aSearchDown, PRBool &aIsFound)
 | |
| {
 | |
|   return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| // Methods from nsIProgressEventSink
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnProgress(nsIChannel* channel, nsISupports* ctxt, 
 | |
|     PRUint32 aProgress, 
 | |
|     PRUint32 aProgressMax)
 | |
| {
 | |
|     if (nsnull != mDocLoaderObserver)
 | |
|     {
 | |
|         return mDocLoaderObserver->OnProgressURLLoad(
 | |
|             mDocLoader,
 | |
|             channel,
 | |
|             aProgress,
 | |
|             aProgressMax);
 | |
|     }
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::OnStatus(nsIChannel* channel, nsISupports* ctxt, 
 | |
|     const PRUnichar* aMsg)
 | |
| {
 | |
|     if (nsnull != mDocLoaderObserver)
 | |
|     {
 | |
|         nsAutoString temp(aMsg);
 | |
| #ifdef DEBUG_gagan
 | |
| 
 | |
| #ifdef XP_UNIX
 | |
|         printf("\033[33m"); // Start yellow
 | |
| #endif
 | |
| 
 | |
|         char* tmp = temp.ToNewCString();
 | |
|         printf("%s\n",tmp);
 | |
|         CRTFREEIF(tmp);
 | |
| #ifdef XP_UNIX
 | |
|         printf("\033[0m"); // End colors
 | |
| #endif
 | |
| 
 | |
| #endif // DEBUG_gagan
 | |
|         nsresult rv =  mDocLoaderObserver->OnStatusURLLoad(
 | |
|             mDocLoader,
 | |
|             channel,
 | |
|             temp);
 | |
| 
 | |
|         return rv;
 | |
|     }
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| nsresult nsWebShell::GetViewManager(nsIViewManager* *viewManager)
 | |
| {
 | |
| 	nsresult rv = NS_ERROR_FAILURE;
 | |
| 	*viewManager = nsnull;
 | |
| 	do {
 | |
| 		if (nsnull == mContentViewer) break;
 | |
| 	
 | |
| 		nsCOMPtr<nsIDocumentViewer> docViewer;
 | |
| 		rv = mContentViewer->QueryInterface(kIDocumentViewerIID,
 | |
| 											getter_AddRefs(docViewer));
 | |
| 		if (NS_FAILED(rv)) break;
 | |
| 		
 | |
| 		nsCOMPtr<nsIPresContext> context;
 | |
| 		rv = docViewer->GetPresContext(*getter_AddRefs(context));
 | |
| 		if (NS_FAILED(rv)) break;
 | |
| 		
 | |
| 		nsCOMPtr<nsIPresShell> shell;
 | |
| 		rv = context->GetShell(getter_AddRefs(shell));
 | |
| 		if (NS_FAILED(rv)) break;
 | |
| 		
 | |
| 		rv = shell->GetViewManager(viewManager);
 | |
| 	} while (0);
 | |
| 	return rv;
 | |
| }
 | |
| 
 | |
| 
 | |
| #define DIALOG_STRING_URI "chrome://global/locale/appstrings.properties"
 | |
| 
 | |
| nsresult nsWebShell::InitDialogVars(void)
 | |
| {
 | |
|     nsresult rv = NS_OK;
 | |
|     if (!mPrompter) {
 | |
|         // Get an nsIPrompt so we can throw dialogs.
 | |
|         nsCOMPtr<nsIWebShellContainer> topLevelWindow;
 | |
|         GetTopLevelWindow(getter_AddRefs(topLevelWindow));
 | |
|         if (topLevelWindow)
 | |
|             mPrompter = do_QueryInterface(topLevelWindow);
 | |
|     }
 | |
| 
 | |
|     if (!mStringBundle) {
 | |
|         // Get a string bundle so we can retrieve dialog strings
 | |
|         nsCOMPtr<nsILocale> locale;
 | |
|         NS_WITH_SERVICE(nsILocaleService, localeServ, kLocaleServiceCID, &rv);
 | |
|         if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|         rv = localeServ->GetSystemLocale(getter_AddRefs(locale));
 | |
|         if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|         NS_WITH_SERVICE(nsIStringBundleService, service, kCStringBundleServiceCID, &rv);
 | |
|         if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|         rv = service->CreateBundle(DIALOG_STRING_URI, locale, getter_AddRefs(mStringBundle));
 | |
|     }
 | |
|     return rv;
 | |
| }
 | |
| 
 | |
| //*****************************************************************************
 | |
| // nsWebShell::nsIBaseWindow
 | |
| //*****************************************************************************   
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::InitWindow(nativeWindow parentNativeWindow,
 | |
|    nsIWidget* parentWidget, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)   
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::Create()
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::Destroy()
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   //Fire unload event before we blow anything away.
 | |
|   if (nsnull != mScriptGlobal) {
 | |
|     nsIDocumentViewer* docViewer;
 | |
|     if (nsnull != mContentViewer &&
 | |
|         NS_OK == mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer)) {
 | |
|       nsIPresContext *presContext;
 | |
|       if (NS_OK == docViewer->GetPresContext(presContext)) {
 | |
|         nsEventStatus status = nsEventStatus_eIgnore;
 | |
|         nsMouseEvent event;
 | |
|         event.eventStructType = NS_EVENT;
 | |
|         event.message = NS_PAGE_UNLOAD;
 | |
|         rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
 | |
| 
 | |
|         NS_RELEASE(presContext);
 | |
|       }
 | |
|       NS_RELEASE(docViewer);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Stop any URLs that are currently being loaded...
 | |
|   Stop();
 | |
|   mDocLoader->Destroy();
 | |
| 
 | |
|   SetContainer(nsnull);
 | |
|   SetDocLoaderObserver(nsnull);
 | |
| 
 | |
|   // Remove this webshell from its parent's child list
 | |
|   nsCOMPtr<nsIWebShell> webShellParent(do_QueryInterface(mParent));
 | |
| 
 | |
|   if (webShellParent) {
 | |
|     webShellParent->RemoveChild(this);
 | |
|   }
 | |
| 
 | |
|   if (nsnull != mDocLoader) {
 | |
|     mDocLoader->SetContainer(nsnull);
 | |
|   }
 | |
| 
 | |
|   mContentViewer = nsnull;
 | |
| 
 | |
|   // Destroy our child web shells and release references to them
 | |
|   DestroyChildren();
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetPosition(PRInt32 aX, PRInt32 aY)
 | |
| {
 | |
|    NS_PRECONDITION(nsnull != mWindow, "null window");
 | |
| 
 | |
|    if(mWindow)
 | |
|       mWindow->Move(aX, aY);
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetPosition(PRInt32* aX, PRInt32* aY)
 | |
| {
 | |
|    PRInt32 dummyHolder;
 | |
| 
 | |
|    return GetPositionAndSize(aX, aY, &dummyHolder, &dummyHolder);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetSize(PRInt32 aCX, PRInt32 aCY, PRBool aRepaint)
 | |
| {
 | |
|    PRInt32 x = 0, y = 0;
 | |
|    GetPosition(&x, &y);
 | |
|    return SetPositionAndSize(x, y, aCX, aCY, aRepaint);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetSize(PRInt32* aCX, PRInt32* aCY)
 | |
| {
 | |
|    PRInt32 dummyHolder;
 | |
| 
 | |
|    return GetPositionAndSize(&dummyHolder, &dummyHolder, aCX, aCY);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx,
 | |
|    PRInt32 cy, PRBool fRepaint)
 | |
| {
 | |
|      /*
 | |
|   --dwc0001
 | |
|   NS_PRECONDITION(nsnull != mWindow, "null window");
 | |
|   */
 | |
| 
 | |
|   PRInt32 borderWidth  = 0;
 | |
|   PRInt32 borderHeight = 0;
 | |
|   if (nsnull != mWindow) {
 | |
|     mWindow->GetBorderSize(borderWidth, borderHeight);
 | |
|     // Don't have the widget repaint. Layout will generate repaint requests
 | |
|     // during reflow
 | |
|     mWindow->Resize(x, y, cx, cy, fRepaint);
 | |
|   }
 | |
| 
 | |
|   mBounds.SetRect(x,y,cx,cy);   // set the webshells bounds --dwc0001
 | |
| 
 | |
|   // Set the size of the content area, which is the size of the window
 | |
|   // minus the borders
 | |
|   if (nsnull != mContentViewer) {
 | |
|     nsRect rr(0, 0, cx-(borderWidth*2), cy-(borderHeight*2));
 | |
|     mContentViewer->SetBounds(rr);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetPositionAndSize(PRInt32* aX, PRInt32* aY, 
 | |
|    PRInt32* aCX, PRInt32* aCY)
 | |
| {
 | |
|    nsRect result;
 | |
| 
 | |
|    if(mWindow)
 | |
|       mWindow->GetClientBounds(result);
 | |
|    else
 | |
|       result = mBounds;
 | |
| 
 | |
|    *aX = result.x;
 | |
|    *aY = result.y;
 | |
|    *aCX = result.width;
 | |
|    *aCY = result.height;
 | |
| 
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::Repaint(PRBool aForce)
 | |
| {
 | |
|   /*
 | |
|   --dwc0001
 | |
|   NS_PRECONDITION(nsnull != mWindow, "null window");
 | |
|   */
 | |
| 
 | |
|   if (nsnull != mWindow) {
 | |
|     mWindow->Invalidate(aForce);
 | |
|   }
 | |
| 
 | |
| #if 0
 | |
| 	if (nsnull != mWindow) {
 | |
| 		mWindow->Invalidate(aForce);
 | |
| 	}
 | |
| 	return NS_OK;
 | |
| #else
 | |
| 	nsresult rv;
 | |
| 	nsCOMPtr<nsIViewManager> viewManager;
 | |
| 	rv = GetViewManager(getter_AddRefs(viewManager));
 | |
| 	if (NS_SUCCEEDED(rv) && viewManager) {
 | |
| 		rv = viewManager->UpdateAllViews(0);
 | |
| 	}
 | |
| 	return rv;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetParentWidget(nsIWidget** parentWidget)
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetParentWidget(nsIWidget* parentWidget)
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetParentNativeWindow(nativeWindow* parentNativeWindow)
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetParentNativeWindow(nativeWindow parentNativeWindow)
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetVisibility(PRBool* aVisibility)
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetVisibility(PRBool aVisibility)
 | |
| {
 | |
|    if(mWindow)
 | |
|       mWindow->Show(aVisibility);
 | |
| 
 | |
|    if(aVisibility)
 | |
|       {
 | |
|       if(mContentViewer)
 | |
|          mContentViewer->Show();
 | |
|       }
 | |
|    else
 | |
|       {
 | |
|       if(mContentViewer)
 | |
|          mContentViewer->Hide();
 | |
|       }
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetMainWidget(nsIWidget** mainWidget)
 | |
| {
 | |
|    NS_WARN_IF_FALSE(PR_FALSE, "NOT IMPLEMENTED");
 | |
|    return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetFocus()
 | |
| {
 | |
|   /*
 | |
|   --dwc0001
 | |
|   NS_PRECONDITION(nsnull != mWindow, "null window");
 | |
|   */
 | |
| 
 | |
|   if (nsnull != mWindow) {
 | |
|     mWindow->SetFocus();
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::FocusAvailable(nsIBaseWindow* aCurrentFocus, PRBool* aTookFocus)
 | |
| {
 | |
|    NS_ENSURE_ARG_POINTER(aTookFocus);
 | |
|    // Next person we should call is first the parent otherwise the 
 | |
|    // docshell tree owner.
 | |
|    nsCOMPtr<nsIBaseWindow> nextCallWin(do_QueryInterface(mParent));
 | |
|    if(!nextCallWin)
 | |
|       {//XXX Enable this when docShellTreeOwner is added
 | |
|       //nextCallWin = do_QueryInterface(mDocShellTreeOwner);
 | |
|       }
 | |
| 
 | |
|    //If the current focus is us, offer it to the next owner.
 | |
|    if(aCurrentFocus == NS_STATIC_CAST(nsIBaseWindow*, this))
 | |
|       {
 | |
|       if(nextCallWin)
 | |
|          return nextCallWin->FocusAvailable(aCurrentFocus, aTookFocus);
 | |
|       return NS_OK;
 | |
|       }
 | |
| 
 | |
|    //Otherwise, check the chilren and offer it to the next sibling.
 | |
|    PRInt32 i;
 | |
|    PRInt32 n = mChildren.Count();
 | |
|    for(i = 0; i < n; i++)
 | |
|       {
 | |
|       nsCOMPtr<nsIBaseWindow> 
 | |
|          child(do_QueryInterface((nsISupports*)mChildren.ElementAt(i)));
 | |
|       if(child.get() == aCurrentFocus)
 | |
|          {
 | |
|          while(++i < n)
 | |
|             {
 | |
|             child = do_QueryInterface((nsISupports*)mChildren.ElementAt(i));
 | |
|             if(NS_SUCCEEDED(child->SetFocus()))
 | |
|                {
 | |
|                *aTookFocus = PR_TRUE;
 | |
|                return NS_OK;
 | |
|                }
 | |
|             }
 | |
|          }
 | |
|       }
 | |
|    if(nextCallWin)
 | |
|       return nextCallWin->FocusAvailable(aCurrentFocus, aTookFocus);
 | |
|    return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetTitle(PRUnichar** aTitle)
 | |
| {
 | |
|    return nsDocShell::GetTitle(aTitle);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetTitle(const PRUnichar* aTitle)
 | |
| {
 | |
|   // Record local title
 | |
|   mTitle = aTitle;
 | |
| 
 | |
|   // Title's set on the top level web-shell are passed ont to the container
 | |
|   nsCOMPtr<nsIDocShellTreeItem> parent;
 | |
|   GetSameTypeParent(getter_AddRefs(parent));
 | |
|   if (!parent) {
 | |
|     nsIBrowserWindow *browserWindow = GetBrowserWindow();
 | |
|     if (nsnull != browserWindow) {
 | |
|       browserWindow->SetTitle(aTitle);
 | |
|       NS_RELEASE(browserWindow);
 | |
| 
 | |
|       // Oh this hack sucks. But there isn't any other way that I can
 | |
|       // reliably get the title text. Sorry.
 | |
|       do {
 | |
|         nsresult rv;
 | |
|         NS_WITH_SERVICE(nsIGlobalHistory, history, "component://netscape/browser/global-history", &rv);
 | |
|         if (NS_FAILED(rv)) break;
 | |
| 
 | |
|         rv = history->SetPageTitle(nsCAutoString(mURL), aTitle);
 | |
|         if (NS_FAILED(rv)) break;
 | |
|       } while (0);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| //*****************************************************************************
 | |
| // nsWebShell::nsIDocShell
 | |
| //*****************************************************************************   
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::LoadURI(nsIURI* aUri, 
 | |
|    nsIPresContext* presContext)
 | |
| {
 | |
|    return nsDocShell::LoadURI(aUri, presContext);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::LoadURIVia(nsIURI* aUri, 
 | |
|    nsIPresContext* aPresContext, PRUint32 aAdapterBinding)
 | |
| {
 | |
|    return nsDocShell::LoadURIVia(aUri, aPresContext, aAdapterBinding);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetDocument(nsIDOMDocument** aDocument)
 | |
| {
 | |
|    return nsDocShell::GetDocument(aDocument);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetCurrentURI(nsIURI** aURI)
 | |
| {
 | |
|    return nsDocShell::GetCurrentURI(aURI);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetDocument(nsIDOMDocument *aDOMDoc, 
 | |
|    nsIDOMElement *aRootNode)
 | |
| {
 | |
|   // The tricky part is bypassing the normal load process and just putting a document into
 | |
|   // the webshell.  This is particularly nasty, since webshells don't normally even know
 | |
|   // about their documents
 | |
| 
 | |
|   // (1) Create a document viewer 
 | |
|   nsCOMPtr<nsIContentViewer> documentViewer;
 | |
|   nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
 | |
|   static NS_DEFINE_CID(kLayoutDocumentLoaderFactoryCID, NS_LAYOUT_DOCUMENT_LOADER_FACTORY_CID);
 | |
|   NS_ENSURE_SUCCESS(nsComponentManager::CreateInstance(kLayoutDocumentLoaderFactoryCID, nsnull, 
 | |
|                                                        NS_GET_IID(nsIDocumentLoaderFactory),
 | |
|                                                        (void**)getter_AddRefs(docFactory)),
 | |
|                     NS_ERROR_FAILURE);
 | |
| 
 | |
|   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDOMDoc);
 | |
|   if (!doc) { return NS_ERROR_NULL_POINTER; }
 | |
| 
 | |
|   NS_ENSURE_SUCCESS(docFactory->CreateInstanceForDocument(NS_STATIC_CAST(nsIContentViewerContainer*, (nsIWebShell*)this),
 | |
|                                                           doc,
 | |
|                                                           "view",
 | |
|                                                           getter_AddRefs(documentViewer)),
 | |
|                     NS_ERROR_FAILURE); 
 | |
| 
 | |
|   // (2) Feed the webshell to the content viewer
 | |
|   NS_ENSURE_SUCCESS(documentViewer->SetContainer((nsIWebShell*)this), NS_ERROR_FAILURE);
 | |
| 
 | |
|   // (3) Tell the content viewer container to embed the content viewer.
 | |
|   //     (This step causes everything to be set up for an initial flow.)
 | |
|   NS_ENSURE_SUCCESS(Embed(documentViewer, "view", nsnull), NS_ERROR_FAILURE);
 | |
| 
 | |
|   // XXX: It would be great to get rid of this dummy channel!
 | |
|   const nsAutoString uriString = "about:blank";
 | |
|   nsCOMPtr<nsIURI> uri;
 | |
|   NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(uri), uriString), NS_ERROR_FAILURE);
 | |
|   if (!uri) { return NS_ERROR_OUT_OF_MEMORY; }
 | |
| 
 | |
|   nsCOMPtr<nsIChannel> dummyChannel;
 | |
|   NS_ENSURE_SUCCESS(NS_OpenURI(getter_AddRefs(dummyChannel), uri, nsnull), NS_ERROR_FAILURE);
 | |
| 
 | |
|   // (4) fire start document load notification
 | |
|   nsCOMPtr<nsIStreamListener> outStreamListener;  // a valid pointer is required for the returned stream listener
 | |
|     // XXX: warning: magic cookie!  should get string "view delayedContentLoad"
 | |
|     //      from somewhere, maybe nsIHTMLDocument?
 | |
|   NS_ENSURE_SUCCESS(doc->StartDocumentLoad("view delayedContentLoad", dummyChannel, nsnull, NS_STATIC_CAST(nsIContentViewerContainer*, (nsIWebShell*)this),
 | |
|                                            getter_AddRefs(outStreamListener)), 
 | |
|                     NS_ERROR_FAILURE);
 | |
|   NS_ENSURE_SUCCESS(OnStartDocumentLoad(mDocLoader, uri, "load"), NS_ERROR_FAILURE);
 | |
| 
 | |
|   // (5) hook up the document and its content
 | |
|   nsCOMPtr<nsIContent> rootContent = do_QueryInterface(aRootNode);
 | |
|   if (!doc) { return NS_ERROR_OUT_OF_MEMORY; }
 | |
|   NS_ENSURE_SUCCESS(rootContent->SetDocument(doc, PR_FALSE), NS_ERROR_FAILURE);
 | |
|   doc->SetRootContent(rootContent);
 | |
|   rootContent->SetDocument(doc, PR_TRUE);
 | |
| 
 | |
|   // (6) reflow the document
 | |
|   SetScrolling(-1, PR_FALSE);
 | |
|   PRInt32 i;
 | |
|   PRInt32 ns = doc->GetNumberOfShells();
 | |
|   for (i = 0; i < ns; i++) 
 | |
|   {
 | |
|     nsCOMPtr<nsIPresShell> shell(dont_AddRef(doc->GetShellAt(i)));
 | |
|     if (shell) 
 | |
|     {
 | |
|       // Make shell an observer for next time
 | |
|       NS_ENSURE_SUCCESS(shell->BeginObservingDocument(), NS_ERROR_FAILURE);
 | |
| 
 | |
|       // Resize-reflow this time
 | |
|       nsCOMPtr<nsIDocumentViewer> docViewer = do_QueryInterface(documentViewer);
 | |
|       if (!docViewer) { return NS_ERROR_OUT_OF_MEMORY; }
 | |
|       nsCOMPtr<nsIPresContext> presContext;
 | |
|       NS_ENSURE_SUCCESS(docViewer->GetPresContext(*(getter_AddRefs(presContext))), NS_ERROR_FAILURE);
 | |
|       if (!presContext) { return NS_ERROR_OUT_OF_MEMORY; }
 | |
|       float p2t;
 | |
|       presContext->GetScaledPixelsToTwips(&p2t);
 | |
| 
 | |
|       nsRect r;
 | |
|       GetPositionAndSize(&r.x, &r.y, &r.width, &r.height);
 | |
|       NS_ENSURE_SUCCESS(shell->InitialReflow(NSToCoordRound(r.width * p2t), NSToCoordRound(r.height * p2t)), NS_ERROR_FAILURE);
 | |
| 
 | |
|       // Now trigger a refresh
 | |
|       nsCOMPtr<nsIViewManager> vm;
 | |
|       NS_ENSURE_SUCCESS(shell->GetViewManager(getter_AddRefs(vm)), NS_ERROR_FAILURE);
 | |
|       if (vm) 
 | |
|       {
 | |
|         PRBool enabled;
 | |
|         documentViewer->GetEnableRendering(&enabled);
 | |
|         if (enabled) {
 | |
|           vm->EnableRefresh();
 | |
|         }
 | |
|         NS_ENSURE_SUCCESS(vm->SetWindowDimensions(NSToCoordRound(r.width * p2t), 
 | |
|                                                   NSToCoordRound(r.height * p2t)), 
 | |
|                           NS_ERROR_FAILURE);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // (7) fire end document load notification
 | |
| 	mProcessedEndDocumentLoad = PR_FALSE;
 | |
|   nsresult rv = NS_OK;
 | |
|   NS_ENSURE_SUCCESS(OnEndDocumentLoad(mDocLoader, dummyChannel, rv), NS_ERROR_FAILURE);
 | |
|   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);  // test the resulting out-param separately
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetPresContext(nsIPresContext** aPresContext)
 | |
| {
 | |
|    return nsDocShell::GetPresContext(aPresContext);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetPresShell(nsIPresShell** aPresShell)
 | |
| {
 | |
|    return nsDocShell::GetPresShell(aPresShell);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetContentViewer(nsIContentViewer** aContentViewer)
 | |
| {
 | |
|    return nsDocShell::GetContentViewer(aContentViewer);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetChromeEventHandler(nsIChromeEventHandler** aChromeEventHandler)
 | |
| {
 | |
|    return nsDocShell::GetChromeEventHandler(aChromeEventHandler);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetChromeEventHandler(nsIChromeEventHandler* aChromeEventHandler)
 | |
| {
 | |
|    return nsDocShell::SetChromeEventHandler(aChromeEventHandler);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetParentURIContentListener(nsIURIContentListener**
 | |
|    aParent)
 | |
| {
 | |
|    return nsDocShell::GetParentURIContentListener(aParent);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetParentURIContentListener(nsIURIContentListener*
 | |
|    aParent)
 | |
| {
 | |
|    return nsDocShell::SetParentURIContentListener(aParent);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetPrefs(nsIPref** aPrefs)
 | |
| {
 | |
|    NS_ENSURE_ARG_POINTER(aPrefs);
 | |
| 
 | |
|   *aPrefs = mPrefs;
 | |
|   NS_IF_ADDREF(*aPrefs);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetPrefs(nsIPref* aPrefs)
 | |
| {
 | |
|   NS_IF_RELEASE(mPrefs);
 | |
|   mPrefs = aPrefs;
 | |
|   NS_IF_ADDREF(mPrefs);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::GetZoom(float* aZoom)
 | |
| {
 | |
|   *aZoom = mZoom;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsWebShell::SetZoom(float aZoom)
 | |
| {
 | |
|   mZoom = aZoom;
 | |
| 
 | |
|   if (mDeviceContext)
 | |
|     mDeviceContext->SetZoom(mZoom);
 | |
| 
 | |
|   if (mContentViewer) {
 | |
|     nsIDocumentViewer* docv = nsnull;
 | |
|     mContentViewer->QueryInterface(kIDocumentViewerIID, (void**) &docv);
 | |
|     if (nsnull != docv) {
 | |
|       nsIPresContext* cx = nsnull;
 | |
|       docv->GetPresContext(cx);
 | |
|       if (nsnull != cx) {
 | |
|         nsIPresShell  *shell = nsnull;
 | |
|         cx->GetShell(&shell);
 | |
|         if (nsnull != shell) {
 | |
|           nsIViewManager  *vm = nsnull;
 | |
|           shell->GetViewManager(&vm);
 | |
|           if (nsnull != vm) {
 | |
|             nsIView *rootview = nsnull;
 | |
|             nsIScrollableView *sv = nsnull;
 | |
|             vm->GetRootScrollableView(&sv);
 | |
|             if (nsnull != sv)
 | |
|               sv->ComputeScrollOffsets();
 | |
|             vm->GetRootView(rootview);
 | |
|             if (nsnull != rootview)
 | |
|               vm->UpdateView(rootview, 0);
 | |
|               NS_RELEASE(vm);
 | |
|           }
 | |
|           NS_RELEASE(shell);
 | |
|         }
 | |
|         NS_RELEASE(cx);
 | |
|       }
 | |
|       NS_RELEASE(docv);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP 
 | |
| nsWebShell::GetDocLoaderObserver(nsIDocumentLoaderObserver * *aDocLoaderObserver)
 | |
| {
 | |
|    return nsDocShell::GetDocLoaderObserver(aDocLoaderObserver);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP 
 | |
| nsWebShell::SetDocLoaderObserver(nsIDocumentLoaderObserver * aDocLoaderObserver)
 | |
| {
 | |
|    return nsDocShell::SetDocLoaderObserver(aDocLoaderObserver);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetMarginWidth(PRInt32* aWidth)
 | |
| {
 | |
|    return nsDocShell::GetMarginWidth(aWidth);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetMarginWidth(PRInt32 aWidth)
 | |
| {
 | |
|    return nsDocShell::SetMarginWidth(aWidth);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetMarginHeight(PRInt32* aHeight)
 | |
| {
 | |
|    return nsDocShell::GetMarginHeight(aHeight);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::SetMarginHeight(PRInt32 aHeight)
 | |
| {
 | |
|    return nsDocShell::SetMarginHeight(aHeight);
 | |
| }
 | |
| 
 | |
| //*****************************************************************************
 | |
| // nsWebShell::nsIScriptGlobalObjectOwner
 | |
| //*****************************************************************************   
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWebShell::GetScriptGlobalObject(nsIScriptGlobalObject** aGlobal)
 | |
| {
 | |
|   NS_PRECONDITION(nsnull != aGlobal, "null arg");
 | |
|   nsresult res = NS_OK;
 | |
| 
 | |
|   res = CreateScriptEnvironment();
 | |
| 
 | |
|   if (NS_SUCCEEDED(res)) {
 | |
|     *aGlobal = mScriptGlobal;
 | |
|     NS_IF_ADDREF(mScriptGlobal);
 | |
|   }
 | |
| 
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP 
 | |
| nsWebShell::ReportScriptError(const char* aErrorString,
 | |
|                               const char* aFileName,
 | |
|                               PRInt32     aLineNo,
 | |
|                               const char* aLineBuf)
 | |
| {
 | |
|    return nsDocShell::ReportScriptError(aErrorString, aFileName, aLineNo, 
 | |
|       aLineBuf);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| // Factory code for creating nsWebShell's
 | |
| 
 | |
| class nsWebShellFactory : public nsIFactory
 | |
| {
 | |
| public:
 | |
|   nsWebShellFactory();
 | |
|   virtual ~nsWebShellFactory();
 | |
| 
 | |
|   NS_DECL_ISUPPORTS
 | |
| 
 | |
|   // nsIFactory methods
 | |
|   NS_IMETHOD CreateInstance(nsISupports *aOuter,
 | |
|                             const nsIID &aIID,
 | |
|                             void **aResult);
 | |
| 
 | |
|   NS_IMETHOD LockFactory(PRBool aLock);
 | |
| };
 | |
| 
 | |
| nsWebShellFactory::nsWebShellFactory()
 | |
| {
 | |
|    NS_INIT_REFCNT();
 | |
| }
 | |
| 
 | |
| nsWebShellFactory::~nsWebShellFactory()
 | |
| {
 | |
| }
 | |
| 
 | |
| NS_IMPL_ADDREF(nsWebShellFactory);
 | |
| NS_IMPL_RELEASE(nsWebShellFactory);
 | |
| 
 | |
| NS_INTERFACE_MAP_BEGIN(nsWebShellFactory)
 | |
|    NS_INTERFACE_MAP_ENTRY(nsISupports)
 | |
|    NS_INTERFACE_MAP_ENTRY(nsIFactory)
 | |
| NS_INTERFACE_MAP_END
 | |
| 
 | |
| nsresult
 | |
| nsWebShellFactory::CreateInstance(nsISupports *aOuter,
 | |
|                                   const nsIID &aIID,
 | |
|                                   void **aResult)
 | |
| {
 | |
|   nsresult rv;
 | |
|   nsWebShell *inst;
 | |
| 
 | |
|   NS_ENSURE_ARG_POINTER(aResult);
 | |
|   NS_ENSURE_NO_AGGREGATION(aOuter);
 | |
|   *aResult = NULL;
 | |
| 
 | |
|   NS_NEWXPCOM(inst, nsWebShell);
 | |
|   NS_ENSURE_TRUE(inst, NS_ERROR_OUT_OF_MEMORY);
 | |
| 
 | |
|   NS_ADDREF(inst);
 | |
|   rv = inst->QueryInterface(aIID, aResult);
 | |
|   NS_RELEASE(inst);
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsWebShellFactory::LockFactory(PRBool aLock)
 | |
| {
 | |
|   // Not implemented in simplest case.
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| extern "C" NS_WEB nsresult
 | |
| NS_NewWebShellFactory(nsIFactory** aFactory)
 | |
| {
 | |
|   nsresult rv = NS_OK;
 | |
|   nsIFactory* inst = new nsWebShellFactory();
 | |
|   if (nsnull == inst) {
 | |
|     rv = NS_ERROR_OUT_OF_MEMORY;
 | |
|   }
 | |
|   else {
 | |
|     NS_ADDREF(inst);
 | |
|   }
 | |
|   *aFactory = inst;
 | |
|   return rv;
 | |
| }
 | 
