michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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: /* michael@0: * Class for managing loading of a subframe (creation of the docshell, michael@0: * handling of loads in it, recursion-checking). michael@0: */ michael@0: michael@0: #ifndef nsFrameLoader_h_ michael@0: #define nsFrameLoader_h_ michael@0: michael@0: #include "nsIDocShell.h" michael@0: #include "nsStringFwd.h" michael@0: #include "nsIFrameLoader.h" michael@0: #include "nsPoint.h" michael@0: #include "nsSize.h" michael@0: #include "nsIURI.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsFrameMessageManager.h" michael@0: #include "mozilla/dom/Element.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "FrameMetrics.h" michael@0: #include "nsStubMutationObserver.h" michael@0: michael@0: class nsIURI; michael@0: class nsSubDocumentFrame; michael@0: class nsView; michael@0: class nsIInProcessContentFrameMessageManager; michael@0: class AutoResetInShow; michael@0: class nsITabParent; michael@0: class nsIDocShellTreeItem; michael@0: class nsIDocShellTreeOwner; michael@0: class mozIApplication; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class ContentParent; michael@0: class PBrowserParent; michael@0: class TabParent; michael@0: struct StructuredCloneData; michael@0: } michael@0: michael@0: namespace layout { michael@0: class RenderFrameParent; michael@0: } michael@0: } michael@0: michael@0: #if defined(MOZ_WIDGET_GTK) michael@0: typedef struct _GtkWidget GtkWidget; michael@0: #endif michael@0: #ifdef MOZ_WIDGET_QT michael@0: class QX11EmbedContainer; michael@0: #endif michael@0: michael@0: /** michael@0: * Defines a target configuration for this 's content michael@0: * document's view. If the content document's actual view michael@0: * doesn't match this nsIContentView, then on paints its pixels michael@0: * are transformed to compensate for the difference. michael@0: * michael@0: * Used to support asynchronous re-paints of content pixels; see michael@0: * nsIContentView. michael@0: */ michael@0: class nsContentView MOZ_FINAL : public nsIContentView michael@0: { michael@0: public: michael@0: typedef mozilla::layers::FrameMetrics::ViewID ViewID; michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSICONTENTVIEW michael@0: michael@0: struct ViewConfig { michael@0: ViewConfig() michael@0: : mScrollOffset(0, 0) michael@0: , mXScale(1.0) michael@0: , mYScale(1.0) michael@0: {} michael@0: michael@0: // Default copy ctor and operator= are fine michael@0: michael@0: bool operator==(const ViewConfig& aOther) const michael@0: { michael@0: return (mScrollOffset == aOther.mScrollOffset && michael@0: mXScale == aOther.mXScale && michael@0: mYScale == aOther.mYScale); michael@0: } michael@0: michael@0: // This is the scroll offset the user wishes or expects michael@0: // its enclosed content document to have. "Scroll offset" here michael@0: // means the document pixel at pixel (0,0) within the CSS michael@0: // viewport. If the content document's actual scroll offset michael@0: // doesn't match |mScrollOffset|, the difference is used to define michael@0: // a translation transform when painting the content document. michael@0: nsPoint mScrollOffset; michael@0: // The scale at which the user wishes to paint its michael@0: // enclosed content document. If content-document layers have a michael@0: // lower or higher resolution than the desired scale, then the michael@0: // ratio is used to define a scale transform when painting the michael@0: // content document. michael@0: float mXScale; michael@0: float mYScale; michael@0: }; michael@0: michael@0: nsContentView(nsFrameLoader* aFrameLoader, ViewID aScrollId, bool aIsRoot, michael@0: ViewConfig aConfig = ViewConfig()) michael@0: : mViewportSize(0, 0) michael@0: , mContentSize(0, 0) michael@0: , mParentScaleX(1.0) michael@0: , mParentScaleY(1.0) michael@0: , mFrameLoader(aFrameLoader) michael@0: , mScrollId(aScrollId) michael@0: , mIsRoot(aIsRoot) michael@0: , mConfig(aConfig) michael@0: {} michael@0: michael@0: bool IsRoot() const michael@0: { michael@0: return mIsRoot; michael@0: } michael@0: michael@0: ViewID GetId() const michael@0: { michael@0: return mScrollId; michael@0: } michael@0: michael@0: ViewConfig GetViewConfig() const michael@0: { michael@0: return mConfig; michael@0: } michael@0: michael@0: nsSize mViewportSize; michael@0: nsSize mContentSize; michael@0: float mParentScaleX; michael@0: float mParentScaleY; michael@0: michael@0: nsFrameLoader* mFrameLoader; // WEAK michael@0: michael@0: private: michael@0: nsresult Update(const ViewConfig& aConfig); michael@0: michael@0: ViewID mScrollId; michael@0: bool mIsRoot; michael@0: ViewConfig mConfig; michael@0: }; michael@0: michael@0: michael@0: class nsFrameLoader MOZ_FINAL : public nsIFrameLoader, michael@0: public nsIContentViewManager, michael@0: public nsStubMutationObserver, michael@0: public mozilla::dom::ipc::MessageManagerCallback michael@0: { michael@0: friend class AutoResetInShow; michael@0: typedef mozilla::dom::PBrowserParent PBrowserParent; michael@0: typedef mozilla::dom::TabParent TabParent; michael@0: typedef mozilla::layout::RenderFrameParent RenderFrameParent; michael@0: michael@0: protected: michael@0: nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated); michael@0: michael@0: public: michael@0: ~nsFrameLoader(); michael@0: michael@0: bool AsyncScrollEnabled() const michael@0: { michael@0: return !!(mRenderMode & RENDER_MODE_ASYNC_SCROLL); michael@0: } michael@0: michael@0: static nsFrameLoader* Create(mozilla::dom::Element* aOwner, michael@0: bool aNetworkCreated); michael@0: michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader) michael@0: NS_DECL_NSIFRAMELOADER michael@0: NS_DECL_NSICONTENTVIEWMANAGER michael@0: NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED michael@0: NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); michael@0: nsresult ReallyStartLoading(); michael@0: void Finalize(); michael@0: nsIDocShell* GetExistingDocShell() { return mDocShell; } michael@0: mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget(); michael@0: nsresult CreateStaticClone(nsIFrameLoader* aDest); michael@0: michael@0: /** michael@0: * MessageManagerCallback methods that we override. michael@0: */ michael@0: virtual bool DoLoadFrameScript(const nsAString& aURL, michael@0: bool aRunInGlobalScope) MOZ_OVERRIDE; michael@0: virtual bool DoSendAsyncMessage(JSContext* aCx, michael@0: const nsAString& aMessage, michael@0: const mozilla::dom::StructuredCloneData& aData, michael@0: JS::Handle aCpows, michael@0: nsIPrincipal* aPrincipal) MOZ_OVERRIDE; michael@0: virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE; michael@0: virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE; michael@0: virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Called from the layout frame associated with this frame loader; michael@0: * this notifies us to hook up with the widget and view. michael@0: */ michael@0: bool Show(int32_t marginWidth, int32_t marginHeight, michael@0: int32_t scrollbarPrefX, int32_t scrollbarPrefY, michael@0: nsSubDocumentFrame* frame); michael@0: michael@0: /** michael@0: * Called when the margin properties of the containing frame are changed. michael@0: */ michael@0: void MarginsChanged(uint32_t aMarginWidth, uint32_t aMarginHeight); michael@0: michael@0: /** michael@0: * Called from the layout frame associated with this frame loader, when michael@0: * the frame is being torn down; this notifies us that out widget and view michael@0: * are going away and we should unhook from them. michael@0: */ michael@0: void Hide(); michael@0: michael@0: nsresult CloneForStatic(nsIFrameLoader* aOriginal); michael@0: michael@0: // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A michael@0: // frame loader owner needs to call this, and pass in the two references to michael@0: // nsRefPtrs for frame loaders that need to be swapped. michael@0: nsresult SwapWithOtherLoader(nsFrameLoader* aOther, michael@0: nsRefPtr& aFirstToSwap, michael@0: nsRefPtr& aSecondToSwap); michael@0: michael@0: // When IPC is enabled, destroy any associated child process. michael@0: void DestroyChild(); michael@0: michael@0: /** michael@0: * Return the primary frame for our owning content, or null if it michael@0: * can't be found. michael@0: */ michael@0: nsIFrame* GetPrimaryFrameOfOwningContent() const michael@0: { michael@0: return mOwnerContent ? mOwnerContent->GetPrimaryFrame() : nullptr; michael@0: } michael@0: michael@0: /** michael@0: * Return the document that owns this, or null if we don't have michael@0: * an owner. michael@0: */ michael@0: nsIDocument* GetOwnerDoc() const michael@0: { return mOwnerContent ? mOwnerContent->OwnerDoc() : nullptr; } michael@0: michael@0: PBrowserParent* GetRemoteBrowser(); michael@0: michael@0: /** michael@0: * The "current" render frame is the one on which the most recent michael@0: * remote layer-tree transaction was executed. If no content has michael@0: * been drawn yet, or the remote browser doesn't have any drawn michael@0: * content for whatever reason, return nullptr. The returned render michael@0: * frame has an associated shadow layer tree. michael@0: * michael@0: * Note that the returned render frame might not be a frame michael@0: * constructed for this->GetURL(). This can happen, e.g., if the michael@0: * was just navigated to a new URL, but hasn't painted the michael@0: * new page yet. A render frame for the previous page may be michael@0: * returned. (In-process behaves similarly, and this michael@0: * behavior seems desirable.) michael@0: */ michael@0: RenderFrameParent* GetCurrentRemoteFrame() const michael@0: { michael@0: return mCurrentRemoteFrame; michael@0: } michael@0: michael@0: /** michael@0: * |aFrame| can be null. If non-null, it must be the remote frame michael@0: * on which the most recent layer transaction completed for this's michael@0: * . michael@0: */ michael@0: void SetCurrentRemoteFrame(RenderFrameParent* aFrame) michael@0: { michael@0: mCurrentRemoteFrame = aFrame; michael@0: } michael@0: nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; } michael@0: michael@0: mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; } michael@0: bool ShouldClipSubdocument() { return mClipSubdocument; } michael@0: michael@0: bool ShouldClampScrollPosition() { return mClampScrollPosition; } michael@0: michael@0: /** michael@0: * Tell this FrameLoader to use a particular remote browser. michael@0: * michael@0: * This will assert if mRemoteBrowser or mCurrentRemoteFrame is non-null. In michael@0: * practice, this means you can't have successfully run TryRemoteBrowser() on michael@0: * this object, which means you can't have called ShowRemoteFrame() or michael@0: * ReallyStartLoading(). michael@0: */ michael@0: void SetRemoteBrowser(nsITabParent* aTabParent); michael@0: michael@0: /** michael@0: * Stashes a detached view on the frame loader. We do this when we're michael@0: * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is michael@0: * being reframed we'll restore the detached view when it's recreated, michael@0: * otherwise we'll discard the old presentation and set the detached michael@0: * subdoc view to null. aContainerDoc is the document containing the michael@0: * the subdoc frame. This enables us to detect when the containing michael@0: * document has changed during reframe, so we can discard the presentation michael@0: * in that case. michael@0: */ michael@0: void SetDetachedSubdocView(nsView* aDetachedView, michael@0: nsIDocument* aContainerDoc); michael@0: michael@0: /** michael@0: * Retrieves the detached view and the document containing the view, michael@0: * as set by SetDetachedSubdocView(). michael@0: */ michael@0: nsView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const; michael@0: michael@0: /** michael@0: * Applies a new set of sandbox flags. These are merged with the sandbox michael@0: * flags from our owning content's owning document with a logical OR, this michael@0: * ensures that we can only add restrictions and never remove them. michael@0: */ michael@0: void ApplySandboxFlags(uint32_t sandboxFlags); michael@0: michael@0: void GetURL(nsString& aURL); michael@0: michael@0: private: michael@0: michael@0: void SetOwnerContent(mozilla::dom::Element* aContent); michael@0: michael@0: bool ShouldUseRemoteProcess(); michael@0: michael@0: /** michael@0: * Is this a frameloader for a bona fide