Bug 1761242 - Make link asset parsing accessible in nsNetUtils.h r=necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D142053
This commit is contained in:
Manuel Bucher 2022-04-01 13:45:20 +00:00
Родитель dc5bb9ccbc
Коммит 09b6c321e4
5 изменённых файлов: 178 добавлений и 178 удалений

Просмотреть файл

@ -438,18 +438,17 @@ void nsContentSink::PreloadHref(const nsAString& aHref, const nsAString& aAs,
}
nsAttrValue asAttr;
HTMLLinkElement::ParseAsValue(aAs, asAttr);
mozilla::net::ParseAsValue(aAs, asAttr);
nsAutoString mimeType;
nsAutoString notUsed;
nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
auto policyType = HTMLLinkElement::AsValueToContentPolicy(asAttr);
auto policyType = mozilla::net::AsValueToContentPolicy(asAttr);
if (policyType == nsIContentPolicy::TYPE_INVALID ||
!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, aMedia,
mDocument)) {
!mozilla::net::CheckPreloadAttrs(asAttr, mimeType, aMedia, mDocument)) {
// Ignore preload wrong or empty attributes.
HTMLLinkElement::WarnIgnoredPreload(*mDocument, *uri);
mozilla::net::WarnIgnoredPreload(*mDocument, *uri);
return;
}

Просмотреть файл

