/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// If this is reinserted back into the document it will not be // from the parser.
Document* oldDoc = GetUncomposedDoc();
ShadowRoot* oldShadowRoot = GetContainingShadow();
// We want to update the localization but only if the link is removed from a // DOM change, and not because the document is going away. bool ignore;
if (oldDoc) {
if (oldDoc->GetScriptHandlingObject(ignore) &&
AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization,
eIgnoreCase)) {
oldDoc->LocalizationLinkRemoved(this);
}
}
// In the unlikely case that both rev is specified *and* rel=stylesheet, // this code will cause the event to fire, on the principle that maybe the // page really does want to specify that its author is a stylesheet. Since // this should never actually happen and the performance hit is minimal, // doing the "right" thing costs virtually nothing here, even if it doesn't // make much sense. static AttrArray::AttrValuesArray strings[] = {
nsGkAtoms::_empty, nsGkAtoms::stylesheet, nullptr};
RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher( this, aEventName, CanBubble::eYes, ChromeOnlyDispatch::eYes); // Always run async in order to avoid running script when the content // sink isn't expecting it.
asyncDispatcher->PostDOMEvent();
}
// If the link has `rel=localization` and its `href` attribute is changed, // update the list of localization links.
if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization,
eIgnoreCase)) {
if (Document* doc = GetUncomposedDoc()) {
if (aOldValue) {
doc->LocalizationLinkRemoved(this);
}
if (aValue) {
doc->LocalizationLinkAdded(this);
}
}
}
}
// If a link's `rel` attribute was changed from or to `localization`, // update the list of localization links.
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::rel) {
if (Document* doc = GetUncomposedDoc()) {
if ((aValue && aValue->Equals(nsGkAtoms::localization, eIgnoreCase)) &&
(!aOldValue ||
!aOldValue->Equals(nsGkAtoms::localization, eIgnoreCase))) {
doc->LocalizationLinkAdded(this);
} else if ((aOldValue &&
aOldValue->Equals(nsGkAtoms::localization, eIgnoreCase)) &&
(!aValue ||
!aValue->Equals(nsGkAtoms::localization, eIgnoreCase))) {
doc->LocalizationLinkRemoved(this);
}
}
}
// Keep this and the arrays below in sync with ToLinkMask in LinkStyle.cpp. #define SUPPORTED_REL_VALUES_BASE \ "preload", "prefetch", "dns-prefetch", "stylesheet", "next", "alternate", \ "preconnect", "icon", "search", nullptr
// It is okay to include the size of mCachedURI here even though it might have // strong references from elsewhere because the URI was created for this // object, in nsGenericHTMLElement::GetURIAttr(). Only objects that created // their own URI will call nsIURIWithSizeOf::SizeOfIncludingThis().
if (mCachedURI) {
*aNodeSize += SizeOfIncludingThisIfURIWithSizeOf(
mCachedURI, aSizes.mState.mMallocSizeOf);
}
}
void HTMLLinkElement::
TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender() {
MOZ_ASSERT(IsInComposedDoc());
if (!HasAttr(nsGkAtoms::href)) { // Per HTML spec, imagesrcset can substitute for href on image preloads.
nsAutoString as;
GetAttr(nsGkAtoms::as, as);
if (!as.LowerCaseEqualsASCII("image") || !HasAttr(nsGkAtoms::imagesrcset)) { return;
}
}
nsAutoString rel;
if (!GetAttr(nsGkAtoms::rel, rel)) { return;
}
if (!nsContentUtils::PrefetchPreloadEnabled(OwnerDoc()->GetDocShell())) { return;
}
uint32_t linkTypes = ParseLinkTypes(rel);
if ((linkTypes & ePREFETCH) || (linkTypes & eNEXT)) {
nsCOMPtr<nsIPrefetchService> prefetchService(
components::Prefetch::Service());
if (prefetchService) {
if (nsCOMPtr<nsIURI> uri = GetURI()) { auto referrerInfo = MakeRefPtr<ReferrerInfo>(*this);
prefetchService->PrefetchURI(uri, referrerInfo, this,
linkTypes & ePREFETCH); return;
}
}
}
if (linkTypes & eCOMPRESSION_DICTIONARY) {
if (nsCOMPtr<nsIURI> uri = GetURI()) {
StartPreload(nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD); return;
}
}
if (linkTypes & ePRELOAD) {
nsCOMPtr<nsIURI> uri = GetURI();
// Image preloads can derive their URI from imagesrcset without href.
if (!uri && (policyType != nsIContentPolicy::TYPE_IMAGE ||
!HasAttr(nsGkAtoms::imagesrcset))) { return;
}
if (policyType == nsIContentPolicy::TYPE_INVALID ||
!net::CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) { // Ignore preload with a wrong or empty as attribute.
nsAutoString srcset;
GetAttr(nsGkAtoms::imagesrcset, srcset);
net::WarnIgnoredPreload(*OwnerDoc(), uri, srcset); return;
}
// https://html.spec.whatwg.org/#translate-a-preload-destination // If destination is not "fetch", "font", "image", "script", "style", or // "track", then return null.
int16_t asValue = asAttr.GetEnumValue();
if (asValue != net::DESTINATION_FETCH && asValue != net::DESTINATION_FONT &&
asValue != net::DESTINATION_IMAGE &&
asValue != net::DESTINATION_SCRIPT &&
asValue != net::DESTINATION_STYLE &&
asValue != net::DESTINATION_TRACK) { // TODO: Currently the spec doesn't define an event handler to be called // , but this is under discussion. // See: https://github.com/whatwg/html/issues/10940 // // Post a "load" event here to match the legacy behavior.
RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher( this, u"load"_ns, CanBubble::eNo, ChromeOnlyDispatch::eNo);
asyncDispatcher->PostDOMEvent(); return;
}
StartPreload(policyType); return;
}
if (linkTypes & eMODULE_PRELOAD) {
ScriptLoader* scriptLoader = OwnerDoc()->GetScriptLoader();
if (!scriptLoader) { return;
}
ModuleLoader* moduleLoader = scriptLoader->GetModuleLoader();
if (!moduleLoader) { // For the print preview documents, at this moment it doesn't have module // loader yet, as the (print preview) document is not attached to the // nsIDocumentViewer yet, so it doesn't have the GlobalObject. // Also, the script elements won't be processed as they are also cloned // from the original document. // So we simply bail out if the module loader is null. return;
}
if (!StaticPrefs::network_modulepreload() &&
!StaticPrefs::dom_multiple_import_maps_enabled()) { // Keep behavior from https://phabricator.services.mozilla.com/D149371, // prior to main implementation of modulepreload
moduleLoader->DisallowImportMaps(); return;
}
// https://html.spec.whatwg.org/multipage/semantics.html#processing-the-media-attribute // TODO: apply this check for all linkTypes
nsAutoString media;
if (GetAttr(nsGkAtoms::media, media)) {
RefPtr<mozilla::dom::MediaList> mediaList =
mozilla::dom::MediaList::Create(NS_ConvertUTF16toUTF8(media));
if (!mediaList->Matches(*OwnerDoc())) { return;
}
}
// TODO: per spec, apply this check for ePREFETCH as well
if (!HasNonEmptyAttr(nsGkAtoms::href)) { return;
}
nsAutoString as;
GetAttr(nsGkAtoms::as, as);
if (!net::IsScriptLikeOrInvalid(as)) {
RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher( this, u"error"_ns, CanBubble::eNo, ChromeOnlyDispatch::eNo);
asyncDispatcher->PostDOMEvent(); return;
}
nsCOMPtr<nsIURI> uri = GetURI();
if (!uri) { return;
}
if (asPolicyType == nsIContentPolicy::TYPE_INVALID ||
!net::CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) { // Ignore preload with a wrong or empty as attribute, but be sure to cancel // the old one.
CancelPrefetchOrPreload();
nsAutoString srcset;
GetAttr(nsGkAtoms::imagesrcset, srcset);
net::WarnIgnoredPreload(*OwnerDoc(), uri, srcset); return;
}
nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
if (prefetchService) {
if (nsCOMPtr<nsIURI> uri = GetURI()) {
prefetchService->CancelPrefetchPreloadURI(uri, this);
}
}
}
void HTMLLinkElement::StartPreload(nsContentPolicyType aPolicyType) {
MOZ_ASSERT(!mPreload, "Forgot to cancel the running preload");
RefPtr<PreloaderBase> preload =
OwnerDoc()->Preloads().PreloadLinkElement(this, aPolicyType);
mPreload = preload.get();
}
void HTMLLinkElement::CancelPreload() {
if (mPreload) { // This will cancel the loading channel if this was the last referred node // and the preload is not used up until now to satisfy a regular tag load // request.
mPreload->RemoveLinkPreloadNode(this);
mPreload = nullptr;
}
}
bool HTMLLinkElement::IsCSSMimeTypeAttributeForLinkElement( const Element& aSelf) { // Processing the type attribute per // https://html.spec.whatwg.org/multipage/semantics.html#processing-the-type-attribute // for HTML link elements.
nsAutoString type;
nsAutoString mimeType;
nsAutoString notUsed;
aSelf.GetAttr(nsGkAtoms::type, type);
nsContentUtils::SplitMimeType(type, mimeType, notUsed); return mimeType.IsEmpty() || mimeType.LowerCaseEqualsLiteral("text/css");
}
nsDOMTokenList* HTMLLinkElement::Blocking() {
if (!mBlocking) {
mBlocking =
new nsDOMTokenList(this, nsGkAtoms::blocking, sSupportedBlockingValues);
} return mBlocking;
}
// TODO: handle implicitly potentially render blocking // https://html.spec.whatwg.org/#implicitly-potentially-render-blocking // The default type for resources given by the stylesheet keyword is text/css. // A link element of this type is implicitly potentially render-blocking if // the element was created by its node document's parser.
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.