/* 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/. */
ListenerArray::ForwardIterator iter(mListenerInfoList); while (iter.HasMore()) {
ListenerInfo& info = iter.GetNext(); if (!(info.mNotifyMask & aFlag)) { continue;
}
nsCOMPtr<nsIWebProgressListener> listener =
do_QueryReferent(info.mWeakListener); if (!listener) {
mListenerInfoList.RemoveElement(info); continue;
}
aCallback(listener);
}
mListenerInfoList.Compact();
// Notify the parent BrowsingContextWebProgress of the event to continue // propagating. auto* parent = mCurrentBrowsingContext->GetParent(); if (parent && parent->GetWebProgress()) {
aCallback(parent->GetWebProgress());
}
}
void BrowsingContextWebProgress::ContextDiscarded() { if (mBounceTrackingState) {
mBounceTrackingState->OnBrowsingContextDiscarded();
}
if (!mIsLoadingDocument) { return;
}
// If our BrowsingContext is being discarded while still loading a document, // fire a synthetic `STATE_STOP` to end the ongoing load.
MOZ_LOG(gBCWebProgressLog, LogLevel::Info,
("Discarded while loading %s",
DescribeBrowsingContext(mCurrentBrowsingContext).get()));
// This matches what nsDocLoader::doStopDocumentLoad does, except we don't // bother notifying for `STATE_STOP | STATE_IS_DOCUMENT`, // nsBrowserStatusFilter would filter it out before it gets to the parent // process.
nsCOMPtr<nsIRequest> request = mLoadingDocumentRequest;
OnStateChange(this, request, STATE_STOP | STATE_IS_WINDOW | STATE_IS_NETWORK,
NS_ERROR_ABORT);
}
// We may receive a request from an in-process nsDocShell which doesn't have // `aWebProgress == this` which we should still consider as targeting // ourselves. if (nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aWebProgress);
docShell && docShell->GetBrowsingContext() == mCurrentBrowsingContext) {
targetIsThis = true;
aWebProgress->GetLoadType(&mLoadType);
}
// Track `mIsLoadingDocument` based on the notifications we've received so far // if the nsIWebProgress being targeted is this one. if (targetIsThis) {
constexpr uint32_t startFlags = nsIWebProgressListener::STATE_START |
nsIWebProgressListener::STATE_IS_DOCUMENT |
nsIWebProgressListener::STATE_IS_REQUEST |
nsIWebProgressListener::STATE_IS_WINDOW |
nsIWebProgressListener::STATE_IS_NETWORK;
constexpr uint32_t stopFlags = nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_WINDOW;
constexpr uint32_t redirectFlags =
nsIWebProgressListener::STATE_IS_REDIRECTED_DOCUMENT; if ((aStateFlags & startFlags) == startFlags) { if (mIsLoadingDocument) { // We received a duplicate `STATE_START` notification, silence this // notification until we receive the matching `STATE_STOP` to not fire // duplicate `STATE_START` notifications into frontend on process // switches. return NS_OK;
}
mIsLoadingDocument = true;
// Record the request we started the load with, so we can emit a synthetic // `STATE_STOP` notification if the BrowsingContext is discarded before // the notification arrives.
mLoadingDocumentRequest = aRequest;
} elseif ((aStateFlags & stopFlags) == stopFlags) { // We've received a `STATE_STOP` notification targeting this web progress, // clear our loading document flag.
mIsLoadingDocument = false;
mLoadingDocumentRequest = nullptr;
} elseif (mIsLoadingDocument &&
(aStateFlags & redirectFlags) == redirectFlags) { // If we see a redirected document load, update the loading request which // we'll emit the synthetic STATE_STOP notification with.
mLoadingDocumentRequest = aRequest;
}
}
// Hackily fetch the names of each constant from the XPT information used for // reflecting it into JS. This doesn't need to be reliable and just exists as // a logging aid. // // If a change to xpt in the future breaks this code, just delete it and // replace it with a normal hex log. if (constauto* ifaceInfo =
nsXPTInterfaceInfo::ByIID(NS_GET_IID(nsIWebProgressListener))) { for (uint16_t i = 0; i < ifaceInfo->ConstantCount(); ++i) { constauto& constInfo = ifaceInfo->Constant(i);
nsDependentCString name(constInfo.Name()); if (!StringBeginsWith(name, aPrefix)) { continue;
}
if (remaining & constInfo.mValue) {
remaining &= ~constInfo.mValue; if (!flags.IsEmpty()) {
flags.AppendLiteral("|");
}
flags.Append(name);
}
}
} if (remaining != 0 || flags.IsEmpty()) { if (!flags.IsEmpty()) {
flags.AppendLiteral("|");
}
flags.AppendInt(remaining, 16);
} return flags;
}
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.