/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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 "nsAutoPtr.h" #include "nsFrameMessageManager.h" #include "mozilla/dom/Element.h" #include "mozilla/Attributes.h" #include "FrameMetrics.h" #include "nsStubMutationObserver.h" class nsIURI; class nsSubDocumentFrame; class nsView; class nsIInProcessContentFrameMessageManager; class AutoResetInShow; class nsITabParent; class nsIDocShellTreeItem; class nsIDocShellTreeOwner; class nsIDocShellTreeNode; class mozIApplication; namespace mozilla { namespace dom { class PBrowserParent; class TabParent; struct StructuredCloneData; } namespace layout { class RenderFrameParent; } } #ifdef MOZ_WIDGET_GTK2 typedef struct _GtkWidget GtkWidget; #endif #ifdef MOZ_WIDGET_QT class QX11EmbedContainer; #endif /** * Defines a target configuration for this 's content * document's view. If the content document's actual view * doesn't match this nsIContentView, then on paints its pixels * are transformed to compensate for the difference. * * Used to support asynchronous re-paints of content pixels; see * nsIContentView. */ class nsContentView MOZ_FINAL : public nsIContentView { public: typedef mozilla::layers::FrameMetrics::ViewID ViewID; NS_DECL_ISUPPORTS NS_DECL_NSICONTENTVIEW struct ViewConfig { ViewConfig() : mScrollOffset(0, 0) , mXScale(1.0) , mYScale(1.0) {} // Default copy ctor and operator= are fine bool operator==(const ViewConfig& aOther) const { return (mScrollOffset == aOther.mScrollOffset && mXScale == aOther.mXScale && mYScale == aOther.mYScale); } // This is the scroll offset the user wishes or expects // its enclosed content document to have. "Scroll offset" here // means the document pixel at pixel (0,0) within the CSS // viewport. If the content document's actual scroll offset // doesn't match |mScrollOffset|, the difference is used to define // a translation transform when painting the content document. nsPoint mScrollOffset; // The scale at which the user wishes to paint its // enclosed content document. If content-document layers have a // lower or higher resolution than the desired scale, then the // ratio is used to define a scale transform when painting the // content document. float mXScale; float mYScale; }; nsContentView(nsFrameLoader* aFrameLoader, ViewID aScrollId, ViewConfig aConfig = ViewConfig()) : mViewportSize(0, 0) , mContentSize(0, 0) , mParentScaleX(1.0) , mParentScaleY(1.0) , mFrameLoader(aFrameLoader) , mScrollId(aScrollId) , mConfig(aConfig) {} bool IsRoot() const; ViewID GetId() const { return mScrollId; } ViewConfig GetViewConfig() const { return mConfig; } nsSize mViewportSize; nsSize mContentSize; float mParentScaleX; float mParentScaleY; nsFrameLoader* mFrameLoader; // WEAK private: nsresult Update(const ViewConfig& aConfig); ViewID mScrollId; ViewConfig mConfig; }; class nsFrameLoader MOZ_FINAL : public nsIFrameLoader, public nsIContentViewManager, public nsStubMutationObserver, public mozilla::dom::ipc::MessageManagerCallback { friend class AutoResetInShow; typedef mozilla::dom::PBrowserParent PBrowserParent; typedef mozilla::dom::TabParent TabParent; typedef mozilla::layout::RenderFrameParent RenderFrameParent; protected: nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated); public: ~nsFrameLoader() { mNeedsAsyncDestroy = true; if (mMessageManager) { mMessageManager->Disconnect(); } nsFrameLoader::Destroy(); } bool AsyncScrollEnabled() const { return !!(mRenderMode & RENDER_MODE_ASYNC_SCROLL); } static nsFrameLoader* Create(mozilla::dom::Element* aOwner, bool aNetworkCreated); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader) NS_DECL_NSIFRAMELOADER NS_DECL_NSICONTENTVIEWMANAGER NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); nsresult ReallyStartLoading(); void Finalize(); nsIDocShell* GetExistingDocShell() { return mDocShell; } mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget(); nsresult CreateStaticClone(nsIFrameLoader* aDest); /** * MessageManagerCallback methods that we override. */ virtual bool DoLoadFrameScript(const nsAString& aURL); virtual bool DoSendAsyncMessage(const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData); virtual bool CheckPermission(const nsAString& aPermission); virtual bool CheckManifestURL(const nsAString& aManifestURL); virtual bool CheckAppHasPermission(const nsAString& aPermission); /** * 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, nsRefPtr& aFirstToSwap, nsRefPtr& aSecondToSwap); // When IPC is enabled, destroy any associated child process. void DestroyChild(); /** * 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(); /** * 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 * 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 behaves similarly, and this * behavior seems desirable.) */ RenderFrameParent* GetCurrentRemoteFrame() const { return mCurrentRemoteFrame; } /** * |aFrame| can be null. If non-null, it must be the remote frame * on which the most recent layer transaction completed for this's * . */ void SetCurrentRemoteFrame(RenderFrameParent* aFrame) { mCurrentRemoteFrame = aFrame; } 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 or mCurrentRemoteFrame 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 view on the frame loader. We do this when we're * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is * being reframed we'll restore the detached view when it's recreated, * otherwise we'll discard the old presentation and set the detached * subdoc view 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 SetDetachedSubdocView(nsView* aDetachedView, nsIDocument* aContainerDoc); /** * Retrieves the detached view and the document containing the view, * as set by SetDetachedSubdocView(). */ nsView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const; private: void SetOwnerContent(mozilla::dom::Element* aContent); bool ShouldUseRemoteProcess(); /** * Is this a frameloader for a bona fide