Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / base / nsObjectLoadingContent.h
blobc679a7cc5d4cb6600191e93d345274de1fe05a66
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 * A base class implementing nsIObjectLoadingContent for use by
9 * various content nodes that want to provide plugin/document/image
10 * loading functionality (eg <embed>, <object>, etc).
13 #ifndef NSOBJECTLOADINGCONTENT_H_
14 #define NSOBJECTLOADINGCONTENT_H_
16 #include "mozilla/Maybe.h"
17 #include "mozilla/dom/BindingDeclarations.h"
18 #include "nsIFrame.h" // for WeakFrame only
19 #include "nsIStreamListener.h"
20 #include "nsIChannelEventSink.h"
21 #include "nsIObjectLoadingContent.h"
22 #include "nsFrameLoaderOwner.h"
24 class nsStopPluginRunnable;
25 class nsIPrincipal;
26 class nsFrameLoader;
28 namespace mozilla::dom {
29 struct BindContext;
30 template <typename T>
31 class Sequence;
32 class HTMLIFrameElement;
33 template <typename T>
34 struct Nullable;
35 class WindowProxyHolder;
36 class XULFrameElement;
37 } // namespace mozilla::dom
39 class nsObjectLoadingContent : public nsIStreamListener,
40 public nsFrameLoaderOwner,
41 public nsIObjectLoadingContent,
42 public nsIChannelEventSink {
43 friend class AutoSetLoadingToFalse;
45 public:
46 // This enum's values must be the same as the constants on
47 // nsIObjectLoadingContent
48 enum class ObjectType : uint8_t {
49 // Loading, type not yet known. We may be waiting for a channel to open.
50 Loading = TYPE_LOADING,
51 // Content is a subdocument, possibly SVG
52 Document = TYPE_DOCUMENT,
53 // Content is unknown and should be represented by an empty element.
54 Fallback = TYPE_FALLBACK
57 nsObjectLoadingContent();
58 virtual ~nsObjectLoadingContent();
60 NS_DECL_NSIREQUESTOBSERVER
61 NS_DECL_NSISTREAMLISTENER
62 NS_DECL_NSIOBJECTLOADINGCONTENT
63 NS_DECL_NSICHANNELEVENTSINK
65 ObjectType Type() const { return mType; }
67 void SetIsNetworkCreated(bool aNetworkCreated) {
68 mNetworkCreated = aNetworkCreated;
71 static bool IsSuccessfulRequest(nsIRequest*, nsresult* aStatus);
73 // WebIDL API
74 mozilla::dom::Document* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
75 void GetActualType(nsAString& aType) const {
76 CopyUTF8toUTF16(mContentType, aType);
78 uint32_t DisplayedType() const { return uint32_t(mType); }
79 nsIURI* GetSrcURI() const { return mURI; }
81 void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
82 mozilla::ErrorResult& aRv) {
83 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
85 void SwapFrameLoaders(mozilla::dom::XULFrameElement& aOtherLoaderOwner,
86 mozilla::ErrorResult& aRv) {
87 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
90 bool IsRewrittenYoutubeEmbed() const { return mRewrittenYoutubeEmbed; }
92 const mozilla::Maybe<mozilla::IntrinsicSize>& GetSubdocumentIntrinsicSize()
93 const {
94 return mSubdocumentIntrinsicSize;
97 const mozilla::Maybe<mozilla::AspectRatio>& GetSubdocumentIntrinsicRatio()
98 const {
99 return mSubdocumentIntrinsicRatio;
102 void SubdocumentIntrinsicSizeOrRatioChanged(
103 const mozilla::Maybe<mozilla::IntrinsicSize>& aIntrinsicSize,
104 const mozilla::Maybe<mozilla::AspectRatio>& aIntrinsicRatio);
106 void SubdocumentImageLoadComplete(nsresult aResult);
108 protected:
110 * Begins loading the object when called
112 * Attributes of |this| QI'd to nsIContent will be inspected, depending on
113 * the node type. This function currently assumes it is a <object> or
114 * <embed> tag.
116 * The instantiated plugin depends on:
117 * - The URI (<embed src>, <object data>)
118 * - The type 'hint' (type attribute)
119 * - The mime type returned by opening the URI
120 * - Enabled plugins claiming the ultimate mime type
121 * - The capabilities returned by GetCapabilities
122 * - The classid attribute, if eFallbackIfClassIDPresent is among the
123 * capabilities
125 * If eAllowPluginSkipChannel is true, we may skip opening the URI if our
126 * type hint points to a valid plugin, deferring that responsibility to the
127 * plugin.
128 * Similarly, if no URI is provided, but a type hint for a valid plugin is
129 * present, that plugin will be instantiated
131 * Otherwise a request to that URI is made and the type sent by the server
132 * is used to find a suitable handler, EXCEPT when:
133 * - The type hint refers to a *supported* plugin, in which case that
134 * plugin will be instantiated regardless of the server provided type
135 * - The server returns a binary-stream type, and our type hint refers to
136 * a valid non-document type, we will use the type hint
138 * @param aNotify If we should send notifications. If false, content
139 * loading may be deferred while appropriate frames are
140 * created
141 * @param aForceLoad If we should reload this content (and re-attempt the
142 * channel open) even if our parameters did not change
144 nsresult LoadObject(bool aNotify, bool aForceLoad = false);
146 enum Capabilities {
147 eSupportImages = 1u << 0, // Images are supported (imgILoader)
148 eSupportDocuments = 1u << 1, // Documents are supported
149 // (DocumentLoaderFactory)
150 // This flag always includes SVG
152 // Node supports class ID as an attribute, and should fallback if it is
153 // present, as class IDs are not supported.
154 eFallbackIfClassIDPresent = 1u << 2,
156 // If possible to get a *plugin* type from the type attribute *or* file
157 // extension, we can use that type and begin loading the plugin before
158 // opening a channel.
159 // A side effect of this is if the channel fails, the plugin is still
160 // running.
161 eAllowPluginSkipChannel = 1u << 3
165 * Returns the list of capabilities this content node supports. This is a
166 * bitmask consisting of flags from the Capabilities enum.
168 * The default implementation supports all types but not
169 * eSupportClassID or eAllowPluginSkipChannel
171 virtual uint32_t GetCapabilities() const;
174 * Destroys all loaded documents/plugins and releases references
176 void Destroy();
178 // Subclasses should call cycle collection methods from the respective
179 // traverse / unlink.
180 static void Traverse(nsObjectLoadingContent* tmp,
181 nsCycleCollectionTraversalCallback& cb);
182 static void Unlink(nsObjectLoadingContent* tmp);
184 void CreateStaticClone(nsObjectLoadingContent* aDest) const;
186 void UnbindFromTree();
189 * Return the content policy type used for loading the element.
191 virtual nsContentPolicyType GetContentPolicyType() const = 0;
193 virtual const mozilla::dom::Element* AsElement() const = 0;
194 mozilla::dom::Element* AsElement() {
195 return const_cast<mozilla::dom::Element*>(
196 const_cast<const nsObjectLoadingContent*>(this)->AsElement());
200 * Decides whether we should load <embed>/<object> node content.
202 * If this is an <embed> or <object> node there are cases in which we should
203 * not try to load the content:
205 * - If the node is the child of a media element
206 * - If the node is the child of an <object> node that already has
207 * content being loaded.
209 * In these cases, this function will return false, which will cause
210 * us to skip calling LoadObject.
212 bool BlockEmbedOrObjectContentLoading();
214 private:
215 // Object parameter changes returned by UpdateObjectParameters
216 enum ParameterUpdateFlags {
217 eParamNoChange = 0,
218 // Parameters that potentially affect the channel changed
219 // - mOriginalURI, mOriginalContentType
220 eParamChannelChanged = 1u << 0,
221 // Parameters that affect displayed content changed
222 // - mURI, mContentType, mType, mBaseURI
223 eParamStateChanged = 1u << 1,
224 // The effective content type changed, independant of object type. This
225 // can happen when changing from Loading -> Final type, but doesn't
226 // necessarily happen when changing between object types. E.g., if a PDF
227 // handler was installed between the last load of this object and now, we
228 // might change from Document -> Plugin without changing
229 // ContentType
230 eParamContentTypeChanged = 1u << 2
234 * If we're an <object>, and show fallback, we might need to start nested
235 * <embed> or <object> loads that would otherwise be blocked by
236 * BlockEmbedOrObjectContentLoading().
238 void TriggerInnerFallbackLoads();
241 * Internal version of LoadObject that should only be used by this class
242 * aLoadingChannel is passed by the LoadObject call from OnStartRequest,
243 * primarily for sanity-preservation
245 nsresult LoadObject(bool aNotify, bool aForceLoad,
246 nsIRequest* aLoadingChannel);
249 * Inspects the object and sets the following member variables:
250 * - mOriginalContentType : This is the type attribute on the element
251 * - mOriginalURI : The src or data attribute on the element
252 * - mURI : The final URI, considering mChannel if
253 * mChannelLoaded is set
254 * - mContentType : The final content type, considering mChannel if
255 * mChannelLoaded is set
256 * - mBaseURI : The object's base URI, which may be set by the
257 * object
258 * - mType : The type the object is determined to be based
259 * on the above
261 * NOTE The class assumes that mType is the currently loaded type at various
262 * points, so the caller of this function must take the appropriate
263 * actions to ensure this
265 * NOTE This function does not perform security checks, only determining the
266 * requested type and parameters of the object.
268 * @return Returns a bitmask of ParameterUpdateFlags values
270 ParameterUpdateFlags UpdateObjectParameters();
272 public:
273 bool IsAboutBlankLoadOntoInitialAboutBlank(nsIURI* aURI,
274 bool aInheritPrincipal,
275 nsIPrincipal* aPrincipalToInherit);
277 private:
279 * Opens the channel pointed to by mURI into mChannel.
281 nsresult OpenChannel();
284 * Closes and releases references to mChannel and, if opened, mFinalListener
286 nsresult CloseChannel();
289 * If this object should be tested against blocking list.
291 bool ShouldBlockContent();
294 * This method tells the final answer on whether this object's fallback
295 * content should be used instead of the original plugin content.
297 * @param aIsPluginClickToPlay Whether this object instance is CTP.
299 bool PreferFallback(bool aIsPluginClickToPlay);
302 * Helper to check if our current URI passes policy
304 * @param aContentPolicy [out] The result of the content policy decision
306 * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
308 bool CheckLoadPolicy(int16_t* aContentPolicy);
311 * Helper to check if the object passes process policy. Assumes we have a
312 * final determined type.
314 * @param aContentPolicy [out] The result of the content policy decision
316 * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
318 bool CheckProcessPolicy(int16_t* aContentPolicy);
320 void SetupFrameLoader();
323 * Helper to spawn mFrameLoader and return a pointer to its docshell
325 * @param aURI URI we intend to load for the recursive load check (does not
326 * actually load anything)
328 already_AddRefed<nsIDocShell> SetupDocShell(nsIURI* aRecursionCheckURI);
331 * Unloads all content and resets the object to a completely unloaded state
333 * NOTE Calls StopPluginInstance() and may spin the event loop
335 * @param aResetState Reset the object type to 'loading' and destroy channel
336 * as well
338 void UnloadObject(bool aResetState = true);
341 * Notifies document observes about a new type/state of this object.
342 * Triggers frame construction as needed. mType must be set correctly when
343 * this method is called. This method is cheap if the type and state didn't
344 * actually change.
346 * @param aNotify if false, only need to update the state of our element.
348 void NotifyStateChanged(ObjectType aOldType, bool aNotify);
351 * Returns a ObjectType value corresponding to the type of content we would
352 * support the given MIME type as, taking capabilities and plugin state
353 * into account
355 * @return The ObjectType enum value that we would attempt to load
357 * NOTE this does not consider whether the content would be suppressed by
358 * click-to-play or other content policy checks
360 ObjectType GetTypeOfContent(const nsCString& aMIMEType);
363 * Used for identifying whether we can rewrite a youtube flash embed to
364 * possibly use HTML5 instead.
366 * Returns true if plugin.rewrite_youtube_embeds pref is true and the
367 * element this nsObjectLoadingContent instance represents:
369 * - is an embed or object node
370 * - has a URL pointing at the youtube.com domain, using "/v/" style video
371 * path reference.
373 * Having the enablejsapi flag means the document that contains the element
374 * could possibly be manipulating the youtube video elsewhere on the page
375 * via javascript. In the context of embed elements, this usage has been
376 * deprecated by youtube, so we can just rewrite as normal.
378 * If we can rewrite the URL, we change the "/v/" to "/embed/", and change
379 * our type to Document so that we render similarly to an iframe
380 * embed.
382 void MaybeRewriteYoutubeEmbed(nsIURI* aURI, nsIURI* aBaseURI,
383 nsIURI** aRewrittenURI);
385 // Utility for firing an error event, if we're an <object>.
386 void MaybeFireErrorEvent();
389 * Store feature policy in container browsing context so that it can be
390 * accessed cross process.
392 void MaybeStoreCrossOriginFeaturePolicy();
394 // The final listener for mChannel (uriloader, pluginstreamlistener, etc.)
395 nsCOMPtr<nsIStreamListener> mFinalListener;
397 // The content type of our current load target, updated by
398 // UpdateObjectParameters(). Takes the channel's type into account once
399 // opened.
401 // May change if a channel is opened, does not imply a loaded state
402 nsCString mContentType;
404 // The content type 'hint' provided by the element's type attribute. May
405 // or may not be used as a final type
406 nsCString mOriginalContentType;
408 // The channel that's currently being loaded. If set, but mChannelLoaded is
409 // false, has not yet reached OnStartRequest
410 nsCOMPtr<nsIChannel> mChannel;
412 // The URI of the current content.
413 // May change as we open channels and encounter redirects - does not imply
414 // a loaded type
415 nsCOMPtr<nsIURI> mURI;
417 // The original URI obtained from inspecting the element. May differ from
418 // mURI due to redirects
419 nsCOMPtr<nsIURI> mOriginalURI;
421 // The baseURI used for constructing mURI.
422 nsCOMPtr<nsIURI> mBaseURI;
424 // Type of the currently-loaded content.
425 ObjectType mType;
427 // If true, we have opened a channel as the listener and it has reached
428 // OnStartRequest. Does not get set for channels that are passed directly to
429 // the plugin listener.
430 bool mChannelLoaded : 1;
432 // True when the object is created for an element which the parser has
433 // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
434 // it may lose the flag.
435 bool mNetworkCreated : 1;
437 // Whether content blocking is enabled or not for this object.
438 bool mContentBlockingEnabled : 1;
440 // Protects DoStopPlugin from reentry (bug 724781).
441 bool mIsStopping : 1;
443 // Protects LoadObject from re-entry
444 bool mIsLoading : 1;
446 // For plugin stand-in types (click-to-play) tracks whether content js has
447 // tried to access the plugin script object.
448 bool mScriptRequested : 1;
450 // True if object represents an object/embed tag pointing to a flash embed
451 // for a youtube video. When possible (see IsRewritableYoutubeEmbed function
452 // comments for details), we change these to try to load HTML5 versions of
453 // videos.
454 bool mRewrittenYoutubeEmbed : 1;
456 bool mLoadingSyntheticDocument : 1;
458 // The intrinsic size and aspect ratio from a child SVG document that
459 // we should use. These are only set when we are an <object> or <embed>
460 // and the inner document is SVG.
462 // We store these here rather than on nsSubDocumentFrame since we are
463 // sometimes notified of our child's intrinsics before we've constructed
464 // our own frame.
465 mozilla::Maybe<mozilla::IntrinsicSize> mSubdocumentIntrinsicSize;
466 mozilla::Maybe<mozilla::AspectRatio> mSubdocumentIntrinsicRatio;
469 #endif