@ -148,7 +148,7 @@ bool HTMLLinkElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
if (aAttribute == nsGkAtoms::as) {
ParseAsValue(aValue, aResult);
net::ParseAsValue(aValue, aResult);
return true;
}
@ -419,79 +419,13 @@ void HTMLLinkElement::GetAs(nsAString& aResult) {
GetEnumAttr(nsGkAtoms::as, "", aResult);
}
enum ASDestination : uint8_t {
DESTINATION_INVALID,
DESTINATION_AUDIO,
DESTINATION_DOCUMENT,
DESTINATION_EMBED,
DESTINATION_FONT,
DESTINATION_IMAGE,
DESTINATION_MANIFEST,
DESTINATION_OBJECT,
DESTINATION_REPORT,
DESTINATION_SCRIPT,
DESTINATION_SERVICEWORKER,
DESTINATION_SHAREDWORKER,
DESTINATION_STYLE,
DESTINATION_TRACK,
DESTINATION_VIDEO,
DESTINATION_WORKER,
DESTINATION_XSLT,
DESTINATION_FETCH
};
static const nsAttrValue::EnumTable kAsAttributeTable[] = {
{"", DESTINATION_INVALID}, {"audio", DESTINATION_AUDIO},
{"font", DESTINATION_FONT}, {"image", DESTINATION_IMAGE},
{"script", DESTINATION_SCRIPT}, {"style", DESTINATION_STYLE},
{"track", DESTINATION_TRACK}, {"video", DESTINATION_VIDEO},
{"fetch", DESTINATION_FETCH}, {nullptr, 0}};
/* static */
void HTMLLinkElement::ParseAsValue(const nsAString& aValue,
nsAttrValue& aResult) {
DebugOnly<bool> success =
aResult.ParseEnumValue(aValue, kAsAttributeTable, false,
// default value is a empty string
// if aValue is not a value we
// understand
&kAsAttributeTable[0]);
MOZ_ASSERT(success);
}
/* static */
nsContentPolicyType HTMLLinkElement::AsValueToContentPolicy(
const nsAttrValue& aValue) {
switch (aValue.GetEnumValue()) {
case DESTINATION_INVALID:
return nsIContentPolicy::TYPE_INVALID;
case DESTINATION_AUDIO:
return nsIContentPolicy::TYPE_INTERNAL_AUDIO;
case DESTINATION_TRACK:
return nsIContentPolicy::TYPE_INTERNAL_TRACK;
case DESTINATION_VIDEO:
return nsIContentPolicy::TYPE_INTERNAL_VIDEO;
case DESTINATION_FONT:
return nsIContentPolicy::TYPE_FONT;
case DESTINATION_IMAGE:
return nsIContentPolicy::TYPE_IMAGE;
case DESTINATION_SCRIPT:
return nsIContentPolicy::TYPE_SCRIPT;
case DESTINATION_STYLE:
return nsIContentPolicy::TYPE_STYLESHEET;
case DESTINATION_FETCH:
return nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD;
}
return nsIContentPolicy::TYPE_INVALID;
}
void HTMLLinkElement::GetContentPolicyMimeTypeMedia(
nsAttrValue& aAsAttr, nsContentPolicyType& aPolicyType, nsString& aMimeType,
nsAString& aMedia) {
nsAutoString as;
GetAttr(kNameSpaceID_None, nsGkAtoms::as, as);
ParseAsValue(as, aAsAttr);
aPolicyType = AsValueToContentPolicy(aAsAttr);
net::ParseAsValue(as, aAsAttr);
aPolicyType = net::AsValueToContentPolicy(aAsAttr);
nsAutoString type;
GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
@ -542,9 +476,9 @@ void HTMLLinkElement::
GetContentPolicyMimeTypeMedia(asAttr, policyType, mimeType, media);
if (policyType == nsIContentPolicy::TYPE_INVALID ||
!CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) {
!net::CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) {
// Ignore preload with a wrong or empty as attribute.
WarnIgnoredPreload(*OwnerDoc(), *uri);
net::WarnIgnoredPreload(*OwnerDoc(), *uri);
return;
}
@ -601,11 +535,11 @@ void HTMLLinkElement::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
GetContentPolicyMimeTypeMedia(asAttr, asPolicyType, mimeType, media);
if (asPolicyType == nsIContentPolicy::TYPE_INVALID ||
!CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) {
!net::CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) {
// Ignore preload with a wrong or empty as attribute, but be sure to cancel
// the old one.
CancelPrefetchOrPreload();
WarnIgnoredPreload(*OwnerDoc(), *uri);
net::WarnIgnoredPreload(*OwnerDoc(), *uri);
return;
}
@ -623,8 +557,8 @@ void HTMLLinkElement::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
if (aName == nsGkAtoms::as) {
if (aOldValue) {
oldPolicyType = AsValueToContentPolicy(*aOldValue);
if (!CheckPreloadAttrs(*aOldValue, mimeType, media, OwnerDoc())) {
oldPolicyType = net::AsValueToContentPolicy(*aOldValue);
if (!net::CheckPreloadAttrs(*aOldValue, mimeType, media, OwnerDoc())) {
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
}
} else {
@ -638,7 +572,7 @@ void HTMLLinkElement::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
}
nsAutoString oldMimeType;
nsContentUtils::SplitMimeType(oldType, oldMimeType, notUsed);
if (CheckPreloadAttrs(asAttr, oldMimeType, media, OwnerDoc())) {
if (net::CheckPreloadAttrs(asAttr, oldMimeType, media, OwnerDoc())) {
oldPolicyType = asPolicyType;
} else {
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
@ -649,7 +583,7 @@ void HTMLLinkElement::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
if (aOldValue) {
aOldValue->ToString(oldMedia);
}
if (CheckPreloadAttrs(asAttr, mimeType, oldMedia, OwnerDoc())) {
if (net::CheckPreloadAttrs(asAttr, mimeType, oldMedia, OwnerDoc())) {
oldPolicyType = asPolicyType;
} else {
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
@ -695,95 +629,6 @@ void HTMLLinkElement::CancelPreload() {
}
}
// We will use official mime-types from:
// https://www.iana.org/assignments/media-types/media-types.xhtml#font
// We do not support old deprecated mime-types for preload feature.
// (We currectly do not support font/collection)
static uint32_t StyleLinkElementFontMimeTypesNum = 5;
static const char* StyleLinkElementFontMimeTypes[] = {
"font/otf", "font/sfnt", "font/ttf", "font/woff", "font/woff2"};
bool IsFontMimeType(const nsAString& aType) {
if (aType.IsEmpty()) {
return true;
}
for (uint32_t i = 0; i < StyleLinkElementFontMimeTypesNum; i++) {
if (aType.EqualsASCII(StyleLinkElementFontMimeTypes[i])) {
return true;
}
}
return false;
}
bool HTMLLinkElement::CheckPreloadAttrs(const nsAttrValue& aAs,
const nsAString& aType,
const nsAString& aMedia,
Document* aDocument) {
nsContentPolicyType policyType = AsValueToContentPolicy(aAs);
if (policyType == nsIContentPolicy::TYPE_INVALID) {
return false;
}
// Check if media attribute is valid.
if (!aMedia.IsEmpty()) {
RefPtr<MediaList> mediaList =
MediaList::Create(NS_ConvertUTF16toUTF8(aMedia));
if (!mediaList->Matches(*aDocument)) {
return false;
}
}
if (aType.IsEmpty()) {
return true;
}
if (policyType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD) {
return true;
}
nsAutoString type(aType);
ToLowerCase(type);
if (policyType == nsIContentPolicy::TYPE_MEDIA) {
if (aAs.GetEnumValue() == DESTINATION_TRACK) {
return type.EqualsASCII("text/vtt");
}
Maybe<MediaContainerType> mimeType = MakeMediaContainerType(aType);
if (!mimeType) {
return false;
}
DecoderDoctorDiagnostics diagnostics;
CanPlayStatus status =
DecoderTraits::CanHandleContainerType(*mimeType, &diagnostics);
// Preload if this return CANPLAY_YES and CANPLAY_MAYBE.
return status != CANPLAY_NO;
}
if (policyType == nsIContentPolicy::TYPE_FONT) {
return IsFontMimeType(type);
}
if (policyType == nsIContentPolicy::TYPE_IMAGE) {
return imgLoader::SupportImageWithMimeType(
NS_ConvertUTF16toUTF8(type), AcceptedMimeTypes::IMAGES_AND_DOCUMENTS);
}
if (policyType == nsIContentPolicy::TYPE_SCRIPT) {
return nsContentUtils::IsJavascriptMIMEType(type);
}
if (policyType == nsIContentPolicy::TYPE_STYLESHEET) {
return type.EqualsASCII("text/css");
}
return false;
}
void HTMLLinkElement::WarnIgnoredPreload(const Document& aDoc, nsIURI& aURI) {
AutoTArray<nsString, 1> params;
{
nsCString uri = nsContentUtils::TruncatedURLForDisplay(&aURI);
AppendUTF8toUTF16(uri, *params.AppendElement());
}
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, &aDoc,
nsContentUtils::eDOM_PROPERTIES,
"PreloadIgnoredInvalidAttr", params);
}
bool HTMLLinkElement::IsCSSMimeTypeAttributeForLinkElement(
const Element& aSelf) {
// Processing the type attribute per

Просмотреть файл

@ -115,9 +115,6 @@ class HTMLLinkElement final : public nsGenericHTMLElement,
SetAttr(nsGkAtoms::as, aAs, aRv);
}
static void ParseAsValue(const nsAString& aValue, nsAttrValue& aResult);
static nsContentPolicyType AsValueToContentPolicy(const nsAttrValue& aValue);
nsDOMTokenList* Sizes() {
if (!mSizes) {
mSizes = new nsDOMTokenList(this, nsGkAtoms::sizes);
@ -176,10 +173,6 @@ class HTMLLinkElement final : public nsGenericHTMLElement,
nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
}
static bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType,
const nsAString& aMedia, Document* aDocument);
static void WarnIgnoredPreload(const Document&, nsIURI&);
protected:
virtual ~HTMLLinkElement();

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first
#include "DecoderDoctorDiagnostics.h"
#include "HttpLog.h"
#include "nsNetUtil.h"
@ -105,6 +106,10 @@
#include "nsParserConstants.h"
#include "nsCRT.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/MediaList.h"
#include "MediaContainerType.h"
#include "DecoderTraits.h"
#include "imgLoader.h"
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
# include "nsNewMailnewsURI.h"
@ -3662,6 +3667,135 @@ nsTArray<LinkHeader> ParseLinkHeader(const nsAString& aLinkData) {
return linkHeaders;
}
// We will use official mime-types from:
// https://www.iana.org/assignments/media-types/media-types.xhtml#font
// We do not support old deprecated mime-types for preload feature.
// (We currectly do not support font/collection)
static uint32_t StyleLinkElementFontMimeTypesNum = 5;
static const char* StyleLinkElementFontMimeTypes[] = {
"font/otf", "font/sfnt", "font/ttf", "font/woff", "font/woff2"};
bool IsFontMimeType(const nsAString& aType) {
if (aType.IsEmpty()) {
return true;
}
for (uint32_t i = 0; i < StyleLinkElementFontMimeTypesNum; i++) {
if (aType.EqualsASCII(StyleLinkElementFontMimeTypes[i])) {
return true;
}
}
return false;
}
static const nsAttrValue::EnumTable kAsAttributeTable[] = {
{"", DESTINATION_INVALID}, {"audio", DESTINATION_AUDIO},
{"font", DESTINATION_FONT}, {"image", DESTINATION_IMAGE},
{"script", DESTINATION_SCRIPT}, {"style", DESTINATION_STYLE},
{"track", DESTINATION_TRACK}, {"video", DESTINATION_VIDEO},
{"fetch", DESTINATION_FETCH}, {nullptr, 0}};
void ParseAsValue(const nsAString& aValue, nsAttrValue& aResult) {
DebugOnly<bool> success =
aResult.ParseEnumValue(aValue, kAsAttributeTable, false,
// default value is a empty string
// if aValue is not a value we
// understand
&kAsAttributeTable[0]);
MOZ_ASSERT(success);
}
nsContentPolicyType AsValueToContentPolicy(const nsAttrValue& aValue) {
switch (aValue.GetEnumValue()) {
case DESTINATION_INVALID:
return nsIContentPolicy::TYPE_INVALID;
case DESTINATION_AUDIO:
return nsIContentPolicy::TYPE_INTERNAL_AUDIO;
case DESTINATION_TRACK:
return nsIContentPolicy::TYPE_INTERNAL_TRACK;
case DESTINATION_VIDEO:
return nsIContentPolicy::TYPE_INTERNAL_VIDEO;
case DESTINATION_FONT:
return nsIContentPolicy::TYPE_FONT;
case DESTINATION_IMAGE:
return nsIContentPolicy::TYPE_IMAGE;
case DESTINATION_SCRIPT:
return nsIContentPolicy::TYPE_SCRIPT;
case DESTINATION_STYLE:
return nsIContentPolicy::TYPE_STYLESHEET;
case DESTINATION_FETCH:
return nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD;
}
return nsIContentPolicy::TYPE_INVALID;
}
bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType,
const nsAString& aMedia,
mozilla::dom::Document* aDocument) {
nsContentPolicyType policyType = AsValueToContentPolicy(aAs);
if (policyType == nsIContentPolicy::TYPE_INVALID) {
return false;
}
// Check if media attribute is valid.
if (!aMedia.IsEmpty()) {
RefPtr<mozilla::dom::MediaList> mediaList =
mozilla::dom::MediaList::Create(NS_ConvertUTF16toUTF8(aMedia));
if (!mediaList->Matches(*aDocument)) {
return false;
}
}
if (aType.IsEmpty()) {
return true;
}
if (policyType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD) {
return true;
}
nsAutoString type(aType);
ToLowerCase(type);
if (policyType == nsIContentPolicy::TYPE_MEDIA) {
if (aAs.GetEnumValue() == DESTINATION_TRACK) {
return type.EqualsASCII("text/vtt");
}
Maybe<MediaContainerType> mimeType = MakeMediaContainerType(aType);
if (!mimeType) {
return false;
}
DecoderDoctorDiagnostics diagnostics;
CanPlayStatus status =
DecoderTraits::CanHandleContainerType(*mimeType, &diagnostics);
// Preload if this return CANPLAY_YES and CANPLAY_MAYBE.
return status != CANPLAY_NO;
}
if (policyType == nsIContentPolicy::TYPE_FONT) {
return IsFontMimeType(type);
}
if (policyType == nsIContentPolicy::TYPE_IMAGE) {
return imgLoader::SupportImageWithMimeType(
NS_ConvertUTF16toUTF8(type), AcceptedMimeTypes::IMAGES_AND_DOCUMENTS);
}
if (policyType == nsIContentPolicy::TYPE_SCRIPT) {
return nsContentUtils::IsJavascriptMIMEType(type);
}
if (policyType == nsIContentPolicy::TYPE_STYLESHEET) {
return type.EqualsASCII("text/css");
}
return false;
}
void WarnIgnoredPreload(const mozilla::dom::Document& aDoc, nsIURI& aURI) {
AutoTArray<nsString, 1> params;
{
nsCString uri = nsContentUtils::TruncatedURLForDisplay(&aURI);
AppendUTF8toUTF16(uri, *params.AppendElement());
}
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, &aDoc,
nsContentUtils::eDOM_PROPERTIES,
"PreloadIgnoredInvalidAttr", params);
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -10,6 +10,7 @@
#include <functional>
#include "mozilla/Maybe.h"
#include "mozilla/ResultExtensions.h"
#include "nsAttrValue.h"
#include "nsCOMPtr.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
@ -1016,6 +1017,34 @@ struct LinkHeader {
nsTArray<LinkHeader> ParseLinkHeader(const nsAString& aLinkData);
enum ASDestination : uint8_t {
DESTINATION_INVALID,
DESTINATION_AUDIO,
DESTINATION_DOCUMENT,
DESTINATION_EMBED,
DESTINATION_FONT,
DESTINATION_IMAGE,
DESTINATION_MANIFEST,
DESTINATION_OBJECT,
DESTINATION_REPORT,
DESTINATION_SCRIPT,
DESTINATION_SERVICEWORKER,
DESTINATION_SHAREDWORKER,
DESTINATION_STYLE,
DESTINATION_TRACK,
DESTINATION_VIDEO,
DESTINATION_WORKER,
DESTINATION_XSLT,
DESTINATION_FETCH
};
void ParseAsValue(const nsAString& aValue, nsAttrValue& aResult);
nsContentPolicyType AsValueToContentPolicy(const nsAttrValue& aValue);
bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType,
const nsAString& aMedia,
mozilla::dom::Document* aDocument);
void WarnIgnoredPreload(const mozilla::dom::Document&, nsIURI&);
} // namespace net
} // namespace mozilla