mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
2fc75424f3
we are going to need it. r=bienvenu,travis a=chofmann
4451 lines
130 KiB
C++
4451 lines
130 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 CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent,
|
|
PRInt32 aXPos, PRInt32 aYPos,
|
|
const nsString& aPopupType, const nsString& anAnchorAlignment,
|
|
const nsString& aPopupAlignment,
|
|
nsIDOMWindow* aWindow, nsIDOMWindow** outPopup);
|
|
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;
|
|
|
|
#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
|
|
|
|
/* 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)
|
|
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(messageStr);
|
|
dnsMsg.Insert(' ', 0);
|
|
dnsMsg.Insert(scheme, 0);
|
|
|
|
(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::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent,
|
|
PRInt32 aXPos, PRInt32 aYPos,
|
|
const nsString& aPopupType, const nsString& anAnchorAlignment,
|
|
const nsString& aPopupAlignment,
|
|
nsIDOMWindow* aWindow, nsIDOMWindow** outPopup)
|
|
{
|
|
if (nsnull != mContainer) {
|
|
return mContainer->CreatePopup(aElement, aPopupContent, aXPos, aYPos, aPopupType,
|
|
anAnchorAlignment, aPopupAlignment,
|
|
aWindow, outPopup);
|
|
}
|
|
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) && (aStatus == NS_ERROR_UNKNOWN_HOST) ) {
|
|
nsXPIDLCString host;
|
|
rv = aURL->GetHost(getter_Copies(host));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
CBufDescriptor buf((const char *)host, PR_TRUE, PL_strlen(host) + 1);
|
|
nsCAutoString hostStr(buf);
|
|
PRInt32 dotLoc = hostStr.FindChar('.');
|
|
|
|
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
|
|
|
|
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;
|
|
|
|
nsAutoString dnsMsg(messageStr);
|
|
dnsMsg.Insert(' ', 0);
|
|
dnsMsg.Insert(host, 0);
|
|
|
|
(void)mPrompter->Alert(dnsMsg.GetUnicode());
|
|
} // unknown host
|
|
} //!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
|
|
virtual 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);
|
|
|
|
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;
|
|
}
|