/src/mozilla-central/dom/base/nsFrameLoader.h
Line | Count | Source (jump to first uncovered line) |
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 "nsIFrameLoaderOwner.h" |
18 | | #include "nsPoint.h" |
19 | | #include "nsSize.h" |
20 | | #include "nsWrapperCache.h" |
21 | | #include "nsIURI.h" |
22 | | #include "nsFrameMessageManager.h" |
23 | | #include "mozilla/dom/BindingUtils.h" |
24 | | #include "mozilla/dom/Element.h" |
25 | | #include "mozilla/dom/ParentSHistory.h" |
26 | | #include "mozilla/Attributes.h" |
27 | | #include "nsStubMutationObserver.h" |
28 | | #include "Units.h" |
29 | | #include "nsIFrame.h" |
30 | | #include "nsPluginTags.h" |
31 | | |
32 | | class nsIURI; |
33 | | class nsSubDocumentFrame; |
34 | | class nsView; |
35 | | class AutoResetInShow; |
36 | | class AutoResetInFrameSwap; |
37 | | class nsITabParent; |
38 | | class nsIDocShellTreeItem; |
39 | | class nsIDocShellTreeOwner; |
40 | | class nsILoadContext; |
41 | | class nsIMessageSender; |
42 | | class nsIPrintSettings; |
43 | | class nsIWebBrowserPersistDocumentReceiver; |
44 | | class nsIWebProgressListener; |
45 | | |
46 | | namespace mozilla { |
47 | | |
48 | | class OriginAttributes; |
49 | | |
50 | | namespace dom { |
51 | | class ChromeMessageSender; |
52 | | class ContentParent; |
53 | | class InProcessTabChildMessageManager; |
54 | | class MessageSender; |
55 | | class PBrowserParent; |
56 | | class ProcessMessageManager; |
57 | | class Promise; |
58 | | class TabParent; |
59 | | class MutableTabContext; |
60 | | |
61 | | namespace ipc { |
62 | | class StructuredCloneData; |
63 | | } // namespace ipc |
64 | | |
65 | | } // namespace dom |
66 | | |
67 | | namespace layout { |
68 | | class RenderFrameParent; |
69 | | } // namespace layout |
70 | | } // namespace mozilla |
71 | | |
72 | | #if defined(MOZ_WIDGET_GTK) |
73 | | typedef struct _GtkWidget GtkWidget; |
74 | | #endif |
75 | | |
76 | | // IID for nsFrameLoader, because some places want to QI to it. |
77 | | #define NS_FRAMELOADER_IID \ |
78 | | { 0x297fd0ea, 0x1b4a, 0x4c9a, \ |
79 | | { 0xa4, 0x04, 0xe5, 0x8b, 0xe8, 0x95, 0x10, 0x50 } } |
80 | | |
81 | | class nsFrameLoader final : public nsStubMutationObserver, |
82 | | public mozilla::dom::ipc::MessageManagerCallback, |
83 | | public nsWrapperCache |
84 | | { |
85 | | friend class AutoResetInShow; |
86 | | friend class AutoResetInFrameSwap; |
87 | | typedef mozilla::dom::PBrowserParent PBrowserParent; |
88 | | typedef mozilla::dom::TabParent TabParent; |
89 | | typedef mozilla::layout::RenderFrameParent RenderFrameParent; |
90 | | |
91 | | public: |
92 | | static nsFrameLoader* Create(mozilla::dom::Element* aOwner, |
93 | | nsPIDOMWindowOuter* aOpener, |
94 | | bool aNetworkCreated, |
95 | | int32_t aJSPluginID = nsFakePluginTag::NOT_JSPLUGIN); |
96 | | |
97 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID) |
98 | | |
99 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
100 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsFrameLoader) |
101 | | |
102 | | NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED |
103 | | nsresult CheckForRecursiveLoad(nsIURI* aURI); |
104 | | nsresult ReallyStartLoading(); |
105 | | void StartDestroy(); |
106 | | void DestroyDocShell(); |
107 | | void DestroyComplete(); |
108 | 0 | nsIDocShell* GetExistingDocShell() { return mDocShell; } |
109 | | mozilla::dom::InProcessTabChildMessageManager* GetTabChildMessageManager() const |
110 | 0 | { |
111 | 0 | return mChildMessageManager; |
112 | 0 | } |
113 | | nsresult CreateStaticClone(nsFrameLoader* aDest); |
114 | | nsresult UpdatePositionAndSize(nsSubDocumentFrame *aIFrame); |
115 | | |
116 | | // WebIDL methods |
117 | | |
118 | | nsIDocShell* GetDocShell(mozilla::ErrorResult& aRv); |
119 | | |
120 | | already_AddRefed<nsITabParent> GetTabParent(); |
121 | | |
122 | | already_AddRefed<nsILoadContext> LoadContext(); |
123 | | |
124 | | /** |
125 | | * Start loading the frame. This method figures out what to load |
126 | | * from the owner content in the frame loader. |
127 | | */ |
128 | | void LoadFrame(bool aOriginalSrc); |
129 | | |
130 | | /** |
131 | | * Loads the specified URI in this frame. Behaves identically to loadFrame, |
132 | | * except that this method allows specifying the URI to load. |
133 | | */ |
134 | | nsresult LoadURI(nsIURI* aURI, bool aOriginalSrc); |
135 | | |
136 | | void AddProcessChangeBlockingPromise(mozilla::dom::Promise& aPromise, mozilla::ErrorResult& aRv); |
137 | | |
138 | | /** |
139 | | * Destroy the frame loader and everything inside it. This will |
140 | | * clear the weak owner content reference. |
141 | | */ |
142 | | void Destroy(); |
143 | | |
144 | | void ActivateRemoteFrame(mozilla::ErrorResult& aRv); |
145 | | |
146 | | void DeactivateRemoteFrame(mozilla::ErrorResult& aRv); |
147 | | |
148 | | void SendCrossProcessMouseEvent(const nsAString& aType, |
149 | | float aX, |
150 | | float aY, |
151 | | int32_t aButton, |
152 | | int32_t aClickCount, |
153 | | int32_t aModifiers, |
154 | | bool aIgnoreRootScrollFrame, |
155 | | mozilla::ErrorResult& aRv); |
156 | | |
157 | | void ActivateFrameEvent(const nsAString& aType, |
158 | | bool aCapture, |
159 | | mozilla::ErrorResult& aRv); |
160 | | |
161 | | void RequestNotifyAfterRemotePaint(); |
162 | | |
163 | | void RequestFrameLoaderClose(mozilla::ErrorResult& aRv); |
164 | | |
165 | | void RequestUpdatePosition(mozilla::ErrorResult& aRv); |
166 | | |
167 | | void Print(uint64_t aOuterWindowID, |
168 | | nsIPrintSettings* aPrintSettings, |
169 | | nsIWebProgressListener* aProgressListener, |
170 | | mozilla::ErrorResult& aRv); |
171 | | |
172 | | void StartPersistence(uint64_t aOuterWindowID, |
173 | | nsIWebBrowserPersistDocumentReceiver* aRecv, |
174 | | mozilla::ErrorResult& aRv); |
175 | | |
176 | | // WebIDL getters |
177 | | |
178 | | already_AddRefed<mozilla::dom::MessageSender> GetMessageManager(); |
179 | | |
180 | | already_AddRefed<Element> GetOwnerElement(); |
181 | | |
182 | | uint32_t LazyWidth() const; |
183 | | |
184 | | uint32_t LazyHeight() const; |
185 | | |
186 | 0 | uint64_t ChildID() const { return mChildID; } |
187 | | |
188 | 0 | bool ClampScrollPosition() const { return mClampScrollPosition; } |
189 | | void SetClampScrollPosition(bool aClamp); |
190 | | |
191 | 0 | bool ClipSubdocument() const { return mClipSubdocument; } |
192 | | void SetClipSubdocument(bool aClip); |
193 | | |
194 | 0 | bool DepthTooGreat() const { return mDepthTooGreat; } |
195 | | |
196 | 0 | bool IsDead() const { return mDestroyCalled; } |
197 | | |
198 | | /** |
199 | | * Is this a frame loader for a bona fide <iframe mozbrowser>? |
200 | | * <xul:browser> is not a mozbrowser, so this is false for that case. |
201 | | */ |
202 | | bool OwnerIsMozBrowserFrame(); |
203 | | |
204 | 0 | nsIContent* GetParentObject() const { return mOwnerContent; } |
205 | | |
206 | | |
207 | | /** |
208 | | * MessageManagerCallback methods that we override. |
209 | | */ |
210 | | virtual bool DoLoadMessageManagerScript(const nsAString& aURL, |
211 | | bool aRunInGlobalScope) override; |
212 | | virtual nsresult DoSendAsyncMessage(JSContext* aCx, |
213 | | const nsAString& aMessage, |
214 | | mozilla::dom::ipc::StructuredCloneData& aData, |
215 | | JS::Handle<JSObject *> aCpows, |
216 | | nsIPrincipal* aPrincipal) override; |
217 | | |
218 | | /** |
219 | | * Called from the layout frame associated with this frame loader; |
220 | | * this notifies us to hook up with the widget and view. |
221 | | */ |
222 | | bool Show(int32_t marginWidth, int32_t marginHeight, |
223 | | int32_t scrollbarPrefX, int32_t scrollbarPrefY, |
224 | | nsSubDocumentFrame* frame); |
225 | | |
226 | | void MaybeShowFrame(); |
227 | | |
228 | | /** |
229 | | * Called when the margin properties of the containing frame are changed. |
230 | | */ |
231 | | void MarginsChanged(uint32_t aMarginWidth, uint32_t aMarginHeight); |
232 | | |
233 | | /** |
234 | | * Called from the layout frame associated with this frame loader, when |
235 | | * the frame is being torn down; this notifies us that out widget and view |
236 | | * are going away and we should unhook from them. |
237 | | */ |
238 | | void Hide(); |
239 | | |
240 | | // Used when content is causing a FrameLoader to be created, and |
241 | | // needs to try forcing layout to flush in order to get accurate |
242 | | // dimensions for the content area. |
243 | | void ForceLayoutIfNecessary(); |
244 | | |
245 | | // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A |
246 | | // frame loader owner needs to call this, and pass in the two references to |
247 | | // nsRefPtrs for frame loaders that need to be swapped. |
248 | | nsresult SwapWithOtherLoader(nsFrameLoader* aOther, |
249 | | nsIFrameLoaderOwner* aThisOwner, |
250 | | nsIFrameLoaderOwner* aOtherOwner); |
251 | | |
252 | | nsresult SwapWithOtherRemoteLoader(nsFrameLoader* aOther, |
253 | | nsIFrameLoaderOwner* aThisOwner, |
254 | | nsIFrameLoaderOwner* aOtherOwner); |
255 | | |
256 | | /** |
257 | | * Return the primary frame for our owning content, or null if it |
258 | | * can't be found. |
259 | | */ |
260 | | nsIFrame* GetPrimaryFrameOfOwningContent() const |
261 | 0 | { |
262 | 0 | return mOwnerContent ? mOwnerContent->GetPrimaryFrame() : nullptr; |
263 | 0 | } |
264 | | |
265 | | /** |
266 | | * Return the document that owns this, or null if we don't have |
267 | | * an owner. |
268 | | */ |
269 | | nsIDocument* GetOwnerDoc() const |
270 | 0 | { return mOwnerContent ? mOwnerContent->OwnerDoc() : nullptr; } |
271 | | |
272 | | PBrowserParent* GetRemoteBrowser() const; |
273 | | |
274 | | /** |
275 | | * The "current" render frame is the one on which the most recent |
276 | | * remote layer-tree transaction was executed. If no content has |
277 | | * been drawn yet, or the remote browser doesn't have any drawn |
278 | | * content for whatever reason, return nullptr. The returned render |
279 | | * frame has an associated shadow layer tree. |
280 | | * |
281 | | * Note that the returned render frame might not be a frame |
282 | | * constructed for this->GetURL(). This can happen, e.g., if the |
283 | | * <browser> was just navigated to a new URL, but hasn't painted the |
284 | | * new page yet. A render frame for the previous page may be |
285 | | * returned. (In-process <browser> behaves similarly, and this |
286 | | * behavior seems desirable.) |
287 | | */ |
288 | | RenderFrameParent* GetCurrentRenderFrame() const; |
289 | | |
290 | 0 | mozilla::dom::ChromeMessageSender* GetFrameMessageManager() { return mMessageManager; } |
291 | | |
292 | 0 | mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; } |
293 | 0 | bool ShouldClipSubdocument() { return mClipSubdocument; } |
294 | | |
295 | 0 | bool ShouldClampScrollPosition() { return mClampScrollPosition; } |
296 | | |
297 | 0 | mozilla::dom::ParentSHistory* GetParentSHistory() { return mParentSHistory; } |
298 | | |
299 | | /** |
300 | | * Tell this FrameLoader to use a particular remote browser. |
301 | | * |
302 | | * This will assert if mRemoteBrowser is non-null. In practice, |
303 | | * this means you can't have successfully run TryRemoteBrowser() on |
304 | | * this object, which means you can't have called ShowRemoteFrame() |
305 | | * or ReallyStartLoading(). |
306 | | */ |
307 | | void SetRemoteBrowser(nsITabParent* aTabParent); |
308 | | |
309 | | /** |
310 | | * Stashes a detached nsIFrame on the frame loader. We do this when we're |
311 | | * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is |
312 | | * being reframed we'll restore the detached nsIFrame when it's recreated, |
313 | | * otherwise we'll discard the old presentation and set the detached |
314 | | * subdoc nsIFrame to null. aContainerDoc is the document containing the |
315 | | * the subdoc frame. This enables us to detect when the containing |
316 | | * document has changed during reframe, so we can discard the presentation |
317 | | * in that case. |
318 | | */ |
319 | | void SetDetachedSubdocFrame(nsIFrame* aDetachedFrame, |
320 | | nsIDocument* aContainerDoc); |
321 | | |
322 | | /** |
323 | | * Retrieves the detached nsIFrame and the document containing the nsIFrame, |
324 | | * as set by SetDetachedSubdocFrame(). |
325 | | */ |
326 | | nsIFrame* GetDetachedSubdocFrame(nsIDocument** aContainerDoc) const; |
327 | | |
328 | | /** |
329 | | * Applies a new set of sandbox flags. These are merged with the sandbox |
330 | | * flags from our owning content's owning document with a logical OR, this |
331 | | * ensures that we can only add restrictions and never remove them. |
332 | | */ |
333 | | void ApplySandboxFlags(uint32_t sandboxFlags); |
334 | | |
335 | | void GetURL(nsString& aURL, nsIPrincipal** aTriggeringPrincipal); |
336 | | |
337 | | // Properly retrieves documentSize of any subdocument type. |
338 | | nsresult GetWindowDimensions(nsIntRect& aRect); |
339 | | |
340 | | virtual mozilla::dom::ProcessMessageManager* GetProcessMessageManager() const override; |
341 | | |
342 | | // public because a callback needs these. |
343 | | RefPtr<mozilla::dom::ChromeMessageSender> mMessageManager; |
344 | | RefPtr<mozilla::dom::InProcessTabChildMessageManager> mChildMessageManager; |
345 | | |
346 | | virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override; |
347 | | |
348 | | private: |
349 | | nsFrameLoader(mozilla::dom::Element* aOwner, |
350 | | nsPIDOMWindowOuter* aOpener, |
351 | | bool aNetworkCreated, |
352 | | int32_t aJSPluginID); |
353 | | ~nsFrameLoader(); |
354 | | |
355 | | void SetOwnerContent(mozilla::dom::Element* aContent); |
356 | | |
357 | | bool ShouldUseRemoteProcess(); |
358 | | |
359 | | /** |
360 | | * Return true if the frame is a remote frame. Return false otherwise |
361 | | */ |
362 | | bool IsRemoteFrame(); |
363 | | |
364 | | bool IsForJSPlugin() |
365 | 0 | { |
366 | 0 | return mJSPluginID != nsFakePluginTag::NOT_JSPLUGIN; |
367 | 0 | } |
368 | | |
369 | | /** |
370 | | * Is this a frame loader for an isolated <iframe mozbrowser>? |
371 | | * |
372 | | * By default, mozbrowser frames are isolated. Isolation can be disabled by |
373 | | * setting the frame's noisolation attribute. Disabling isolation is |
374 | | * only allowed if the containing document is chrome. |
375 | | */ |
376 | | bool OwnerIsIsolatedMozBrowserFrame(); |
377 | | |
378 | | /** |
379 | | * Get our owning element's app manifest URL, or return the empty string if |
380 | | * our owning element doesn't have an app manifest URL. |
381 | | */ |
382 | | void GetOwnerAppManifestURL(nsAString& aOut); |
383 | | |
384 | | /** |
385 | | * If we are an IPC frame, set mRemoteFrame. Otherwise, create and |
386 | | * initialize mDocShell. |
387 | | */ |
388 | | nsresult MaybeCreateDocShell(); |
389 | | nsresult EnsureMessageManager(); |
390 | | nsresult ReallyLoadFrameScripts(); |
391 | | |
392 | | // Updates the subdocument position and size. This gets called only |
393 | | // when we have our own in-process DocShell. |
394 | | void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame); |
395 | | |
396 | | /** |
397 | | * Checks whether a load of the given URI should be allowed, and returns an |
398 | | * error result if it should not. |
399 | | * |
400 | | * @param aURI The URI to check. |
401 | | * @param aTriggeringPrincipal The triggering principal for the load. May be |
402 | | * null, in which case the node principal of the owner content is used. |
403 | | */ |
404 | | nsresult CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal); |
405 | | void FireErrorEvent(); |
406 | | nsresult ReallyStartLoadingInternal(); |
407 | | |
408 | | // Return true if remote browser created; nothing else to do |
409 | | bool TryRemoteBrowser(); |
410 | | |
411 | | // Tell the remote browser that it's now "virtually visible" |
412 | | bool ShowRemoteFrame(const mozilla::ScreenIntSize& size, |
413 | | nsSubDocumentFrame *aFrame = nullptr); |
414 | | |
415 | | bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, |
416 | | nsIDocShellTreeOwner* aOwner, |
417 | | int32_t aParentType, |
418 | | nsIDocShell* aParentNode); |
419 | | |
420 | 0 | nsAtom* TypeAttrName() const { |
421 | 0 | return mOwnerContent->IsXULElement() |
422 | 0 | ? nsGkAtoms::type : nsGkAtoms::mozframetype; |
423 | 0 | } |
424 | | |
425 | | void InitializeBrowserAPI(); |
426 | | void DestroyBrowserFrameScripts(); |
427 | | |
428 | | nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext, |
429 | | nsIURI* aURI = nullptr); |
430 | | |
431 | | enum TabParentChange { |
432 | | eTabParentRemoved, |
433 | | eTabParentChanged |
434 | | }; |
435 | | void MaybeUpdatePrimaryTabParent(TabParentChange aChange); |
436 | | |
437 | | nsresult |
438 | | PopulateUserContextIdFromAttribute(mozilla::OriginAttributes& aAttr); |
439 | | |
440 | | // Swap ourselves with the frameloader aOther, and notify chrome code with |
441 | | // a BrowserChangedProcess event. |
442 | | bool SwapBrowsersAndNotify(nsFrameLoader* aOther); |
443 | | |
444 | | // Returns a promise which will be resolved once all of the blockers have |
445 | | // resolved which were added during the BrowserWillChangeProcess event. |
446 | | already_AddRefed<mozilla::dom::Promise> FireWillChangeProcessEvent(); |
447 | | |
448 | | /** |
449 | | * Triggers a load of the given URI. |
450 | | * |
451 | | * @param aURI The URI to load. |
452 | | * @param aTriggeringPrincipal The triggering principal for the load. May be |
453 | | * null, in which case the node principal of the owner content will be |
454 | | * used. |
455 | | */ |
456 | | nsresult LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal, |
457 | | bool aOriginalSrc); |
458 | | |
459 | | nsCOMPtr<nsIDocShell> mDocShell; |
460 | | nsCOMPtr<nsIURI> mURIToLoad; |
461 | | nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; |
462 | | mozilla::dom::Element* mOwnerContent; // WEAK |
463 | | |
464 | | // After the frameloader has been removed from the DOM but before all of the |
465 | | // messages from the frame have been received, we keep a strong reference to |
466 | | // our <browser> element. |
467 | | RefPtr<mozilla::dom::Element> mOwnerContentStrong; |
468 | | |
469 | | // Stores the root frame of the subdocument while the subdocument is being |
470 | | // reframed. Used to restore the presentation after reframing. |
471 | | WeakFrame mDetachedSubdocFrame; |
472 | | // Stores the containing document of the frame corresponding to this |
473 | | // frame loader. This is reference is kept valid while the subframe's |
474 | | // presentation is detached and stored in mDetachedSubdocFrame. This |
475 | | // enables us to detect whether the frame has moved documents during |
476 | | // a reframe, so that we know not to restore the presentation. |
477 | | nsCOMPtr<nsIDocument> mContainerDocWhileDetached; |
478 | | |
479 | | // An opener window which should be used when the docshell is created. |
480 | | nsCOMPtr<nsPIDOMWindowOuter> mOpener; |
481 | | |
482 | | TabParent* mRemoteBrowser; |
483 | | uint64_t mChildID; |
484 | | |
485 | | int32_t mJSPluginID; |
486 | | |
487 | | // Holds the last known size of the frame. |
488 | | mozilla::ScreenIntSize mLazySize; |
489 | | |
490 | | // A stack-maintained reference to an array of promises which are blocking |
491 | | // grouped history navigation |
492 | | nsTArray<RefPtr<mozilla::dom::Promise>>* mBrowserChangingProcessBlockers; |
493 | | |
494 | | RefPtr<mozilla::dom::ParentSHistory> mParentSHistory; |
495 | | |
496 | | bool mDepthTooGreat : 1; |
497 | | bool mIsTopLevelContent : 1; |
498 | | bool mDestroyCalled : 1; |
499 | | bool mNeedsAsyncDestroy : 1; |
500 | | bool mInSwap : 1; |
501 | | bool mInShow : 1; |
502 | | bool mHideCalled : 1; |
503 | | // True when the object is created for an element which the parser has |
504 | | // created using NS_FROM_PARSER_NETWORK flag. If the element is modified, |
505 | | // it may lose the flag. |
506 | | bool mNetworkCreated : 1; |
507 | | |
508 | | // True if a pending load corresponds to the original src (or srcdoc) |
509 | | // attribute of the frame element. |
510 | | bool mLoadingOriginalSrc : 1; |
511 | | |
512 | | bool mRemoteBrowserShown : 1; |
513 | | bool mRemoteFrame : 1; |
514 | | bool mClipSubdocument : 1; |
515 | | bool mClampScrollPosition : 1; |
516 | | bool mObservingOwnerContent : 1; |
517 | | }; |
518 | | |
519 | | NS_DEFINE_STATIC_IID_ACCESSOR(nsFrameLoader, NS_FRAMELOADER_IID) |
520 | | |
521 | | inline nsISupports* |
522 | | ToSupports(nsFrameLoader* aFrameLoader) |
523 | 0 | { |
524 | 0 | return aFrameLoader; |
525 | 0 | } |
526 | | |
527 | | #endif |