Bug 477979 - Add CheckLoadURI checks for more script loads. r+sr=jst
authorWladimir Palant <trev@adblockplus.org>
Wed, 11 Feb 2009 15:51:37 +0100
changeset 26472 b307ac6d68c9cd7f06cca78ef2de403b9cc6fd11
parent 26471 d0d980778f015fe27306df5fe25d689ba3610abc
child 26473 6da5efbfef2cdbda2bd3feae0ff1a8f1a560ce3e
push idunknown
push userunknown
push dateunknown
bugs477979
milestone1.9.2a1pre
Bug 477979 - Add CheckLoadURI checks for more script loads. r+sr=jst
content/base/src/nsScriptLoader.cpp
content/base/src/nsScriptLoader.h
content/xul/document/src/nsXULDocument.cpp
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -194,24 +194,25 @@ IsScriptEventHandler(nsIScriptElement *a
 
     return PR_TRUE;
   }
 
   return PR_FALSE;
 }
 
 nsresult
-nsScriptLoader::CheckContentPolicy(nsScriptLoadRequest *aRequest,
+nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
                                    nsISupports *aContext,
+                                   nsIURI *aURI,
                                    const nsAString &aType)
 {
   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
-                                          aRequest->mURI,
-                                          mDocument->NodePrincipal(),
+                                          aURI,
+                                          aDocument->NodePrincipal(),
                                           aContext,
                                           NS_LossyConvertUTF16toASCII(aType),
                                           nsnull,    //extra
                                           &shouldLoad,
                                           nsContentUtils::GetContentPolicy(),
                                           nsContentUtils::GetSecurityManager());
   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
     if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
@@ -219,30 +220,44 @@ nsScriptLoader::CheckContentPolicy(nsScr
     }
     return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
   }
 
   return NS_OK;
 }
 
 nsresult
-nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
+nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
+                                 nsISupports* aContext,
+                                 nsIURI* aURI,
+                                 const nsAString &aType)
 {
   // Check that the containing page is allowed to load this URI.
   nsresult rv = nsContentUtils::GetSecurityManager()->
-    CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), aRequest->mURI,
+    CheckLoadURIWithPrincipal(aDocument->NodePrincipal(), aURI,
                               nsIScriptSecurityManager::ALLOW_CHROME);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // After the security manager, the content-policy stuff gets a veto
+  rv = CheckContentPolicy(aDocument, aContext, aURI, aType);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
+{
   nsISupports *context = aRequest->mElement.get()
                          ? static_cast<nsISupports *>(aRequest->mElement.get())
                          : static_cast<nsISupports *>(mDocument);
-  rv = CheckContentPolicy(aRequest, context, aType);
+  nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
   nsCOMPtr<nsIStreamLoader> loader;
 
   nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetScriptGlobalObject()));
@@ -480,17 +495,17 @@ nsScriptLoader::ProcessScriptElement(nsI
       mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
     if (i != nsTArray<PreloadInfo>::NoIndex) {
       request = mPreloads[i].mRequest;
       request->mElement = aElement;
       request->mJSVersion = version;
       request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
       mPreloads.RemoveElementAt(i);
 
-      rv = CheckContentPolicy(request, aElement, type);
+      rv = CheckContentPolicy(mDocument, aElement, request->mURI, type);
       if (NS_FAILED(rv)) {
         // Note, we're dropping our last ref to request here.
         return rv;
       }
 
       if (!request->mLoading && !request->mDefer && !hadPendingRequests &&
             ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) {
         return ProcessRequest(request);
--- a/content/base/src/nsScriptLoader.h
+++ b/content/base/src/nsScriptLoader.h
@@ -176,16 +176,25 @@ public:
                                  nsIDocument* aDocument, nsString& aString);
 
   /**
    * Processes any pending requests that are ready for processing.
    */
   void ProcessPendingRequests();
 
   /**
+   * Check whether it's OK to load a script from aURI in
+   * aDocument.
+   */
+  static nsresult ShouldLoadScript(nsIDocument* aDocument,
+                                   nsISupports* aContext,
+                                   nsIURI* aURI,
+                                   const nsAString &aType);
+
+  /**
    * Check whether it's OK to execute a script loaded via aChannel in
    * aDocument.
    */
   static PRBool ShouldExecuteScript(nsIDocument* aDocument,
                                     nsIChannel* aChannel);
 
   /**
    * Starts deferring deferred scripts and puts them in the mDeferredRequests
@@ -228,19 +237,20 @@ public:
    */
   virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset,
                           const nsAString &aType);
 
 protected:
   /**
    * Helper function to check the content policy for a given request.
    */
-  nsresult CheckContentPolicy(nsScriptLoadRequest *aRequest,
-                              nsISupports *aContext,
-                              const nsAString &aType);
+  static nsresult CheckContentPolicy(nsIDocument* aDocument,
+                                     nsISupports *aContext,
+                                     nsIURI *aURI,
+                                     const nsAString &aType);
 
   /**
    * Start a load for aRequest's URI.
    */
   nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType);
 
   /**
    * Process any pending requests asynchronously (i.e. off an event) if there
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -3422,16 +3422,28 @@ nsXULDocument::LoadScript(nsXULPrototype
             rv = ExecuteScript(aScriptProto);
 
             // Ignore return value from execution, and don't block
             *aBlock = PR_FALSE;
             return NS_OK;
         }
     }
 
+    // Allow security manager and content policies to veto the load. Note that
+    // at this point we already lost context information of the script.
+    rv = nsScriptLoader::ShouldLoadScript(
+                            this,
+                            static_cast<nsIDocument*>(this),
+                            aScriptProto->mSrcURI,
+                            NS_LITERAL_STRING("application/x-javascript"));
+    if (NS_FAILED(rv)) {
+      *aBlock = PR_FALSE;
+      return rv;
+    }
+
     // Set the current script prototype so that OnStreamComplete can report
     // the right file if there are errors in the script.
     NS_ASSERTION(!mCurrentScriptProto,
                  "still loading a script when starting another load?");
     mCurrentScriptProto = aScriptProto;
 
     if (aScriptProto->mSrcLoading) {
         // Another XULDocument load has started, which is still in progress.