1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsFrameLoader.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,466 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * Class for managing loading of a subframe (creation of the docshell, 1.11 + * handling of loads in it, recursion-checking). 1.12 + */ 1.13 + 1.14 +#ifndef nsFrameLoader_h_ 1.15 +#define nsFrameLoader_h_ 1.16 + 1.17 +#include "nsIDocShell.h" 1.18 +#include "nsStringFwd.h" 1.19 +#include "nsIFrameLoader.h" 1.20 +#include "nsPoint.h" 1.21 +#include "nsSize.h" 1.22 +#include "nsIURI.h" 1.23 +#include "nsAutoPtr.h" 1.24 +#include "nsFrameMessageManager.h" 1.25 +#include "mozilla/dom/Element.h" 1.26 +#include "mozilla/Attributes.h" 1.27 +#include "FrameMetrics.h" 1.28 +#include "nsStubMutationObserver.h" 1.29 + 1.30 +class nsIURI; 1.31 +class nsSubDocumentFrame; 1.32 +class nsView; 1.33 +class nsIInProcessContentFrameMessageManager; 1.34 +class AutoResetInShow; 1.35 +class nsITabParent; 1.36 +class nsIDocShellTreeItem; 1.37 +class nsIDocShellTreeOwner; 1.38 +class mozIApplication; 1.39 + 1.40 +namespace mozilla { 1.41 +namespace dom { 1.42 +class ContentParent; 1.43 +class PBrowserParent; 1.44 +class TabParent; 1.45 +struct StructuredCloneData; 1.46 +} 1.47 + 1.48 +namespace layout { 1.49 +class RenderFrameParent; 1.50 +} 1.51 +} 1.52 + 1.53 +#if defined(MOZ_WIDGET_GTK) 1.54 +typedef struct _GtkWidget GtkWidget; 1.55 +#endif 1.56 +#ifdef MOZ_WIDGET_QT 1.57 +class QX11EmbedContainer; 1.58 +#endif 1.59 + 1.60 +/** 1.61 + * Defines a target configuration for this <browser>'s content 1.62 + * document's view. If the content document's actual view 1.63 + * doesn't match this nsIContentView, then on paints its pixels 1.64 + * are transformed to compensate for the difference. 1.65 + * 1.66 + * Used to support asynchronous re-paints of content pixels; see 1.67 + * nsIContentView. 1.68 + */ 1.69 +class nsContentView MOZ_FINAL : public nsIContentView 1.70 +{ 1.71 +public: 1.72 + typedef mozilla::layers::FrameMetrics::ViewID ViewID; 1.73 + NS_DECL_ISUPPORTS 1.74 + NS_DECL_NSICONTENTVIEW 1.75 + 1.76 + struct ViewConfig { 1.77 + ViewConfig() 1.78 + : mScrollOffset(0, 0) 1.79 + , mXScale(1.0) 1.80 + , mYScale(1.0) 1.81 + {} 1.82 + 1.83 + // Default copy ctor and operator= are fine 1.84 + 1.85 + bool operator==(const ViewConfig& aOther) const 1.86 + { 1.87 + return (mScrollOffset == aOther.mScrollOffset && 1.88 + mXScale == aOther.mXScale && 1.89 + mYScale == aOther.mYScale); 1.90 + } 1.91 + 1.92 + // This is the scroll offset the <browser> user wishes or expects 1.93 + // its enclosed content document to have. "Scroll offset" here 1.94 + // means the document pixel at pixel (0,0) within the CSS 1.95 + // viewport. If the content document's actual scroll offset 1.96 + // doesn't match |mScrollOffset|, the difference is used to define 1.97 + // a translation transform when painting the content document. 1.98 + nsPoint mScrollOffset; 1.99 + // The scale at which the <browser> user wishes to paint its 1.100 + // enclosed content document. If content-document layers have a 1.101 + // lower or higher resolution than the desired scale, then the 1.102 + // ratio is used to define a scale transform when painting the 1.103 + // content document. 1.104 + float mXScale; 1.105 + float mYScale; 1.106 + }; 1.107 + 1.108 + nsContentView(nsFrameLoader* aFrameLoader, ViewID aScrollId, bool aIsRoot, 1.109 + ViewConfig aConfig = ViewConfig()) 1.110 + : mViewportSize(0, 0) 1.111 + , mContentSize(0, 0) 1.112 + , mParentScaleX(1.0) 1.113 + , mParentScaleY(1.0) 1.114 + , mFrameLoader(aFrameLoader) 1.115 + , mScrollId(aScrollId) 1.116 + , mIsRoot(aIsRoot) 1.117 + , mConfig(aConfig) 1.118 + {} 1.119 + 1.120 + bool IsRoot() const 1.121 + { 1.122 + return mIsRoot; 1.123 + } 1.124 + 1.125 + ViewID GetId() const 1.126 + { 1.127 + return mScrollId; 1.128 + } 1.129 + 1.130 + ViewConfig GetViewConfig() const 1.131 + { 1.132 + return mConfig; 1.133 + } 1.134 + 1.135 + nsSize mViewportSize; 1.136 + nsSize mContentSize; 1.137 + float mParentScaleX; 1.138 + float mParentScaleY; 1.139 + 1.140 + nsFrameLoader* mFrameLoader; // WEAK 1.141 + 1.142 +private: 1.143 + nsresult Update(const ViewConfig& aConfig); 1.144 + 1.145 + ViewID mScrollId; 1.146 + bool mIsRoot; 1.147 + ViewConfig mConfig; 1.148 +}; 1.149 + 1.150 + 1.151 +class nsFrameLoader MOZ_FINAL : public nsIFrameLoader, 1.152 + public nsIContentViewManager, 1.153 + public nsStubMutationObserver, 1.154 + public mozilla::dom::ipc::MessageManagerCallback 1.155 +{ 1.156 + friend class AutoResetInShow; 1.157 + typedef mozilla::dom::PBrowserParent PBrowserParent; 1.158 + typedef mozilla::dom::TabParent TabParent; 1.159 + typedef mozilla::layout::RenderFrameParent RenderFrameParent; 1.160 + 1.161 +protected: 1.162 + nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated); 1.163 + 1.164 +public: 1.165 + ~nsFrameLoader(); 1.166 + 1.167 + bool AsyncScrollEnabled() const 1.168 + { 1.169 + return !!(mRenderMode & RENDER_MODE_ASYNC_SCROLL); 1.170 + } 1.171 + 1.172 + static nsFrameLoader* Create(mozilla::dom::Element* aOwner, 1.173 + bool aNetworkCreated); 1.174 + 1.175 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.176 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader) 1.177 + NS_DECL_NSIFRAMELOADER 1.178 + NS_DECL_NSICONTENTVIEWMANAGER 1.179 + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED 1.180 + NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); 1.181 + nsresult ReallyStartLoading(); 1.182 + void Finalize(); 1.183 + nsIDocShell* GetExistingDocShell() { return mDocShell; } 1.184 + mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget(); 1.185 + nsresult CreateStaticClone(nsIFrameLoader* aDest); 1.186 + 1.187 + /** 1.188 + * MessageManagerCallback methods that we override. 1.189 + */ 1.190 + virtual bool DoLoadFrameScript(const nsAString& aURL, 1.191 + bool aRunInGlobalScope) MOZ_OVERRIDE; 1.192 + virtual bool DoSendAsyncMessage(JSContext* aCx, 1.193 + const nsAString& aMessage, 1.194 + const mozilla::dom::StructuredCloneData& aData, 1.195 + JS::Handle<JSObject *> aCpows, 1.196 + nsIPrincipal* aPrincipal) MOZ_OVERRIDE; 1.197 + virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE; 1.198 + virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE; 1.199 + virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE; 1.200 + 1.201 + /** 1.202 + * Called from the layout frame associated with this frame loader; 1.203 + * this notifies us to hook up with the widget and view. 1.204 + */ 1.205 + bool Show(int32_t marginWidth, int32_t marginHeight, 1.206 + int32_t scrollbarPrefX, int32_t scrollbarPrefY, 1.207 + nsSubDocumentFrame* frame); 1.208 + 1.209 + /** 1.210 + * Called when the margin properties of the containing frame are changed. 1.211 + */ 1.212 + void MarginsChanged(uint32_t aMarginWidth, uint32_t aMarginHeight); 1.213 + 1.214 + /** 1.215 + * Called from the layout frame associated with this frame loader, when 1.216 + * the frame is being torn down; this notifies us that out widget and view 1.217 + * are going away and we should unhook from them. 1.218 + */ 1.219 + void Hide(); 1.220 + 1.221 + nsresult CloneForStatic(nsIFrameLoader* aOriginal); 1.222 + 1.223 + // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A 1.224 + // frame loader owner needs to call this, and pass in the two references to 1.225 + // nsRefPtrs for frame loaders that need to be swapped. 1.226 + nsresult SwapWithOtherLoader(nsFrameLoader* aOther, 1.227 + nsRefPtr<nsFrameLoader>& aFirstToSwap, 1.228 + nsRefPtr<nsFrameLoader>& aSecondToSwap); 1.229 + 1.230 + // When IPC is enabled, destroy any associated child process. 1.231 + void DestroyChild(); 1.232 + 1.233 + /** 1.234 + * Return the primary frame for our owning content, or null if it 1.235 + * can't be found. 1.236 + */ 1.237 + nsIFrame* GetPrimaryFrameOfOwningContent() const 1.238 + { 1.239 + return mOwnerContent ? mOwnerContent->GetPrimaryFrame() : nullptr; 1.240 + } 1.241 + 1.242 + /** 1.243 + * Return the document that owns this, or null if we don't have 1.244 + * an owner. 1.245 + */ 1.246 + nsIDocument* GetOwnerDoc() const 1.247 + { return mOwnerContent ? mOwnerContent->OwnerDoc() : nullptr; } 1.248 + 1.249 + PBrowserParent* GetRemoteBrowser(); 1.250 + 1.251 + /** 1.252 + * The "current" render frame is the one on which the most recent 1.253 + * remote layer-tree transaction was executed. If no content has 1.254 + * been drawn yet, or the remote browser doesn't have any drawn 1.255 + * content for whatever reason, return nullptr. The returned render 1.256 + * frame has an associated shadow layer tree. 1.257 + * 1.258 + * Note that the returned render frame might not be a frame 1.259 + * constructed for this->GetURL(). This can happen, e.g., if the 1.260 + * <browser> was just navigated to a new URL, but hasn't painted the 1.261 + * new page yet. A render frame for the previous page may be 1.262 + * returned. (In-process <browser> behaves similarly, and this 1.263 + * behavior seems desirable.) 1.264 + */ 1.265 + RenderFrameParent* GetCurrentRemoteFrame() const 1.266 + { 1.267 + return mCurrentRemoteFrame; 1.268 + } 1.269 + 1.270 + /** 1.271 + * |aFrame| can be null. If non-null, it must be the remote frame 1.272 + * on which the most recent layer transaction completed for this's 1.273 + * <browser>. 1.274 + */ 1.275 + void SetCurrentRemoteFrame(RenderFrameParent* aFrame) 1.276 + { 1.277 + mCurrentRemoteFrame = aFrame; 1.278 + } 1.279 + nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; } 1.280 + 1.281 + mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; } 1.282 + bool ShouldClipSubdocument() { return mClipSubdocument; } 1.283 + 1.284 + bool ShouldClampScrollPosition() { return mClampScrollPosition; } 1.285 + 1.286 + /** 1.287 + * Tell this FrameLoader to use a particular remote browser. 1.288 + * 1.289 + * This will assert if mRemoteBrowser or mCurrentRemoteFrame is non-null. In 1.290 + * practice, this means you can't have successfully run TryRemoteBrowser() on 1.291 + * this object, which means you can't have called ShowRemoteFrame() or 1.292 + * ReallyStartLoading(). 1.293 + */ 1.294 + void SetRemoteBrowser(nsITabParent* aTabParent); 1.295 + 1.296 + /** 1.297 + * Stashes a detached view on the frame loader. We do this when we're 1.298 + * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is 1.299 + * being reframed we'll restore the detached view when it's recreated, 1.300 + * otherwise we'll discard the old presentation and set the detached 1.301 + * subdoc view to null. aContainerDoc is the document containing the 1.302 + * the subdoc frame. This enables us to detect when the containing 1.303 + * document has changed during reframe, so we can discard the presentation 1.304 + * in that case. 1.305 + */ 1.306 + void SetDetachedSubdocView(nsView* aDetachedView, 1.307 + nsIDocument* aContainerDoc); 1.308 + 1.309 + /** 1.310 + * Retrieves the detached view and the document containing the view, 1.311 + * as set by SetDetachedSubdocView(). 1.312 + */ 1.313 + nsView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const; 1.314 + 1.315 + /** 1.316 + * Applies a new set of sandbox flags. These are merged with the sandbox 1.317 + * flags from our owning content's owning document with a logical OR, this 1.318 + * ensures that we can only add restrictions and never remove them. 1.319 + */ 1.320 + void ApplySandboxFlags(uint32_t sandboxFlags); 1.321 + 1.322 + void GetURL(nsString& aURL); 1.323 + 1.324 +private: 1.325 + 1.326 + void SetOwnerContent(mozilla::dom::Element* aContent); 1.327 + 1.328 + bool ShouldUseRemoteProcess(); 1.329 + 1.330 + /** 1.331 + * Is this a frameloader for a bona fide <iframe mozbrowser> or 1.332 + * <iframe mozapp>? (I.e., does the frame return true for 1.333 + * nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?) 1.334 + */ 1.335 + bool OwnerIsBrowserOrAppFrame(); 1.336 + 1.337 + /** 1.338 + * Is this a frameloader for a bona fide <iframe mozapp>? (I.e., does the 1.339 + * frame return true for nsIMozBrowserFrame::GetReallyIsApp()?) 1.340 + */ 1.341 + bool OwnerIsAppFrame(); 1.342 + 1.343 + /** 1.344 + * Is this a frame loader for a bona fide <iframe mozbrowser>? 1.345 + */ 1.346 + bool OwnerIsBrowserFrame(); 1.347 + 1.348 + /** 1.349 + * Get our owning element's app manifest URL, or return the empty string if 1.350 + * our owning element doesn't have an app manifest URL. 1.351 + */ 1.352 + void GetOwnerAppManifestURL(nsAString& aOut); 1.353 + 1.354 + /** 1.355 + * Get the app for our frame. This is the app whose manifest is returned by 1.356 + * GetOwnerAppManifestURL. 1.357 + */ 1.358 + already_AddRefed<mozIApplication> GetOwnApp(); 1.359 + 1.360 + /** 1.361 + * Get the app which contains this frame. This is the app associated with 1.362 + * the frame element's principal. 1.363 + */ 1.364 + already_AddRefed<mozIApplication> GetContainingApp(); 1.365 + 1.366 + /** 1.367 + * If we are an IPC frame, set mRemoteFrame. Otherwise, create and 1.368 + * initialize mDocShell. 1.369 + */ 1.370 + nsresult MaybeCreateDocShell(); 1.371 + nsresult EnsureMessageManager(); 1.372 + 1.373 + // Properly retrieves documentSize of any subdocument type. 1.374 + nsresult GetWindowDimensions(nsRect& aRect); 1.375 + 1.376 + // Updates the subdocument position and size. This gets called only 1.377 + // when we have our own in-process DocShell. 1.378 + NS_HIDDEN_(nsresult) UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame); 1.379 + nsresult CheckURILoad(nsIURI* aURI); 1.380 + void FireErrorEvent(); 1.381 + nsresult ReallyStartLoadingInternal(); 1.382 + 1.383 + // Return true if remote browser created; nothing else to do 1.384 + bool TryRemoteBrowser(); 1.385 + 1.386 + // Tell the remote browser that it's now "virtually visible" 1.387 + bool ShowRemoteFrame(const nsIntSize& size, 1.388 + nsSubDocumentFrame *aFrame = nullptr); 1.389 + 1.390 + bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, 1.391 + nsIDocShellTreeOwner* aOwner, 1.392 + int32_t aParentType, 1.393 + nsIDocShell* aParentNode); 1.394 + 1.395 + nsIAtom* TypeAttrName() const { 1.396 + return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype; 1.397 + } 1.398 + 1.399 + // Update the permission manager's app-id refcount based on mOwnerContent's 1.400 + // own-or-containing-app. 1.401 + void ResetPermissionManagerStatus(); 1.402 + 1.403 + nsCOMPtr<nsIDocShell> mDocShell; 1.404 + nsCOMPtr<nsIURI> mURIToLoad; 1.405 + mozilla::dom::Element* mOwnerContent; // WEAK 1.406 + 1.407 + // Note: this variable must be modified only by ResetPermissionManagerStatus() 1.408 + uint32_t mAppIdSentToPermissionManager; 1.409 + 1.410 +public: 1.411 + // public because a callback needs these. 1.412 + nsRefPtr<nsFrameMessageManager> mMessageManager; 1.413 + nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager; 1.414 +private: 1.415 + // Stores the root view of the subdocument while the subdocument is being 1.416 + // reframed. Used to restore the presentation after reframing. 1.417 + nsView* mDetachedSubdocViews; 1.418 + // Stores the containing document of the frame corresponding to this 1.419 + // frame loader. This is reference is kept valid while the subframe's 1.420 + // presentation is detached and stored in mDetachedSubdocViews. This 1.421 + // enables us to detect whether the frame has moved documents during 1.422 + // a reframe, so that we know not to restore the presentation. 1.423 + nsCOMPtr<nsIDocument> mContainerDocWhileDetached; 1.424 + 1.425 + bool mDepthTooGreat : 1; 1.426 + bool mIsTopLevelContent : 1; 1.427 + bool mDestroyCalled : 1; 1.428 + bool mNeedsAsyncDestroy : 1; 1.429 + bool mInSwap : 1; 1.430 + bool mInShow : 1; 1.431 + bool mHideCalled : 1; 1.432 + // True when the object is created for an element which the parser has 1.433 + // created using NS_FROM_PARSER_NETWORK flag. If the element is modified, 1.434 + // it may lose the flag. 1.435 + bool mNetworkCreated : 1; 1.436 + 1.437 + bool mRemoteBrowserShown : 1; 1.438 + bool mRemoteFrame : 1; 1.439 + bool mClipSubdocument : 1; 1.440 + bool mClampScrollPosition : 1; 1.441 + bool mRemoteBrowserInitialized : 1; 1.442 + bool mObservingOwnerContent : 1; 1.443 + 1.444 + // Backs nsIFrameLoader::{Get,Set}Visible. Visibility state here relates to 1.445 + // whether this frameloader's <iframe mozbrowser> is setVisible(true)'ed, and 1.446 + // doesn't necessarily correlate with docshell/document visibility. 1.447 + bool mVisible : 1; 1.448 + 1.449 + // The ContentParent associated with mRemoteBrowser. This was added as a 1.450 + // strong ref in bug 545237, and we're not sure if we can get rid of it. 1.451 + nsRefPtr<mozilla::dom::ContentParent> mContentParent; 1.452 + RenderFrameParent* mCurrentRemoteFrame; 1.453 + TabParent* mRemoteBrowser; 1.454 + uint64_t mChildID; 1.455 + 1.456 + // See nsIFrameLoader.idl. Short story, if !(mRenderMode & 1.457 + // RENDER_MODE_ASYNC_SCROLL), all the fields below are ignored in 1.458 + // favor of what content tells. 1.459 + uint32_t mRenderMode; 1.460 + 1.461 + // See nsIFrameLoader.idl. EVENT_MODE_NORMAL_DISPATCH automatically 1.462 + // forwards some input events to out-of-process content. 1.463 + uint32_t mEventMode; 1.464 + 1.465 + // Indicate if we have sent 'remote-browser-pending'. 1.466 + bool mPendingFrameSent; 1.467 +}; 1.468 + 1.469 +#endif