Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef nsIScriptElement_h___ |
michael@0 | 7 | #define nsIScriptElement_h___ |
michael@0 | 8 | |
michael@0 | 9 | #include "nsISupports.h" |
michael@0 | 10 | #include "nsIURI.h" |
michael@0 | 11 | #include "nsCOMPtr.h" |
michael@0 | 12 | #include "nsIScriptLoaderObserver.h" |
michael@0 | 13 | #include "nsWeakPtr.h" |
michael@0 | 14 | #include "nsIParser.h" |
michael@0 | 15 | #include "nsContentCreatorFunctions.h" |
michael@0 | 16 | #include "nsIDOMHTMLScriptElement.h" |
michael@0 | 17 | #include "mozilla/CORSMode.h" |
michael@0 | 18 | |
michael@0 | 19 | #define NS_ISCRIPTELEMENT_IID \ |
michael@0 | 20 | { 0x491628bc, 0xce7c, 0x4db4, \ |
michael@0 | 21 | { 0x93, 0x3f, 0xce, 0x1b, 0x75, 0xee, 0x75, 0xce } } |
michael@0 | 22 | |
michael@0 | 23 | /** |
michael@0 | 24 | * Internal interface implemented by script elements |
michael@0 | 25 | */ |
michael@0 | 26 | class nsIScriptElement : public nsIScriptLoaderObserver { |
michael@0 | 27 | public: |
michael@0 | 28 | NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID) |
michael@0 | 29 | |
michael@0 | 30 | nsIScriptElement(mozilla::dom::FromParser aFromParser) |
michael@0 | 31 | : mLineNumber(0), |
michael@0 | 32 | mAlreadyStarted(false), |
michael@0 | 33 | mMalformed(false), |
michael@0 | 34 | mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER || |
michael@0 | 35 | aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), |
michael@0 | 36 | mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER || |
michael@0 | 37 | aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), |
michael@0 | 38 | mFrozen(false), |
michael@0 | 39 | mDefer(false), |
michael@0 | 40 | mAsync(false), |
michael@0 | 41 | mExternal(false), |
michael@0 | 42 | mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ? |
michael@0 | 43 | mozilla::dom::NOT_FROM_PARSER : aFromParser), |
michael@0 | 44 | // Fragment parser-created scripts (if executable) |
michael@0 | 45 | // behave like script-created scripts. |
michael@0 | 46 | mCreatorParser(nullptr) |
michael@0 | 47 | { |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | /** |
michael@0 | 51 | * Content type identifying the scripting language. Can be empty, in |
michael@0 | 52 | * which case javascript will be assumed. |
michael@0 | 53 | */ |
michael@0 | 54 | virtual void GetScriptType(nsAString& type) = 0; |
michael@0 | 55 | |
michael@0 | 56 | /** |
michael@0 | 57 | * Location of script source text. Can return null, in which case |
michael@0 | 58 | * this is assumed to be an inline script element. |
michael@0 | 59 | */ |
michael@0 | 60 | nsIURI* GetScriptURI() |
michael@0 | 61 | { |
michael@0 | 62 | NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); |
michael@0 | 63 | return mUri; |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | /** |
michael@0 | 67 | * Script source text for inline script elements. |
michael@0 | 68 | */ |
michael@0 | 69 | virtual void GetScriptText(nsAString& text) = 0; |
michael@0 | 70 | |
michael@0 | 71 | virtual void GetScriptCharset(nsAString& charset) = 0; |
michael@0 | 72 | |
michael@0 | 73 | /** |
michael@0 | 74 | * Freezes the return values of GetScriptDeferred(), GetScriptAsync() and |
michael@0 | 75 | * GetScriptURI() so that subsequent modifications to the attributes don't |
michael@0 | 76 | * change execution behavior. |
michael@0 | 77 | */ |
michael@0 | 78 | virtual void FreezeUriAsyncDefer() = 0; |
michael@0 | 79 | |
michael@0 | 80 | /** |
michael@0 | 81 | * Is the script deferred. Currently only supported by HTML scripts. |
michael@0 | 82 | */ |
michael@0 | 83 | bool GetScriptDeferred() |
michael@0 | 84 | { |
michael@0 | 85 | NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); |
michael@0 | 86 | return mDefer; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | /** |
michael@0 | 90 | * Is the script async. Currently only supported by HTML scripts. |
michael@0 | 91 | */ |
michael@0 | 92 | bool GetScriptAsync() |
michael@0 | 93 | { |
michael@0 | 94 | NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); |
michael@0 | 95 | return mAsync; |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | /** |
michael@0 | 99 | * Is the script an external script? |
michael@0 | 100 | */ |
michael@0 | 101 | bool GetScriptExternal() |
michael@0 | 102 | { |
michael@0 | 103 | NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); |
michael@0 | 104 | return mExternal; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | /** |
michael@0 | 108 | * Returns how the element was created. |
michael@0 | 109 | */ |
michael@0 | 110 | mozilla::dom::FromParser GetParserCreated() |
michael@0 | 111 | { |
michael@0 | 112 | return mParserCreated; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | void SetScriptLineNumber(uint32_t aLineNumber) |
michael@0 | 116 | { |
michael@0 | 117 | mLineNumber = aLineNumber; |
michael@0 | 118 | } |
michael@0 | 119 | uint32_t GetScriptLineNumber() |
michael@0 | 120 | { |
michael@0 | 121 | return mLineNumber; |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | void SetIsMalformed() |
michael@0 | 125 | { |
michael@0 | 126 | mMalformed = true; |
michael@0 | 127 | } |
michael@0 | 128 | bool IsMalformed() |
michael@0 | 129 | { |
michael@0 | 130 | return mMalformed; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | void PreventExecution() |
michael@0 | 134 | { |
michael@0 | 135 | mAlreadyStarted = true; |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | void LoseParserInsertedness() |
michael@0 | 139 | { |
michael@0 | 140 | mFrozen = false; |
michael@0 | 141 | mUri = nullptr; |
michael@0 | 142 | mCreatorParser = nullptr; |
michael@0 | 143 | mParserCreated = mozilla::dom::NOT_FROM_PARSER; |
michael@0 | 144 | bool async = false; |
michael@0 | 145 | nsCOMPtr<nsIDOMHTMLScriptElement> htmlScript = do_QueryInterface(this); |
michael@0 | 146 | if (htmlScript) { |
michael@0 | 147 | htmlScript->GetAsync(&async); |
michael@0 | 148 | } |
michael@0 | 149 | mForceAsync = !async; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | void SetCreatorParser(nsIParser* aParser) |
michael@0 | 153 | { |
michael@0 | 154 | mCreatorParser = do_GetWeakReference(aParser); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | /** |
michael@0 | 158 | * Unblocks the creator parser |
michael@0 | 159 | */ |
michael@0 | 160 | void UnblockParser() |
michael@0 | 161 | { |
michael@0 | 162 | nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser); |
michael@0 | 163 | if (parser) { |
michael@0 | 164 | parser->UnblockParser(); |
michael@0 | 165 | } |
michael@0 | 166 | } |
michael@0 | 167 | |
michael@0 | 168 | /** |
michael@0 | 169 | * Attempts to resume parsing asynchronously |
michael@0 | 170 | */ |
michael@0 | 171 | void ContinueParserAsync() |
michael@0 | 172 | { |
michael@0 | 173 | nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser); |
michael@0 | 174 | if (parser) { |
michael@0 | 175 | parser->ContinueInterruptedParsingAsync(); |
michael@0 | 176 | } |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | /** |
michael@0 | 180 | * Informs the creator parser that the evaluation of this script is starting |
michael@0 | 181 | */ |
michael@0 | 182 | void BeginEvaluating() |
michael@0 | 183 | { |
michael@0 | 184 | nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser); |
michael@0 | 185 | if (parser) { |
michael@0 | 186 | parser->BeginEvaluatingParserInsertedScript(); |
michael@0 | 187 | } |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | /** |
michael@0 | 191 | * Informs the creator parser that the evaluation of this script is ending |
michael@0 | 192 | */ |
michael@0 | 193 | void EndEvaluating() |
michael@0 | 194 | { |
michael@0 | 195 | nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser); |
michael@0 | 196 | if (parser) { |
michael@0 | 197 | parser->EndEvaluatingParserInsertedScript(); |
michael@0 | 198 | } |
michael@0 | 199 | } |
michael@0 | 200 | |
michael@0 | 201 | /** |
michael@0 | 202 | * Retrieves a pointer to the creator parser if this has one or null if not |
michael@0 | 203 | */ |
michael@0 | 204 | already_AddRefed<nsIParser> GetCreatorParser() |
michael@0 | 205 | { |
michael@0 | 206 | nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser); |
michael@0 | 207 | return parser.forget(); |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | /** |
michael@0 | 211 | * This method is called when the parser finishes creating the script |
michael@0 | 212 | * element's children, if any are present. |
michael@0 | 213 | * |
michael@0 | 214 | * @return whether the parser will be blocked while this script is being |
michael@0 | 215 | * loaded |
michael@0 | 216 | */ |
michael@0 | 217 | bool AttemptToExecute() |
michael@0 | 218 | { |
michael@0 | 219 | mDoneAddingChildren = true; |
michael@0 | 220 | bool block = MaybeProcessScript(); |
michael@0 | 221 | if (!mAlreadyStarted) { |
michael@0 | 222 | // Need to lose parser-insertedness here to allow another script to cause |
michael@0 | 223 | // execution later. |
michael@0 | 224 | LoseParserInsertedness(); |
michael@0 | 225 | } |
michael@0 | 226 | return block; |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | /** |
michael@0 | 230 | * Get the CORS mode of the script element |
michael@0 | 231 | */ |
michael@0 | 232 | virtual mozilla::CORSMode GetCORSMode() const |
michael@0 | 233 | { |
michael@0 | 234 | /* Default to no CORS */ |
michael@0 | 235 | return mozilla::CORS_NONE; |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | /** |
michael@0 | 239 | * Fire an error event |
michael@0 | 240 | */ |
michael@0 | 241 | virtual nsresult FireErrorEvent() = 0; |
michael@0 | 242 | |
michael@0 | 243 | protected: |
michael@0 | 244 | /** |
michael@0 | 245 | * Processes the script if it's in the document-tree and links to or |
michael@0 | 246 | * contains a script. Once it has been evaluated there is no way to make it |
michael@0 | 247 | * reevaluate the script, you'll have to create a new element. This also means |
michael@0 | 248 | * that when adding a src attribute to an element that already contains an |
michael@0 | 249 | * inline script, the script referenced by the src attribute will not be |
michael@0 | 250 | * loaded. |
michael@0 | 251 | * |
michael@0 | 252 | * In order to be able to use multiple childNodes, or to use the |
michael@0 | 253 | * fallback mechanism of using both inline script and linked script you have |
michael@0 | 254 | * to add all attributes and childNodes before adding the element to the |
michael@0 | 255 | * document-tree. |
michael@0 | 256 | * |
michael@0 | 257 | * @return whether the parser will be blocked while this script is being |
michael@0 | 258 | * loaded |
michael@0 | 259 | */ |
michael@0 | 260 | virtual bool MaybeProcessScript() = 0; |
michael@0 | 261 | |
michael@0 | 262 | /** |
michael@0 | 263 | * The start line number of the script. |
michael@0 | 264 | */ |
michael@0 | 265 | uint32_t mLineNumber; |
michael@0 | 266 | |
michael@0 | 267 | /** |
michael@0 | 268 | * The "already started" flag per HTML5. |
michael@0 | 269 | */ |
michael@0 | 270 | bool mAlreadyStarted; |
michael@0 | 271 | |
michael@0 | 272 | /** |
michael@0 | 273 | * The script didn't have an end tag. |
michael@0 | 274 | */ |
michael@0 | 275 | bool mMalformed; |
michael@0 | 276 | |
michael@0 | 277 | /** |
michael@0 | 278 | * False if parser-inserted but the parser hasn't triggered running yet. |
michael@0 | 279 | */ |
michael@0 | 280 | bool mDoneAddingChildren; |
michael@0 | 281 | |
michael@0 | 282 | /** |
michael@0 | 283 | * If true, the .async property returns true instead of reflecting the |
michael@0 | 284 | * content attribute. |
michael@0 | 285 | */ |
michael@0 | 286 | bool mForceAsync; |
michael@0 | 287 | |
michael@0 | 288 | /** |
michael@0 | 289 | * Whether src, defer and async are frozen. |
michael@0 | 290 | */ |
michael@0 | 291 | bool mFrozen; |
michael@0 | 292 | |
michael@0 | 293 | /** |
michael@0 | 294 | * The effective deferredness. |
michael@0 | 295 | */ |
michael@0 | 296 | bool mDefer; |
michael@0 | 297 | |
michael@0 | 298 | /** |
michael@0 | 299 | * The effective asyncness. |
michael@0 | 300 | */ |
michael@0 | 301 | bool mAsync; |
michael@0 | 302 | |
michael@0 | 303 | /** |
michael@0 | 304 | * The effective externalness. A script can be external with mUri being null |
michael@0 | 305 | * if the src attribute contained an invalid URL string. |
michael@0 | 306 | */ |
michael@0 | 307 | bool mExternal; |
michael@0 | 308 | |
michael@0 | 309 | /** |
michael@0 | 310 | * Whether this element was parser-created. |
michael@0 | 311 | */ |
michael@0 | 312 | mozilla::dom::FromParser mParserCreated; |
michael@0 | 313 | |
michael@0 | 314 | /** |
michael@0 | 315 | * The effective src (or null if no src). |
michael@0 | 316 | */ |
michael@0 | 317 | nsCOMPtr<nsIURI> mUri; |
michael@0 | 318 | |
michael@0 | 319 | /** |
michael@0 | 320 | * The creator parser of a non-defer, non-async parser-inserted script. |
michael@0 | 321 | */ |
michael@0 | 322 | nsWeakPtr mCreatorParser; |
michael@0 | 323 | }; |
michael@0 | 324 | |
michael@0 | 325 | NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID) |
michael@0 | 326 | |
michael@0 | 327 | #endif // nsIScriptElement_h___ |