content/base/src/nsObjectLoadingContent.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 // vim:set et cin sw=2 sts=2:
     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>, <applet>, etc).
    11  */
    13 #ifndef NSOBJECTLOADINGCONTENT_H_
    14 #define NSOBJECTLOADINGCONTENT_H_
    16 #include "mozilla/Attributes.h"
    17 #include "nsImageLoadingContent.h"
    18 #include "nsIStreamListener.h"
    19 #include "nsIChannelEventSink.h"
    20 #include "nsIObjectLoadingContent.h"
    21 #include "nsIRunnable.h"
    22 #include "nsIThreadInternal.h"
    23 #include "nsIFrame.h"
    24 #include "nsIFrameLoader.h"
    26 class nsAsyncInstantiateEvent;
    27 class nsStopPluginRunnable;
    28 class AutoSetInstantiatingToFalse;
    29 class nsObjectFrame;
    30 class nsFrameLoader;
    31 class nsXULElement;
    32 class nsPluginInstanceOwner;
    34 namespace mozilla {
    35 namespace dom {
    36 template<typename T> class Sequence;
    37 }
    38 }
    40 class nsObjectLoadingContent : public nsImageLoadingContent
    41                              , public nsIStreamListener
    42                              , public nsIFrameLoaderOwner
    43                              , public nsIObjectLoadingContent
    44                              , public nsIChannelEventSink
    45 {
    46   friend class AutoSetInstantiatingToFalse;
    47   friend class AutoSetLoadingToFalse;
    48   friend class CheckPluginStopEvent;
    49   friend class nsStopPluginRunnable;
    50   friend class nsAsyncInstantiateEvent;
    52   public:
    53     // This enum's values must be the same as the constants on
    54     // nsIObjectLoadingContent
    55     enum ObjectType {
    56       // Loading, type not yet known. We may be waiting for a channel to open.
    57       eType_Loading        = TYPE_LOADING,
    58       // Content is a *non-svg* image
    59       eType_Image          = TYPE_IMAGE,
    60       // Content is a plugin
    61       eType_Plugin         = TYPE_PLUGIN,
    62       // Content is a subdocument, possibly SVG
    63       eType_Document       = TYPE_DOCUMENT,
    64       // No content loaded (fallback). May be showing alternate content or
    65       // a custom error handler - *including* click-to-play dialogs
    66       eType_Null           = TYPE_NULL
    67     };
    68     enum FallbackType {
    69       // The content type is not supported (e.g. plugin not installed)
    70       eFallbackUnsupported = nsIObjectLoadingContent::PLUGIN_UNSUPPORTED,
    71       // Showing alternate content
    72       eFallbackAlternate = nsIObjectLoadingContent::PLUGIN_ALTERNATE,
    73       // The plugin exists, but is disabled
    74       eFallbackDisabled = nsIObjectLoadingContent::PLUGIN_DISABLED,
    75       // The plugin is blocklisted and disabled
    76       eFallbackBlocklisted = nsIObjectLoadingContent::PLUGIN_BLOCKLISTED,
    77       // The plugin is considered outdated, but not disabled
    78       eFallbackOutdated = nsIObjectLoadingContent::PLUGIN_OUTDATED,
    79       // The plugin has crashed
    80       eFallbackCrashed = nsIObjectLoadingContent::PLUGIN_CRASHED,
    81       // Suppressed by security policy
    82       eFallbackSuppressed = nsIObjectLoadingContent::PLUGIN_SUPPRESSED,
    83       // Blocked by content policy
    84       eFallbackUserDisabled = nsIObjectLoadingContent::PLUGIN_USER_DISABLED,
    85       /// ** All values >= eFallbackClickToPlay are plugin placeholder types
    86       ///    that would be replaced by a real plugin if activated (PlayPlugin())
    87       /// ** Furthermore, values >= eFallbackClickToPlay and
    88       ///    <= eFallbackVulnerableNoUpdate are click-to-play types.
    89       // The plugin is disabled until the user clicks on it
    90       eFallbackClickToPlay = nsIObjectLoadingContent::PLUGIN_CLICK_TO_PLAY,
    91       // The plugin is vulnerable (update available)
    92       eFallbackVulnerableUpdatable = nsIObjectLoadingContent::PLUGIN_VULNERABLE_UPDATABLE,
    93       // The plugin is vulnerable (no update available)
    94       eFallbackVulnerableNoUpdate = nsIObjectLoadingContent::PLUGIN_VULNERABLE_NO_UPDATE,
    95       // The plugin is disabled and play preview content is displayed until
    96       // the extension code enables it by sending the MozPlayPlugin event
    97       eFallbackPlayPreview = nsIObjectLoadingContent::PLUGIN_PLAY_PREVIEW
    98     };
   100     nsObjectLoadingContent();
   101     virtual ~nsObjectLoadingContent();
   103     NS_DECL_NSIREQUESTOBSERVER
   104     NS_DECL_NSISTREAMLISTENER
   105     NS_DECL_NSIFRAMELOADEROWNER
   106     NS_DECL_NSIOBJECTLOADINGCONTENT
   107     NS_DECL_NSICHANNELEVENTSINK
   109     /**
   110      * Object state. This is a bitmask of NS_EVENT_STATEs epresenting the
   111      * current state of the object.
   112      */
   113     mozilla::EventStates ObjectState() const;
   115     ObjectType Type() const { return mType; }
   117     void SetIsNetworkCreated(bool aNetworkCreated)
   118     {
   119       mNetworkCreated = aNetworkCreated;
   120     }
   122     /**
   123      * Immediately instantiate a plugin instance. This is a no-op if mType !=
   124      * eType_Plugin or a plugin is already running.
   125      *
   126      * aIsLoading indicates that we are in the loading code, and we can bypass
   127      * the mIsLoading check.
   128      */
   129     nsresult InstantiatePluginInstance(bool aIsLoading = false);
   131     /**
   132      * Notify this class the document state has changed
   133      * Called by nsDocument so we may suspend plugins in inactive documents)
   134      */
   135     void NotifyOwnerDocumentActivityChanged();
   137     /**
   138      * When a plug-in is instantiated, it can create a scriptable
   139      * object that the page wants to interact with.  We expose this
   140      * object by placing it on the prototype chain of our element,
   141      * between the element itself and its most-derived DOM prototype.
   142      *
   143      * SetupProtoChain handles actually inserting the plug-in
   144      * scriptable object into the proto chain if needed.
   145      *
   146      * DoNewResolve is a hook that allows us to find out when the web
   147      * page is looking up a property name on our object and make sure
   148      * that our plug-in, if any, is instantiated.
   149      */
   150     // Helper for WebIDL node wrapping
   151     void SetupProtoChain(JSContext* aCx, JS::Handle<JSObject*> aObject);
   153     // Remove plugin from protochain
   154     void TeardownProtoChain();
   156     // Helper for WebIDL newResolve
   157     bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
   158                       JS::Handle<jsid> aId,
   159                       JS::MutableHandle<JSPropertyDescriptor> aDesc);
   160     // Helper for WebIDL enumeration
   161     void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& /* unused */,
   162                              mozilla::ErrorResult& aRv);
   164     // WebIDL API
   165     nsIDocument* GetContentDocument();
   166     void GetActualType(nsAString& aType) const
   167     {
   168       CopyUTF8toUTF16(mContentType, aType);
   169     }
   170     uint32_t DisplayedType() const
   171     {
   172       return mType;
   173     }
   174     uint32_t GetContentTypeForMIMEType(const nsAString& aMIMEType)
   175     {
   176       return GetTypeOfContent(NS_ConvertUTF16toUTF8(aMIMEType));
   177     }
   178     void PlayPlugin(mozilla::ErrorResult& aRv)
   179     {
   180       aRv = PlayPlugin();
   181     }
   182     void Reload(bool aClearActivation, mozilla::ErrorResult& aRv)
   183     {
   184       aRv = Reload(aClearActivation);
   185     }
   186     bool Activated() const
   187     {
   188       return mActivated;
   189     }
   190     nsIURI* GetSrcURI() const
   191     {
   192       return mURI;
   193     }
   195     /**
   196      * The default state that this plugin would be without manual activation.
   197      * @returns PLUGIN_ACTIVE if the default state would be active.
   198      */
   199     uint32_t DefaultFallbackType();
   201     uint32_t PluginFallbackType() const
   202     {
   203       return mFallbackType;
   204     }
   205     bool HasRunningPlugin() const
   206     {
   207       return !!mInstanceOwner;
   208     }
   209     void CancelPlayPreview(mozilla::ErrorResult& aRv)
   210     {
   211       aRv = CancelPlayPreview();
   212     }
   213     void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aRv)
   214     {
   215       aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   216     }
   217     void LegacyCall(JSContext* aCx, JS::Handle<JS::Value> aThisVal,
   218                     const mozilla::dom::Sequence<JS::Value>& aArguments,
   219                     JS::MutableHandle<JS::Value> aRetval,
   220                     mozilla::ErrorResult& aRv);
   222   protected:
   223     /**
   224      * Begins loading the object when called
   225      *
   226      * Attributes of |this| QI'd to nsIContent will be inspected, depending on
   227      * the node type. This function currently assumes it is a <applet>,
   228      * <object>, or <embed> tag.
   229      *
   230      * The instantiated plugin depends on:
   231      * - The URI (<embed src>, <object data>)
   232      * - The type 'hint' (type attribute)
   233      * - The mime type returned by opening the URI
   234      * - Enabled plugins claiming the ultimate mime type
   235      * - The capabilities returned by GetCapabilities
   236      * - The classid attribute, if eSupportClassID is among the capabilities
   237      *
   238      * If eAllowPluginSkipChannel is true, we may skip opening the URI if our
   239      * type hint points to a valid plugin, deferring that responsibility to the
   240      * plugin.
   241      * Similarly, if no URI is provided, but a type hint for a valid plugin is
   242      * present, that plugin will be instantiated
   243      *
   244      * Otherwise a request to that URI is made and the type sent by the server
   245      * is used to find a suitable handler, EXCEPT when:
   246      *  - The type hint refers to a *supported* plugin, in which case that
   247      *    plugin will be instantiated regardless of the server provided type
   248      *  - The server returns a binary-stream type, and our type hint refers to
   249      *    a valid non-document type, we will use the type hint
   250      *
   251      * @param aNotify    If we should send notifications. If false, content
   252      *                   loading may be deferred while appropriate frames are
   253      *                   created
   254      * @param aForceLoad If we should reload this content (and re-attempt the
   255      *                   channel open) even if our parameters did not change
   256      */
   257     nsresult LoadObject(bool aNotify,
   258                         bool aForceLoad = false);
   260     enum Capabilities {
   261       eSupportImages       = 1u << 0, // Images are supported (imgILoader)
   262       eSupportPlugins      = 1u << 1, // Plugins are supported (nsIPluginHost)
   263       eSupportDocuments    = 1u << 2, // Documents are supported
   264                                         // (nsIDocumentLoaderFactory)
   265                                         // This flag always includes SVG
   266       eSupportSVG          = 1u << 3, // SVG is supported (image/svg+xml)
   267       eSupportClassID      = 1u << 4, // The classid attribute is supported
   269       // If possible to get a *plugin* type from the type attribute *or* file
   270       // extension, we can use that type and begin loading the plugin before
   271       // opening a channel.
   272       // A side effect of this is if the channel fails, the plugin is still
   273       // running.
   274       eAllowPluginSkipChannel  = 1u << 5
   275     };
   277     /**
   278      * Returns the list of capabilities this content node supports. This is a
   279      * bitmask consisting of flags from the Capabilities enum.
   280      *
   281      * The default implementation supports all types but not
   282      * eSupportClassID or eAllowPluginSkipChannel
   283      */
   284     virtual uint32_t GetCapabilities() const;
   286     /**
   287      * Destroys all loaded documents/plugins and releases references
   288      */
   289     void DestroyContent();
   291     static void Traverse(nsObjectLoadingContent *tmp,
   292                          nsCycleCollectionTraversalCallback &cb);
   294     void CreateStaticClone(nsObjectLoadingContent* aDest) const;
   296     void DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner, bool aDelayedStop,
   297                       bool aForcedReentry = false);
   299     nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
   300                         nsIContent* aBindingParent,
   301                         bool aCompileEventHandler);
   302     void UnbindFromTree(bool aDeep = true,
   303                         bool aNullParent = true);
   305   private:
   307     // Object parameter changes returned by UpdateObjectParameters
   308     enum ParameterUpdateFlags {
   309       eParamNoChange           = 0,
   310       // Parameters that potentially affect the channel changed
   311       // - mOriginalURI, mOriginalContentType
   312       eParamChannelChanged     = 1u << 0,
   313       // Parameters that affect displayed content changed
   314       // - mURI, mContentType, mType, mBaseURI
   315       eParamStateChanged       = 1u << 1,
   316       // The effective content type changed, independant of object type. This
   317       // can happen when changing from Loading -> Final type, but doesn't
   318       // necessarily happen when changing between object types. E.g., if a PDF
   319       // handler was installed between the last load of this object and now, we
   320       // might change from eType_Document -> eType_Plugin without changing
   321       // ContentType
   322       eParamContentTypeChanged = 1u << 2
   323     };
   325     /**
   326      * Loads fallback content with the specified FallbackType
   327      *
   328      * @param aType   FallbackType value for type of fallback we're loading
   329      * @param aNotify Send notifications and events. If false, caller is
   330      *                responsible for doing so
   331      */
   332     void LoadFallback(FallbackType aType, bool aNotify);
   334     /**
   335      * Internal version of LoadObject that should only be used by this class
   336      * aLoadingChannel is passed by the LoadObject call from OnStartRequest,
   337      * primarily for sanity-preservation
   338      */
   339     nsresult LoadObject(bool aNotify,
   340                         bool aForceLoad,
   341                         nsIRequest *aLoadingChannel);
   343     /**
   344      * Introspects the object and sets the following member variables:
   345      * - mOriginalContentType : This is the type attribute on the element
   346      * - mOriginalURI         : The src or data attribute on the element
   347      * - mURI                 : The final URI, considering mChannel if
   348      *                          mChannelLoaded is set
   349      * - mContentType         : The final content type, considering mChannel if
   350      *                          mChannelLoaded is set
   351      * - mBaseURI             : The object's base URI, which may be set by the
   352      *                          object (codebase attribute)
   353      * - mType                : The type the object is determined to be based
   354      *                          on the above
   355      * 
   356      * NOTE The class assumes that mType is the currently loaded type at various
   357      *      points, so the caller of this function must take the appropriate
   358      *      actions to ensure this
   359      * 
   360      * NOTE This function does not perform security checks, only determining the
   361      *      requested type and parameters of the object.
   362      *
   363      * @param aJavaURI Specify that the URI will be consumed by java, which
   364      *                 changes codebase parsing and URI construction. Used
   365      *                 internally.
   366      *
   367      * @return Returns a bitmask of ParameterUpdateFlags values
   368      */
   369     ParameterUpdateFlags UpdateObjectParameters(bool aJavaURI = false);
   371     /**
   372      * Queue a CheckPluginStopEvent and track it in mPendingCheckPluginStopEvent
   373      */
   374     void QueueCheckPluginStopEvent();
   376     void NotifyContentObjectWrapper();
   378     /**
   379      * Opens the channel pointed to by mURI into mChannel.
   380      */
   381     nsresult OpenChannel();
   383     /**
   384      * Closes and releases references to mChannel and, if opened, mFinalListener
   385      */
   386     nsresult CloseChannel();
   388     /**
   389      * If this object is allowed to play plugin content, or if it would display
   390      * click-to-play instead.
   391      * NOTE that this does not actually check if the object is a loadable plugin
   392      * NOTE This ignores the current activated state. The caller should check this if appropriate.
   393      */
   394     bool ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentType);
   396     /*
   397      * Helper to check if mBaseURI can be used by java as a codebase
   398      */
   399     bool CheckJavaCodebase();
   401     /**
   402      * Helper to check if our current URI passes policy
   403      *
   404      * @param aContentPolicy [out] The result of the content policy decision
   405      *
   406      * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
   407      */
   408     bool CheckLoadPolicy(int16_t *aContentPolicy);
   410     /**
   411      * Helper to check if the object passes process policy. Assumes we have a
   412      * final determined type.
   413      *
   414      * @param aContentPolicy [out] The result of the content policy decision
   415      *
   416      * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
   417      */
   418     bool CheckProcessPolicy(int16_t *aContentPolicy);
   420     /**
   421      * Checks whether the given type is a supported document type
   422      *
   423      * NOTE Does not take content policy or capabilities into account
   424      */
   425     bool IsSupportedDocument(const nsCString& aType);
   427     /**
   428      * Gets the plugin instance and creates a plugin stream listener, assigning
   429      * it to mFinalListener
   430      */
   431     bool MakePluginListener();
   433     /**
   434      * Unloads all content and resets the object to a completely unloaded state
   435      *
   436      * NOTE Calls StopPluginInstance() and may spin the event loop
   437      *
   438      * @param aResetState Reset the object type to 'loading' and destroy channel
   439      *                    as well
   440      */
   441     void UnloadObject(bool aResetState = true);
   443     /**
   444      * Notifies document observes about a new type/state of this object.
   445      * Triggers frame construction as needed. mType must be set correctly when
   446      * this method is called. This method is cheap if the type and state didn't
   447      * actually change.
   448      *
   449      * @param aSync If a synchronous frame construction is required. If false,
   450      *              the construction may either be sync or async.
   451      * @param aNotify if false, only need to update the state of our element.
   452      */
   453     void NotifyStateChanged(ObjectType aOldType,
   454                             mozilla::EventStates aOldState,
   455                             bool aSync, bool aNotify);
   457     /**
   458      * Returns a ObjectType value corresponding to the type of content we would
   459      * support the given MIME type as, taking capabilities and plugin state
   460      * into account
   461      * 
   462      * NOTE this does not consider whether the content would be suppressed by
   463      *      click-to-play or other content policy checks
   464      */
   465     ObjectType GetTypeOfContent(const nsCString& aMIMEType);
   467     /**
   468      * Gets the frame that's associated with this content node.
   469      * Does not flush.
   470      */
   471     nsObjectFrame* GetExistingFrame();
   473     // Helper class for SetupProtoChain
   474     class SetupProtoChainRunner MOZ_FINAL : public nsIRunnable
   475     {
   476     public:
   477       NS_DECL_ISUPPORTS
   479       SetupProtoChainRunner(nsIScriptContext* scriptContext,
   480                             nsObjectLoadingContent* aContent);
   482       NS_IMETHOD Run() MOZ_OVERRIDE;
   484     private:
   485       nsCOMPtr<nsIScriptContext> mContext;
   486       // We store an nsIObjectLoadingContent because we can
   487       // unambiguously refcount that.
   488       nsRefPtr<nsIObjectLoadingContent> mContent;
   489     };
   491     // Utility getter for getting our nsNPAPIPluginInstance in a safe way.
   492     nsresult ScriptRequestPluginInstance(JSContext* aCx,
   493                                          nsNPAPIPluginInstance** aResult);
   495     // Utility method for getting our plugin JSObject
   496     static nsresult GetPluginJSObject(JSContext *cx,
   497                                       JS::Handle<JSObject*> obj,
   498                                       nsNPAPIPluginInstance *plugin_inst,
   499                                       JS::MutableHandle<JSObject*> plugin_obj,
   500                                       JS::MutableHandle<JSObject*> plugin_proto);
   502     // The final listener for mChannel (uriloader, pluginstreamlistener, etc.)
   503     nsCOMPtr<nsIStreamListener> mFinalListener;
   505     // Frame loader, for content documents we load.
   506     nsRefPtr<nsFrameLoader>     mFrameLoader;
   508     // Track if we have a pending AsyncInstantiateEvent
   509     nsCOMPtr<nsIRunnable>       mPendingInstantiateEvent;
   511     // Tracks if we have a pending CheckPluginStopEvent
   512     nsCOMPtr<nsIRunnable>       mPendingCheckPluginStopEvent;
   514     // The content type of our current load target, updated by
   515     // UpdateObjectParameters(). Takes the channel's type into account once
   516     // opened.
   517     //
   518     // May change if a channel is opened, does not imply a loaded state
   519     nsCString                   mContentType;
   521     // The content type 'hint' provided by the element's type attribute. May
   522     // or may not be used as a final type
   523     nsCString                   mOriginalContentType;
   525     // The channel that's currently being loaded. If set, but mChannelLoaded is
   526     // false, has not yet reached OnStartRequest
   527     nsCOMPtr<nsIChannel>        mChannel;
   529     // The URI of the current content.
   530     // May change as we open channels and encounter redirects - does not imply
   531     // a loaded type
   532     nsCOMPtr<nsIURI>            mURI;
   534     // The original URI obtained from inspecting the element (codebase, and
   535     // src/data). May differ from mURI due to redirects
   536     nsCOMPtr<nsIURI>            mOriginalURI;
   538     // The baseURI used for constructing mURI, and used by some plugins (java)
   539     // as a root for other resource requests.
   540     nsCOMPtr<nsIURI>            mBaseURI;
   544     // Type of the currently-loaded content.
   545     ObjectType                  mType           : 8;
   546     // The type of fallback content we're showing (see ObjectState())
   547     FallbackType                mFallbackType : 8;
   549     // If true, we have opened a channel as the listener and it has reached
   550     // OnStartRequest. Does not get set for channels that are passed directly to
   551     // the plugin listener.
   552     bool                        mChannelLoaded    : 1;
   554     // Whether we are about to call instantiate on our frame. If we aren't,
   555     // SetFrame needs to asynchronously call Instantiate.
   556     bool                        mInstantiating : 1;
   558     // True when the object is created for an element which the parser has
   559     // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
   560     // it may lose the flag.
   561     bool                        mNetworkCreated : 1;
   563     // Used to keep track of whether or not a plugin has been explicitly
   564     // activated by PlayPlugin(). (see ShouldPlay())
   565     bool                        mActivated : 1;
   567     // Used to keep track of whether or not a plugin is blocked by play-preview.
   568     bool                        mPlayPreviewCanceled : 1;
   570     // Protects DoStopPlugin from reentry (bug 724781).
   571     bool                        mIsStopping : 1;
   573     // Protects LoadObject from re-entry
   574     bool                        mIsLoading : 1;
   576     // For plugin stand-in types (click-to-play, play preview, ...) tracks
   577     // whether content js has tried to access the plugin script object.
   578     bool                        mScriptRequested : 1;
   580     nsWeakFrame                 mPrintFrame;
   582     nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
   583 };
   585 #endif

mercurial