tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsIScriptElement.h (10279B)


      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/. */
      6 
      7 #ifndef nsIScriptElement_h___
      8 #define nsIScriptElement_h___
      9 
     10 #include "js/ColumnNumber.h"  // JS::ColumnNumberOneOrigin
     11 #include "js/loader/ScriptKind.h"
     12 #include "mozilla/AlreadyAddRefed.h"
     13 #include "mozilla/Assertions.h"
     14 #include "mozilla/CORSMode.h"
     15 #include "mozilla/dom/FromParser.h"
     16 #include "nsCOMPtr.h"
     17 #include "nsID.h"
     18 #include "nsIScriptLoaderObserver.h"
     19 #include "nsIWeakReferenceUtils.h"
     20 #include "nsStringFwd.h"
     21 #include "nscore.h"
     22 
     23 // XXX Avoid including this here by moving function bodies to the cpp file
     24 #include "nsIPrincipal.h"
     25 
     26 class nsIContent;
     27 class nsIParser;
     28 class nsIPrincipal;
     29 class nsIURI;
     30 
     31 namespace mozilla::dom {
     32 class Document;
     33 enum class FetchPriority : uint8_t;
     34 enum class ReferrerPolicy : uint8_t;
     35 }  // namespace mozilla::dom
     36 
     37 // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
     38 #define NS_ISCRIPTELEMENT_IID \
     39  {0xe60fca9b, 0x1b96, 0x4e4e, {0xa9, 0xb4, 0xdc, 0x98, 0x4f, 0x88, 0x3f, 0x9c}}
     40 
     41 /**
     42 * Internal interface implemented by script elements
     43 */
     44 class nsIScriptElement : public nsIScriptLoaderObserver {
     45 public:
     46  NS_INLINE_DECL_STATIC_IID(NS_ISCRIPTELEMENT_IID)
     47 
     48  explicit nsIScriptElement(mozilla::dom::FromParser aFromParser)
     49      : mLineNumber(1),
     50        mColumnNumber(1),
     51        mAlreadyStarted(false),
     52        mMalformed(false),
     53        mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
     54                            aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
     55        mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
     56                    aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
     57        mFrozen(false),
     58        mDefer(false),
     59        mAsync(false),
     60        mExternal(false),
     61        mIsTrusted(true),
     62        mKind(JS::loader::ScriptKind::eClassic),
     63        mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT
     64                           ? mozilla::dom::NOT_FROM_PARSER
     65                           : aFromParser),
     66        // Fragment parser-created scripts (if executable)
     67        // behave like script-created scripts.
     68        mCreatorParser(nullptr) {}
     69 
     70  /**
     71   * Content type identifying the scripting language. Can be empty, in
     72   * which case javascript will be assumed.
     73   * Return false if type attribute is not found.
     74   */
     75  virtual bool GetScriptType(nsAString& type) = 0;
     76 
     77  /**
     78   * Location of script source text. Can return null, in which case
     79   * this is assumed to be an inline script element.
     80   */
     81  nsIURI* GetScriptURI() {
     82    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
     83    return mUri;
     84  }
     85 
     86  nsIPrincipal* GetScriptURITriggeringPrincipal() {
     87    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
     88    return mSrcTriggeringPrincipal;
     89  }
     90 
     91  /**
     92   * Script source text for inline script elements.
     93   */
     94  virtual void GetScriptText(nsAString& text) const = 0;
     95 
     96  virtual void GetScriptCharset(nsAString& charset) = 0;
     97 
     98  /**
     99   * Freezes the return values of the following methods so that subsequent
    100   * modifications to the attributes don't change execution behavior:
    101   *  - GetScriptIsModule()
    102   *  - GetScriptIsImportMap()
    103   *  - GetScriptDeferred()
    104   *  - GetScriptAsync()
    105   *  - GetScriptURI()
    106   *  - GetScriptExternal()
    107   */
    108  virtual void FreezeExecutionAttrs(const mozilla::dom::Document*) = 0;
    109 
    110  /**
    111   * Is the script a module script.
    112   */
    113  bool GetScriptIsModule() {
    114    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
    115    return mKind == JS::loader::ScriptKind::eModule;
    116  }
    117 
    118  /**
    119   * Is the script an import map.
    120   */
    121  bool GetScriptIsImportMap() {
    122    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
    123    return mKind == JS::loader::ScriptKind::eImportMap;
    124  }
    125 
    126  /**
    127   * Is the script deferred.
    128   */
    129  bool GetScriptDeferred() {
    130    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
    131    return mDefer;
    132  }
    133 
    134  /**
    135   * Is the script async.
    136   */
    137  bool GetScriptAsync() {
    138    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
    139    return mAsync;
    140  }
    141 
    142  /**
    143   * Is the script an external script?
    144   */
    145  bool GetScriptExternal() {
    146    MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
    147    return mExternal;
    148  }
    149 
    150  /**
    151   * Returns how the element was created.
    152   */
    153  mozilla::dom::FromParser GetParserCreated() { return mParserCreated; }
    154 
    155  void SetScriptLineNumber(uint32_t aLineNumber) { mLineNumber = aLineNumber; }
    156 
    157  uint32_t GetScriptLineNumber() { return mLineNumber; }
    158 
    159  void SetScriptColumnNumber(JS::ColumnNumberOneOrigin aColumnNumber) {
    160    mColumnNumber = aColumnNumber;
    161  }
    162 
    163  JS::ColumnNumberOneOrigin GetScriptColumnNumber() { return mColumnNumber; }
    164 
    165  void SetIsMalformed() { mMalformed = true; }
    166 
    167  bool IsMalformed() { return mMalformed; }
    168 
    169  void PreventExecution() { mAlreadyStarted = true; }
    170 
    171  void LoseParserInsertedness() {
    172    mUri = nullptr;
    173    mCreatorParser = nullptr;
    174    mParserCreated = mozilla::dom::NOT_FROM_PARSER;
    175    mForceAsync = !GetAsyncState();
    176 
    177    // Reset state set by FreezeExecutionAttrs().
    178    mFrozen = false;
    179    mExternal = false;
    180    mAsync = false;
    181    mDefer = false;
    182    mKind = JS::loader::ScriptKind::eClassic;
    183  }
    184 
    185  void SetCreatorParser(nsIParser* aParser);
    186 
    187  /**
    188   * Unblocks the creator parser
    189   */
    190  void UnblockParser();
    191 
    192  /**
    193   * Attempts to resume parsing asynchronously
    194   */
    195  void ContinueParserAsync();
    196 
    197  /**
    198   * Informs the creator parser that the evaluation of this script is starting
    199   */
    200  void BeginEvaluating();
    201 
    202  /**
    203   * Informs the creator parser that the evaluation of this script is ending
    204   */
    205  void EndEvaluating();
    206 
    207  /**
    208   * Retrieves a pointer to the creator parser if this has one or null if not
    209   */
    210  already_AddRefed<nsIParser> GetCreatorParser();
    211 
    212  /**
    213   * This method is called when the parser finishes creating the script
    214   * element's children, if any are present.
    215   *
    216   * @param aParser If non-null, a parser that can be blocked until the script
    217   *        becomes available.
    218   * @return whether a non-null aParser would be blocked while this script is
    219   *         being loaded.
    220   */
    221  bool AttemptToExecute(nsCOMPtr<nsIParser> aParser);
    222 
    223  /**
    224   * Get the CORS mode of the script element
    225   */
    226  virtual mozilla::CORSMode GetCORSMode() const {
    227    /* Default to no CORS */
    228    return mozilla::CORS_NONE;
    229  }
    230 
    231  /**
    232   * Get the fetch priority
    233   * (https://html.spec.whatwg.org/multipage/scripting.html#attr-script-fetchpriority)
    234   * of the script element.
    235   */
    236  virtual mozilla::dom::FetchPriority GetFetchPriority() const = 0;
    237 
    238  /**
    239   * Get referrer policy of the script element
    240   */
    241  virtual mozilla::dom::ReferrerPolicy GetReferrerPolicy();
    242 
    243  /**
    244   * Fire an error event
    245   */
    246  virtual nsresult FireErrorEvent() = 0;
    247 
    248  /**
    249   * This must be called on scripts with mIsTrusted set to false in
    250   * order retrieve the associated aSourceText (source text after
    251   * application of the Trusted Types's default policy).
    252   */
    253  virtual MOZ_CAN_RUN_SCRIPT nsresult
    254  GetTrustedTypesCompliantInlineScriptText(nsString& aSourceText) = 0;
    255 
    256 protected:
    257  /**
    258   * Processes the script if it's in the document-tree and links to or
    259   * contains a script. Once it has been evaluated there is no way to make it
    260   * reevaluate the script, you'll have to create a new element. This also means
    261   * that when adding a src attribute to an element that already contains an
    262   * inline script, the script referenced by the src attribute will not be
    263   * loaded.
    264   *
    265   * In order to be able to use multiple childNodes, or to use the
    266   * fallback mechanism of using both inline script and linked script you have
    267   * to add all attributes and childNodes before adding the element to the
    268   * document-tree.
    269   *
    270   * @return whether the parser will be blocked while this script is being
    271   *         loaded
    272   */
    273  virtual bool MaybeProcessScript(nsCOMPtr<nsIParser> aParser) = 0;
    274 
    275  /**
    276   * Since we've removed the XPCOM interface to HTML elements, we need a way to
    277   * retreive async state from script elements without bringing the type in.
    278   */
    279  virtual bool GetAsyncState() = 0;
    280 
    281  /**
    282   * Allow implementing elements to avoid unnecessary QueryReferences.
    283   */
    284  virtual nsIContent* GetAsContent() = 0;
    285 
    286  /**
    287   * Determine whether this is a(n) classic/module/importmap script.
    288   */
    289  void DetermineKindFromType(const mozilla::dom::Document* aOwnerDoc);
    290 
    291  bool IsClassicNonAsyncDefer();
    292 
    293  /**
    294   * The start line number of the script.
    295   */
    296  uint32_t mLineNumber;
    297 
    298  /**
    299   * The start column number of the script.
    300   */
    301  JS::ColumnNumberOneOrigin mColumnNumber;
    302 
    303  /**
    304   * The "already started" flag per HTML5.
    305   */
    306  bool mAlreadyStarted;
    307 
    308  /**
    309   * The script didn't have an end tag.
    310   */
    311  bool mMalformed;
    312 
    313  /**
    314   * False if parser-inserted but the parser hasn't triggered running yet.
    315   */
    316  bool mDoneAddingChildren;
    317 
    318  /**
    319   * If true, the .async property returns true instead of reflecting the
    320   * content attribute.
    321   */
    322  bool mForceAsync;
    323 
    324  /**
    325   * Whether src, defer and async are frozen.
    326   */
    327  bool mFrozen;
    328 
    329  /**
    330   * The effective deferredness.
    331   */
    332  bool mDefer;
    333 
    334  /**
    335   * The effective asyncness.
    336   */
    337  bool mAsync;
    338 
    339  /**
    340   * The effective externalness. A script can be external with mUri being null
    341   * if the src attribute contained an invalid URL string.
    342   */
    343  bool mExternal;
    344 
    345  /**
    346   *  Whether a script element is considered trustworthy for execution.
    347   *  https://github.com/w3c/trusted-types/pull/579
    348   */
    349  bool mIsTrusted;
    350 
    351  /**
    352   * The effective script kind.
    353   */
    354  JS::loader::ScriptKind mKind;
    355 
    356  /**
    357   * Whether this element was parser-created.
    358   */
    359  mozilla::dom::FromParser mParserCreated;
    360 
    361  /**
    362   * The effective src (or null if no src).
    363   */
    364  nsCOMPtr<nsIURI> mUri;
    365 
    366  /**
    367   * The triggering principal for the src URL.
    368   */
    369  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
    370 
    371  /**
    372   * The creator parser of a non-defer, non-async parser-inserted script.
    373   */
    374  nsWeakPtr mCreatorParser;
    375 };
    376 
    377 #endif  // nsIScriptElement_h___