From 3b2211a50bd06e0c3464b07df73af3a8e0a43727 Mon Sep 17 00:00:00 2001 From: Arthur Edelstein Date: Wed, 10 May 2017 17:10:23 -0700 Subject: [PATCH] Bug 22327: Isolate Page Info media previews to content first party --- browser/base/content/pageinfo/pageInfo.js | 9 ++++ dom/base/nsContentUtils.cpp | 63 +++++++++++++++++------ dom/base/nsContentUtils.h | 7 +++ dom/html/HTMLMediaElement.cpp | 2 + dom/media/MediaResource.cpp | 2 + 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/browser/base/content/pageinfo/pageInfo.js b/browser/base/content/pageinfo/pageInfo.js index 7a6d0a0630758..fc3e3bbf83799 100644 --- a/browser/base/content/pageinfo/pageInfo.js +++ b/browser/base/content/pageinfo/pageInfo.js @@ -4,6 +4,11 @@ Components.utils.import("resource://gre/modules/LoadContextInfo.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "gSerializationHelper", + "@mozilla.org/network/serialization-helper;1", + "nsISerializationHelper"); // define a js object to implement nsITreeView function pageInfoTreeView(treeid, copycol) @@ -881,6 +886,8 @@ function makePreview(row) var newImage = new Image; newImage.id = "thepreviewimage"; + let loadingPrincipalString = gSerializationHelper.serializeToString(gDocInfo.principal); + newImage.setAttribute("loadingprincipal", loadingPrincipalString); var physWidth = 0, physHeight = 0; var width = 0, height = 0; @@ -928,6 +935,7 @@ function makePreview(row) else if (item.HTMLVideoElement && isProtocolAllowed) { newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); newImage.id = "thepreviewimage"; + newImage.setAttribute("loadingprincipal", loadingPrincipalString); newImage.src = url; newImage.controls = true; width = physWidth = item.videoWidth; @@ -939,6 +947,7 @@ function makePreview(row) else if (item.HTMLAudioElement && isProtocolAllowed) { newImage = new Audio; newImage.id = "thepreviewimage"; + newImage.setAttribute("loadingprincipal", loadingPrincipalString); newImage.src = url; newImage.controls = true; isAudio = true; diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 48f7991b233fe..f93274280f7c2 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3367,6 +3367,15 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsINode* aContext, NS_PRECONDITION(aLoadingPrincipal, "Must have a principal"); NS_PRECONDITION(aRequest, "Null out param"); + // If the image is in a chrome document and the image node has been assigned a + // "loadingprincipal" attribute, we should use that principal instead. + if (IsSystemPrincipal(aLoadingPrincipal) && aContext->IsContent()) { + nsContentPolicyType contentPolicyType; + GetContentPolicyTypeForUIImageLoading(aContext->AsContent(), + &aLoadingPrincipal, contentPolicyType); + aContentPolicyType = (int32_t) contentPolicyType; + } + imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument); if (!imgLoader) { // nothing we can do here @@ -9879,25 +9888,45 @@ nsContentUtils::GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode, { // Use the serialized loadingPrincipal from the image element. Fall back // to mContent's principal (SystemPrincipal) if not available. - aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; nsCOMPtr loadingPrincipal = aLoadingNode->NodePrincipal(); - nsAutoString imageLoadingPrincipal; - aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal, - imageLoadingPrincipal); - if (!imageLoadingPrincipal.IsEmpty()) { - nsCOMPtr serializedPrincipal; - NS_DeserializeObject(NS_ConvertUTF16toUTF8(imageLoadingPrincipal), - getter_AddRefs(serializedPrincipal)); - loadingPrincipal = do_QueryInterface(serializedPrincipal); - - if (loadingPrincipal) { - // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for - // indicating it's a favicon loading. - aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; - } else { - // Fallback if the deserialization is failed. - loadingPrincipal = aLoadingNode->NodePrincipal(); + if (IsSystemPrincipal(loadingPrincipal)) { + aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; + nsAutoString imageLoadingPrincipal; + aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal, + imageLoadingPrincipal); + if (!imageLoadingPrincipal.IsEmpty()) { + nsCOMPtr serializedPrincipal; + NS_DeserializeObject(NS_ConvertUTF16toUTF8(imageLoadingPrincipal), + getter_AddRefs(serializedPrincipal)); + loadingPrincipal = do_QueryInterface(serializedPrincipal); + + if (loadingPrincipal) { + // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for + // indicating it's a favicon loading. + aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; + } else { + // Fallback if the deserialization is failed. + loadingPrincipal = aLoadingNode->NodePrincipal(); + } } } loadingPrincipal.forget(aLoadingPrincipal); } + +/* static */ void +nsContentUtils::ApplyCustomLoadPrincipalToChannel(Element* aElement, nsIChannel* aChannel) +{ + nsCOMPtr loadingPrincipal = aElement->NodePrincipal(); + if (loadingPrincipal && nsContentUtils::IsSystemPrincipal(loadingPrincipal)) { + nsContentPolicyType dummyContentPolicyType; + nsContentUtils::GetContentPolicyTypeForUIImageLoading( + aElement, getter_AddRefs(loadingPrincipal), dummyContentPolicyType); + NeckoOriginAttributes neckoAttrs; + neckoAttrs.InheritFromDocToNecko( + BasePrincipal::Cast(loadingPrincipal)->OriginAttributesRef()); + nsCOMPtr loadInfo = aChannel->GetLoadInfo(); + if (loadInfo) { + Unused << loadInfo->SetOriginAttributes(neckoAttrs); + } + } +} diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 3c7d9eb648a26..08c5cbf02e259 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -2746,6 +2746,13 @@ public: nsIPrincipal** aLoadingPrincipal, nsContentPolicyType& aContentPolicyType); + /** + * If aElement has a "loadprincipal" attribute, apply the origin attributes + * to the loadInfo belonging to aChannel. + */ + static void + ApplyCustomLoadPrincipalToChannel(Element* aElement, nsIChannel* aChannel); + private: static bool InitializeEventTable(); diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 4ac9bdc883523..ccc495c3650da 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -586,6 +586,8 @@ public: return; } + nsContentUtils::ApplyCustomLoadPrincipalToChannel(aElement, channel); + // The listener holds a strong reference to us. This creates a // reference cycle, once we've set mChannel, which is manually broken // in the listener's OnStartRequest method after it is finished with diff --git a/dom/media/MediaResource.cpp b/dom/media/MediaResource.cpp index d36783be7c92f..a8f600f3a6ed3 100644 --- a/dom/media/MediaResource.cpp +++ b/dom/media/MediaResource.cpp @@ -833,6 +833,8 @@ ChannelMediaResource::RecreateChannel() loadFlags); NS_ENSURE_SUCCESS(rv, rv); + nsContentUtils::ApplyCustomLoadPrincipalToChannel(element, mChannel); + // We have cached the Content-Type, which should not change. Give a hint to // the channel to avoid a sniffing failure, which would be expected because we // are probably seeking in the middle of the bitstream, and sniffing relies -- GitLab