michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: // vim:set et cin sw=2 sts=2: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * A base class implementing nsIObjectLoadingContent for use by michael@0: * various content nodes that want to provide plugin/document/image michael@0: * loading functionality (eg , , , etc). michael@0: */ michael@0: michael@0: #ifndef NSOBJECTLOADINGCONTENT_H_ michael@0: #define NSOBJECTLOADINGCONTENT_H_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsImageLoadingContent.h" michael@0: #include "nsIStreamListener.h" michael@0: #include "nsIChannelEventSink.h" michael@0: #include "nsIObjectLoadingContent.h" michael@0: #include "nsIRunnable.h" michael@0: #include "nsIThreadInternal.h" michael@0: #include "nsIFrame.h" michael@0: #include "nsIFrameLoader.h" michael@0: michael@0: class nsAsyncInstantiateEvent; michael@0: class nsStopPluginRunnable; michael@0: class AutoSetInstantiatingToFalse; michael@0: class nsObjectFrame; michael@0: class nsFrameLoader; michael@0: class nsXULElement; michael@0: class nsPluginInstanceOwner; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: template class Sequence; michael@0: } michael@0: } michael@0: michael@0: class nsObjectLoadingContent : public nsImageLoadingContent michael@0: , public nsIStreamListener michael@0: , public nsIFrameLoaderOwner michael@0: , public nsIObjectLoadingContent michael@0: , public nsIChannelEventSink michael@0: { michael@0: friend class AutoSetInstantiatingToFalse; michael@0: friend class AutoSetLoadingToFalse; michael@0: friend class CheckPluginStopEvent; michael@0: friend class nsStopPluginRunnable; michael@0: friend class nsAsyncInstantiateEvent; michael@0: michael@0: public: michael@0: // This enum's values must be the same as the constants on michael@0: // nsIObjectLoadingContent michael@0: enum ObjectType { michael@0: // Loading, type not yet known. We may be waiting for a channel to open. michael@0: eType_Loading = TYPE_LOADING, michael@0: // Content is a *non-svg* image michael@0: eType_Image = TYPE_IMAGE, michael@0: // Content is a plugin michael@0: eType_Plugin = TYPE_PLUGIN, michael@0: // Content is a subdocument, possibly SVG michael@0: eType_Document = TYPE_DOCUMENT, michael@0: // No content loaded (fallback). May be showing alternate content or michael@0: // a custom error handler - *including* click-to-play dialogs michael@0: eType_Null = TYPE_NULL michael@0: }; michael@0: enum FallbackType { michael@0: // The content type is not supported (e.g. plugin not installed) michael@0: eFallbackUnsupported = nsIObjectLoadingContent::PLUGIN_UNSUPPORTED, michael@0: // Showing alternate content michael@0: eFallbackAlternate = nsIObjectLoadingContent::PLUGIN_ALTERNATE, michael@0: // The plugin exists, but is disabled michael@0: eFallbackDisabled = nsIObjectLoadingContent::PLUGIN_DISABLED, michael@0: // The plugin is blocklisted and disabled michael@0: eFallbackBlocklisted = nsIObjectLoadingContent::PLUGIN_BLOCKLISTED, michael@0: // The plugin is considered outdated, but not disabled michael@0: eFallbackOutdated = nsIObjectLoadingContent::PLUGIN_OUTDATED, michael@0: // The plugin has crashed michael@0: eFallbackCrashed = nsIObjectLoadingContent::PLUGIN_CRASHED, michael@0: // Suppressed by security policy michael@0: eFallbackSuppressed = nsIObjectLoadingContent::PLUGIN_SUPPRESSED, michael@0: // Blocked by content policy michael@0: eFallbackUserDisabled = nsIObjectLoadingContent::PLUGIN_USER_DISABLED, michael@0: /// ** All values >= eFallbackClickToPlay are plugin placeholder types michael@0: /// that would be replaced by a real plugin if activated (PlayPlugin()) michael@0: /// ** Furthermore, values >= eFallbackClickToPlay and michael@0: /// <= eFallbackVulnerableNoUpdate are click-to-play types. michael@0: // The plugin is disabled until the user clicks on it michael@0: eFallbackClickToPlay = nsIObjectLoadingContent::PLUGIN_CLICK_TO_PLAY, michael@0: // The plugin is vulnerable (update available) michael@0: eFallbackVulnerableUpdatable = nsIObjectLoadingContent::PLUGIN_VULNERABLE_UPDATABLE, michael@0: // The plugin is vulnerable (no update available) michael@0: eFallbackVulnerableNoUpdate = nsIObjectLoadingContent::PLUGIN_VULNERABLE_NO_UPDATE, michael@0: // The plugin is disabled and play preview content is displayed until michael@0: // the extension code enables it by sending the MozPlayPlugin event michael@0: eFallbackPlayPreview = nsIObjectLoadingContent::PLUGIN_PLAY_PREVIEW michael@0: }; michael@0: michael@0: nsObjectLoadingContent(); michael@0: virtual ~nsObjectLoadingContent(); michael@0: michael@0: NS_DECL_NSIREQUESTOBSERVER michael@0: NS_DECL_NSISTREAMLISTENER michael@0: NS_DECL_NSIFRAMELOADEROWNER michael@0: NS_DECL_NSIOBJECTLOADINGCONTENT michael@0: NS_DECL_NSICHANNELEVENTSINK michael@0: michael@0: /** michael@0: * Object state. This is a bitmask of NS_EVENT_STATEs epresenting the michael@0: * current state of the object. michael@0: */ michael@0: mozilla::EventStates ObjectState() const; michael@0: michael@0: ObjectType Type() const { return mType; } michael@0: michael@0: void SetIsNetworkCreated(bool aNetworkCreated) michael@0: { michael@0: mNetworkCreated = aNetworkCreated; michael@0: } michael@0: michael@0: /** michael@0: * Immediately instantiate a plugin instance. This is a no-op if mType != michael@0: * eType_Plugin or a plugin is already running. michael@0: * michael@0: * aIsLoading indicates that we are in the loading code, and we can bypass michael@0: * the mIsLoading check. michael@0: */ michael@0: nsresult InstantiatePluginInstance(bool aIsLoading = false); michael@0: michael@0: /** michael@0: * Notify this class the document state has changed michael@0: * Called by nsDocument so we may suspend plugins in inactive documents) michael@0: */ michael@0: void NotifyOwnerDocumentActivityChanged(); michael@0: michael@0: /** michael@0: * When a plug-in is instantiated, it can create a scriptable michael@0: * object that the page wants to interact with. We expose this michael@0: * object by placing it on the prototype chain of our element, michael@0: * between the element itself and its most-derived DOM prototype. michael@0: * michael@0: * SetupProtoChain handles actually inserting the plug-in michael@0: * scriptable object into the proto chain if needed. michael@0: * michael@0: * DoNewResolve is a hook that allows us to find out when the web michael@0: * page is looking up a property name on our object and make sure michael@0: * that our plug-in, if any, is instantiated. michael@0: */ michael@0: // Helper for WebIDL node wrapping michael@0: void SetupProtoChain(JSContext* aCx, JS::Handle aObject); michael@0: michael@0: // Remove plugin from protochain michael@0: void TeardownProtoChain(); michael@0: michael@0: // Helper for WebIDL newResolve michael@0: bool DoNewResolve(JSContext* aCx, JS::Handle aObject, michael@0: JS::Handle aId, michael@0: JS::MutableHandle aDesc); michael@0: // Helper for WebIDL enumeration michael@0: void GetOwnPropertyNames(JSContext* aCx, nsTArray& /* unused */, michael@0: mozilla::ErrorResult& aRv); michael@0: michael@0: // WebIDL API michael@0: nsIDocument* GetContentDocument(); michael@0: void GetActualType(nsAString& aType) const michael@0: { michael@0: CopyUTF8toUTF16(mContentType, aType); michael@0: } michael@0: uint32_t DisplayedType() const michael@0: { michael@0: return mType; michael@0: } michael@0: uint32_t GetContentTypeForMIMEType(const nsAString& aMIMEType) michael@0: { michael@0: return GetTypeOfContent(NS_ConvertUTF16toUTF8(aMIMEType)); michael@0: } michael@0: void PlayPlugin(mozilla::ErrorResult& aRv) michael@0: { michael@0: aRv = PlayPlugin(); michael@0: } michael@0: void Reload(bool aClearActivation, mozilla::ErrorResult& aRv) michael@0: { michael@0: aRv = Reload(aClearActivation); michael@0: } michael@0: bool Activated() const michael@0: { michael@0: return mActivated; michael@0: } michael@0: nsIURI* GetSrcURI() const michael@0: { michael@0: return mURI; michael@0: } michael@0: michael@0: /** michael@0: * The default state that this plugin would be without manual activation. michael@0: * @returns PLUGIN_ACTIVE if the default state would be active. michael@0: */ michael@0: uint32_t DefaultFallbackType(); michael@0: michael@0: uint32_t PluginFallbackType() const michael@0: { michael@0: return mFallbackType; michael@0: } michael@0: bool HasRunningPlugin() const michael@0: { michael@0: return !!mInstanceOwner; michael@0: } michael@0: void CancelPlayPreview(mozilla::ErrorResult& aRv) michael@0: { michael@0: aRv = CancelPlayPreview(); michael@0: } michael@0: void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aRv) michael@0: { michael@0: aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); michael@0: } michael@0: void LegacyCall(JSContext* aCx, JS::Handle aThisVal, michael@0: const mozilla::dom::Sequence& aArguments, michael@0: JS::MutableHandle aRetval, michael@0: mozilla::ErrorResult& aRv); michael@0: michael@0: protected: michael@0: /** michael@0: * Begins loading the object when called michael@0: * michael@0: * Attributes of |this| QI'd to nsIContent will be inspected, depending on michael@0: * the node type. This function currently assumes it is a , michael@0: * , or tag. michael@0: * michael@0: * The instantiated plugin depends on: michael@0: * - The URI (, ) michael@0: * - The type 'hint' (type attribute) michael@0: * - The mime type returned by opening the URI michael@0: * - Enabled plugins claiming the ultimate mime type michael@0: * - The capabilities returned by GetCapabilities michael@0: * - The classid attribute, if eSupportClassID is among the capabilities michael@0: * michael@0: * If eAllowPluginSkipChannel is true, we may skip opening the URI if our michael@0: * type hint points to a valid plugin, deferring that responsibility to the michael@0: * plugin. michael@0: * Similarly, if no URI is provided, but a type hint for a valid plugin is michael@0: * present, that plugin will be instantiated michael@0: * michael@0: * Otherwise a request to that URI is made and the type sent by the server michael@0: * is used to find a suitable handler, EXCEPT when: michael@0: * - The type hint refers to a *supported* plugin, in which case that michael@0: * plugin will be instantiated regardless of the server provided type michael@0: * - The server returns a binary-stream type, and our type hint refers to michael@0: * a valid non-document type, we will use the type hint michael@0: * michael@0: * @param aNotify If we should send notifications. If false, content michael@0: * loading may be deferred while appropriate frames are michael@0: * created michael@0: * @param aForceLoad If we should reload this content (and re-attempt the michael@0: * channel open) even if our parameters did not change michael@0: */ michael@0: nsresult LoadObject(bool aNotify, michael@0: bool aForceLoad = false); michael@0: michael@0: enum Capabilities { michael@0: eSupportImages = 1u << 0, // Images are supported (imgILoader) michael@0: eSupportPlugins = 1u << 1, // Plugins are supported (nsIPluginHost) michael@0: eSupportDocuments = 1u << 2, // Documents are supported michael@0: // (nsIDocumentLoaderFactory) michael@0: // This flag always includes SVG michael@0: eSupportSVG = 1u << 3, // SVG is supported (image/svg+xml) michael@0: eSupportClassID = 1u << 4, // The classid attribute is supported michael@0: michael@0: // If possible to get a *plugin* type from the type attribute *or* file michael@0: // extension, we can use that type and begin loading the plugin before michael@0: // opening a channel. michael@0: // A side effect of this is if the channel fails, the plugin is still michael@0: // running. michael@0: eAllowPluginSkipChannel = 1u << 5 michael@0: }; michael@0: michael@0: /** michael@0: * Returns the list of capabilities this content node supports. This is a michael@0: * bitmask consisting of flags from the Capabilities enum. michael@0: * michael@0: * The default implementation supports all types but not michael@0: * eSupportClassID or eAllowPluginSkipChannel michael@0: */ michael@0: virtual uint32_t GetCapabilities() const; michael@0: michael@0: /** michael@0: * Destroys all loaded documents/plugins and releases references michael@0: */ michael@0: void DestroyContent(); michael@0: michael@0: static void Traverse(nsObjectLoadingContent *tmp, michael@0: nsCycleCollectionTraversalCallback &cb); michael@0: michael@0: void CreateStaticClone(nsObjectLoadingContent* aDest) const; michael@0: michael@0: void DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner, bool aDelayedStop, michael@0: bool aForcedReentry = false); michael@0: michael@0: nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, michael@0: nsIContent* aBindingParent, michael@0: bool aCompileEventHandler); michael@0: void UnbindFromTree(bool aDeep = true, michael@0: bool aNullParent = true); michael@0: michael@0: private: michael@0: michael@0: // Object parameter changes returned by UpdateObjectParameters michael@0: enum ParameterUpdateFlags { michael@0: eParamNoChange = 0, michael@0: // Parameters that potentially affect the channel changed michael@0: // - mOriginalURI, mOriginalContentType michael@0: eParamChannelChanged = 1u << 0, michael@0: // Parameters that affect displayed content changed michael@0: // - mURI, mContentType, mType, mBaseURI michael@0: eParamStateChanged = 1u << 1, michael@0: // The effective content type changed, independant of object type. This michael@0: // can happen when changing from Loading -> Final type, but doesn't michael@0: // necessarily happen when changing between object types. E.g., if a PDF michael@0: // handler was installed between the last load of this object and now, we michael@0: // might change from eType_Document -> eType_Plugin without changing michael@0: // ContentType michael@0: eParamContentTypeChanged = 1u << 2 michael@0: }; michael@0: michael@0: /** michael@0: * Loads fallback content with the specified FallbackType michael@0: * michael@0: * @param aType FallbackType value for type of fallback we're loading michael@0: * @param aNotify Send notifications and events. If false, caller is michael@0: * responsible for doing so michael@0: */ michael@0: void LoadFallback(FallbackType aType, bool aNotify); michael@0: michael@0: /** michael@0: * Internal version of LoadObject that should only be used by this class michael@0: * aLoadingChannel is passed by the LoadObject call from OnStartRequest, michael@0: * primarily for sanity-preservation michael@0: */ michael@0: nsresult LoadObject(bool aNotify, michael@0: bool aForceLoad, michael@0: nsIRequest *aLoadingChannel); michael@0: michael@0: /** michael@0: * Introspects the object and sets the following member variables: michael@0: * - mOriginalContentType : This is the type attribute on the element michael@0: * - mOriginalURI : The src or data attribute on the element michael@0: * - mURI : The final URI, considering mChannel if michael@0: * mChannelLoaded is set michael@0: * - mContentType : The final content type, considering mChannel if michael@0: * mChannelLoaded is set michael@0: * - mBaseURI : The object's base URI, which may be set by the michael@0: * object (codebase attribute) michael@0: * - mType : The type the object is determined to be based michael@0: * on the above michael@0: * michael@0: * NOTE The class assumes that mType is the currently loaded type at various michael@0: * points, so the caller of this function must take the appropriate michael@0: * actions to ensure this michael@0: * michael@0: * NOTE This function does not perform security checks, only determining the michael@0: * requested type and parameters of the object. michael@0: * michael@0: * @param aJavaURI Specify that the URI will be consumed by java, which michael@0: * changes codebase parsing and URI construction. Used michael@0: * internally. michael@0: * michael@0: * @return Returns a bitmask of ParameterUpdateFlags values michael@0: */ michael@0: ParameterUpdateFlags UpdateObjectParameters(bool aJavaURI = false); michael@0: michael@0: /** michael@0: * Queue a CheckPluginStopEvent and track it in mPendingCheckPluginStopEvent michael@0: */ michael@0: void QueueCheckPluginStopEvent(); michael@0: michael@0: void NotifyContentObjectWrapper(); michael@0: michael@0: /** michael@0: * Opens the channel pointed to by mURI into mChannel. michael@0: */ michael@0: nsresult OpenChannel(); michael@0: michael@0: /** michael@0: * Closes and releases references to mChannel and, if opened, mFinalListener michael@0: */ michael@0: nsresult CloseChannel(); michael@0: michael@0: /** michael@0: * If this object is allowed to play plugin content, or if it would display michael@0: * click-to-play instead. michael@0: * NOTE that this does not actually check if the object is a loadable plugin michael@0: * NOTE This ignores the current activated state. The caller should check this if appropriate. michael@0: */ michael@0: bool ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentType); michael@0: michael@0: /* michael@0: * Helper to check if mBaseURI can be used by java as a codebase michael@0: */ michael@0: bool CheckJavaCodebase(); michael@0: michael@0: /** michael@0: * Helper to check if our current URI passes policy michael@0: * michael@0: * @param aContentPolicy [out] The result of the content policy decision michael@0: * michael@0: * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy) michael@0: */ michael@0: bool CheckLoadPolicy(int16_t *aContentPolicy); michael@0: michael@0: /** michael@0: * Helper to check if the object passes process policy. Assumes we have a michael@0: * final determined type. michael@0: * michael@0: * @param aContentPolicy [out] The result of the content policy decision michael@0: * michael@0: * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy) michael@0: */ michael@0: bool CheckProcessPolicy(int16_t *aContentPolicy); michael@0: michael@0: /** michael@0: * Checks whether the given type is a supported document type michael@0: * michael@0: * NOTE Does not take content policy or capabilities into account michael@0: */ michael@0: bool IsSupportedDocument(const nsCString& aType); michael@0: michael@0: /** michael@0: * Gets the plugin instance and creates a plugin stream listener, assigning michael@0: * it to mFinalListener michael@0: */ michael@0: bool MakePluginListener(); michael@0: michael@0: /** michael@0: * Unloads all content and resets the object to a completely unloaded state michael@0: * michael@0: * NOTE Calls StopPluginInstance() and may spin the event loop michael@0: * michael@0: * @param aResetState Reset the object type to 'loading' and destroy channel michael@0: * as well michael@0: */ michael@0: void UnloadObject(bool aResetState = true); michael@0: michael@0: /** michael@0: * Notifies document observes about a new type/state of this object. michael@0: * Triggers frame construction as needed. mType must be set correctly when michael@0: * this method is called. This method is cheap if the type and state didn't michael@0: * actually change. michael@0: * michael@0: * @param aSync If a synchronous frame construction is required. If false, michael@0: * the construction may either be sync or async. michael@0: * @param aNotify if false, only need to update the state of our element. michael@0: */ michael@0: void NotifyStateChanged(ObjectType aOldType, michael@0: mozilla::EventStates aOldState, michael@0: bool aSync, bool aNotify); michael@0: michael@0: /** michael@0: * Returns a ObjectType value corresponding to the type of content we would michael@0: * support the given MIME type as, taking capabilities and plugin state michael@0: * into account michael@0: * michael@0: * NOTE this does not consider whether the content would be suppressed by michael@0: * click-to-play or other content policy checks michael@0: */ michael@0: ObjectType GetTypeOfContent(const nsCString& aMIMEType); michael@0: michael@0: /** michael@0: * Gets the frame that's associated with this content node. michael@0: * Does not flush. michael@0: */ michael@0: nsObjectFrame* GetExistingFrame(); michael@0: michael@0: // Helper class for SetupProtoChain michael@0: class SetupProtoChainRunner MOZ_FINAL : public nsIRunnable michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: SetupProtoChainRunner(nsIScriptContext* scriptContext, michael@0: nsObjectLoadingContent* aContent); michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: nsCOMPtr mContext; michael@0: // We store an nsIObjectLoadingContent because we can michael@0: // unambiguously refcount that. michael@0: nsRefPtr mContent; michael@0: }; michael@0: michael@0: // Utility getter for getting our nsNPAPIPluginInstance in a safe way. michael@0: nsresult ScriptRequestPluginInstance(JSContext* aCx, michael@0: nsNPAPIPluginInstance** aResult); michael@0: michael@0: // Utility method for getting our plugin JSObject michael@0: static nsresult GetPluginJSObject(JSContext *cx, michael@0: JS::Handle obj, michael@0: nsNPAPIPluginInstance *plugin_inst, michael@0: JS::MutableHandle plugin_obj, michael@0: JS::MutableHandle plugin_proto); michael@0: michael@0: // The final listener for mChannel (uriloader, pluginstreamlistener, etc.) michael@0: nsCOMPtr mFinalListener; michael@0: michael@0: // Frame loader, for content documents we load. michael@0: nsRefPtr mFrameLoader; michael@0: michael@0: // Track if we have a pending AsyncInstantiateEvent michael@0: nsCOMPtr mPendingInstantiateEvent; michael@0: michael@0: // Tracks if we have a pending CheckPluginStopEvent michael@0: nsCOMPtr mPendingCheckPluginStopEvent; michael@0: michael@0: // The content type of our current load target, updated by michael@0: // UpdateObjectParameters(). Takes the channel's type into account once michael@0: // opened. michael@0: // michael@0: // May change if a channel is opened, does not imply a loaded state michael@0: nsCString mContentType; michael@0: michael@0: // The content type 'hint' provided by the element's type attribute. May michael@0: // or may not be used as a final type michael@0: nsCString mOriginalContentType; michael@0: michael@0: // The channel that's currently being loaded. If set, but mChannelLoaded is michael@0: // false, has not yet reached OnStartRequest michael@0: nsCOMPtr mChannel; michael@0: michael@0: // The URI of the current content. michael@0: // May change as we open channels and encounter redirects - does not imply michael@0: // a loaded type michael@0: nsCOMPtr mURI; michael@0: michael@0: // The original URI obtained from inspecting the element (codebase, and michael@0: // src/data). May differ from mURI due to redirects michael@0: nsCOMPtr mOriginalURI; michael@0: michael@0: // The baseURI used for constructing mURI, and used by some plugins (java) michael@0: // as a root for other resource requests. michael@0: nsCOMPtr mBaseURI; michael@0: michael@0: michael@0: michael@0: // Type of the currently-loaded content. michael@0: ObjectType mType : 8; michael@0: // The type of fallback content we're showing (see ObjectState()) michael@0: FallbackType mFallbackType : 8; michael@0: michael@0: // If true, we have opened a channel as the listener and it has reached michael@0: // OnStartRequest. Does not get set for channels that are passed directly to michael@0: // the plugin listener. michael@0: bool mChannelLoaded : 1; michael@0: michael@0: // Whether we are about to call instantiate on our frame. If we aren't, michael@0: // SetFrame needs to asynchronously call Instantiate. michael@0: bool mInstantiating : 1; michael@0: michael@0: // True when the object is created for an element which the parser has michael@0: // created using NS_FROM_PARSER_NETWORK flag. If the element is modified, michael@0: // it may lose the flag. michael@0: bool mNetworkCreated : 1; michael@0: michael@0: // Used to keep track of whether or not a plugin has been explicitly michael@0: // activated by PlayPlugin(). (see ShouldPlay()) michael@0: bool mActivated : 1; michael@0: michael@0: // Used to keep track of whether or not a plugin is blocked by play-preview. michael@0: bool mPlayPreviewCanceled : 1; michael@0: michael@0: // Protects DoStopPlugin from reentry (bug 724781). michael@0: bool mIsStopping : 1; michael@0: michael@0: // Protects LoadObject from re-entry michael@0: bool mIsLoading : 1; michael@0: michael@0: // For plugin stand-in types (click-to-play, play preview, ...) tracks michael@0: // whether content js has tried to access the plugin script object. michael@0: bool mScriptRequested : 1; michael@0: michael@0: nsWeakFrame mPrintFrame; michael@0: michael@0: nsRefPtr mInstanceOwner; michael@0: }; michael@0: michael@0: #endif