diff options
Diffstat (limited to 'dom/base/nsFrameLoader.h')
-rw-r--r-- | dom/base/nsFrameLoader.h | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h new file mode 100644 index 000000000..bbbd52f58 --- /dev/null +++ b/dom/base/nsFrameLoader.h @@ -0,0 +1,400 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Class for managing loading of a subframe (creation of the docshell, + * handling of loads in it, recursion-checking). + */ + +#ifndef nsFrameLoader_h_ +#define nsFrameLoader_h_ + +#include "nsIDocShell.h" +#include "nsStringFwd.h" +#include "nsIFrameLoader.h" +#include "nsPoint.h" +#include "nsSize.h" +#include "nsIURI.h" +#include "nsFrameMessageManager.h" +#include "mozilla/dom/Element.h" +#include "mozilla/Attributes.h" +#include "nsStubMutationObserver.h" +#include "Units.h" +#include "nsIWebBrowserPersistable.h" +#include "nsIFrame.h" +#include "nsIGroupedSHistory.h" + +class nsIURI; +class nsSubDocumentFrame; +class nsView; +class nsIInProcessContentFrameMessageManager; +class AutoResetInShow; +class AutoResetInFrameSwap; +class nsITabParent; +class nsIDocShellTreeItem; +class nsIDocShellTreeOwner; +class mozIApplication; + +namespace mozilla { + +class DocShellOriginAttributes; + +namespace dom { +class ContentParent; +class PBrowserParent; +class TabParent; +class MutableTabContext; +} // namespace dom + +namespace ipc { +class StructuredCloneData; +} // namespace ipc + +namespace layout { +class RenderFrameParent; +} // namespace layout +} // namespace mozilla + +#if defined(MOZ_WIDGET_GTK) +typedef struct _GtkWidget GtkWidget; +#endif + +class nsFrameLoader final : public nsIFrameLoader, + public nsIWebBrowserPersistable, + public nsStubMutationObserver, + public mozilla::dom::ipc::MessageManagerCallback +{ + friend class AutoResetInShow; + friend class AutoResetInFrameSwap; + typedef mozilla::dom::PBrowserParent PBrowserParent; + typedef mozilla::dom::TabParent TabParent; + typedef mozilla::layout::RenderFrameParent RenderFrameParent; + +public: + static nsFrameLoader* Create(mozilla::dom::Element* aOwner, + nsPIDOMWindowOuter* aOpener, + bool aNetworkCreated); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader) + NS_DECL_NSIFRAMELOADER + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIWEBBROWSERPERSISTABLE + nsresult CheckForRecursiveLoad(nsIURI* aURI); + nsresult ReallyStartLoading(); + void StartDestroy(); + void DestroyDocShell(); + void DestroyComplete(); + nsIDocShell* GetExistingDocShell() { return mDocShell; } + mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget(); + nsresult CreateStaticClone(nsIFrameLoader* aDest); + + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoLoadMessageManagerScript(const nsAString& aURL, + bool aRunInGlobalScope) override; + virtual nsresult DoSendAsyncMessage(JSContext* aCx, + const nsAString& aMessage, + mozilla::dom::ipc::StructuredCloneData& aData, + JS::Handle<JSObject *> aCpows, + nsIPrincipal* aPrincipal) override; + virtual bool CheckPermission(const nsAString& aPermission) override; + virtual bool CheckManifestURL(const nsAString& aManifestURL) override; + virtual bool CheckAppHasPermission(const nsAString& aPermission) override; + + /** + * Called from the layout frame associated with this frame loader; + * this notifies us to hook up with the widget and view. + */ + bool Show(int32_t marginWidth, int32_t marginHeight, + int32_t scrollbarPrefX, int32_t scrollbarPrefY, + nsSubDocumentFrame* frame); + + /** + * Called when the margin properties of the containing frame are changed. + */ + void MarginsChanged(uint32_t aMarginWidth, uint32_t aMarginHeight); + + /** + * Called from the layout frame associated with this frame loader, when + * the frame is being torn down; this notifies us that out widget and view + * are going away and we should unhook from them. + */ + void Hide(); + + nsresult CloneForStatic(nsIFrameLoader* aOriginal); + + // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A + // frame loader owner needs to call this, and pass in the two references to + // nsRefPtrs for frame loaders that need to be swapped. + nsresult SwapWithOtherLoader(nsFrameLoader* aOther, + nsIFrameLoaderOwner* aThisOwner, + nsIFrameLoaderOwner* aOtherOwner); + + nsresult SwapWithOtherRemoteLoader(nsFrameLoader* aOther, + nsIFrameLoaderOwner* aThisOwner, + nsIFrameLoaderOwner* aOtherOwner); + + /** + * Return the primary frame for our owning content, or null if it + * can't be found. + */ + nsIFrame* GetPrimaryFrameOfOwningContent() const + { + return mOwnerContent ? mOwnerContent->GetPrimaryFrame() : nullptr; + } + + /** + * Return the document that owns this, or null if we don't have + * an owner. + */ + nsIDocument* GetOwnerDoc() const + { return mOwnerContent ? mOwnerContent->OwnerDoc() : nullptr; } + + PBrowserParent* GetRemoteBrowser() const; + + /** + * The "current" render frame is the one on which the most recent + * remote layer-tree transaction was executed. If no content has + * been drawn yet, or the remote browser doesn't have any drawn + * content for whatever reason, return nullptr. The returned render + * frame has an associated shadow layer tree. + * + * Note that the returned render frame might not be a frame + * constructed for this->GetURL(). This can happen, e.g., if the + * <browser> was just navigated to a new URL, but hasn't painted the + * new page yet. A render frame for the previous page may be + * returned. (In-process <browser> behaves similarly, and this + * behavior seems desirable.) + */ + RenderFrameParent* GetCurrentRenderFrame() const; + + nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; } + + mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; } + bool ShouldClipSubdocument() { return mClipSubdocument; } + + bool ShouldClampScrollPosition() { return mClampScrollPosition; } + + /** + * Tell this FrameLoader to use a particular remote browser. + * + * This will assert if mRemoteBrowser is non-null. In practice, + * this means you can't have successfully run TryRemoteBrowser() on + * this object, which means you can't have called ShowRemoteFrame() + * or ReallyStartLoading(). + */ + void SetRemoteBrowser(nsITabParent* aTabParent); + + /** + * Stashes a detached nsIFrame on the frame loader. We do this when we're + * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is + * being reframed we'll restore the detached nsIFrame when it's recreated, + * otherwise we'll discard the old presentation and set the detached + * subdoc nsIFrame to null. aContainerDoc is the document containing the + * the subdoc frame. This enables us to detect when the containing + * document has changed during reframe, so we can discard the presentation + * in that case. + */ + void SetDetachedSubdocFrame(nsIFrame* aDetachedFrame, + nsIDocument* aContainerDoc); + + /** + * Retrieves the detached nsIFrame and the document containing the nsIFrame, + * as set by SetDetachedSubdocFrame(). + */ + nsIFrame* GetDetachedSubdocFrame(nsIDocument** aContainerDoc) const; + + /** + * Applies a new set of sandbox flags. These are merged with the sandbox + * flags from our owning content's owning document with a logical OR, this + * ensures that we can only add restrictions and never remove them. + */ + void ApplySandboxFlags(uint32_t sandboxFlags); + + void GetURL(nsString& aURL); + + // Properly retrieves documentSize of any subdocument type. + nsresult GetWindowDimensions(nsIntRect& aRect); + + virtual nsIMessageSender* GetProcessMessageManager() const override; + + // public because a callback needs these. + RefPtr<nsFrameMessageManager> mMessageManager; + nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager; + +private: + nsFrameLoader(mozilla::dom::Element* aOwner, + nsPIDOMWindowOuter* aOpener, + bool aNetworkCreated); + ~nsFrameLoader(); + + void SetOwnerContent(mozilla::dom::Element* aContent); + + bool ShouldUseRemoteProcess(); + + /** + * Return true if the frame is a remote frame. Return false otherwise + */ + bool IsRemoteFrame(); + + /** + * Is this a frameloader for a bona fide <iframe mozbrowser> or + * <iframe mozapp>? (I.e., does the frame return true for + * nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?) + * <xul:browser> is not a mozbrowser or app, so this is false for that case. + */ + bool OwnerIsMozBrowserOrAppFrame(); + + /** + * Is this a frameloader for a bona fide <iframe mozapp>? (I.e., does the + * frame return true for nsIMozBrowserFrame::GetReallyIsApp()?) + */ + bool OwnerIsAppFrame(); + + /** + * Is this a frame loader for a bona fide <iframe mozbrowser>? + * <xul:browser> is not a mozbrowser, so this is false for that case. + */ + bool OwnerIsMozBrowserFrame(); + + /** + * Is this a frame loader for an isolated <iframe mozbrowser>? + * + * By default, mozbrowser frames are isolated. Isolation can be disabled by + * setting the frame's noisolation attribute. Disabling isolation is + * only allowed if the containing document is chrome. + */ + bool OwnerIsIsolatedMozBrowserFrame(); + + /** + * Get our owning element's app manifest URL, or return the empty string if + * our owning element doesn't have an app manifest URL. + */ + void GetOwnerAppManifestURL(nsAString& aOut); + + /** + * Get the app for our frame. This is the app whose manifest is returned by + * GetOwnerAppManifestURL. + */ + already_AddRefed<mozIApplication> GetOwnApp(); + + /** + * Get the app which contains this frame. This is the app associated with + * the frame element's principal. + */ + already_AddRefed<mozIApplication> GetContainingApp(); + + /** + * If we are an IPC frame, set mRemoteFrame. Otherwise, create and + * initialize mDocShell. + */ + nsresult MaybeCreateDocShell(); + nsresult EnsureMessageManager(); + nsresult ReallyLoadFrameScripts(); + + // Updates the subdocument position and size. This gets called only + // when we have our own in-process DocShell. + void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame); + nsresult CheckURILoad(nsIURI* aURI); + void FireErrorEvent(); + nsresult ReallyStartLoadingInternal(); + + // Return true if remote browser created; nothing else to do + bool TryRemoteBrowser(); + + // Tell the remote browser that it's now "virtually visible" + bool ShowRemoteFrame(const mozilla::ScreenIntSize& size, + nsSubDocumentFrame *aFrame = nullptr); + + bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, + nsIDocShellTreeOwner* aOwner, + int32_t aParentType, + nsIDocShell* aParentNode); + + nsIAtom* TypeAttrName() const { + return mOwnerContent->IsXULElement() + ? nsGkAtoms::type : nsGkAtoms::mozframetype; + } + + void InitializeBrowserAPI(); + void DestroyBrowserFrameScripts(); + + nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext, + nsIURI* aURI = nullptr); + + enum TabParentChange { + eTabParentRemoved, + eTabParentChanged + }; + void MaybeUpdatePrimaryTabParent(TabParentChange aChange); + + nsresult + PopulateUserContextIdFromAttribute(mozilla::DocShellOriginAttributes& aAttr); + + nsCOMPtr<nsIDocShell> mDocShell; + nsCOMPtr<nsIURI> mURIToLoad; + mozilla::dom::Element* mOwnerContent; // WEAK + + // After the frameloader has been removed from the DOM but before all of the + // messages from the frame have been received, we keep a strong reference to + // our <browser> element. + RefPtr<mozilla::dom::Element> mOwnerContentStrong; + + // Stores the root frame of the subdocument while the subdocument is being + // reframed. Used to restore the presentation after reframing. + nsWeakFrame mDetachedSubdocFrame; + // Stores the containing document of the frame corresponding to this + // frame loader. This is reference is kept valid while the subframe's + // presentation is detached and stored in mDetachedSubdocFrame. This + // enables us to detect whether the frame has moved documents during + // a reframe, so that we know not to restore the presentation. + nsCOMPtr<nsIDocument> mContainerDocWhileDetached; + + // An opener window which should be used when the docshell is created. + nsCOMPtr<nsPIDOMWindowOuter> mOpener; + + TabParent* mRemoteBrowser; + uint64_t mChildID; + + // See nsIFrameLoader.idl. EVENT_MODE_NORMAL_DISPATCH automatically + // forwards some input events to out-of-process content. + uint32_t mEventMode; + + // Holds the last known size of the frame. + mozilla::ScreenIntSize mLazySize; + + nsCOMPtr<nsIPartialSHistory> mPartialSessionHistory; + nsCOMPtr<nsIGroupedSHistory> mGroupedSessionHistory; + + bool mIsPrerendered : 1; + bool mDepthTooGreat : 1; + bool mIsTopLevelContent : 1; + bool mDestroyCalled : 1; + bool mNeedsAsyncDestroy : 1; + bool mInSwap : 1; + bool mInShow : 1; + bool mHideCalled : 1; + // True when the object is created for an element which the parser has + // created using NS_FROM_PARSER_NETWORK flag. If the element is modified, + // it may lose the flag. + bool mNetworkCreated : 1; + + bool mRemoteBrowserShown : 1; + bool mRemoteFrame : 1; + bool mClipSubdocument : 1; + bool mClampScrollPosition : 1; + bool mObservingOwnerContent : 1; + + // Backs nsIFrameLoader::{Get,Set}Visible. Visibility state here relates to + // whether this frameloader's <iframe mozbrowser> is setVisible(true)'ed, and + // doesn't necessarily correlate with docshell/document visibility. + bool mVisible : 1; + bool mFreshProcess : 1; +}; + +#endif |