gecko/content/base/src/nsObjectLoadingContent.h

420 lines
16 KiB
C
Raw Normal View History

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set et cin sw=2 sts=2:
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla <object> loading code.
*
* The Initial Developer of the Original Code is
* Christian Biesinger <cbiesinger@web.de>.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
2010-01-05 10:30:00 -08:00
* A base class implementing nsIObjectLoadingContent for use by
* various content nodes that want to provide plugin/document/image
* loading functionality (eg <embed>, <object>, <applet>, etc).
*/
#ifndef NSOBJECTLOADINGCONTENT_H_
#define NSOBJECTLOADINGCONTENT_H_
#include "nsImageLoadingContent.h"
#include "nsIStreamListener.h"
#include "nsFrameLoader.h"
#include "nsIInterfaceRequestor.h"
#include "nsIChannelEventSink.h"
#include "nsIObjectLoadingContent.h"
#include "nsIRunnable.h"
#include "nsIFrame.h"
class nsAsyncInstantiateEvent;
class AutoNotifier;
class AutoFallback;
class AutoSetInstantiatingToFalse;
enum PluginSupportState {
ePluginUnsupported, // The plugin is not supported (e.g. not installed)
ePluginDisabled, // The plugin has been explicitly disabled by the user
ePluginBlocklisted, // The plugin is blocklisted and disabled
ePluginOutdated, // The plugin is considered outdated, but not disabled
ePluginOtherState, // Something else (e.g. uninitialized or not a plugin)
ePluginCrashed
};
/**
* INVARIANTS OF THIS CLASS
* - mChannel is non-null between asyncOpen and onStopRequest (NOTE: Only needs
* to be valid until onStopRequest is called on mFinalListener, not
* necessarily until the channel calls onStopRequest on us)
* - mChannel corresponds to the channel that gets passed to the
* nsIRequestObserver/nsIStreamListener methods
* - mChannel can be cancelled and ODA calls will stop
* - mFinalListener is non-null (only) after onStartRequest has been called on
* it and before onStopRequest has been called on it
* (i.e. calling onStopRequest doesn't violate the nsIRequestObserver
* contract)
* - mFrameLoader is null while this node is not in a document (XXX this
* invariant only exists due to nsFrameLoader suckage and needs to go away)
* - mInstantiating is true while in LoadObject (it may be true in other
* cases as well). Only the function that set mInstantiating should trigger
* frame construction or notifications like ContentStatesChanged or flushes.
*/
class nsObjectLoadingContent : public nsImageLoadingContent
, public nsIStreamListener
, public nsIFrameLoaderOwner
, public nsIObjectLoadingContent
, public nsIInterfaceRequestor
, public nsIChannelEventSink
{
friend class AutoNotifier;
friend class AutoFallback;
friend class AutoSetInstantiatingToFalse;
public:
// This enum's values must be the same as the constants on
// nsIObjectLoadingContent
enum ObjectType {
eType_Loading = TYPE_LOADING, ///< Type not yet known
eType_Image = TYPE_IMAGE, ///< This content is an image
eType_Plugin = TYPE_PLUGIN, ///< This content is a plugin
eType_Document = TYPE_DOCUMENT, ///< This is a document type (e.g. HTML)
eType_Null = TYPE_NULL ///< Type can't be handled
};
nsObjectLoadingContent();
virtual ~nsObjectLoadingContent();
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIFRAMELOADEROWNER
NS_DECL_NSIOBJECTLOADINGCONTENT
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
// Fix gcc compile warnings
using nsImageLoadingContent::OnStartRequest;
using nsImageLoadingContent::OnDataAvailable;
using nsImageLoadingContent::OnStopRequest;
#endif
ObjectType Type() { return mType; }
/**
* Object state. This is a bitmask consisting of a subset of
* NS_EVENT_STATE_BROKEN, NS_EVENT_STATE_USERDISABLED and
* NS_EVENT_STATE_SUPPRESSED representing the current state of the object.
*/
nsEventStates ObjectState() const;
void SetIsNetworkCreated(PRBool aNetworkCreated)
{
mNetworkCreated = aNetworkCreated;
}
protected:
/**
* Load the object from the given URI.
* @param aURI The URI to load.
* @param aNotify If true, nsIDocumentObserver state change notifications
* will be sent as needed.
* @param aTypeHint MIME Type hint. Overridden by the server unless this
* class has the eOverrideServerType capability.
* @param aForceLoad If true, the object will be refetched even if the URI
* is the same as the currently-loaded object.
* @note Prefer the nsIURI-taking version of this function if a URI object
* is already available.
* @see the URI-taking version of this function for a detailed description
* of how a plugin will be found.
*/
nsresult LoadObject(const nsAString& aURI,
PRBool aNotify,
const nsCString& aTypeHint = EmptyCString(),
PRBool aForceLoad = PR_FALSE);
/**
* Loads the object from the given URI.
*
* The URI and type can both be null; if the URI is null a plugin will be
* instantiated in the hope that there is a <param> with a useful URI
* somewhere around. Other attributes of |this| QI'd to nsIContent will be
* inspected. This function attempts hard to find a suitable plugin.
*
* The instantiated plugin depends on three values:
* - The passed-in URI
* - The passed-in type hint
* - The classid attribute, if eSupportClassID is among the capabilities
* and such an attribute is present..
*
* Supported class ID attributes override any other value.
*
* If no class ID is present and aForceType is true, the handler given by
* aTypeHint will be instantiated for this content.
* If the URI is null or not supported, and a type hint is given, the plugin
* corresponding to that type is instantiated.
*
* Otherwise a request to that URI is made and the type sent by the server
* is used to find a suitable handler.
*
* @param aForceLoad If true, the object will be refetched even if the URI
* is the same as the currently-loaded object.
*/
nsresult LoadObject(nsIURI* aURI,
PRBool aNotify,
const nsCString& aTypeHint = EmptyCString(),
PRBool aForceLoad = PR_FALSE);
enum Capabilities {
eSupportImages = PR_BIT(0), // Images are supported (imgILoader)
eSupportPlugins = PR_BIT(1), // Plugins are supported (nsIPluginHost)
eSupportDocuments = PR_BIT(2), // Documents are supported
// (nsIDocumentLoaderFactory)
// This flag always includes SVG
eSupportSVG = PR_BIT(3), // SVG is supported (image/svg+xml)
eSupportClassID = PR_BIT(4), // The classid attribute is supported
eOverrideServerType = PR_BIT(5) // The server-sent MIME type is ignored
// (ignored if no type is specified)
};
/**
* Returns the list of capabilities this content node supports. This is a
* bitmask consisting of flags from the Capabilities enum.
*
* The default implementation supports all types but no classids.
*/
virtual PRUint32 GetCapabilities() const;
/**
* Fall back to rendering the alternative content.
*/
void Fallback(PRBool aNotify);
/**
* Subclasses must call this function when they are removed from the
* document.
*
* XXX This is a temporary workaround for docshell suckyness
*/
void RemovedFromDocument();
void Traverse(nsCycleCollectionTraversalCallback &cb);
void CreateStaticClone(nsObjectLoadingContent* aDest) const;
private:
/**
* Check whether the given request represents a successful load.
*/
static PRBool IsSuccessfulRequest(nsIRequest* aRequest);
/**
* Check whether the URI can be handled internally.
*/
static PRBool CanHandleURI(nsIURI* aURI);
/**
* Checks whether the given type is a supported document type.
*/
PRBool IsSupportedDocument(const nsCString& aType);
/**
* Unload the currently loaded content. This removes all state related to
* the displayed content and sets the type to eType_Null.
* Note: This does not send any notifications.
*/
void UnloadContent();
/**
* Notifies document observes about a new type/state of this object.
* Triggers frame construction as needed. mType must be set correctly when
* this method is called. This method is cheap if the type and state didn't
* actually change.
*
* @param aSync If a synchronous frame construction is required. If false,
* the construction may either be sync or async.
*/
void NotifyStateChanged(ObjectType aOldType, nsEventStates aOldState,
PRBool aSync);
/**
* Fires the "Plugin not found" event. This function doesn't do any checks
* whether it should be fired, the caller should do that.
*/
static void FirePluginError(nsIContent* thisContent, PluginSupportState state);
ObjectType GetTypeOfContent(const nsCString& aMIMEType);
/**
* For a classid, returns the MIME type that can be used to instantiate
* a plugin for this ID.
*
* @return NS_ERROR_NOT_AVAILABLE Unsupported class ID.
*/
nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType);
/**
* Gets the base URI to be used for this object. This differs from
* nsIContent::GetBaseURI in that it takes codebase attributes into
* account.
*/
void GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI);
/**
* Gets the frame that's associated with this content node in
* presentation 0. Always returns null if the node doesn't currently
* have a frame.
*
* @param aFlush When eFlushContent will flush content notifications
* before returning a non-null value.
* When eFlushLayout will flush layout and content
* notifications before returning a non-null value.
* When eDontFlush will never flush.
*
* eFlushLayout is needed in some cases by plug-ins to ensure
* that NPP_SetWindow() gets called (from nsObjectFrame::DidReflow).
*/
enum FlushType {
eFlushContent,
eFlushLayout,
eDontFlush
};
nsIObjectFrame* GetExistingFrame(FlushType aFlushType);
/**
* Handle being blocked by a content policy. aStatus is the nsresult
* return value of the Should* call, while aRetval is what it returned in
* its out parameter.
*/
void HandleBeingBlockedByContentPolicy(nsresult aStatus,
PRInt16 aRetval);
/**
* Checks if we have a frame that's ready for instantiation, and
* if so, calls Instantiate(). Note that this can cause the frame
* to be deleted while we're instantiating the plugin.
*/
nsresult TryInstantiate(const nsACString& aMIMEType, nsIURI* aURI);
/**
* Instantiates the plugin. This differs from
* GetFrame()->Instantiate() in that it ensures that the URI will
* be non-null, and that a MIME type will be passed. Note that
* this can cause the frame to be deleted while we're
* instantiating the plugin.
*/
nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
/**
* Get the plugin support state for the given content node and MIME type.
* This is used for purposes of determining whether to fire PluginNotFound
* events etc. aContentType is the MIME type we ended up with.
*
* This should only be called if the type of this content is eType_Null.
*/
static PluginSupportState
GetPluginSupportState(nsIContent* aContent,
const nsCString& aContentType);
/**
* If the plugin for aContentType is disabled, return ePluginDisabled.
* Otherwise (including if there is no plugin for aContentType at all),
* return ePluginUnsupported.
*
* This should only be called if the type of this content is eType_Null.
*/
static PluginSupportState
GetPluginDisabledState(const nsCString& aContentType);
/**
* When there is no usable plugin available this will send UI events and
* update the AutoFallback object appropriate to the reason for there being
* no plugin available.
*/
static void
UpdateFallbackState(nsIContent* aContent, AutoFallback& fallback,
const nsCString& aTypeHint);
/**
* The final listener to ship the data to (imagelib, uriloader, etc)
*/
nsCOMPtr<nsIStreamListener> mFinalListener;
/**
* Frame loader, for content documents we load.
*/
nsRefPtr<nsFrameLoader> mFrameLoader;
/**
* A pending nsAsyncInstantiateEvent (may be null). This is a weak ref.
*/
nsIRunnable *mPendingInstantiateEvent;
/**
* The content type of the resource we were last asked to load.
*/
nsCString mContentType;
/**
* The channel that's currently being loaded. This is a weak reference.
* Non-null between asyncOpen and onStopRequest.
*/
nsIChannel* mChannel;
// The data we were last asked to load
nsCOMPtr<nsIURI> mURI;
/**
* Type of the currently-loaded content.
*/
ObjectType mType : 16;
/**
* Whether we are about to call instantiate on our frame. If we aren't,
* SetFrame needs to asynchronously call Instantiate.
*/
PRPackedBool mInstantiating : 1;
// Blocking status from content policy
PRPackedBool mUserDisabled : 1;
PRPackedBool mSuppressed : 1;
// True when the object is created for an element which the parser has
// created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
// it may lose the flag.
PRPackedBool mNetworkCreated : 1;
// A specific state that caused us to fallback
PluginSupportState mFallbackReason;
nsWeakFrame mPrintFrame;
friend class nsAsyncInstantiateEvent;
};
#endif