Bug 464754 - nsIContentPolicy.shouldLoad() called without context for scripts. r...
[mozilla-central.git] / content / base / src / nsScriptLoader.h
bloba3074de902c1ae72c9642590251cad44dbd74c97
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications.
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Vidur Apparao <vidur@netscape.com> (original author)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 * A class that handles loading and evaluation of <script> elements.
43 #ifndef __nsScriptLoader_h__
44 #define __nsScriptLoader_h__
46 #include "nsCOMPtr.h"
47 #include "nsIScriptElement.h"
48 #include "nsIURI.h"
49 #include "nsCOMArray.h"
50 #include "nsTArray.h"
51 #include "nsAutoPtr.h"
52 #include "nsIDocument.h"
53 #include "nsIStreamLoader.h"
55 class nsScriptLoadRequest;
57 //////////////////////////////////////////////////////////////
58 // Script loader implementation
59 //////////////////////////////////////////////////////////////
61 class nsScriptLoader : public nsIStreamLoaderObserver
63 public:
64 nsScriptLoader(nsIDocument* aDocument);
65 virtual ~nsScriptLoader();
67 NS_DECL_ISUPPORTS
68 NS_DECL_NSISTREAMLOADEROBSERVER
70 /**
71 * The loader maintains a weak reference to the document with
72 * which it is initialized. This call forces the reference to
73 * be dropped.
75 void DropDocumentReference()
77 mDocument = nsnull;
80 /**
81 * Add an observer for all scripts loaded through this loader.
83 * @param aObserver observer for all script processing.
85 nsresult AddObserver(nsIScriptLoaderObserver* aObserver)
87 return mObservers.AppendObject(aObserver) ? NS_OK :
88 NS_ERROR_OUT_OF_MEMORY;
91 /**
92 * Remove an observer.
94 * @param aObserver observer to be removed
96 void RemoveObserver(nsIScriptLoaderObserver* aObserver)
98 mObservers.RemoveObject(aObserver);
102 * Process a script element. This will include both loading the
103 * source of the element if it is not inline and evaluating
104 * the script itself.
106 * If the script is an inline script that can be executed immediately
107 * (i.e. there are no other scripts pending) then ScriptAvailable
108 * and ScriptEvaluated will be called before the function returns.
110 * If NS_ERROR_HTMLPARSER_BLOCK is returned the script could not be
111 * executed immediately. In this case ScriptAvailable is guaranteed
112 * to be called at a later point (as well as possibly ScriptEvaluated).
114 * @param aElement The element representing the script to be loaded and
115 * evaluated.
117 nsresult ProcessScriptElement(nsIScriptElement* aElement);
120 * Gets the currently executing script. This is useful if you want to
121 * generate a unique key based on the currently executing script.
123 nsIScriptElement* GetCurrentScript()
125 return mCurrentScript;
129 * Whether the loader is enabled or not.
130 * When disabled, processing of new script elements is disabled.
131 * Any call to ProcessScriptElement() will fail with a return code of
132 * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
133 * currently loading or executing scripts.
135 PRBool GetEnabled()
137 return mEnabled;
139 void SetEnabled(PRBool aEnabled)
141 if (!mEnabled && aEnabled) {
142 ProcessPendingRequestsAsync();
144 mEnabled = aEnabled;
148 * Add/remove blocker. Blockers will stop scripts from executing, but not
149 * from loading.
151 void AddExecuteBlocker()
153 ++mBlockerCount;
155 void RemoveExecuteBlocker()
157 if (!--mBlockerCount) {
158 ProcessPendingRequestsAsync();
163 * Convert the given buffer to a UTF-16 string.
164 * @param aChannel Channel corresponding to the data. May be null.
165 * @param aData The data to convert
166 * @param aLength Length of the data
167 * @param aHintCharset Hint for the character set (e.g., from a charset
168 * attribute). May be the empty string.
169 * @param aDocument Document which the data is loaded for. Must not be
170 * null.
171 * @param aString [out] Data as converted to unicode
173 static nsresult ConvertToUTF16(nsIChannel* aChannel, const PRUint8* aData,
174 PRUint32 aLength,
175 const nsString& aHintCharset,
176 nsIDocument* aDocument, nsString& aString);
179 * Processes any pending requests that are ready for processing.
181 void ProcessPendingRequests();
184 * Check whether it's OK to execute a script loaded via aChannel in
185 * aDocument.
187 static PRBool ShouldExecuteScript(nsIDocument* aDocument,
188 nsIChannel* aChannel);
191 * Starts deferring deferred scripts and puts them in the mDeferredRequests
192 * queue instead.
194 void BeginDeferringScripts()
196 mDeferEnabled = PR_TRUE;
200 * Stops defering scripts and immediately processes the mDeferredRequests
201 * queue.
203 * WARNING: This function will syncronously execute content scripts, so be
204 * prepared that the world might change around you.
206 void EndDeferringScripts();
209 * Adds aURI to the preload list and starts loading it.
211 * @param aURI The URI of the external script.
212 * @param aCharset The charset parameter for the script.
213 * @param aType The type parameter for the script.
215 virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset,
216 const nsAString &aType);
218 protected:
220 * Helper function to check the content policy for a given request.
222 nsresult CheckContentPolicy(nsScriptLoadRequest *aRequest,
223 nsISupports *aContext,
224 const nsAString &aType);
227 * Start a load for aRequest's URI.
229 nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType);
232 * Process any pending requests asyncronously (i.e. off an event) if there
233 * are any. Note that this is a no-op if there aren't any currently pending
234 * requests.
236 virtual void ProcessPendingRequestsAsync();
239 * If true, the loader is ready to execute scripts, and so are all its
240 * ancestors. If the loader itself is ready but some ancestor is not, this
241 * function will add an execute blocker and ask the ancestor to remove it
242 * once it becomes ready.
244 PRBool ReadyToExecuteScripts();
247 * Return whether just this loader is ready to execute scripts.
249 PRBool SelfReadyToExecuteScripts()
251 return mEnabled && !mBlockerCount;
254 PRBool AddPendingChildLoader(nsScriptLoader* aChild) {
255 return mPendingChildLoaders.AppendElement(aChild) != nsnull;
258 nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
259 void FireScriptAvailable(nsresult aResult,
260 nsScriptLoadRequest* aRequest);
261 void FireScriptEvaluated(nsresult aResult,
262 nsScriptLoadRequest* aRequest);
263 nsresult EvaluateScript(nsScriptLoadRequest* aRequest,
264 const nsAFlatString& aScript);
266 nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
267 nsIStreamLoader* aLoader,
268 nsresult aStatus,
269 PRUint32 aStringLen,
270 const PRUint8* aString);
272 // Returns the first pending (non deferred) request
273 nsScriptLoadRequest* GetFirstPendingRequest();
275 nsIDocument* mDocument; // [WEAK]
276 nsCOMArray<nsIScriptLoaderObserver> mObservers;
277 nsCOMArray<nsScriptLoadRequest> mRequests;
279 // In mRequests, the additional information here is stored by the element.
280 struct PreloadInfo {
281 nsRefPtr<nsScriptLoadRequest> mRequest;
282 nsString mCharset;
285 struct PreloadRequestComparator {
286 PRBool Equals(const PreloadInfo &aPi, nsScriptLoadRequest * const &aRequest)
287 const
289 return aRequest == aPi.mRequest;
292 struct PreloadURIComparator {
293 PRBool Equals(const PreloadInfo &aPi, nsIURI * const &aURI) const;
295 nsTArray<PreloadInfo> mPreloads;
297 nsCOMPtr<nsIScriptElement> mCurrentScript;
298 // XXXbz do we want to cycle-collect these or something? Not sure.
299 nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
300 PRUint32 mBlockerCount;
301 PRPackedBool mEnabled;
302 PRPackedBool mDeferEnabled;
305 #endif //__nsScriptLoader_h__