# HG changeset patch # User Dragana Damjanovic # Date 1524217620 -10800 # Node ID ccbbd0a711734c30808a2e934b5788d0907d405b # Parent 06a30ad6e5a71c5ba28197cc381850e811ad9bd2 Bug 1441246 - Move preload code from nsStyleLinkElement to HTMLLinkElement. r=smaug diff --git a/dom/base/Link.cpp b/dom/base/Link.cpp --- a/dom/base/Link.cpp +++ b/dom/base/Link.cpp @@ -24,16 +24,17 @@ #include "nsEscape.h" #include "nsGkAtoms.h" #include "nsHTMLDNSPrefetch.h" #include "nsString.h" #include "mozAutoDocUpdate.h" #include "mozilla/Services.h" #include "nsAttrValueInlines.h" +#include "HTMLLinkElement.h" namespace mozilla { namespace dom { #ifndef ANDROID using places::History; #endif @@ -156,18 +157,18 @@ Link::TryDNSPrefetchOrPreconnectOrPrefet nsAutoString media; GetContentPolicyMimeTypeMedia(asAttr, policyType, mimeType, media); if (policyType == nsIContentPolicy::TYPE_INVALID) { // Ignore preload with a wrong or empty as attribute. return; } - if (!nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, media, - mElement->OwnerDoc())) { + if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media, + mElement->OwnerDoc())) { policyType = nsIContentPolicy::TYPE_INVALID; } prefetchService->PreloadURI(uri, mElement->OwnerDoc()->GetDocumentURI(), domNode, policyType); } else { prefetchService->PrefetchURI(uri, @@ -241,18 +242,18 @@ Link::UpdatePreload(nsIAtom* aName, cons if (asPolicyType == nsIContentPolicy::TYPE_INVALID) { // Ignore preload with a wrong or empty as attribute, but be sure to cancel // the old one. prefetchService->CancelPrefetchPreloadURI(uri, domNode); return; } nsContentPolicyType policyType = asPolicyType; - if (!nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, media, - mElement->OwnerDoc())) { + if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media, + mElement->OwnerDoc())) { policyType = nsIContentPolicy::TYPE_INVALID; } if (aName == nsGkAtoms::crossorigin) { CORSMode corsMode = Element::AttrValueToCORSMode(aValue); CORSMode oldCorsMode = Element::AttrValueToCORSMode(aOldValue); if (corsMode != oldCorsMode) { prefetchService->CancelPrefetchPreloadURI(uri, domNode); @@ -262,49 +263,49 @@ Link::UpdatePreload(nsIAtom* aName, cons return; } nsContentPolicyType oldPolicyType; if (aName == nsGkAtoms::as) { if (aOldValue) { oldPolicyType = AsValueToContentPolicy(*aOldValue); - if (!nsStyleLinkElement::CheckPreloadAttrs(*aOldValue, mimeType, media, - mElement->OwnerDoc())) { + if (!HTMLLinkElement::CheckPreloadAttrs(*aOldValue, mimeType, media, + mElement->OwnerDoc())) { oldPolicyType = nsIContentPolicy::TYPE_INVALID; } } else { oldPolicyType = nsIContentPolicy::TYPE_INVALID; } } else if (aName == nsGkAtoms::type) { nsAutoString oldType; nsAutoString notUsed; if (aOldValue) { aOldValue->ToString(oldType); } else { oldType = EmptyString(); } nsAutoString oldMimeType; nsContentUtils::SplitMimeType(oldType, oldMimeType, notUsed); - if (nsStyleLinkElement::CheckPreloadAttrs(asAttr, oldMimeType, media, - mElement->OwnerDoc())) { + if (HTMLLinkElement::CheckPreloadAttrs(asAttr, oldMimeType, media, + mElement->OwnerDoc())) { oldPolicyType = asPolicyType; } else { oldPolicyType = nsIContentPolicy::TYPE_INVALID; } } else { MOZ_ASSERT(aName == nsGkAtoms::media); nsAutoString oldMedia; if (aOldValue) { aOldValue->ToString(oldMedia); } else { oldMedia = EmptyString(); } - if (nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, oldMedia, - mElement->OwnerDoc())) { + if (HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, oldMedia, + mElement->OwnerDoc())) { oldPolicyType = asPolicyType; } else { oldPolicyType = nsIContentPolicy::TYPE_INVALID; } } if ((policyType != oldPolicyType) && (oldPolicyType != nsIContentPolicy::TYPE_INVALID)) { diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -48,16 +48,17 @@ #include "nsHTMLDNSPrefetch.h" #include "nsIObserverService.h" #include "mozilla/Preferences.h" #include "mozilla/dom/ServiceWorkerDescriptor.h" #include "mozilla/dom/ScriptLoader.h" #include "nsParserConstants.h" #include "nsSandboxFlags.h" #include "Link.h" +#include "HTMLLinkElement.h" using namespace mozilla; using namespace mozilla::dom; LazyLogModule gContentSinkLogModuleInfo("nscontentsink"); NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink) @@ -881,18 +882,18 @@ nsContentSink::PrefetchPreloadHref(const if (policyType == nsIContentPolicy::TYPE_INVALID) { // Ignore preload with a wrong or empty as attribute. return; } nsAutoString mimeType; nsAutoString notUsed; nsContentUtils::SplitMimeType(aType, mimeType, notUsed); - if (!nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, - aMedia,mDocument)) { + if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, + aMedia,mDocument)) { policyType = nsIContentPolicy::TYPE_INVALID; } prefetchService->PreloadURI(uri, mDocumentURI, domNode, policyType); } else { prefetchService->PrefetchURI(uri, mDocumentURI, domNode, aLinkTypes & nsStyleLinkElement::ePREFETCH); } diff --git a/dom/base/nsStyleLinkElement.cpp b/dom/base/nsStyleLinkElement.cpp --- a/dom/base/nsStyleLinkElement.cpp +++ b/dom/base/nsStyleLinkElement.cpp @@ -28,24 +28,16 @@ #include "nsIDOMStyleSheet.h" #include "nsUnicharUtils.h" #include "nsCRT.h" #include "nsXPCOMCIDInternal.h" #include "nsUnicharInputStream.h" #include "nsContentUtils.h" #include "nsStyleUtil.h" #include "nsQueryObject.h" -#include "nsIContentPolicyBase.h" -#include "nsMimeTypes.h" -#include "imgLoader.h" -#include "MediaContainerType.h" -#include "DecoderDoctorDiagnostics.h" -#include "DecoderTraits.h" -#include "MediaList.h" -#include "nsAttrValueInlines.h" using namespace mozilla; using namespace mozilla::dom; nsStyleLinkElement::nsStyleLinkElement() : mDontLoadStyle(false) , mUpdatesEnabled(true) , mLineNumber(1) @@ -182,136 +174,16 @@ uint32_t nsStyleLinkElement::ParseLinkTy } if (inString) { nsContentUtils::ASCIIToLower(Substring(start, current), subString); linkMask |= ToLinkMask(subString); } return linkMask; } -// 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 -nsStyleLinkElement::CheckPreloadAttrs(const nsAttrValue& aAs, - const nsAString& aType, - const nsAString& aMedia, - nsIDocument* aDocument) -{ - nsContentPolicyType policyType = Link::AsValueToContentPolicy(aAs); - if (policyType == nsIContentPolicy::TYPE_INVALID) { - return false; - } - - // Check if media attribute is valid. - if (!aMedia.IsEmpty()) { - RefPtr mediaList = MediaList::Create(aDocument->GetStyleBackendType(), - aMedia); - nsIPresShell* shell = aDocument->GetShell(); - if (!shell) { - return false; - } - - nsPresContext* presContext = shell->GetPresContext(); - if (!presContext) { - return false; - } - if (!mediaList->Matches(presContext)) { - return false; - } - } - - if (aType.IsEmpty()) { - return true; - } - - nsString type = nsString(aType); - ToLowerCase(type); - - if (policyType == nsIContentPolicy::TYPE_OTHER) { - return true; - - } else if (policyType == nsIContentPolicy::TYPE_MEDIA) { - if (aAs.GetEnumValue() == DESTINATION_TRACK) { - if (type.EqualsASCII("text/vtt")) { - return true; - } else { - return false; - } - } - 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. - if (status == CANPLAY_NO) { - return false; - } else { - return true; - } - - } else if (policyType == nsIContentPolicy::TYPE_FONT) { - if (IsFontMimeType(type)) { - return true; - } else { - return false; - } - - } else if (policyType == nsIContentPolicy::TYPE_IMAGE) { - if (imgLoader::SupportImageWithMimeType(NS_ConvertUTF16toUTF8(type).get(), - AcceptedMimeTypes::IMAGES_AND_DOCUMENTS)) { - return true; - } else { - return false; - } - - } else if (policyType == nsIContentPolicy::TYPE_SCRIPT) { - if (nsContentUtils::IsJavascriptMIMEType(type)) { - return true; - } else { - return false; - } - - } else if (policyType == nsIContentPolicy::TYPE_STYLESHEET) { - if (type.EqualsASCII("text/css")) { - return true; - } else { - return false; - } - } - return false; -} - Result nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver, ForceUpdate aForceUpdate) { if (aForceUpdate == ForceUpdate::Yes) { // We remove this stylesheet from the cache to load a new version. nsCOMPtr thisContent = do_QueryInterface(this); nsCOMPtr doc = thisContent->IsInShadowTree() ? diff --git a/dom/base/nsStyleLinkElement.h b/dom/base/nsStyleLinkElement.h --- a/dom/base/nsStyleLinkElement.h +++ b/dom/base/nsStyleLinkElement.h @@ -17,16 +17,17 @@ #include "mozilla/CORSMode.h" #include "mozilla/StyleSheetInlines.h" #include "mozilla/Unused.h" #include "mozilla/net/ReferrerPolicy.h" #include "nsCOMPtr.h" #include "nsIStyleSheetLinkingElement.h" #include "nsTArray.h" #include "nsAttrValue.h" +#include "nsAttrValue.h" class nsIDocument; class nsIURI; namespace mozilla { class CSSStyleSheet; namespace dom { class ShadowRoot; @@ -67,19 +68,16 @@ public: ePRECONNECT = 0x00000020, // NOTE: 0x40 is unused ePRELOAD = 0x00000080 }; // The return value is a bitwise or of 0 or more RelValues. static uint32_t ParseLinkTypes(const nsAString& aTypes); - static bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType, - const nsAString& aMedia, nsIDocument* aDocument); - void UpdateStyleSheetInternal() { mozilla::Unused << UpdateStyleSheetInternal(nullptr, nullptr); } protected: /** * @param aOldDocument should be non-null only if we're updating because we * removed the node from the document. diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp --- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -24,16 +24,24 @@ #include "nsINode.h" #include "nsIStyleSheetLinkingElement.h" #include "nsIURL.h" #include "nsPIDOMWindow.h" #include "nsReadableUtils.h" #include "nsStyleConsts.h" #include "nsStyleLinkElement.h" #include "nsUnicharUtils.h" +#include "nsIContentPolicyBase.h" +#include "nsMimeTypes.h" +#include "imgLoader.h" +#include "MediaContainerType.h" +#include "DecoderDoctorDiagnostics.h" +#include "DecoderTraits.h" +#include "MediaList.h" +#include "nsAttrValueInlines.h" #define LINK_ELEMENT_FLAG_BIT(n_) \ NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) // Link element specific bits enum { // Indicates that a DNS Prefetch has been requested from this Link element. HTML_LINK_DNS_PREFETCH_REQUESTED = LINK_ELEMENT_FLAG_BIT(0), @@ -510,10 +518,131 @@ HTMLLinkElement::WrapNode(JSContext* aCx } void HTMLLinkElement::GetAs(nsAString& aResult) { GetEnumAttr(nsGkAtoms::as, EmptyCString().get(), aResult); } +// 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, + nsIDocument* aDocument) +{ + nsContentPolicyType policyType = Link::AsValueToContentPolicy(aAs); + if (policyType == nsIContentPolicy::TYPE_INVALID) { + return false; + } + + // Check if media attribute is valid. + if (!aMedia.IsEmpty()) { + RefPtr mediaList = MediaList::Create(aDocument->GetStyleBackendType(), + aMedia); + nsIPresShell* shell = aDocument->GetShell(); + if (!shell) { + return false; + } + + nsPresContext* presContext = shell->GetPresContext(); + if (!presContext) { + return false; + } + if (!mediaList->Matches(presContext)) { + return false; + } + } + + if (aType.IsEmpty()) { + return true; + } + + + nsString type = nsString(aType); + ToLowerCase(type); + + if (policyType == nsIContentPolicy::TYPE_OTHER) { + return true; + + } else if (policyType == nsIContentPolicy::TYPE_MEDIA) { + if (aAs.GetEnumValue() == DESTINATION_TRACK) { + if (type.EqualsASCII("text/vtt")) { + return true; + } else { + return false; + } + } + 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. + if (status == CANPLAY_NO) { + return false; + } else { + return true; + } + + } else if (policyType == nsIContentPolicy::TYPE_FONT) { + if (IsFontMimeType(type)) { + return true; + } else { + return false; + } + + } else if (policyType == nsIContentPolicy::TYPE_IMAGE) { + if (imgLoader::SupportImageWithMimeType(NS_ConvertUTF16toUTF8(type).get(), + AcceptedMimeTypes::IMAGES_AND_DOCUMENTS)) { + return true; + } else { + return false; + } + + } else if (policyType == nsIContentPolicy::TYPE_SCRIPT) { + if (nsContentUtils::IsJavascriptMIMEType(type)) { + return true; + } else { + return false; + } + + } else if (policyType == nsIContentPolicy::TYPE_STYLESHEET) { + if (type.EqualsASCII("text/css")) { + return true; + } else { + return false; + } + } + return false; +} + } // namespace dom } // namespace mozilla diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -200,16 +200,18 @@ public: virtual CORSMode GetCORSMode() const override; virtual void NodeInfoChanged(nsIDocument* aOldDoc) final override { ClearHasPendingLinkUpdate(); nsGenericHTMLElement::NodeInfoChanged(aOldDoc); } + static bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType, + const nsAString& aMedia, nsIDocument* aDocument); protected: virtual ~HTMLLinkElement(); // nsStyleLinkElement already_AddRefed GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) final; void GetStyleSheetInfo(nsAString& aTitle,