Bug 1842773 - Part 5: Add ArrayBuffer.prototype.{maxByteLength,resizable} getters...
[gecko.git] / dom / base / nsObjectLoadingContent.h
blob4cc418517333ee8718ba949125e14253daeee712
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 ObjectType {
49 // Loading, type not yet known. We may be waiting for a channel to open.
50 eType_Loading = TYPE_LOADING,
51 // Content is a "special" plugin. Plugins are removed but these MIME
52 // types display an transparent region in their place.
53 // (Special plugins that have an HTML fallback are eType_Null)
54 eType_Fallback = TYPE_FALLBACK,
55 // Content is a subdocument, possibly SVG
56 eType_Document = TYPE_DOCUMENT,
57 // Content is unknown and should be represented by an empty element,
58 // unless an HTML fallback is available.
59 eType_Null = TYPE_NULL
62 nsObjectLoadingContent();
63 virtual ~nsObjectLoadingContent();
65 NS_DECL_NSIREQUESTOBSERVER
66 NS_DECL_NSISTREAMLISTENER
67 NS_DECL_NSIOBJECTLOADINGCONTENT
68 NS_DECL_NSICHANNELEVENTSINK
70 ObjectType Type() const { return mType; }
72 void SetIsNetworkCreated(bool aNetworkCreated) {
73 mNetworkCreated = aNetworkCreated;
76 static bool IsFallbackMimeType(const nsACString& aMimeType);
77 static bool IsSuccessfulRequest(nsIRequest*, nsresult* aStatus);
79 // WebIDL API
80 mozilla::dom::Document* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
81 void GetActualType(nsAString& aType) const {
82 CopyUTF8toUTF16(mContentType, aType);
84 uint32_t DisplayedType() const { return mType; }
85 nsIURI* GetSrcURI() const { return mURI; }
87 void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
88 mozilla::ErrorResult& aRv) {
89 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
91 void SwapFrameLoaders(mozilla::dom::XULFrameElement& aOtherLoaderOwner,
92 mozilla::ErrorResult& aRv) {
93 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
96 bool IsRewrittenYoutubeEmbed() const { return mRewrittenYoutubeEmbed; }
98 const mozilla::Maybe<mozilla::IntrinsicSize>& GetSubdocumentIntrinsicSize()
99 const {
100 return mSubdocumentIntrinsicSize;
103 const mozilla::Maybe<mozilla::AspectRatio>& GetSubdocumentIntrinsicRatio()
104 const {
105 return mSubdocumentIntrinsicRatio;
108 void SubdocumentIntrinsicSizeOrRatioChanged(
109 const mozilla::Maybe<mozilla::IntrinsicSize>& aIntrinsicSize,
110 const mozilla::Maybe<mozilla::AspectRatio>& aIntrinsicRatio);
112 void SubdocumentImageLoadComplete(nsresult aResult);
114 protected:
116 * Begins loading the object when called
118 * Attributes of |this| QI'd to nsIContent will be inspected, depending on
119 * the node type. This function currently assumes it is a <object> or
120 * <embed> tag.
122 * The instantiated plugin depends on:
123 * - The URI (<embed src>, <object data>)
124 * - The type 'hint' (type attribute)
125 * - The mime type returned by opening the URI
126 * - Enabled plugins claiming the ultimate mime type
127 * - The capabilities returned by GetCapabilities
128 * - The classid attribute, if eFallbackIfClassIDPresent is among the
129 * capabilities
131 * If eAllowPluginSkipChannel is true, we may skip opening the URI if our
132 * type hint points to a valid plugin, deferring that responsibility to the
133 * plugin.
134 * Similarly, if no URI is provided, but a type hint for a valid plugin is
135 * present, that plugin will be instantiated
137 * Otherwise a request to that URI is made and the type sent by the server
138 * is used to find a suitable handler, EXCEPT when:
139 * - The type hint refers to a *supported* plugin, in which case that
140 * plugin will be instantiated regardless of the server provided type
141 * - The server returns a binary-stream type, and our type hint refers to
142 * a valid non-document type, we will use the type hint
144 * @param aNotify If we should send notifications. If false, content
145 * loading may be deferred while appropriate frames are
146 * created
147 * @param aForceLoad If we should reload this content (and re-attempt the
148 * channel open) even if our parameters did not change
150 nsresult LoadObject(bool aNotify, bool aForceLoad = false);
152 enum Capabilities {
153 eSupportImages = 1u << 0, // Images are supported (imgILoader)
154 eSupportDocuments = 1u << 1, // Documents are supported
155 // (DocumentLoaderFactory)
156 // This flag always includes SVG
158 // Node supports class ID as an attribute, and should fallback if it is
159 // present, as class IDs are not supported.
160 eFallbackIfClassIDPresent = 1u << 2,
162 // If possible to get a *plugin* type from the type attribute *or* file
163 // extension, we can use that type and begin loading the plugin before
164 // opening a channel.
165 // A side effect of this is if the channel fails, the plugin is still
166 // running.
167 eAllowPluginSkipChannel = 1u << 3
171 * Returns the list of capabilities this content node supports. This is a
172 * bitmask consisting of flags from the Capabilities enum.
174 * The default implementation supports all types but not
175 * eSupportClassID or eAllowPluginSkipChannel
177 virtual uint32_t GetCapabilities() const;
180 * Destroys all loaded documents/plugins and releases references
182 void Destroy();
184 // Subclasses should call cycle collection methods from the respective
185 // traverse / unlink.
186 static void Traverse(nsObjectLoadingContent* tmp,
187 nsCycleCollectionTraversalCallback& cb);
188 static void Unlink(nsObjectLoadingContent* tmp);
190 void CreateStaticClone(nsObjectLoadingContent* aDest) const;
192 void UnbindFromTree(bool aNullParent = true);
195 * Return the content policy type used for loading the element.
197 virtual nsContentPolicyType GetContentPolicyType() const = 0;
199 virtual const mozilla::dom::Element* AsElement() const = 0;
200 mozilla::dom::Element* AsElement() {
201 return const_cast<mozilla::dom::Element*>(
202 const_cast<const nsObjectLoadingContent*>(this)->AsElement());
206 * Decides whether we should load <embed>/<object> node content.
208 * If this is an <embed> or <object> node there are cases in which we should
209 * not try to load the content:
211 * - If the node is the child of a media element
212 * - If the node is the child of an <object> node that already has
213 * content being loaded.
215 * In these cases, this function will return false, which will cause
216 * us to skip calling LoadObject.
218 bool BlockEmbedOrObjectContentLoading();
220 private:
221 // Object parameter changes returned by UpdateObjectParameters
222 enum ParameterUpdateFlags {
223 eParamNoChange = 0,
224 // Parameters that potentially affect the channel changed
225 // - mOriginalURI, mOriginalContentType
226 eParamChannelChanged = 1u << 0,
227 // Parameters that affect displayed content changed
228 // - mURI, mContentType, mType, mBaseURI
229 eParamStateChanged = 1u << 1,
230 // The effective content type changed, independant of object type. This
231 // can happen when changing from Loading -> Final type, but doesn't
232 // necessarily happen when changing between object types. E.g., if a PDF
233 // handler was installed between the last load of this object and now, we
234 // might change from eType_Document -> eType_Plugin without changing
235 // ContentType
236 eParamContentTypeChanged = 1u << 2
240 * Configure fallback for deprecated plugin and broken elements.
242 void ConfigureFallback();
245 * Internal version of LoadObject that should only be used by this class
246 * aLoadingChannel is passed by the LoadObject call from OnStartRequest,
247 * primarily for sanity-preservation
249 nsresult LoadObject(bool aNotify, bool aForceLoad,
250 nsIRequest* aLoadingChannel);
253 * Inspects the object and sets the following member variables:
254 * - mOriginalContentType : This is the type attribute on the element
255 * - mOriginalURI : The src or data attribute on the element
256 * - mURI : The final URI, considering mChannel if
257 * mChannelLoaded is set
258 * - mContentType : The final content type, considering mChannel if
259 * mChannelLoaded is set
260 * - mBaseURI : The object's base URI, which may be set by the
261 * object
262 * - mType : The type the object is determined to be based
263 * on the above
265 * NOTE The class assumes that mType is the currently loaded type at various
266 * points, so the caller of this function must take the appropriate
267 * actions to ensure this
269 * NOTE This function does not perform security checks, only determining the
270 * requested type and parameters of the object.
272 * @return Returns a bitmask of ParameterUpdateFlags values
274 ParameterUpdateFlags UpdateObjectParameters();
276 public:
277 bool IsAboutBlankLoadOntoInitialAboutBlank(nsIURI* aURI,
278 bool aInheritPrincipal,
279 nsIPrincipal* aPrincipalToInherit);
281 private:
283 * Opens the channel pointed to by mURI into mChannel.
285 nsresult OpenChannel();
288 * Closes and releases references to mChannel and, if opened, mFinalListener
290 nsresult CloseChannel();
293 * If this object should be tested against blocking list.
295 bool ShouldBlockContent();
298 * This method tells the final answer on whether this object's fallback
299 * content should be used instead of the original plugin content.
301 * @param aIsPluginClickToPlay Whether this object instance is CTP.
303 bool PreferFallback(bool aIsPluginClickToPlay);
306 * Helper to check if our current URI passes policy
308 * @param aContentPolicy [out] The result of the content policy decision
310 * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
312 bool CheckLoadPolicy(int16_t* aContentPolicy);
315 * Helper to check if the object passes process policy. Assumes we have a
316 * final determined type.
318 * @param aContentPolicy [out] The result of the content policy decision
320 * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
322 bool CheckProcessPolicy(int16_t* aContentPolicy);
324 void SetupFrameLoader();
327 * Helper to spawn mFrameLoader and return a pointer to its docshell
329 * @param aURI URI we intend to load for the recursive load check (does not
330 * actually load anything)
332 already_AddRefed<nsIDocShell> SetupDocShell(nsIURI* aRecursionCheckURI);
335 * Unloads all content and resets the object to a completely unloaded state
337 * NOTE Calls StopPluginInstance() and may spin the event loop
339 * @param aResetState Reset the object type to 'loading' and destroy channel
340 * as well
342 void UnloadObject(bool aResetState = true);
345 * Notifies document observes about a new type/state of this object.
346 * Triggers frame construction as needed. mType must be set correctly when
347 * this method is called. This method is cheap if the type and state didn't
348 * actually change.
350 * @param aNotify if false, only need to update the state of our element.
352 void NotifyStateChanged(ObjectType aOldType, bool aNotify);
355 * Returns a ObjectType value corresponding to the type of content we would
356 * support the given MIME type as, taking capabilities and plugin state
357 * into account
359 * @return The ObjectType enum value that we would attempt to load
361 * NOTE this does not consider whether the content would be suppressed by
362 * click-to-play or other content policy checks
364 ObjectType GetTypeOfContent(const nsCString& aMIMEType);
367 * Used for identifying whether we can rewrite a youtube flash embed to
368 * possibly use HTML5 instead.
370 * Returns true if plugin.rewrite_youtube_embeds pref is true and the
371 * element this nsObjectLoadingContent instance represents:
373 * - is an embed or object node
374 * - has a URL pointing at the youtube.com domain, using "/v/" style video
375 * path reference.
377 * Having the enablejsapi flag means the document that contains the element
378 * could possibly be manipulating the youtube video elsewhere on the page
379 * via javascript. In the context of embed elements, this usage has been
380 * deprecated by youtube, so we can just rewrite as normal.
382 * If we can rewrite the URL, we change the "/v/" to "/embed/", and change
383 * our type to eType_Document so that we render similarly to an iframe
384 * embed.
386 void MaybeRewriteYoutubeEmbed(nsIURI* aURI, nsIURI* aBaseURI,
387 nsIURI** aRewrittenURI);
389 // Utility for firing an error event, if we're an <object>.
390 void MaybeFireErrorEvent();
393 * Store feature policy in container browsing context so that it can be
394 * accessed cross process.
396 void MaybeStoreCrossOriginFeaturePolicy();
398 // The final listener for mChannel (uriloader, pluginstreamlistener, etc.)
399 nsCOMPtr<nsIStreamListener> mFinalListener;
401 // The content type of our current load target, updated by
402 // UpdateObjectParameters(). Takes the channel's type into account once
403 // opened.
405 // May change if a channel is opened, does not imply a loaded state
406 nsCString mContentType;
408 // The content type 'hint' provided by the element's type attribute. May
409 // or may not be used as a final type
410 nsCString mOriginalContentType;
412 // The channel that's currently being loaded. If set, but mChannelLoaded is
413 // false, has not yet reached OnStartRequest
414 nsCOMPtr<nsIChannel> mChannel;
416 // The URI of the current content.
417 // May change as we open channels and encounter redirects - does not imply
418 // a loaded type
419 nsCOMPtr<nsIURI> mURI;
421 // The original URI obtained from inspecting the element. May differ from
422 // mURI due to redirects
423 nsCOMPtr<nsIURI> mOriginalURI;
425 // The baseURI used for constructing mURI.
426 nsCOMPtr<nsIURI> mBaseURI;
428 // Type of the currently-loaded content.
429 ObjectType mType : 8;
431 // If true, we have opened a channel as the listener and it has reached
432 // OnStartRequest. Does not get set for channels that are passed directly to
433 // the plugin listener.
434 bool mChannelLoaded : 1;
436 // True when the object is created for an element which the parser has
437 // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
438 // it may lose the flag.
439 bool mNetworkCreated : 1;
441 // Whether content blocking is enabled or not for this object.
442 bool mContentBlockingEnabled : 1;
444 // Protects DoStopPlugin from reentry (bug 724781).
445 bool mIsStopping : 1;
447 // Protects LoadObject from re-entry
448 bool mIsLoading : 1;
450 // For plugin stand-in types (click-to-play) tracks whether content js has
451 // tried to access the plugin script object.
452 bool mScriptRequested : 1;
454 // True if object represents an object/embed tag pointing to a flash embed
455 // for a youtube video. When possible (see IsRewritableYoutubeEmbed function
456 // comments for details), we change these to try to load HTML5 versions of
457 // videos.
458 bool mRewrittenYoutubeEmbed : 1;
460 bool mLoadingSyntheticDocument : 1;
462 // The intrinsic size and aspect ratio from a child SVG document that
463 // we should use. These are only set when we are an <object> or <embed>
464 // and the inner document is SVG.
466 // We store these here rather than on nsSubDocumentFrame since we are
467 // sometimes notified of our child's intrinsics before we've constructed
468 // our own frame.
469 mozilla::Maybe<mozilla::IntrinsicSize> mSubdocumentIntrinsicSize;
470 mozilla::Maybe<mozilla::AspectRatio> mSubdocumentIntrinsicRatio;
473 #endif