michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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: #ifndef nsIScriptElement_h___ michael@0: #define nsIScriptElement_h___ michael@0: michael@0: #include "nsISupports.h" michael@0: #include "nsIURI.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIScriptLoaderObserver.h" michael@0: #include "nsWeakPtr.h" michael@0: #include "nsIParser.h" michael@0: #include "nsContentCreatorFunctions.h" michael@0: #include "nsIDOMHTMLScriptElement.h" michael@0: #include "mozilla/CORSMode.h" michael@0: michael@0: #define NS_ISCRIPTELEMENT_IID \ michael@0: { 0x491628bc, 0xce7c, 0x4db4, \ michael@0: { 0x93, 0x3f, 0xce, 0x1b, 0x75, 0xee, 0x75, 0xce } } michael@0: michael@0: /** michael@0: * Internal interface implemented by script elements michael@0: */ michael@0: class nsIScriptElement : public nsIScriptLoaderObserver { michael@0: public: michael@0: NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID) michael@0: michael@0: nsIScriptElement(mozilla::dom::FromParser aFromParser) michael@0: : mLineNumber(0), michael@0: mAlreadyStarted(false), michael@0: mMalformed(false), michael@0: mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER || michael@0: aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), michael@0: mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER || michael@0: aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), michael@0: mFrozen(false), michael@0: mDefer(false), michael@0: mAsync(false), michael@0: mExternal(false), michael@0: mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ? michael@0: mozilla::dom::NOT_FROM_PARSER : aFromParser), michael@0: // Fragment parser-created scripts (if executable) michael@0: // behave like script-created scripts. michael@0: mCreatorParser(nullptr) michael@0: { michael@0: } michael@0: michael@0: /** michael@0: * Content type identifying the scripting language. Can be empty, in michael@0: * which case javascript will be assumed. michael@0: */ michael@0: virtual void GetScriptType(nsAString& type) = 0; michael@0: michael@0: /** michael@0: * Location of script source text. Can return null, in which case michael@0: * this is assumed to be an inline script element. michael@0: */ michael@0: nsIURI* GetScriptURI() michael@0: { michael@0: NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); michael@0: return mUri; michael@0: } michael@0: michael@0: /** michael@0: * Script source text for inline script elements. michael@0: */ michael@0: virtual void GetScriptText(nsAString& text) = 0; michael@0: michael@0: virtual void GetScriptCharset(nsAString& charset) = 0; michael@0: michael@0: /** michael@0: * Freezes the return values of GetScriptDeferred(), GetScriptAsync() and michael@0: * GetScriptURI() so that subsequent modifications to the attributes don't michael@0: * change execution behavior. michael@0: */ michael@0: virtual void FreezeUriAsyncDefer() = 0; michael@0: michael@0: /** michael@0: * Is the script deferred. Currently only supported by HTML scripts. michael@0: */ michael@0: bool GetScriptDeferred() michael@0: { michael@0: NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); michael@0: return mDefer; michael@0: } michael@0: michael@0: /** michael@0: * Is the script async. Currently only supported by HTML scripts. michael@0: */ michael@0: bool GetScriptAsync() michael@0: { michael@0: NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); michael@0: return mAsync; michael@0: } michael@0: michael@0: /** michael@0: * Is the script an external script? michael@0: */ michael@0: bool GetScriptExternal() michael@0: { michael@0: NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); michael@0: return mExternal; michael@0: } michael@0: michael@0: /** michael@0: * Returns how the element was created. michael@0: */ michael@0: mozilla::dom::FromParser GetParserCreated() michael@0: { michael@0: return mParserCreated; michael@0: } michael@0: michael@0: void SetScriptLineNumber(uint32_t aLineNumber) michael@0: { michael@0: mLineNumber = aLineNumber; michael@0: } michael@0: uint32_t GetScriptLineNumber() michael@0: { michael@0: return mLineNumber; michael@0: } michael@0: michael@0: void SetIsMalformed() michael@0: { michael@0: mMalformed = true; michael@0: } michael@0: bool IsMalformed() michael@0: { michael@0: return mMalformed; michael@0: } michael@0: michael@0: void PreventExecution() michael@0: { michael@0: mAlreadyStarted = true; michael@0: } michael@0: michael@0: void LoseParserInsertedness() michael@0: { michael@0: mFrozen = false; michael@0: mUri = nullptr; michael@0: mCreatorParser = nullptr; michael@0: mParserCreated = mozilla::dom::NOT_FROM_PARSER; michael@0: bool async = false; michael@0: nsCOMPtr htmlScript = do_QueryInterface(this); michael@0: if (htmlScript) { michael@0: htmlScript->GetAsync(&async); michael@0: } michael@0: mForceAsync = !async; michael@0: } michael@0: michael@0: void SetCreatorParser(nsIParser* aParser) michael@0: { michael@0: mCreatorParser = do_GetWeakReference(aParser); michael@0: } michael@0: michael@0: /** michael@0: * Unblocks the creator parser michael@0: */ michael@0: void UnblockParser() michael@0: { michael@0: nsCOMPtr parser = do_QueryReferent(mCreatorParser); michael@0: if (parser) { michael@0: parser->UnblockParser(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Attempts to resume parsing asynchronously michael@0: */ michael@0: void ContinueParserAsync() michael@0: { michael@0: nsCOMPtr parser = do_QueryReferent(mCreatorParser); michael@0: if (parser) { michael@0: parser->ContinueInterruptedParsingAsync(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Informs the creator parser that the evaluation of this script is starting michael@0: */ michael@0: void BeginEvaluating() michael@0: { michael@0: nsCOMPtr parser = do_QueryReferent(mCreatorParser); michael@0: if (parser) { michael@0: parser->BeginEvaluatingParserInsertedScript(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Informs the creator parser that the evaluation of this script is ending michael@0: */ michael@0: void EndEvaluating() michael@0: { michael@0: nsCOMPtr parser = do_QueryReferent(mCreatorParser); michael@0: if (parser) { michael@0: parser->EndEvaluatingParserInsertedScript(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Retrieves a pointer to the creator parser if this has one or null if not michael@0: */ michael@0: already_AddRefed GetCreatorParser() michael@0: { michael@0: nsCOMPtr parser = do_QueryReferent(mCreatorParser); michael@0: return parser.forget(); michael@0: } michael@0: michael@0: /** michael@0: * This method is called when the parser finishes creating the script michael@0: * element's children, if any are present. michael@0: * michael@0: * @return whether the parser will be blocked while this script is being michael@0: * loaded michael@0: */ michael@0: bool AttemptToExecute() michael@0: { michael@0: mDoneAddingChildren = true; michael@0: bool block = MaybeProcessScript(); michael@0: if (!mAlreadyStarted) { michael@0: // Need to lose parser-insertedness here to allow another script to cause michael@0: // execution later. michael@0: LoseParserInsertedness(); michael@0: } michael@0: return block; michael@0: } michael@0: michael@0: /** michael@0: * Get the CORS mode of the script element michael@0: */ michael@0: virtual mozilla::CORSMode GetCORSMode() const michael@0: { michael@0: /* Default to no CORS */ michael@0: return mozilla::CORS_NONE; michael@0: } michael@0: michael@0: /** michael@0: * Fire an error event michael@0: */ michael@0: virtual nsresult FireErrorEvent() = 0; michael@0: michael@0: protected: michael@0: /** michael@0: * Processes the script if it's in the document-tree and links to or michael@0: * contains a script. Once it has been evaluated there is no way to make it michael@0: * reevaluate the script, you'll have to create a new element. This also means michael@0: * that when adding a src attribute to an element that already contains an michael@0: * inline script, the script referenced by the src attribute will not be michael@0: * loaded. michael@0: * michael@0: * In order to be able to use multiple childNodes, or to use the michael@0: * fallback mechanism of using both inline script and linked script you have michael@0: * to add all attributes and childNodes before adding the element to the michael@0: * document-tree. michael@0: * michael@0: * @return whether the parser will be blocked while this script is being michael@0: * loaded michael@0: */ michael@0: virtual bool MaybeProcessScript() = 0; michael@0: michael@0: /** michael@0: * The start line number of the script. michael@0: */ michael@0: uint32_t mLineNumber; michael@0: michael@0: /** michael@0: * The "already started" flag per HTML5. michael@0: */ michael@0: bool mAlreadyStarted; michael@0: michael@0: /** michael@0: * The script didn't have an end tag. michael@0: */ michael@0: bool mMalformed; michael@0: michael@0: /** michael@0: * False if parser-inserted but the parser hasn't triggered running yet. michael@0: */ michael@0: bool mDoneAddingChildren; michael@0: michael@0: /** michael@0: * If true, the .async property returns true instead of reflecting the michael@0: * content attribute. michael@0: */ michael@0: bool mForceAsync; michael@0: michael@0: /** michael@0: * Whether src, defer and async are frozen. michael@0: */ michael@0: bool mFrozen; michael@0: michael@0: /** michael@0: * The effective deferredness. michael@0: */ michael@0: bool mDefer; michael@0: michael@0: /** michael@0: * The effective asyncness. michael@0: */ michael@0: bool mAsync; michael@0: michael@0: /** michael@0: * The effective externalness. A script can be external with mUri being null michael@0: * if the src attribute contained an invalid URL string. michael@0: */ michael@0: bool mExternal; michael@0: michael@0: /** michael@0: * Whether this element was parser-created. michael@0: */ michael@0: mozilla::dom::FromParser mParserCreated; michael@0: michael@0: /** michael@0: * The effective src (or null if no src). michael@0: */ michael@0: nsCOMPtr mUri; michael@0: michael@0: /** michael@0: * The creator parser of a non-defer, non-async parser-inserted script. michael@0: */ michael@0: nsWeakPtr mCreatorParser; michael@0: }; michael@0: michael@0: NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID) michael@0: michael@0: #endif // nsIScriptElement_h___