michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=4 sw=4 et tw=80: michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsDocShell_h__ michael@0: #define nsDocShell_h__ michael@0: michael@0: #include "nsITimer.h" michael@0: #include "nsIDocShell.h" michael@0: #include "nsIDocShellTreeItem.h" michael@0: #include "nsIBaseWindow.h" michael@0: #include "nsIScrollable.h" michael@0: #include "nsITextScroll.h" michael@0: #include "nsIContentViewerContainer.h" michael@0: #include "nsIDOMStorageManager.h" michael@0: #include "nsDocLoader.h" michael@0: #include "mozilla/WeakPtr.h" michael@0: michael@0: // Helper Classes michael@0: #include "nsCOMPtr.h" michael@0: #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences michael@0: #include "nsString.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsThreadUtils.h" michael@0: michael@0: // Threshold value in ms for META refresh based redirects michael@0: #define REFRESH_REDIRECT_TIMER 15000 michael@0: michael@0: // Interfaces Needed michael@0: #include "nsIDocCharset.h" michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIRefreshURI.h" michael@0: #include "nsIWebNavigation.h" michael@0: #include "nsIWebPageDescriptor.h" michael@0: #include "nsIWebProgressListener.h" michael@0: #include "nsIDocShellLoadInfo.h" michael@0: #include "nsIAuthPromptProvider.h" michael@0: #include "nsILoadContext.h" michael@0: #include "nsIWebShellServices.h" michael@0: #include "nsILinkHandler.h" michael@0: #include "nsIClipboardCommands.h" michael@0: #include "nsCRT.h" michael@0: #include "prtime.h" michael@0: #include "nsRect.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class EventTarget; michael@0: } michael@0: } michael@0: michael@0: class nsDocShell; michael@0: class nsDOMNavigationTiming; michael@0: class nsGlobalWindow; michael@0: class nsIController; michael@0: class nsIScrollableFrame; michael@0: class OnLinkClickEvent; michael@0: class nsDSURIContentListener; michael@0: class nsDocShellEditorData; michael@0: class nsIClipboardDragDropHookList; michael@0: class nsICommandManager; michael@0: class nsIContentViewer; michael@0: class nsIDocument; michael@0: class nsIDOMNode; michael@0: class nsIDocShellTreeOwner; michael@0: class nsIGlobalHistory2; michael@0: class nsIHttpChannel; michael@0: class nsIPrompt; michael@0: class nsISHistory; michael@0: class nsISecureBrowserUI; michael@0: class nsIStringBundle; michael@0: class nsISupportsArray; michael@0: class nsIURIFixup; michael@0: class nsIURILoader; michael@0: class nsIWebBrowserFind; michael@0: class nsIWidget; michael@0: michael@0: /* load commands were moved to nsIDocShell.h */ michael@0: /* load types were moved to nsDocShellLoadTypes.h */ michael@0: michael@0: /* internally used ViewMode types */ michael@0: enum ViewMode { michael@0: viewNormal = 0x0, michael@0: viewSource = 0x1 michael@0: }; michael@0: michael@0: //***************************************************************************** michael@0: //*** nsRefreshTimer michael@0: //***************************************************************************** michael@0: michael@0: class nsRefreshTimer : public nsITimerCallback michael@0: { michael@0: public: michael@0: nsRefreshTimer(); michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSITIMERCALLBACK michael@0: michael@0: int32_t GetDelay() { return mDelay ;} michael@0: michael@0: nsRefPtr mDocShell; michael@0: nsCOMPtr mURI; michael@0: int32_t mDelay; michael@0: bool mRepeat; michael@0: bool mMetaRefresh; michael@0: michael@0: protected: michael@0: virtual ~nsRefreshTimer(); michael@0: }; michael@0: michael@0: typedef enum { michael@0: eCharsetReloadInit, michael@0: eCharsetReloadRequested, michael@0: eCharsetReloadStopOrigional michael@0: } eCharsetReloadState; michael@0: michael@0: //***************************************************************************** michael@0: //*** nsDocShell michael@0: //***************************************************************************** michael@0: michael@0: class nsDocShell : public nsDocLoader, michael@0: public nsIDocShell, michael@0: public nsIWebNavigation, michael@0: public nsIBaseWindow, michael@0: public nsIScrollable, michael@0: public nsITextScroll, michael@0: public nsIDocCharset, michael@0: public nsIContentViewerContainer, michael@0: public nsIRefreshURI, michael@0: public nsIWebProgressListener, michael@0: public nsIWebPageDescriptor, michael@0: public nsIAuthPromptProvider, michael@0: public nsILoadContext, michael@0: public nsIWebShellServices, michael@0: public nsILinkHandler, michael@0: public nsIClipboardCommands, michael@0: public nsIDOMStorageManager, michael@0: public mozilla::SupportsWeakPtr michael@0: { michael@0: friend class nsDSURIContentListener; michael@0: michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_TYPENAME(nsDocShell) michael@0: // Object Management michael@0: nsDocShell(); michael@0: michael@0: NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW michael@0: michael@0: virtual nsresult Init(); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: NS_DECL_NSIDOCSHELL michael@0: NS_DECL_NSIDOCSHELLTREEITEM michael@0: NS_DECL_NSIWEBNAVIGATION michael@0: NS_DECL_NSIBASEWINDOW michael@0: NS_DECL_NSISCROLLABLE michael@0: NS_DECL_NSITEXTSCROLL michael@0: NS_DECL_NSIDOCCHARSET michael@0: NS_DECL_NSIINTERFACEREQUESTOR michael@0: NS_DECL_NSIWEBPROGRESSLISTENER michael@0: NS_DECL_NSIREFRESHURI michael@0: NS_DECL_NSICONTENTVIEWERCONTAINER michael@0: NS_DECL_NSIWEBPAGEDESCRIPTOR michael@0: NS_DECL_NSIAUTHPROMPTPROVIDER michael@0: NS_DECL_NSICLIPBOARDCOMMANDS michael@0: NS_DECL_NSIWEBSHELLSERVICES michael@0: NS_FORWARD_SAFE_NSIDOMSTORAGEMANAGER(TopSessionStorageManager()) michael@0: michael@0: NS_IMETHOD Stop() { michael@0: // Need this here because otherwise nsIWebNavigation::Stop michael@0: // overrides the docloader's Stop() michael@0: return nsDocLoader::Stop(); michael@0: } michael@0: michael@0: // Need to implement (and forward) nsISecurityEventSink, because michael@0: // nsIWebProgressListener has methods with identical names... michael@0: NS_FORWARD_NSISECURITYEVENTSINK(nsDocLoader::) michael@0: michael@0: // nsILinkHandler michael@0: NS_IMETHOD OnLinkClick(nsIContent* aContent, michael@0: nsIURI* aURI, michael@0: const char16_t* aTargetSpec, michael@0: const nsAString& aFileName, michael@0: nsIInputStream* aPostDataStream, michael@0: nsIInputStream* aHeadersDataStream, michael@0: bool aIsTrusted); michael@0: NS_IMETHOD OnLinkClickSync(nsIContent* aContent, michael@0: nsIURI* aURI, michael@0: const char16_t* aTargetSpec, michael@0: const nsAString& aFileName, michael@0: nsIInputStream* aPostDataStream = 0, michael@0: nsIInputStream* aHeadersDataStream = 0, michael@0: nsIDocShell** aDocShell = 0, michael@0: nsIRequest** aRequest = 0); michael@0: NS_IMETHOD OnOverLink(nsIContent* aContent, michael@0: nsIURI* aURI, michael@0: const char16_t* aTargetSpec); michael@0: NS_IMETHOD OnLeaveLink(); michael@0: michael@0: nsDocShellInfoLoadType ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType); michael@0: uint32_t ConvertDocShellLoadInfoToLoadType(nsDocShellInfoLoadType aDocShellLoadType); michael@0: michael@0: // Don't use NS_DECL_NSILOADCONTEXT because some of nsILoadContext's methods michael@0: // are shared with nsIDocShell (appID, etc.) and can't be declared twice. michael@0: NS_IMETHOD GetAssociatedWindow(nsIDOMWindow**); michael@0: NS_IMETHOD GetTopWindow(nsIDOMWindow**); michael@0: NS_IMETHOD GetTopFrameElement(nsIDOMElement**); michael@0: NS_IMETHOD IsAppOfType(uint32_t, bool*); michael@0: NS_IMETHOD GetIsContent(bool*); michael@0: NS_IMETHOD GetUsePrivateBrowsing(bool*); michael@0: NS_IMETHOD SetUsePrivateBrowsing(bool); michael@0: NS_IMETHOD SetPrivateBrowsing(bool); michael@0: NS_IMETHOD GetUseRemoteTabs(bool*); michael@0: NS_IMETHOD SetRemoteTabs(bool); michael@0: michael@0: // Restores a cached presentation from history (mLSHE). michael@0: // This method swaps out the content viewer and simulates loads for michael@0: // subframes. It then simulates the completion of the toplevel load. michael@0: nsresult RestoreFromHistory(); michael@0: michael@0: // Perform a URI load from a refresh timer. This is just like the michael@0: // ForceRefreshURI method on nsIRefreshURI, but makes sure to take michael@0: // the timer involved out of mRefreshURIList if it's there. michael@0: // aTimer must not be null. michael@0: nsresult ForceRefreshURIFromTimer(nsIURI * aURI, int32_t aDelay, michael@0: bool aMetaRefresh, nsITimer* aTimer); michael@0: michael@0: friend class OnLinkClickEvent; michael@0: michael@0: // We need dummy OnLocationChange in some cases to update the UI without michael@0: // updating security info. michael@0: void FireDummyOnLocationChange() michael@0: { michael@0: FireOnLocationChange(this, nullptr, mCurrentURI, michael@0: LOCATION_CHANGE_SAME_DOCUMENT); michael@0: } michael@0: michael@0: nsresult HistoryTransactionRemoved(int32_t aIndex); michael@0: protected: michael@0: // Object Management michael@0: virtual ~nsDocShell(); michael@0: virtual void DestroyChildren(); michael@0: michael@0: // Content Viewer Management michael@0: NS_IMETHOD EnsureContentViewer(); michael@0: // aPrincipal can be passed in if the caller wants. If null is michael@0: // passed in, the about:blank principal will end up being used. michael@0: nsresult CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal, michael@0: nsIURI* aBaseURI, michael@0: bool aTryToSaveOldPresentation = true); michael@0: NS_IMETHOD CreateContentViewer(const char * aContentType, michael@0: nsIRequest * request, nsIStreamListener ** aContentHandler); michael@0: NS_IMETHOD NewContentViewerObj(const char * aContentType, michael@0: nsIRequest * request, nsILoadGroup * aLoadGroup, michael@0: nsIStreamListener ** aContentHandler, nsIContentViewer ** aViewer); michael@0: NS_IMETHOD SetupNewViewer(nsIContentViewer * aNewViewer); michael@0: michael@0: void SetupReferrerFromChannel(nsIChannel * aChannel); michael@0: michael@0: NS_IMETHOD GetEldestPresContext(nsPresContext** aPresContext); michael@0: michael@0: // Get the principal that we'll set on the channel if we're inheriting. If michael@0: // aConsiderCurrentDocument is true, we try to use the current document if michael@0: // at all possible. If that fails, we fall back on the parent document. michael@0: // If that fails too, we force creation of a content viewer and use the michael@0: // resulting principal. If aConsiderCurrentDocument is false, we just look michael@0: // at the parent. michael@0: nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument); michael@0: michael@0: // Actually open a channel and perform a URI load. Note: whatever owner is michael@0: // passed to this function will be set on the channel. Callers who wish to michael@0: // not have an owner on the channel should just pass null. michael@0: // If aSrcdoc is not void, the load will be considered as a srcdoc load, michael@0: // and the contents of aSrcdoc will be loaded instead of aURI. michael@0: virtual nsresult DoURILoad(nsIURI * aURI, michael@0: nsIURI * aReferrer, michael@0: bool aSendReferrer, michael@0: nsISupports * aOwner, michael@0: const char * aTypeHint, michael@0: const nsAString & aFileName, michael@0: nsIInputStream * aPostData, michael@0: nsIInputStream * aHeadersData, michael@0: bool firstParty, michael@0: nsIDocShell ** aDocShell, michael@0: nsIRequest ** aRequest, michael@0: bool aIsNewWindowTarget, michael@0: bool aBypassClassifier, michael@0: bool aForceAllowCookies, michael@0: const nsAString &aSrcdoc, michael@0: nsIURI * baseURI); michael@0: NS_IMETHOD AddHeadersToChannel(nsIInputStream * aHeadersData, michael@0: nsIChannel * aChannel); michael@0: virtual nsresult DoChannelLoad(nsIChannel * aChannel, michael@0: nsIURILoader * aURILoader, michael@0: bool aBypassClassifier); michael@0: michael@0: nsresult ScrollToAnchor(nsACString & curHash, nsACString & newHash, michael@0: uint32_t aLoadType); michael@0: michael@0: // Tries to serialize a given variant using structured clone. This only michael@0: // works if the variant is backed by a JSVal. michael@0: nsresult SerializeJSValVariant(JSContext *aCx, nsIVariant *aData, michael@0: nsAString &aResult); michael@0: michael@0: // Returns true if would have called FireOnLocationChange, michael@0: // but did not because aFireOnLocationChange was false on entry. michael@0: // In this case it is the caller's responsibility to ensure michael@0: // FireOnLocationChange is called. michael@0: // In all other cases false is returned. michael@0: bool OnLoadingSite(nsIChannel * aChannel, michael@0: bool aFireOnLocationChange, michael@0: bool aAddToGlobalHistory = true); michael@0: michael@0: // Returns true if would have called FireOnLocationChange, michael@0: // but did not because aFireOnLocationChange was false on entry. michael@0: // In this case it is the caller's responsibility to ensure michael@0: // FireOnLocationChange is called. michael@0: // In all other cases false is returned. michael@0: // Either aChannel or aOwner must be null. If aChannel is michael@0: // present, the owner should be gotten from it. michael@0: // If OnNewURI calls AddToSessionHistory, it will pass its michael@0: // aCloneSHChildren argument as aCloneChildren. michael@0: bool OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner, michael@0: uint32_t aLoadType, michael@0: bool aFireOnLocationChange, michael@0: bool aAddToGlobalHistory, michael@0: bool aCloneSHChildren); michael@0: michael@0: virtual void SetReferrerURI(nsIURI * aURI); michael@0: michael@0: // Session History michael@0: virtual bool ShouldAddToSessionHistory(nsIURI * aURI); michael@0: // Either aChannel or aOwner must be null. If aChannel is michael@0: // present, the owner should be gotten from it. michael@0: // If aCloneChildren is true, then our current session history's michael@0: // children will be cloned onto the new entry. This should be michael@0: // used when we aren't actually changing the document while adding michael@0: // the new session history entry. michael@0: virtual nsresult AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel, michael@0: nsISupports* aOwner, michael@0: bool aCloneChildren, michael@0: nsISHEntry ** aNewEntry); michael@0: nsresult DoAddChildSHEntry(nsISHEntry* aNewEntry, int32_t aChildOffset, michael@0: bool aCloneChildren); michael@0: michael@0: NS_IMETHOD LoadHistoryEntry(nsISHEntry * aEntry, uint32_t aLoadType); michael@0: NS_IMETHOD PersistLayoutHistoryState(); michael@0: michael@0: // Clone a session history tree for subframe navigation. michael@0: // The tree rooted at |aSrcEntry| will be cloned into |aDestEntry|, except michael@0: // for the entry with id |aCloneID|, which will be replaced with michael@0: // |aReplaceEntry|. |aSrcShell| is a (possibly null) docshell which michael@0: // corresponds to |aSrcEntry| via its mLSHE or mOHE pointers, and will michael@0: // have that pointer updated to point to the cloned history entry. michael@0: // If aCloneChildren is true then the children of the entry with id michael@0: // |aCloneID| will be cloned into |aReplaceEntry|. michael@0: static nsresult CloneAndReplace(nsISHEntry *aSrcEntry, michael@0: nsDocShell *aSrcShell, michael@0: uint32_t aCloneID, michael@0: nsISHEntry *aReplaceEntry, michael@0: bool aCloneChildren, michael@0: nsISHEntry **aDestEntry); michael@0: michael@0: // Child-walking callback for CloneAndReplace michael@0: static nsresult CloneAndReplaceChild(nsISHEntry *aEntry, michael@0: nsDocShell *aShell, michael@0: int32_t aChildIndex, void *aData); michael@0: michael@0: nsresult GetRootSessionHistory(nsISHistory ** aReturn); michael@0: nsresult GetHttpChannel(nsIChannel * aChannel, nsIHttpChannel ** aReturn); michael@0: bool ShouldDiscardLayoutState(nsIHttpChannel * aChannel); michael@0: michael@0: // Determine whether this docshell corresponds to the given history entry, michael@0: // via having a pointer to it in mOSHE or mLSHE. michael@0: bool HasHistoryEntry(nsISHEntry *aEntry) const michael@0: { michael@0: return aEntry && (aEntry == mOSHE || aEntry == mLSHE); michael@0: } michael@0: michael@0: // Update any pointers (mOSHE or mLSHE) to aOldEntry to point to aNewEntry michael@0: void SwapHistoryEntries(nsISHEntry *aOldEntry, nsISHEntry *aNewEntry); michael@0: michael@0: // Call this method to swap in a new history entry to m[OL]SHE, rather than michael@0: // setting it directly. This completes the navigation in all docshells michael@0: // in the case of a subframe navigation. michael@0: void SetHistoryEntry(nsCOMPtr *aPtr, nsISHEntry *aEntry); michael@0: michael@0: // Child-walking callback for SetHistoryEntry michael@0: static nsresult SetChildHistoryEntry(nsISHEntry *aEntry, michael@0: nsDocShell *aShell, michael@0: int32_t aEntryIndex, void *aData); michael@0: michael@0: // Callback prototype for WalkHistoryEntries. michael@0: // aEntry is the child history entry, aShell is its corresponding docshell, michael@0: // aChildIndex is the child's index in its parent entry, and aData is michael@0: // the opaque pointer passed to WalkHistoryEntries. michael@0: typedef nsresult (*WalkHistoryEntriesFunc)(nsISHEntry *aEntry, michael@0: nsDocShell *aShell, michael@0: int32_t aChildIndex, michael@0: void *aData); michael@0: michael@0: // For each child of aRootEntry, find the corresponding docshell which is michael@0: // a child of aRootShell, and call aCallback. The opaque pointer aData michael@0: // is passed to the callback. michael@0: static nsresult WalkHistoryEntries(nsISHEntry *aRootEntry, michael@0: nsDocShell *aRootShell, michael@0: WalkHistoryEntriesFunc aCallback, michael@0: void *aData); michael@0: michael@0: // overridden from nsDocLoader, this provides more information than the michael@0: // normal OnStateChange with flags STATE_REDIRECTING michael@0: virtual void OnRedirectStateChange(nsIChannel* aOldChannel, michael@0: nsIChannel* aNewChannel, michael@0: uint32_t aRedirectFlags, michael@0: uint32_t aStateFlags); michael@0: michael@0: /** michael@0: * Helper function that determines if channel is an HTTP POST. michael@0: * michael@0: * @param aChannel michael@0: * The channel to test michael@0: * michael@0: * @return True iff channel is an HTTP post. michael@0: */ michael@0: bool ChannelIsPost(nsIChannel* aChannel); michael@0: michael@0: /** michael@0: * Helper function that finds the last URI and its transition flags for a michael@0: * channel. michael@0: * michael@0: * This method first checks the channel's property bag to see if previous michael@0: * info has been saved. If not, it gives back the referrer of the channel. michael@0: * michael@0: * @param aChannel michael@0: * The channel we are transitioning to michael@0: * @param aURI michael@0: * Output parameter with the previous URI, not addref'd michael@0: * @param aChannelRedirectFlags michael@0: * If a redirect, output parameter with the previous redirect flags michael@0: * from nsIChannelEventSink michael@0: */ michael@0: void ExtractLastVisit(nsIChannel* aChannel, michael@0: nsIURI** aURI, michael@0: uint32_t* aChannelRedirectFlags); michael@0: michael@0: /** michael@0: * Helper function that caches a URI and a transition for saving later. michael@0: * michael@0: * @param aChannel michael@0: * Channel that will have these properties saved michael@0: * @param aURI michael@0: * The URI to save for later michael@0: * @param aChannelRedirectFlags michael@0: * The nsIChannelEventSink redirect flags to save for later michael@0: */ michael@0: void SaveLastVisit(nsIChannel* aChannel, michael@0: nsIURI* aURI, michael@0: uint32_t aChannelRedirectFlags); michael@0: michael@0: /** michael@0: * Helper function for adding a URI visit using IHistory. If IHistory is michael@0: * not available, the method tries nsIGlobalHistory2. michael@0: * michael@0: * The IHistory API maintains chains of visits, tracking both HTTP referrers michael@0: * and redirects for a user session. VisitURI requires the current URI and michael@0: * the previous URI in the chain. michael@0: * michael@0: * Visits can be saved either during a redirect or when the request has michael@0: * reached its final destination. The previous URI in the visit may be michael@0: * from another redirect or it may be the referrer. michael@0: * michael@0: * @pre aURI is not null. michael@0: * michael@0: * @param aURI michael@0: * The URI that was just visited michael@0: * @param aReferrerURI michael@0: * The referrer URI of this request michael@0: * @param aPreviousURI michael@0: * The previous URI of this visit (may be the same as aReferrerURI) michael@0: * @param aChannelRedirectFlags michael@0: * For redirects, the redirect flags from nsIChannelEventSink michael@0: * (0 otherwise) michael@0: * @param aResponseStatus michael@0: * For HTTP channels, the response code (0 otherwise). michael@0: */ michael@0: void AddURIVisit(nsIURI* aURI, michael@0: nsIURI* aReferrerURI, michael@0: nsIURI* aPreviousURI, michael@0: uint32_t aChannelRedirectFlags, michael@0: uint32_t aResponseStatus=0); michael@0: michael@0: // Helper Routines michael@0: nsresult ConfirmRepost(bool * aRepost); michael@0: NS_IMETHOD GetPromptAndStringBundle(nsIPrompt ** aPrompt, michael@0: nsIStringBundle ** aStringBundle); michael@0: NS_IMETHOD GetChildOffset(nsIDOMNode * aChild, nsIDOMNode * aParent, michael@0: int32_t * aOffset); michael@0: nsIScrollableFrame* GetRootScrollFrame(); michael@0: NS_IMETHOD EnsureScriptEnvironment(); michael@0: NS_IMETHOD EnsureEditorData(); michael@0: nsresult EnsureTransferableHookData(); michael@0: NS_IMETHOD EnsureFind(); michael@0: nsresult RefreshURIFromQueue(); michael@0: NS_IMETHOD LoadErrorPage(nsIURI *aURI, const char16_t *aURL, michael@0: const char *aErrorPage, michael@0: const char16_t *aErrorType, michael@0: const char16_t *aDescription, michael@0: const char *aCSSClass, michael@0: nsIChannel* aFailedChannel); michael@0: bool IsNavigationAllowed(bool aDisplayPrintErrorDialog = true); michael@0: bool IsPrintingOrPP(bool aDisplayErrorDialog = true); michael@0: michael@0: nsresult SetBaseUrlForWyciwyg(nsIContentViewer * aContentViewer); michael@0: michael@0: static inline uint32_t michael@0: PRTimeToSeconds(PRTime t_usec) michael@0: { michael@0: PRTime usec_per_sec = PR_USEC_PER_SEC; michael@0: return uint32_t(t_usec /= usec_per_sec); michael@0: } michael@0: michael@0: inline bool UseErrorPages() michael@0: { michael@0: return (mObserveErrorPages ? sUseErrorPages : mUseErrorPages); michael@0: } michael@0: michael@0: bool IsFrame(); michael@0: michael@0: // michael@0: // Helper method that is called when a new document (including any michael@0: // sub-documents - ie. frames) has been completely loaded. michael@0: // michael@0: virtual nsresult EndPageLoad(nsIWebProgress * aProgress, michael@0: nsIChannel * aChannel, michael@0: nsresult aResult); michael@0: michael@0: // Sets the current document's current state object to the given SHEntry's michael@0: // state object. The current state object is eventually given to the page michael@0: // in the PopState event. michael@0: nsresult SetDocCurrentStateObj(nsISHEntry *shEntry); michael@0: michael@0: nsresult CheckLoadingPermissions(); michael@0: michael@0: // Security checks to prevent frameset spoofing. See comments at michael@0: // implementation sites. michael@0: static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem, michael@0: nsIDocShellTreeItem* aAccessingItem, michael@0: bool aConsiderOpener = true); michael@0: static bool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem, michael@0: nsIDocShellTreeItem* aTargetTreeItem); michael@0: michael@0: // Returns true if would have called FireOnLocationChange, michael@0: // but did not because aFireOnLocationChange was false on entry. michael@0: // In this case it is the caller's responsibility to ensure michael@0: // FireOnLocationChange is called. michael@0: // In all other cases false is returned. michael@0: bool SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest, michael@0: bool aFireOnLocationChange, michael@0: uint32_t aLocationFlags); michael@0: michael@0: // The following methods deal with saving and restoring content viewers michael@0: // in session history. michael@0: michael@0: // mContentViewer points to the current content viewer associated with michael@0: // this docshell. When loading a new document, the content viewer is michael@0: // either destroyed or stored into a session history entry. To make sure michael@0: // that destruction happens in a controlled fashion, a given content viewer michael@0: // is always owned in exactly one of these ways: michael@0: // 1) The content viewer is active and owned by a docshell's michael@0: // mContentViewer. michael@0: // 2) The content viewer is still being displayed while we begin loading michael@0: // a new document. The content viewer is owned by the _new_ michael@0: // content viewer's mPreviousViewer, and has a pointer to the michael@0: // nsISHEntry where it will eventually be stored. The content viewer michael@0: // has been close()d by the docshell, which detaches the document from michael@0: // the window object. michael@0: // 3) The content viewer is cached in session history. The nsISHEntry michael@0: // has the only owning reference to the content viewer. The viewer michael@0: // has released its nsISHEntry pointer to prevent circular ownership. michael@0: // michael@0: // When restoring a content viewer from session history, open() is called michael@0: // to reattach the document to the window object. The content viewer is michael@0: // then placed into mContentViewer and removed from the history entry. michael@0: // (mContentViewer is put into session history as described above, if michael@0: // applicable). michael@0: michael@0: // Determines whether we can safely cache the current mContentViewer in michael@0: // session history. This checks a number of factors such as cache policy, michael@0: // pending requests, and unload handlers. michael@0: // |aLoadType| should be the load type that will replace the current michael@0: // presentation. |aNewRequest| should be the request for the document to michael@0: // be loaded in place of the current document, or null if such a request michael@0: // has not been created yet. |aNewDocument| should be the document that will michael@0: // replace the current document. michael@0: bool CanSavePresentation(uint32_t aLoadType, michael@0: nsIRequest *aNewRequest, michael@0: nsIDocument *aNewDocument); michael@0: michael@0: // Captures the state of the supporting elements of the presentation michael@0: // (the "window" object, docshell tree, meta-refresh loads, and security michael@0: // state) and stores them on |mOSHE|. michael@0: nsresult CaptureState(); michael@0: michael@0: // Begin the toplevel restore process for |aSHEntry|. michael@0: // This simulates a channel open, and defers the real work until michael@0: // RestoreFromHistory is called from a PLEvent. michael@0: nsresult RestorePresentation(nsISHEntry *aSHEntry, bool *aRestoring); michael@0: michael@0: // Call BeginRestore(nullptr, false) for each child of this shell. michael@0: nsresult BeginRestoreChildren(); michael@0: michael@0: // Method to get our current position and size without flushing michael@0: void DoGetPositionAndSize(int32_t * x, int32_t * y, int32_t * cx, michael@0: int32_t * cy); michael@0: michael@0: // Call this when a URI load is handed to us (via OnLinkClick or michael@0: // InternalLoad). This makes sure that we're not inside unload, or that if michael@0: // we are it's still OK to load this URI. michael@0: bool IsOKToLoadURI(nsIURI* aURI); michael@0: michael@0: void ReattachEditorToWindow(nsISHEntry *aSHEntry); michael@0: michael@0: nsCOMPtr mSessionStorageManager; michael@0: nsIDOMStorageManager* TopSessionStorageManager(); michael@0: michael@0: // helpers for executing commands michael@0: nsresult GetControllerForCommand(const char *inCommand, michael@0: nsIController** outController); michael@0: nsresult EnsureCommandHandler(); michael@0: michael@0: nsIChannel* GetCurrentDocChannel(); michael@0: michael@0: bool ShouldBlockLoadingForBackButton(); michael@0: michael@0: // Convenience method for getting our parent docshell. Can return null michael@0: already_AddRefed GetParentDocshell(); michael@0: protected: michael@0: nsresult GetCurScrollPos(int32_t scrollOrientation, int32_t * curPos); michael@0: nsresult SetCurScrollPosEx(int32_t curHorizontalPos, int32_t curVerticalPos); michael@0: michael@0: // Override the parent setter from nsDocLoader michael@0: virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader); michael@0: michael@0: void ClearFrameHistory(nsISHEntry* aEntry); michael@0: michael@0: /** michael@0: * Initializes mTiming if it isn't yet. michael@0: * After calling this, mTiming is non-null. michael@0: */ michael@0: void MaybeInitTiming(); michael@0: michael@0: // Event type dispatched by RestorePresentation michael@0: class RestorePresentationEvent : public nsRunnable { michael@0: public: michael@0: NS_DECL_NSIRUNNABLE michael@0: RestorePresentationEvent(nsDocShell *ds) : mDocShell(ds) {} michael@0: void Revoke() { mDocShell = nullptr; } michael@0: private: michael@0: nsRefPtr mDocShell; michael@0: }; michael@0: michael@0: bool JustStartedNetworkLoad(); michael@0: michael@0: enum FrameType { michael@0: eFrameTypeRegular, michael@0: eFrameTypeBrowser, michael@0: eFrameTypeApp michael@0: }; michael@0: michael@0: static const nsCString FrameTypeToString(FrameType aFrameType) michael@0: { michael@0: switch (aFrameType) { michael@0: case FrameType::eFrameTypeApp: michael@0: return NS_LITERAL_CSTRING("app"); michael@0: case FrameType::eFrameTypeBrowser: michael@0: return NS_LITERAL_CSTRING("browser"); michael@0: case FrameType::eFrameTypeRegular: michael@0: return NS_LITERAL_CSTRING("regular"); michael@0: default: michael@0: NS_ERROR("Unknown frame type"); michael@0: return EmptyCString(); michael@0: } michael@0: } michael@0: michael@0: FrameType GetInheritedFrameType(); michael@0: michael@0: bool HasUnloadedParent(); michael@0: michael@0: // Dimensions of the docshell michael@0: nsIntRect mBounds; michael@0: nsString mName; michael@0: nsString mTitle; michael@0: michael@0: /** michael@0: * Content-Type Hint of the most-recently initiated load. Used for michael@0: * session history entries. michael@0: */ michael@0: nsCString mContentTypeHint; michael@0: nsIntPoint mDefaultScrollbarPref; // persistent across doc loads michael@0: michael@0: nsCOMPtr mRefreshURIList; michael@0: nsCOMPtr mSavedRefreshURIList; michael@0: nsRefPtr mContentListener; michael@0: nsCOMPtr mContentViewer; michael@0: nsCOMPtr mParentWidget; michael@0: michael@0: // mCurrentURI should be marked immutable on set if possible. michael@0: nsCOMPtr mCurrentURI; michael@0: nsCOMPtr mReferrerURI; michael@0: nsRefPtr mScriptGlobal; michael@0: nsCOMPtr mSessionHistory; michael@0: nsCOMPtr mGlobalHistory; michael@0: nsCOMPtr mFind; michael@0: nsCOMPtr mCommandManager; michael@0: // Reference to the SHEntry for this docshell until the page is destroyed. michael@0: // Somebody give me better name michael@0: nsCOMPtr mOSHE; michael@0: // Reference to the SHEntry for this docshell until the page is loaded michael@0: // Somebody give me better name. michael@0: // If mLSHE is non-null, non-pushState subframe loads don't create separate michael@0: // root history entries. That is, frames loaded during the parent page michael@0: // load don't generate history entries the way frame navigation after the michael@0: // parent has loaded does. (This isn't the only purpose of mLSHE.) michael@0: nsCOMPtr mLSHE; michael@0: michael@0: // Holds a weak pointer to a RestorePresentationEvent object if any that michael@0: // holds a weak pointer back to us. We use this pointer to possibly revoke michael@0: // the event whenever necessary. michael@0: nsRevocableEventPtr mRestorePresentationEvent; michael@0: michael@0: // Editor data, if this document is designMode or contentEditable. michael@0: nsAutoPtr mEditorData; michael@0: michael@0: // Transferable hooks/callbacks michael@0: nsCOMPtr mTransferableHookData; michael@0: michael@0: // Secure browser UI object michael@0: nsCOMPtr mSecurityUI; michael@0: michael@0: // The URI we're currently loading. This is only relevant during the michael@0: // firing of a pagehide/unload. The caller of FirePageHideNotification() michael@0: // is responsible for setting it and unsetting it. It may be null if the michael@0: // pagehide/unload is happening for some reason other than just loading a michael@0: // new URI. michael@0: nsCOMPtr mLoadingURI; michael@0: michael@0: // Set in LoadErrorPage from the method argument and used later michael@0: // in CreateContentViewer. We have to delay an shistory entry creation michael@0: // for which these objects are needed. michael@0: nsCOMPtr mFailedURI; michael@0: nsCOMPtr mFailedChannel; michael@0: uint32_t mFailedLoadType; michael@0: michael@0: // Set in DoURILoad when either the LOAD_RELOAD_ALLOW_MIXED_CONTENT flag or michael@0: // the LOAD_NORMAL_ALLOW_MIXED_CONTENT flag is set. michael@0: // Checked in nsMixedContentBlocker, to see if the channels match. michael@0: nsCOMPtr mMixedContentChannel; michael@0: michael@0: // WEAK REFERENCES BELOW HERE. michael@0: // Note these are intentionally not addrefd. Doing so will create a cycle. michael@0: // For that reasons don't use nsCOMPtr. michael@0: michael@0: nsIDocShellTreeOwner * mTreeOwner; // Weak Reference michael@0: mozilla::dom::EventTarget* mChromeEventHandler; //Weak Reference michael@0: michael@0: eCharsetReloadState mCharsetReloadState; michael@0: michael@0: // Offset in the parent's child list. michael@0: // -1 if the docshell is added dynamically to the parent shell. michael@0: uint32_t mChildOffset; michael@0: uint32_t mBusyFlags; michael@0: uint32_t mAppType; michael@0: uint32_t mLoadType; michael@0: michael@0: int32_t mMarginWidth; michael@0: int32_t mMarginHeight; michael@0: michael@0: // This can either be a content docshell or a chrome docshell. After michael@0: // Create() is called, the type is not expected to change. michael@0: int32_t mItemType; michael@0: michael@0: // Index into the SHTransaction list, indicating the previous and current michael@0: // transaction at the time that this DocShell begins to load michael@0: int32_t mPreviousTransIndex; michael@0: int32_t mLoadedTransIndex; michael@0: michael@0: uint32_t mSandboxFlags; michael@0: nsWeakPtr mOnePermittedSandboxedNavigator; michael@0: michael@0: // mFullscreenAllowed stores how we determine whether fullscreen is allowed michael@0: // when GetFullscreenAllowed() is called. Fullscreen is allowed in a michael@0: // docshell when all containing iframes have the allowfullscreen michael@0: // attribute set to true. When mFullscreenAllowed is CHECK_ATTRIBUTES michael@0: // we check this docshell's containing frame for the allowfullscreen michael@0: // attribute, and recurse onto the parent docshell to ensure all containing michael@0: // frames also have the allowfullscreen attribute. If we find an ancestor michael@0: // docshell with mFullscreenAllowed not equal to CHECK_ATTRIBUTES, we've michael@0: // reached a content boundary, and mFullscreenAllowed denotes whether the michael@0: // parent across the content boundary has allowfullscreen=true in all its michael@0: // containing iframes. mFullscreenAllowed defaults to CHECK_ATTRIBUTES and michael@0: // is set otherwise when docshells which are content boundaries are created. michael@0: enum FullscreenAllowedState { michael@0: CHECK_ATTRIBUTES, michael@0: PARENT_ALLOWS, michael@0: PARENT_PROHIBITS michael@0: }; michael@0: FullscreenAllowedState mFullscreenAllowed; michael@0: michael@0: // Cached value of the "browser.xul.error_pages.enabled" preference. michael@0: static bool sUseErrorPages; michael@0: michael@0: bool mCreated; michael@0: bool mAllowSubframes; michael@0: bool mAllowPlugins; michael@0: bool mAllowJavascript; michael@0: bool mAllowMetaRedirects; michael@0: bool mAllowImages; michael@0: bool mAllowMedia; michael@0: bool mAllowDNSPrefetch; michael@0: bool mAllowWindowControl; michael@0: bool mAllowContentRetargeting; michael@0: bool mCreatingDocument; // (should be) debugging only michael@0: bool mUseErrorPages; michael@0: bool mObserveErrorPages; michael@0: bool mAllowAuth; michael@0: bool mAllowKeywordFixup; michael@0: bool mIsOffScreenBrowser; michael@0: bool mIsActive; michael@0: bool mIsAppTab; michael@0: bool mUseGlobalHistory; michael@0: bool mInPrivateBrowsing; michael@0: bool mUseRemoteTabs; michael@0: bool mDeviceSizeIsPageSize; michael@0: michael@0: // Because scriptability depends on the mAllowJavascript values of our michael@0: // ancestors, we cache the effective scriptability and recompute it when michael@0: // it might have changed; michael@0: bool mCanExecuteScripts; michael@0: void RecomputeCanExecuteScripts(); michael@0: michael@0: // This boolean is set to true right before we fire pagehide and generally michael@0: // unset when we embed a new content viewer. While it's true no navigation michael@0: // is allowed in this docshell. michael@0: bool mFiredUnloadEvent; michael@0: michael@0: // this flag is for bug #21358. a docshell may load many urls michael@0: // which don't result in new documents being created (i.e. a new michael@0: // content viewer) we want to make sure we don't call a on load michael@0: // event more than once for a given content viewer. michael@0: bool mEODForCurrentDocument; michael@0: bool mURIResultedInDocument; michael@0: michael@0: bool mIsBeingDestroyed; michael@0: michael@0: bool mIsExecutingOnLoadHandler; michael@0: michael@0: // Indicates that a DocShell in this "docshell tree" is printing michael@0: bool mIsPrintingOrPP; michael@0: michael@0: // Indicates to CreateContentViewer() that it is safe to cache the old michael@0: // presentation of the page, and to SetupNewViewer() that the old viewer michael@0: // should be passed a SHEntry to save itself into. michael@0: bool mSavingOldViewer; michael@0: michael@0: // @see nsIDocShellHistory::createdDynamically michael@0: bool mDynamicallyCreated; michael@0: #ifdef DEBUG michael@0: bool mInEnsureScriptEnv; michael@0: #endif michael@0: bool mAffectPrivateSessionLifetime; michael@0: bool mInvisible; michael@0: uint64_t mHistoryID; michael@0: uint32_t mDefaultLoadFlags; michael@0: michael@0: static nsIURIFixup *sURIFixup; michael@0: michael@0: nsRefPtr mTiming; michael@0: michael@0: // Are we a regular frame, a browser frame, or an app frame? michael@0: FrameType mFrameType; michael@0: michael@0: // We only expect mOwnOrContainingAppId to be something other than michael@0: // UNKNOWN_APP_ID if mFrameType != eFrameTypeRegular. For vanilla iframes michael@0: // inside an app, we'll retrieve the containing app-id by walking up the michael@0: // docshell hierarchy. michael@0: // michael@0: // (This needs to be the docshell's own /or containing/ app id because the michael@0: // containing app frame might be in another process, in which case we won't michael@0: // find it by walking up the docshell hierarchy.) michael@0: uint32_t mOwnOrContainingAppId; michael@0: michael@0: private: michael@0: nsCString mForcedCharset; michael@0: nsCString mParentCharset; michael@0: int32_t mParentCharsetSource; michael@0: nsCOMPtr mParentCharsetPrincipal; michael@0: nsTObserverArray mPrivacyObservers; michael@0: nsTObserverArray mReflowObservers; michael@0: nsTObserverArray mScrollObservers; michael@0: nsCString mOriginalUriString; michael@0: michael@0: // Separate function to do the actual name (i.e. not _top, _self etc.) michael@0: // searching for FindItemWithName. michael@0: nsresult DoFindItemWithName(const char16_t* aName, michael@0: nsISupports* aRequestor, michael@0: nsIDocShellTreeItem* aOriginalRequestor, michael@0: nsIDocShellTreeItem** _retval); michael@0: michael@0: #ifdef DEBUG michael@0: // We're counting the number of |nsDocShells| to help find leaks michael@0: static unsigned long gNumberOfDocShells; michael@0: #endif /* DEBUG */ michael@0: michael@0: public: michael@0: class InterfaceRequestorProxy : public nsIInterfaceRequestor { michael@0: public: michael@0: InterfaceRequestorProxy(nsIInterfaceRequestor* p); michael@0: virtual ~InterfaceRequestorProxy(); michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIINTERFACEREQUESTOR michael@0: michael@0: protected: michael@0: InterfaceRequestorProxy() {} michael@0: nsWeakPtr mWeakPtr; michael@0: }; michael@0: }; michael@0: michael@0: #endif /* nsDocShell_h__ */