/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Change this if we want to cancel and remove the associated preload on removal // of all <link rel=preload> tags from the tree.
constexpr staticbool kCancelAndRemovePreloadOnZeroReferences = false;
class PreloaderBase::RedirectSink final : public nsIInterfaceRequestor, public nsIChannelEventSink, public nsIRedirectResultListener {
RedirectSink() = delete; virtual ~RedirectSink();
void PreloaderBase::NotifyOpen(const PreloadHashKey& aKey,
dom::Document* aDocument, bool aIsPreload, bool aIsModule) { if (aDocument) {
DebugOnly<bool> alreadyRegistered =
aDocument->Preloads().RegisterPreload(aKey, this); // This means there is already a preload registered under this key in this // document. We only allow replacement when this is a regular load. // Otherwise, this should never happen and is a suspected misuse of the API.
MOZ_ASSERT_IF(alreadyRegistered, !aIsPreload);
}
mKey = aKey;
mIsUsed = !aIsPreload;
// Start usage timer for rel="preload", but not for rel="modulepreload" // because modules may be loaded for functionality the user does not // immediately interact with after page load (e.g. a docs search box) if (!aIsModule && !mIsUsed && !mUsageTimer) { auto callback = MakeRefPtr<UsageTimer>(this, aDocument);
NS_NewTimerWithCallback(getter_AddRefs(mUsageTimer), callback, 10000,
nsITimer::TYPE_ONE_SHOT);
}
// Preloads are initially set the LOAD_BACKGROUND flag. When becoming // regular loads by hitting its consuming tag, we need to drop that flag, // which also means to re-add the request from/to it's loadgroup to reflect // that flag change. if (loadFlags & nsIRequest::LOAD_BACKGROUND) {
nsCOMPtr<nsILoadGroup> loadGroup;
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
nsresult status;
mChannel->GetStatus(&status);
if (aNewPreloader) {
aNewPreloader->mNodes = std::move(mNodes);
}
}
void PreloaderBase::NotifyStart(nsIRequest* aRequest) { // If there is no channel assigned on this preloader, we are not between // channel switching, so we can freely update the mShouldFireLoadEvent using // the given channel. if (mChannel && !SameCOMIdentity(aRequest, mChannel)) { return;
}
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); if (!httpChannel) { return;
}
// if the load is cross origin without CORS, or the CORS access is rejected, // always fire load event to avoid leaking site information.
nsresult rv;
nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->LoadInfo();
mShouldFireLoadEvent =
loadInfo->GetTainting() == LoadTainting::Opaque ||
(loadInfo->GetTainting() == LoadTainting::CORS &&
(NS_FAILED(httpChannel->GetStatus(&rv)) || NS_FAILED(rv)));
}
void PreloaderBase::NotifyStop(nsIRequest* aRequest, nsresult aStatus) { // Filter out notifications that may be arriving from the old channel before // restarting this request. if (!SameCOMIdentity(aRequest, mChannel)) { return;
}
void PreloaderBase::RemoveLinkPreloadNode(nsINode* aNode) { // Note that do_GetWeakReference returns the internal weak proxy, which is // always the same, so we can use it to search the array using default // comparator.
nsWeakPtr node = do_GetWeakReference(aNode);
mNodes.RemoveElement(node);
if (kCancelAndRemovePreloadOnZeroReferences && mNodes.Length() == 0 &&
!mIsUsed) { // Keep a reference, because the following call may release us. The caller // may use a WeakPtr to access this.
RefPtr<PreloaderBase> self(this);
RemoveSelf(aNode->OwnerDoc());
if (mChannel) {
mChannel->CancelWithReason(NS_BINDING_ABORTED, "PreloaderBase::RemoveLinkPreloadNode"_ns);
}
}
}
if (mKey.As() == PreloadHashKey::ResourceType::NONE) { return;
}
// The labels are structured as type1-used, type1-unused, type2-used, ... // The first "as" resource type is NONE with value 0. auto index = (static_cast<uint32_t>(mKey.As()) - 1) * 2; if (!mIsUsed) {
++index;
}
auto label = static_cast<Telemetry::LABELS_REL_PRELOAD_MISS_RATIO>(index);
Telemetry::AccumulateCategorical(label);
}
nsresult PreloaderBase::AsyncConsume(nsIStreamListener* aListener) { // We want to return an error so that consumers can't ever use a preload to // consume data unless it's properly implemented. return NS_ERROR_NOT_IMPLEMENTED;
}
if (mPreload->IsUsed()) { // Left in the hashtable, but marked as used. This is a valid case, and we // don't want to emit a warning for this preload then. return NS_OK;
}
mPreload->ReportUsageTelemetry();
// PreloadHashKey overrides GetKey, we need to use the nsURIHashKey one to get // the URI.
nsIURI* uri = static_cast<nsURIHashKey*>(&mPreload->mKey)->GetKey(); if (!uri) { return NS_OK;
}
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 ist noch experimentell.