Bug 1206961 - Use channel->AsyncOpen2() for imageLoader; Remove security checks from callsites (r=bz)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Wed, 27 Apr 2016 19:41:13 +0200
changeset 295129 65911fba8069
parent 295128 a6e3503205e8
child 295130 bf69c3219b5e
push id75810
push usermozilla@christophkerschbaumer.com
push date2016-04-27 18:09 +0000
treeherdermozilla-inbound@bf69c3219b5e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1206961
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1206961 - Use channel->AsyncOpen2() for imageLoader; Remove security checks from callsites (r=bz)
dom/security/nsContentSecurityManager.cpp
dom/xbl/nsXBLResourceLoader.cpp
layout/style/ImageLoader.cpp
layout/xul/nsImageBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -34,45 +34,86 @@ static bool SchemeIs(nsIURI* aURI, const
 {
   nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
   NS_ENSURE_TRUE(baseURI, false);
 
   bool isScheme = false;
   return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
 }
 
+
+static bool IsImageLoadInEditorAppType(nsILoadInfo* aLoadInfo)
+{
+  // Editor apps get special treatment here, editors can load images
+  // from anywhere.  This allows editor to insert images from file://
+  // into documents that are being edited.
+  nsContentPolicyType type = aLoadInfo->InternalContentPolicyType();
+  if (type != nsIContentPolicy::TYPE_INTERNAL_IMAGE  &&
+      type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD &&
+      type != nsIContentPolicy::TYPE_IMAGESET) {
+    return false;
+  }
+
+  uint32_t appType = nsIDocShell::APP_TYPE_UNKNOWN;
+  nsINode* node = aLoadInfo->LoadingNode();
+  if (!node) {
+    return false;
+  }
+  nsIDocument* doc = node->OwnerDoc();
+  if (!doc) {
+    return false;
+  }
+
+  nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
+  if (!docShellTreeItem) {
+    return false;
+  }
+
+  nsCOMPtr<nsIDocShellTreeItem> root;
+  docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
+  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
+  if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
+    appType = nsIDocShell::APP_TYPE_UNKNOWN;
+  }
+
+  return appType == nsIDocShell::APP_TYPE_EDITOR;
+}
+
 static nsresult
 DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
 {
   // Bug 1228117: determine the correct security policy for DTD loads
   if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DTD) {
     return NS_OK;
   }
 
   nsresult rv = NS_OK;
 
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
   uint32_t flags = nsIScriptSecurityManager::STANDARD;
   if (aLoadInfo->GetAllowChrome()) {
     flags |= nsIScriptSecurityManager::ALLOW_CHROME;
   }
 
+  bool isImageInEditorType = IsImageLoadInEditorAppType(aLoadInfo);
+
   // We don't have a loadingPrincipal for TYPE_DOCUMENT
