diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp index 8210bc33de7d..521e4ac7d551 100644 --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -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; } diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp index 18f127fef023..47e1634e800c 100644 --- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -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 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::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 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 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 diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index 2d1c00353287..64edde509cdf 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -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(); diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 9d53ee5c9540..61cb735069d2 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -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 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 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 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 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 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 diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h index 7d62296b9bc3..b17ac5780a49 100644 --- a/netwerk/base/nsNetUtil.h +++ b/netwerk/base/nsNetUtil.h @@ -10,6 +10,7 @@ #include #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 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