Line data Source code
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/. */
6 :
7 : /*
8 : * Class for managing loading of a subframe (creation of the docshell,
9 : * handling of loads in it, recursion-checking).
10 : */
11 :
12 : #ifndef nsFrameLoader_h_
13 : #define nsFrameLoader_h_
14 :
15 : #include "nsIDocShell.h"
16 : #include "nsStringFwd.h"
17 : #include "nsIFrameLoader.h"
18 : #include "nsPoint.h"
19 : #include "nsSize.h"
20 : #include "nsIURI.h"
21 : #include "nsFrameMessageManager.h"
22 : #include "mozilla/dom/Element.h"
23 : #include "mozilla/Attributes.h"
24 : #include "nsStubMutationObserver.h"
25 : #include "Units.h"
26 : #include "nsIWebBrowserPersistable.h"
27 : #include "nsIFrame.h"
28 : #include "nsIGroupedSHistory.h"
29 : #include "nsPluginTags.h"
30 :
31 : class nsIURI;
32 : class nsSubDocumentFrame;
33 : class nsView;
34 : class nsIInProcessContentFrameMessageManager;
35 : class AutoResetInShow;
36 : class AutoResetInFrameSwap;
37 : class nsITabParent;
38 : class nsIDocShellTreeItem;
39 : class nsIDocShellTreeOwner;
40 :
41 : namespace mozilla {
42 :
43 : class OriginAttributes;
44 :
45 : namespace dom {
46 : class ContentParent;
47 : class PBrowserParent;
48 : class Promise;
49 : class TabParent;
50 : class MutableTabContext;
51 :
52 : namespace ipc {
53 : class StructuredCloneData;
54 : } // namespace ipc
55 :
56 : } // namespace dom
57 :
58 : namespace layout {
59 : class RenderFrameParent;
60 : } // namespace layout
61 : } // namespace mozilla
62 :
63 : #if defined(MOZ_WIDGET_GTK)
64 : typedef struct _GtkWidget GtkWidget;
65 : #endif
66 :
67 : class nsFrameLoader final : public nsIFrameLoader,
68 : public nsIWebBrowserPersistable,
69 : public nsStubMutationObserver,
70 : public mozilla::dom::ipc::MessageManagerCallback
71 : {
72 : friend class AutoResetInShow;
73 : friend class AutoResetInFrameSwap;
74 : friend class AppendPartialSHistoryAndSwapHelper;
75 : friend class RequestGroupedHistoryNavigationHelper;
76 : typedef mozilla::dom::PBrowserParent PBrowserParent;
77 : typedef mozilla::dom::TabParent TabParent;
78 : typedef mozilla::layout::RenderFrameParent RenderFrameParent;
79 :
80 : public:
81 : static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
82 : nsPIDOMWindowOuter* aOpener,
83 : bool aNetworkCreated,
84 : int32_t aJSPluginID = nsFakePluginTag::NOT_JSPLUGIN);
85 :
86 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
87 709 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader)
88 : NS_DECL_NSIFRAMELOADER
89 : NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
90 : NS_DECL_NSIWEBBROWSERPERSISTABLE
91 : nsresult CheckForRecursiveLoad(nsIURI* aURI);
92 : nsresult ReallyStartLoading();
93 : void StartDestroy();
94 : void DestroyDocShell();
95 : void DestroyComplete();
96 1 : nsIDocShell* GetExistingDocShell() { return mDocShell; }
97 : mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget();
98 : nsresult CreateStaticClone(nsIFrameLoader* aDest);
99 :
100 : /**
101 : * MessageManagerCallback methods that we override.
102 : */
103 : virtual bool DoLoadMessageManagerScript(const nsAString& aURL,
104 : bool aRunInGlobalScope) override;
105 : virtual nsresult DoSendAsyncMessage(JSContext* aCx,
106 : const nsAString& aMessage,
107 : mozilla::dom::ipc::StructuredCloneData& aData,
108 : JS::Handle<JSObject *> aCpows,
109 : nsIPrincipal* aPrincipal) override;
110 :
111 : /**
112 : * Called from the layout frame associated with this frame loader;
113 : * this notifies us to hook up with the widget and view.
114 : */
115 : bool Show(int32_t marginWidth, int32_t marginHeight,
116 : int32_t scrollbarPrefX, int32_t scrollbarPrefY,
117 : nsSubDocumentFrame* frame);
118 :
119 : /**
120 : * Called when the margin properties of the containing frame are changed.
121 : */
122 : void MarginsChanged(uint32_t aMarginWidth, uint32_t aMarginHeight);
123 :
124 : /**
125 : * Called from the layout frame associated with this frame loader, when
126 : * the frame is being torn down; this notifies us that out widget and view
127 : * are going away and we should unhook from them.
128 : */
129 : void Hide();
130 :
131 : nsresult CloneForStatic(nsIFrameLoader* aOriginal);
132 :
133 : // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A
134 : // frame loader owner needs to call this, and pass in the two references to
135 : // nsRefPtrs for frame loaders that need to be swapped.
136 : nsresult SwapWithOtherLoader(nsFrameLoader* aOther,
137 : nsIFrameLoaderOwner* aThisOwner,
138 : nsIFrameLoaderOwner* aOtherOwner);
139 :
140 : nsresult SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
141 : nsIFrameLoaderOwner* aThisOwner,
142 : nsIFrameLoaderOwner* aOtherOwner);
143 :
144 : /**
145 : * Return the primary frame for our owning content, or null if it
146 : * can't be found.
147 : */
148 15 : nsIFrame* GetPrimaryFrameOfOwningContent() const
149 : {
150 15 : return mOwnerContent ? mOwnerContent->GetPrimaryFrame() : nullptr;
151 : }
152 :
153 : /**
154 : * Return the document that owns this, or null if we don't have
155 : * an owner.
156 : */
157 2 : nsIDocument* GetOwnerDoc() const
158 2 : { return mOwnerContent ? mOwnerContent->OwnerDoc() : nullptr; }
159 :
160 : PBrowserParent* GetRemoteBrowser() const;
161 :
162 : /**
163 : * The "current" render frame is the one on which the most recent
164 : * remote layer-tree transaction was executed. If no content has
165 : * been drawn yet, or the remote browser doesn't have any drawn
166 : * content for whatever reason, return nullptr. The returned render
167 : * frame has an associated shadow layer tree.
168 : *
169 : * Note that the returned render frame might not be a frame
170 : * constructed for this->GetURL(). This can happen, e.g., if the
171 : * <browser> was just navigated to a new URL, but hasn't painted the
172 : * new page yet. A render frame for the previous page may be
173 : * returned. (In-process <browser> behaves similarly, and this
174 : * behavior seems desirable.)
175 : */
176 : RenderFrameParent* GetCurrentRenderFrame() const;
177 :
178 58 : nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
179 :
180 3 : mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
181 4 : bool ShouldClipSubdocument() { return mClipSubdocument; }
182 :
183 0 : bool ShouldClampScrollPosition() { return mClampScrollPosition; }
184 :
185 : /**
186 : * Tell this FrameLoader to use a particular remote browser.
187 : *
188 : * This will assert if mRemoteBrowser is non-null. In practice,
189 : * this means you can't have successfully run TryRemoteBrowser() on
190 : * this object, which means you can't have called ShowRemoteFrame()
191 : * or ReallyStartLoading().
192 : */
193 : void SetRemoteBrowser(nsITabParent* aTabParent);
194 :
195 : /**
196 : * Stashes a detached nsIFrame on the frame loader. We do this when we're
197 : * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
198 : * being reframed we'll restore the detached nsIFrame when it's recreated,
199 : * otherwise we'll discard the old presentation and set the detached
200 : * subdoc nsIFrame to null. aContainerDoc is the document containing the
201 : * the subdoc frame. This enables us to detect when the containing
202 : * document has changed during reframe, so we can discard the presentation
203 : * in that case.
204 : */
205 : void SetDetachedSubdocFrame(nsIFrame* aDetachedFrame,
206 : nsIDocument* aContainerDoc);
207 :
208 : /**
209 : * Retrieves the detached nsIFrame and the document containing the nsIFrame,
210 : * as set by SetDetachedSubdocFrame().
211 : */
212 : nsIFrame* GetDetachedSubdocFrame(nsIDocument** aContainerDoc) const;
213 :
214 : /**
215 : * Applies a new set of sandbox flags. These are merged with the sandbox
216 : * flags from our owning content's owning document with a logical OR, this
217 : * ensures that we can only add restrictions and never remove them.
218 : */
219 : void ApplySandboxFlags(uint32_t sandboxFlags);
220 :
221 : void GetURL(nsString& aURL);
222 :
223 : // Properly retrieves documentSize of any subdocument type.
224 : nsresult GetWindowDimensions(nsIntRect& aRect);
225 :
226 : virtual nsIMessageSender* GetProcessMessageManager() const override;
227 :
228 : // public because a callback needs these.
229 : RefPtr<nsFrameMessageManager> mMessageManager;
230 : nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
231 :
232 : private:
233 : nsFrameLoader(mozilla::dom::Element* aOwner,
234 : nsPIDOMWindowOuter* aOpener,
235 : bool aNetworkCreated,
236 : int32_t aJSPluginID);
237 : ~nsFrameLoader();
238 :
239 : void SetOwnerContent(mozilla::dom::Element* aContent);
240 :
241 : bool ShouldUseRemoteProcess();
242 :
243 : /**
244 : * Return true if the frame is a remote frame. Return false otherwise
245 : */
246 : bool IsRemoteFrame();
247 :
248 9 : bool IsForJSPlugin()
249 : {
250 9 : return mJSPluginID != nsFakePluginTag::NOT_JSPLUGIN;
251 : }
252 :
253 : /**
254 : * Is this a frame loader for a bona fide <iframe mozbrowser>?
255 : * <xul:browser> is not a mozbrowser, so this is false for that case.
256 : */
257 : bool OwnerIsMozBrowserFrame();
258 :
259 : /**
260 : * Is this a frame loader for an isolated <iframe mozbrowser>?
261 : *
262 : * By default, mozbrowser frames are isolated. Isolation can be disabled by
263 : * setting the frame's noisolation attribute. Disabling isolation is
264 : * only allowed if the containing document is chrome.
265 : */
266 : bool OwnerIsIsolatedMozBrowserFrame();
267 :
268 : /**
269 : * Get our owning element's app manifest URL, or return the empty string if
270 : * our owning element doesn't have an app manifest URL.
271 : */
272 : void GetOwnerAppManifestURL(nsAString& aOut);
273 :
274 : /**
275 : * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
276 : * initialize mDocShell.
277 : */
278 : nsresult MaybeCreateDocShell();
279 : nsresult EnsureMessageManager();
280 : nsresult ReallyLoadFrameScripts();
281 :
282 : // Updates the subdocument position and size. This gets called only
283 : // when we have our own in-process DocShell.
284 : void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
285 : nsresult CheckURILoad(nsIURI* aURI);
286 : void FireErrorEvent();
287 : nsresult ReallyStartLoadingInternal();
288 :
289 : // Return true if remote browser created; nothing else to do
290 : bool TryRemoteBrowser();
291 :
292 : // Tell the remote browser that it's now "virtually visible"
293 : bool ShowRemoteFrame(const mozilla::ScreenIntSize& size,
294 : nsSubDocumentFrame *aFrame = nullptr);
295 :
296 : bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
297 : nsIDocShellTreeOwner* aOwner,
298 : int32_t aParentType,
299 : nsIDocShell* aParentNode);
300 :
301 3 : nsIAtom* TypeAttrName() const {
302 3 : return mOwnerContent->IsXULElement()
303 3 : ? nsGkAtoms::type : nsGkAtoms::mozframetype;
304 : }
305 :
306 : void InitializeBrowserAPI();
307 : void DestroyBrowserFrameScripts();
308 :
309 : nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext,
310 : nsIURI* aURI = nullptr);
311 :
312 : enum TabParentChange {
313 : eTabParentRemoved,
314 : eTabParentChanged
315 : };
316 : void MaybeUpdatePrimaryTabParent(TabParentChange aChange);
317 :
318 : nsresult
319 : PopulateUserContextIdFromAttribute(mozilla::OriginAttributes& aAttr);
320 :
321 : // Swap ourselves with the frameloader aOther, and notify chrome code with
322 : // a BrowserChangedProcess event.
323 : bool SwapBrowsersAndNotify(nsFrameLoader* aOther);
324 :
325 : // Returns a promise which will be resolved once all of the blockers have
326 : // resolved which were added during the BrowserWillChangeProcess event.
327 : already_AddRefed<mozilla::dom::Promise> FireWillChangeProcessEvent();
328 :
329 : nsCOMPtr<nsIDocShell> mDocShell;
330 : nsCOMPtr<nsIURI> mURIToLoad;
331 : mozilla::dom::Element* mOwnerContent; // WEAK
332 :
333 : // After the frameloader has been removed from the DOM but before all of the
334 : // messages from the frame have been received, we keep a strong reference to
335 : // our <browser> element.
336 : RefPtr<mozilla::dom::Element> mOwnerContentStrong;
337 :
338 : // Stores the root frame of the subdocument while the subdocument is being
339 : // reframed. Used to restore the presentation after reframing.
340 : WeakFrame mDetachedSubdocFrame;
341 : // Stores the containing document of the frame corresponding to this
342 : // frame loader. This is reference is kept valid while the subframe's
343 : // presentation is detached and stored in mDetachedSubdocFrame. This
344 : // enables us to detect whether the frame has moved documents during
345 : // a reframe, so that we know not to restore the presentation.
346 : nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
347 :
348 : // An opener window which should be used when the docshell is created.
349 : nsCOMPtr<nsPIDOMWindowOuter> mOpener;
350 :
351 : TabParent* mRemoteBrowser;
352 : uint64_t mChildID;
353 :
354 : int32_t mJSPluginID;
355 :
356 : // See nsIFrameLoader.idl. EVENT_MODE_NORMAL_DISPATCH automatically
357 : // forwards some input events to out-of-process content.
358 : uint32_t mEventMode;
359 :
360 : // Holds the last known size of the frame.
361 : mozilla::ScreenIntSize mLazySize;
362 :
363 : nsCOMPtr<nsIPartialSHistory> mPartialSHistory;
364 :
365 : // A stack-maintained reference to an array of promises which are blocking
366 : // grouped history navigation
367 : nsTArray<RefPtr<mozilla::dom::Promise>>* mBrowserChangingProcessBlockers;
368 :
369 : bool mIsPrerendered : 1;
370 : bool mDepthTooGreat : 1;
371 : bool mIsTopLevelContent : 1;
372 : bool mDestroyCalled : 1;
373 : bool mNeedsAsyncDestroy : 1;
374 : bool mInSwap : 1;
375 : bool mInShow : 1;
376 : bool mHideCalled : 1;
377 : // True when the object is created for an element which the parser has
378 : // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
379 : // it may lose the flag.
380 : bool mNetworkCreated : 1;
381 :
382 : bool mRemoteBrowserShown : 1;
383 : bool mRemoteFrame : 1;
384 : bool mClipSubdocument : 1;
385 : bool mClampScrollPosition : 1;
386 : bool mObservingOwnerContent : 1;
387 :
388 : bool mFreshProcess : 1;
389 : };
390 :
391 : #endif
|