-  if (aLoadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
+  if (aLoadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT &&
+      !isImageInEditorType) {
     rv = nsContentUtils::GetSecurityManager()->
       CheckLoadURIWithPrincipal(loadingPrincipal,
                                 aURI,
                                 flags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // If the loadingPrincipal and the triggeringPrincipal are different, then make
   // sure the triggeringPrincipal is allowed to access that URI.
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = aLoadInfo->TriggeringPrincipal();
-  if (loadingPrincipal != triggeringPrincipal) {
+  if (loadingPrincipal != triggeringPrincipal && !isImageInEditorType) {
     rv = nsContentUtils::GetSecurityManager()->
            CheckLoadURIWithPrincipal(triggeringPrincipal,
                                      aURI,
                                      flags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
@@ -150,17 +191,18 @@ DoContentSecurityChecks(nsIURI* aURI, ns
 
     case nsIContentPolicy::TYPE_SCRIPT: {
       mimeTypeGuess = NS_LITERAL_CSTRING("application/javascript");
       requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_IMAGE: {
-      MOZ_ASSERT(false, "contentPolicyType not supported yet");
+      mimeTypeGuess = EmptyCString();
+      requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_STYLESHEET: {
       mimeTypeGuess = NS_LITERAL_CSTRING("text/css");
       requestingContext = aLoadInfo->LoadingNode();
       break;
     }
@@ -290,17 +332,18 @@ DoContentSecurityChecks(nsIURI* aURI, ns
 
     case nsIContentPolicy::TYPE_FETCH: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_IMAGESET: {
-      MOZ_ASSERT(false, "contentPolicyType not supported yet");
+      mimeTypeGuess = EmptyCString();
+      requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_WEB_MANIFEST: {
       mimeTypeGuess = NS_LITERAL_CSTRING("application/manifest+json");
       requestingContext = aLoadInfo->LoadingNode();
       break;
     }
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -108,21 +108,16 @@ nsXBLResourceLoader::LoadResources(bool*
     if (curr->mSrc.IsEmpty())
       continue;
 
     if (NS_FAILED(NS_NewURI(getter_AddRefs(url), curr->mSrc,
                             doc->GetDocumentCharacterSet().get(), docURL)))
       continue;
 
     if (curr->mType == nsGkAtoms::image) {
-      if (!nsContentUtils::CanLoadImage(url, doc, doc, docPrincipal)) {
-        // We're not permitted to load this image, move on...
-        continue;
-      }
-
       // Now kick off the image load...
       // Passing nullptr for pretty much everything -- cause we don't care!
       // XXX: initialDocumentURI is nullptr! 
       RefPtr<imgRequestProxy> req;
       nsContentUtils::LoadImage(url, doc, doc, docPrincipal, docURL,
                                 doc->GetReferrerPolicy(), nullptr,
                                 nsIRequest::LOAD_BACKGROUND, EmptyString(),
                                 getter_AddRefs(req));
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -252,36 +252,31 @@ ImageLoader::LoadImage(nsIURI* aURI, nsI
   NS_ASSERTION(aImage->mRequests.Count() == 0, "Huh?");
 
   aImage->mRequests.Put(nullptr, nullptr);
 
   if (!aURI) {
     return;
   }
 
-  if (!nsContentUtils::CanLoadImage(aURI, mDocument, mDocument,
-                                    aOriginPrincipal)) {
-    return;
-  }
+  RefPtr<imgRequestProxy> request;
+  nsresult rv = nsContentUtils::LoadImage(aURI, mDocument, mDocument,
+                                          aOriginPrincipal, aReferrer,
+                                          mDocument->GetReferrerPolicy(),
+                                          nullptr, nsIRequest::LOAD_NORMAL,
+                                          NS_LITERAL_STRING("css"),
+                                          getter_AddRefs(request));
 
-  RefPtr<imgRequestProxy> request;
-  nsContentUtils::LoadImage(aURI, mDocument, mDocument,
-                            aOriginPrincipal, aReferrer,
-                            mDocument->GetReferrerPolicy(),
-                            nullptr, nsIRequest::LOAD_NORMAL,
-                            NS_LITERAL_STRING("css"),
-                            getter_AddRefs(request));
-
-  if (!request) {
+  if (NS_FAILED(rv) || !request) {
     return;
   }
 
   RefPtr<imgRequestProxy> clonedRequest;
   mInClone = true;
-  nsresult rv = request->Clone(this, getter_AddRefs(clonedRequest));
+  rv = request->Clone(this, getter_AddRefs(clonedRequest));
   mInClone = false;
 
   if (NS_FAILED(rv)) {
     return;
   }
 
   aImage->mRequests.Put(nullptr, request);
   aImage->mRequests.Put(mDocument, clonedRequest);
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -228,25 +228,23 @@ nsImageBoxFrame::UpdateImage()
       return;
     }
     nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
     nsCOMPtr<nsIURI> uri;
     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
                                               src,
                                               doc,
                                               baseURI);
+    if (uri) {
+      nsresult rv = nsContentUtils::LoadImage(uri, mContent, doc, mContent->NodePrincipal(),
+                                              doc->GetDocumentURI(), doc->GetReferrerPolicy(),
+                                              mListener, mLoadFlags,
+                                              EmptyString(), getter_AddRefs(mImageRequest));
 
-    if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
-                                            mContent->NodePrincipal())) {
-      nsContentUtils::LoadImage(uri, mContent, doc, mContent->NodePrincipal(),
-                                doc->GetDocumentURI(), doc->GetReferrerPolicy(),
-                                mListener, mLoadFlags,
-                                EmptyString(), getter_AddRefs(mImageRequest));
-
-      if (mImageRequest) {
+      if (NS_SUCCEEDED(rv) && mImageRequest) {
         nsLayoutUtils::RegisterImageRequestIfAnimated(presContext,
                                                       mImageRequest,
                                                       &mRequestRegistered);
       }
     }
   } else {
     // Only get the list-style-image if we aren't being drawn
     // by a native theme.
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2183,31 +2183,27 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn
                                                 imageSrc,
                                                 doc,
                                                 baseURI);
       if (!srcURI)
         return NS_ERROR_FAILURE;
 
       // XXXbz what's the origin principal for this stuff that comes from our
       // view?  I guess we should assume that it's the node's principal...
-      if (nsContentUtils::CanLoadImage(srcURI, mContent, doc,
-                                       mContent->NodePrincipal())) {
-        nsresult rv = nsContentUtils::LoadImage(srcURI,
-                                                mContent,
-                                                doc,
-                                                mContent->NodePrincipal(),
-                                                doc->GetDocumentURI(),
-                                                doc->GetReferrerPolicy(),
-                                                imgNotificationObserver,
-                                                nsIRequest::LOAD_NORMAL,
-                                                EmptyString(),
-                                                getter_AddRefs(imageRequest));
-        NS_ENSURE_SUCCESS(rv, rv);
-                                  
-      }
+      nsresult rv = nsContentUtils::LoadImage(srcURI,
+                                              mContent,
+                                              doc,
+                                              mContent->NodePrincipal(),
+                                              doc->GetDocumentURI(),
+                                              doc->GetReferrerPolicy(),
+                                              imgNotificationObserver,
+                                              nsIRequest::LOAD_NORMAL,
+                                              EmptyString(),
+                                              getter_AddRefs(imageRequest));
+      NS_ENSURE_SUCCESS(rv, rv);
     }
     listener->UnsuppressInvalidation();
 
     if (!imageRequest)
       return NS_ERROR_FAILURE;
 
     // We don't want discarding/decode-on-draw for xul images
     imageRequest->StartDecoding();