Bug 1854550 - pt 10. Allow LOG() with zero extra arguments r=glandium
[gecko.git] / dom / base / nsFrameLoader.h
blob159e3865a61163734d0dfb93dd31ac84c982309a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * Class for managing loading of a subframe (creation of the docshell,
9 * handling of loads in it, recursion-checking).
12 #ifndef nsFrameLoader_h_
13 #define nsFrameLoader_h_
15 #include <cstdint>
16 #include "ErrorList.h"
17 #include "Units.h"
18 #include "js/RootingAPI.h"
19 #include "mozilla/AlreadyAddRefed.h"
20 #include "mozilla/Assertions.h"
21 #include "mozilla/Attributes.h"
22 #include "mozilla/LinkedList.h"
23 #include "mozilla/RefPtr.h"
24 #include "mozilla/dom/BrowsingContext.h"
25 #include "mozilla/dom/Nullable.h"
26 #include "mozilla/dom/Promise.h"
27 #include "mozilla/dom/ReferrerPolicyBinding.h"
28 #include "mozilla/dom/WindowProxyHolder.h"
29 #include "mozilla/dom/ipc/IdType.h"
30 #include "mozilla/layers/LayersTypes.h"
31 #include "nsCOMPtr.h"
32 #include "nsCycleCollectionParticipant.h"
33 #include "nsDocShell.h"
34 #include "mozilla/dom/MessageManagerCallback.h"
35 #include "nsID.h"
36 #include "nsIFrame.h"
37 #include "nsIMutationObserver.h"
38 #include "nsISupports.h"
39 #include "nsRect.h"
40 #include "nsStringFwd.h"
41 #include "nsStubMutationObserver.h"
42 #include "nsWrapperCache.h"
44 class nsIURI;
45 class nsSubDocumentFrame;
46 class AutoResetInShow;
47 class AutoResetInFrameSwap;
48 class nsFrameLoaderOwner;
49 class nsIRemoteTab;
50 class nsIDocShellTreeItem;
51 class nsIDocShellTreeOwner;
52 class nsILoadContext;
53 class nsIPrintSettings;
54 class nsIWebBrowserPersistDocumentReceiver;
55 class nsIWebProgressListener;
56 class nsIOpenWindowInfo;
58 namespace mozilla {
60 class OriginAttributes;
62 namespace dom {
63 class ChromeMessageSender;
64 class ContentParent;
65 class Document;
66 class Element;
67 class InProcessBrowserChildMessageManager;
68 class MessageSender;
69 class ProcessMessageManager;
70 class BrowserParent;
71 class MutableTabContext;
72 class BrowserBridgeChild;
73 class RemoteBrowser;
74 struct RemotenessOptions;
75 struct NavigationIsolationOptions;
76 class SessionStoreChild;
77 class SessionStoreParent;
79 struct LazyLoadFrameResumptionState {
80 RefPtr<nsIURI> mBaseURI;
81 ReferrerPolicy mReferrerPolicy = ReferrerPolicy::_empty;
83 void Clear() {
84 mBaseURI = nullptr;
85 mReferrerPolicy = ReferrerPolicy::_empty;
89 namespace ipc {
90 class StructuredCloneData;
91 } // namespace ipc
93 } // namespace dom
95 namespace ipc {
96 class MessageChannel;
97 } // namespace ipc
98 } // namespace mozilla
100 #if defined(MOZ_WIDGET_GTK)
101 typedef struct _GtkWidget GtkWidget;
102 #endif
104 // IID for nsFrameLoader, because some places want to QI to it.
105 #define NS_FRAMELOADER_IID \
107 0x297fd0ea, 0x1b4a, 0x4c9a, { \
108 0xa4, 0x04, 0xe5, 0x8b, 0xe8, 0x95, 0x10, 0x50 \
112 class nsFrameLoader final : public nsStubMutationObserver,
113 public mozilla::dom::ipc::MessageManagerCallback,
114 public nsWrapperCache,
115 public mozilla::LinkedListElement<nsFrameLoader> {
116 friend class AutoResetInShow;
117 friend class AutoResetInFrameSwap;
118 friend class nsFrameLoaderOwner;
119 using Document = mozilla::dom::Document;
120 using Element = mozilla::dom::Element;
121 using BrowserParent = mozilla::dom::BrowserParent;
122 using BrowserBridgeChild = mozilla::dom::BrowserBridgeChild;
123 using BrowsingContext = mozilla::dom::BrowsingContext;
124 using BrowsingContextGroup = mozilla::dom::BrowsingContextGroup;
125 using Promise = mozilla::dom::Promise;
127 public:
128 // Called by Frame Elements to create a new FrameLoader.
129 static already_AddRefed<nsFrameLoader> Create(
130 Element* aOwner, bool aNetworkCreated,
131 nsIOpenWindowInfo* aOpenWindowInfo = nullptr);
133 // Called by nsFrameLoaderOwner::ChangeRemoteness when switching out
134 // FrameLoaders.
135 static already_AddRefed<nsFrameLoader> Recreate(
136 Element* aOwner, BrowsingContext* aContext, BrowsingContextGroup* aGroup,
137 const mozilla::dom::NavigationIsolationOptions& aRemotenessOptions,
138 bool aIsRemote, bool aNetworkCreated, bool aPreserveContext);
140 NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID)
142 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
143 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(nsFrameLoader)
145 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
146 nsresult CheckForRecursiveLoad(nsIURI* aURI);
147 nsresult ReallyStartLoading();
148 void StartDestroy(bool aForProcessSwitch);
149 void DestroyDocShell();
150 void DestroyComplete();
151 nsDocShell* GetExistingDocShell() const { return mDocShell; }
152 mozilla::dom::InProcessBrowserChildMessageManager*
153 GetBrowserChildMessageManager() const {
154 return mChildMessageManager;
156 nsresult UpdatePositionAndSize(nsSubDocumentFrame* aIFrame);
157 void PropagateIsUnderHiddenEmbedderElement(
158 bool aIsUnderHiddenEmbedderElement);
160 void UpdateRemoteStyle(mozilla::StyleImageRendering aImageRendering);
162 // When creating a nsFrameLoaderOwner which is a static clone, a
163 // `nsFrameLoader` is not immediately attached to it. Instead, it is added to
164 // the static clone document's `PendingFrameStaticClones` list.
166 // After the parent document has been fully cloned, a new frameloader will be
167 // created for the cloned iframe, and `FinishStaticClone` will be called on
168 // it, which will clone the inner document of the source nsFrameLoader.
169 nsresult FinishStaticClone(nsFrameLoader* aStaticCloneOf,
170 nsIPrintSettings* aPrintSettings,
171 bool* aOutHasInProcessPrintCallbacks);
173 nsresult DoRemoteStaticClone(nsFrameLoader* aStaticCloneOf,
174 nsIPrintSettings* aPrintSettings);
176 // WebIDL methods
178 nsDocShell* GetDocShell(mozilla::ErrorResult& aRv);
180 already_AddRefed<nsIRemoteTab> GetRemoteTab();
182 already_AddRefed<nsILoadContext> GetLoadContext();
184 mozilla::dom::BrowsingContext* GetBrowsingContext();
185 mozilla::dom::BrowsingContext* GetExtantBrowsingContext();
186 mozilla::dom::BrowsingContext* GetMaybePendingBrowsingContext() {
187 return mPendingBrowsingContext;
191 * Start loading the frame. This method figures out what to load
192 * from the owner content in the frame loader.
194 void LoadFrame(bool aOriginalSrc);
197 * Loads the specified URI in this frame. Behaves identically to loadFrame,
198 * except that this method allows specifying the URI to load.
200 * @param aURI The URI to load.
201 * @param aTriggeringPrincipal The triggering principal for the load. May be
202 * null, in which case the node principal of the owner content will be
203 * used.
204 * @param aCsp The CSP to be used for the load. That is not the CSP to be
205 * applied to subresources within the frame, but to the iframe load
206 * itself. E.g. if the CSP holds upgrade-insecure-requests the the
207 * frame load is upgraded from http to https.
209 nsresult LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal,
210 nsIContentSecurityPolicy* aCsp, bool aOriginalSrc);
213 * Resume a redirected load within this frame.
215 * @param aPendingSwitchID ID of a process-switching load to be reusmed
216 * within this frame.
218 void ResumeLoad(uint64_t aPendingSwitchID);
221 * Destroy the frame loader and everything inside it. This will
222 * clear the weak owner content reference.
224 void Destroy(bool aForProcessSwitch = false);
226 void AsyncDestroy() {
227 mNeedsAsyncDestroy = true;
228 Destroy();
231 void RequestUpdatePosition(mozilla::ErrorResult& aRv);
233 already_AddRefed<Promise> RequestTabStateFlush(mozilla::ErrorResult& aRv);
235 void RequestEpochUpdate(uint32_t aEpoch);
237 void RequestSHistoryUpdate();
239 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> PrintPreview(
240 nsIPrintSettings* aPrintSettings, BrowsingContext* aSourceBC,
241 mozilla::ErrorResult& aRv);
243 void ExitPrintPreview();
245 void StartPersistence(BrowsingContext* aContext,
246 nsIWebBrowserPersistDocumentReceiver* aRecv,
247 mozilla::ErrorResult& aRv);
249 // WebIDL getters
251 already_AddRefed<mozilla::dom::MessageSender> GetMessageManager();
253 already_AddRefed<Element> GetOwnerElement();
255 uint32_t LazyWidth() const;
257 uint32_t LazyHeight() const;
259 uint64_t ChildID() const { return mChildID; }
261 bool DepthTooGreat() const { return mDepthTooGreat; }
263 bool IsDead() const { return mDestroyCalled; }
265 bool IsNetworkCreated() const { return mNetworkCreated; }
268 * Is this a frame loader for a bona fide <iframe mozbrowser>?
269 * <xul:browser> is not a mozbrowser, so this is false for that case.
271 bool OwnerIsMozBrowserFrame();
273 nsIContent* GetParentObject() const;
276 * MessageManagerCallback methods that we override.
278 virtual bool DoLoadMessageManagerScript(const nsAString& aURL,
279 bool aRunInGlobalScope) override;
280 virtual nsresult DoSendAsyncMessage(
281 const nsAString& aMessage,
282 mozilla::dom::ipc::StructuredCloneData& aData) override;
285 * Called from the layout frame associated with this frame loader;
286 * this notifies us to hook up with the widget and view.
288 MOZ_CAN_RUN_SCRIPT_BOUNDARY bool Show(nsSubDocumentFrame*);
290 void MaybeShowFrame();
293 * Called when the margin properties of the containing frame are changed.
295 void MarginsChanged();
298 * Called from the layout frame associated with this frame loader, when
299 * the frame is being torn down; this notifies us that out widget and view
300 * are going away and we should unhook from them.
302 void Hide();
304 // Used when content is causing a FrameLoader to be created, and
305 // needs to try forcing layout to flush in order to get accurate
306 // dimensions for the content area.
307 MOZ_CAN_RUN_SCRIPT_BOUNDARY void ForceLayoutIfNecessary();
309 // The guts of an nsFrameLoaderOwner::SwapFrameLoader implementation. A
310 // frame loader owner needs to call this, and pass in the two references to
311 // nsRefPtrs for frame loaders that need to be swapped.
312 nsresult SwapWithOtherLoader(nsFrameLoader* aOther,
313 nsFrameLoaderOwner* aThisOwner,
314 nsFrameLoaderOwner* aOtherOwner);
316 nsresult SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
317 nsFrameLoaderOwner* aThisOwner,
318 nsFrameLoaderOwner* aOtherOwner);
321 * Return the primary frame for our owning content, or null if it
322 * can't be found.
324 nsIFrame* GetPrimaryFrameOfOwningContent() const;
327 * Return the document that owns this, or null if we don't have
328 * an owner.
330 Document* GetOwnerDoc() const;
333 * Returns whether this frame is a remote frame.
335 * This is true for either a top-level remote browser in the parent process,
336 * or a remote subframe in the child process.
338 bool IsRemoteFrame();
340 mozilla::dom::RemoteBrowser* GetRemoteBrowser() const;
343 * Returns the IPDL actor used if this is a top-level remote browser, or null
344 * otherwise.
346 BrowserParent* GetBrowserParent() const;
349 * Returns the IPDL actor used if this is an out-of-process iframe, or null
350 * otherwise.
352 BrowserBridgeChild* GetBrowserBridgeChild() const;
355 * Returns the layers ID that this remote frame is using to render.
357 * This must only be called if this is a remote frame.
359 mozilla::layers::LayersId GetLayersId() const;
361 mozilla::dom::ChromeMessageSender* GetFrameMessageManager() {
362 return mMessageManager;
365 mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
368 * Stashes a detached nsIFrame on the frame loader. We do this when we're
369 * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
370 * being reframed we'll restore the detached nsIFrame when it's recreated,
371 * otherwise we'll discard the old presentation and set the detached
372 * subdoc nsIFrame to null.
374 void SetDetachedSubdocFrame(nsIFrame* aDetachedFrame);
377 * Retrieves the detached nsIFrame as set by SetDetachedSubdocFrame().
379 nsIFrame* GetDetachedSubdocFrame(bool* aOutIsSet = nullptr) const;
382 * Applies a new set of sandbox flags. These are merged with the sandbox
383 * flags from our owning content's owning document with a logical OR, this
384 * ensures that we can only add restrictions and never remove them.
386 void ApplySandboxFlags(uint32_t sandboxFlags);
388 void GetURL(nsString& aURL, nsIPrincipal** aTriggeringPrincipal,
389 nsIContentSecurityPolicy** aCsp);
391 // Properly retrieves documentSize of any subdocument type.
392 nsresult GetWindowDimensions(nsIntRect& aRect);
394 virtual mozilla::dom::ProcessMessageManager* GetProcessMessageManager()
395 const override;
397 // public because a callback needs these.
398 RefPtr<mozilla::dom::ChromeMessageSender> mMessageManager;
399 RefPtr<mozilla::dom::InProcessBrowserChildMessageManager>
400 mChildMessageManager;
402 virtual JSObject* WrapObject(JSContext* cx,
403 JS::Handle<JSObject*> aGivenProto) override;
405 void SetWillChangeProcess();
407 // Configure which remote process should be used to host the remote browser
408 // created in `TryRemoteBrowser`. This method _must_ be called before
409 // `TryRemoteBrowser`, and a script blocker must be on the stack.
411 // |aContentParent|, if set, must have the remote type |aRemoteType|.
412 void ConfigRemoteProcess(const nsACString& aRemoteType,
413 mozilla::dom::ContentParent* aContentParent);
415 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
416 MOZ_CAN_RUN_SCRIPT_BOUNDARY void MaybeNotifyCrashed(
417 mozilla::dom::BrowsingContext* aBrowsingContext,
418 mozilla::dom::ContentParentId aChildID,
419 mozilla::ipc::MessageChannel* aChannel);
421 void FireErrorEvent();
423 mozilla::dom::SessionStoreChild* GetSessionStoreChild() {
424 return mSessionStoreChild;
427 mozilla::dom::SessionStoreParent* GetSessionStoreParent();
429 private:
430 nsFrameLoader(mozilla::dom::Element* aOwner,
431 mozilla::dom::BrowsingContext* aBrowsingContext, bool aIsRemote,
432 bool aNetworkCreated);
433 ~nsFrameLoader();
435 void SetOwnerContent(mozilla::dom::Element* aContent);
438 * Get our owning element's app manifest URL, or return the empty string if
439 * our owning element doesn't have an app manifest URL.
441 void GetOwnerAppManifestURL(nsAString& aOut);
444 * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
445 * initialize mDocShell.
447 nsresult MaybeCreateDocShell();
448 nsresult EnsureMessageManager();
449 nsresult ReallyLoadFrameScripts();
450 nsDocShell* GetDocShell() const { return mDocShell; }
452 void AssertSafeToInit();
454 // Updates the subdocument position and size. This gets called only
455 // when we have our own in-process DocShell.
456 void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame* aIFrame);
459 * Checks whether a load of the given URI should be allowed, and returns an
460 * error result if it should not.
462 * @param aURI The URI to check.
463 * @param aTriggeringPrincipal The triggering principal for the load. May be
464 * null, in which case the node principal of the owner content is used.
466 nsresult CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal);
467 nsresult ReallyStartLoadingInternal();
469 // Returns true if we have a remote browser or else attempts to create a
470 // remote browser and returns true if successful.
471 bool EnsureRemoteBrowser();
473 // Return true if remote browser created; nothing else to do
474 bool TryRemoteBrowser();
475 bool TryRemoteBrowserInternal();
477 // Tell the remote browser that it's now "virtually visible"
478 bool ShowRemoteFrame(const mozilla::ScreenIntSize& size,
479 nsSubDocumentFrame* aFrame = nullptr);
481 void AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
482 nsIDocShellTreeOwner* aOwner);
484 void InitializeBrowserAPI();
485 void DestroyBrowserFrameScripts();
487 nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext,
488 nsIURI* aURI = nullptr);
490 enum BrowserParentChange { eBrowserParentRemoved, eBrowserParentChanged };
491 void MaybeUpdatePrimaryBrowserParent(BrowserParentChange aChange);
493 nsresult PopulateOriginContextIdsFromAttributes(
494 mozilla::OriginAttributes& aAttr);
496 bool EnsureBrowsingContextAttached();
498 // Invoke the callback from nsOpenWindowInfo to indicate that a
499 // browsing context for a newly opened tab/window is ready.
500 void InvokeBrowsingContextReadyCallback();
502 void RequestFinalTabStateFlush();
504 const mozilla::dom::LazyLoadFrameResumptionState&
505 GetLazyLoadFrameResumptionState();
507 RefPtr<mozilla::dom::BrowsingContext> mPendingBrowsingContext;
508 nsCOMPtr<nsIURI> mURIToLoad;
509 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
510 nsCOMPtr<nsIContentSecurityPolicy> mCsp;
511 nsCOMPtr<nsIOpenWindowInfo> mOpenWindowInfo;
512 mozilla::dom::Element* mOwnerContent; // WEAK
514 // After the frameloader has been removed from the DOM but before all of the
515 // messages from the frame have been received, we keep a strong reference to
516 // our <browser> element.
517 RefPtr<mozilla::dom::Element> mOwnerContentStrong;
519 // Stores the root frame of the subdocument while the subdocument is being
520 // reframed. Used to restore the presentation after reframing.
521 WeakFrame mDetachedSubdocFrame;
523 // When performing a process switch, this value is used rather than mURIToLoad
524 // to identify the process-switching load which should be resumed in the
525 // target process.
526 uint64_t mPendingSwitchID;
528 uint64_t mChildID;
529 RefPtr<mozilla::dom::RemoteBrowser> mRemoteBrowser;
530 RefPtr<nsDocShell> mDocShell;
532 // Holds the last known size of the frame.
533 mozilla::ScreenIntSize mLazySize;
535 // Actor for collecting session store data from content children. This will be
536 // cleared and set to null eagerly when taking down the frameloader to break
537 // refcounted cycles early.
538 RefPtr<mozilla::dom::SessionStoreChild> mSessionStoreChild;
540 nsCString mRemoteType;
542 bool mInitialized : 1;
543 bool mDepthTooGreat : 1;
544 bool mIsTopLevelContent : 1;
545 bool mDestroyCalled : 1;
546 bool mNeedsAsyncDestroy : 1;
547 bool mInSwap : 1;
548 bool mInShow : 1;
549 bool mHideCalled : 1;
550 // True when the object is created for an element which the parser has
551 // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
552 // it may lose the flag.
553 bool mNetworkCreated : 1;
555 // True if a pending load corresponds to the original src (or srcdoc)
556 // attribute of the frame element.
557 bool mLoadingOriginalSrc : 1;
559 bool mRemoteBrowserShown : 1;
560 bool mIsRemoteFrame : 1;
561 // If true, the FrameLoader will be re-created with the same BrowsingContext,
562 // but for a different process, after it is destroyed.
563 bool mWillChangeProcess : 1;
564 bool mObservingOwnerContent : 1;
565 // Whether we had a (possibly dead now) mDetachedSubdocFrame.
566 bool mHadDetachedFrame : 1;
568 // When an out-of-process nsFrameLoader crashes, an event is fired on the
569 // frame. To ensure this is only fired once, this bit is checked.
570 bool mTabProcessCrashFired : 1;
573 NS_DEFINE_STATIC_IID_ACCESSOR(nsFrameLoader, NS_FRAMELOADER_IID)
575 inline nsISupports* ToSupports(nsFrameLoader* aFrameLoader) {
576 return aFrameLoader;
579 #endif