/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
/* * Base class for all our document implementations.
*/
~HeaderData() { // Delete iteratively to avoid blowing up the stack, though it shouldn't // happen in practice.
UniquePtr<HeaderData> next = std::move(mNext); while (next) {
next = std::move(next->mNext);
}
}
for (auto iter = mChangeCallbacks->Iter(); !iter.Done(); iter.Next()) {
IdentifierMapEntry::ChangeCallbackEntry* entry = iter.Get(); // Don't fire image changes for non-image observers, and don't fire element // changes for image observers when an image override is active. if (entry->mKey.mForImage ? (mImageElement && !aImageOnly) : aImageOnly) { continue;
}
if (!entry->mKey.mCallback(aOldElement, aNewElement, entry->mKey.mData)) {
iter.Remove();
}
}
}
void IdentifierMapEntry::AddIdElement(Element* aElement) {
MOZ_ASSERT(aElement, "Must have element");
MOZ_ASSERT(!mIdContentList->Contains(nullptr), "Why is null in our list?");
size_t index = mIdContentList.Insert(*aElement); if (index == 0) {
Element* oldElement = mIdContentList->SafeElementAt(1);
FireChangeCallbacks(oldElement, aElement);
}
}
// This should only be called while the document is in an update. // Assertions near the call to this method guarantee this.
// This could fire in OOM situations // Only assert this in HTML documents for now as XUL does all sorts of weird // crap.
NS_ASSERTION(!aElement->OwnerDoc()->IsHTMLDocument() ||
mIdContentList->Contains(aElement), "Removing id entry that doesn't exist");
// XXXbz should this ever Compact() I guess when all the content is gone // we'll just get cleaned up in the natural order of things...
Element* currentElement = mIdContentList->SafeElementAt(0);
mIdContentList.RemoveElement(*aElement); if (currentElement == aElement) {
FireChangeCallbacks(currentElement, mIdContentList->SafeElementAt(0));
}
}
class SimpleHTMLCollection final : public nsSimpleContentList, public nsIHTMLCollection { public: explicit SimpleHTMLCollection(nsINode* aRoot) : nsSimpleContentList(aRoot) {}
class SubDocMapEntry : public PLDHashEntryHdr { public: // Both of these are strong references
dom::Element* mKey; // must be first, to look like PLDHashEntryStub
dom::Document* mSubDocument;
};
class OnloadBlocker final : public nsIRequest { public:
OnloadBlocker() = default;
Document* ExternalResourceMap::RequestResource(
nsIURI* aURI, nsIReferrerInfo* aReferrerInfo, nsINode* aRequestingNode,
Document* aDisplayDocument, ExternalResourceLoad** aPendingLoad) { // If we ever start allowing non-same-origin loads here, we might need to do // something interesting with aRequestingPrincipal even for the hashtable // gets.
MOZ_ASSERT(aURI, "Must have a URI");
MOZ_ASSERT(aRequestingNode, "Must have a node");
MOZ_ASSERT(aReferrerInfo, "Must have a referrerInfo");
*aPendingLoad = nullptr; if (mHaveShutDown) { return nullptr;
}
// First, make sure we strip the ref from aURI.
nsCOMPtr<nsIURI> clone;
nsresult rv = NS_GetURIWithoutRef(aURI, getter_AddRefs(clone)); if (NS_FAILED(rv) || !clone) { return nullptr;
}
ExternalResource* resource;
mMap.Get(clone, &resource); if (resource) { return resource->mDocument;
}
if (NS_FAILED(loadEntry.Data()->StartLoad(clone, aReferrerInfo,
aRequestingNode))) { returnfalse;
}
}
RefPtr<PendingLoad> load(loadEntry.Data());
load.forget(aPendingLoad); returntrue;
}); if (!loadStartSucceeded) { // Make sure we don't thrash things by trying this load again, since // chances are it failed for good reasons (security check, etc). // This must be done outside the WithEntryHandle functor, as it accesses // mPendingLoads.
AddExternalResource(clone, nullptr, nullptr, aDisplayDocument);
}
for (auto& doc : docs) { if (aCallback(*doc) == CallState::Stop) { return;
}
}
}
void ExternalResourceMap::Traverse(
nsCycleCollectionTraversalCallback* aCallback) const { // mPendingLoads will get cleared out as the requests complete, so // no need to worry about those here. for (constauto& entry : mMap) {
ExternalResourceMap::ExternalResource* resource = entry.GetWeak();
// Make sure to do this no matter what
nsresult rv2 =
map.AddExternalResource(mURI, viewer, loadGroup, mDisplayDocument); if (NS_FAILED(rv)) { return rv;
} if (NS_FAILED(rv2)) {
mTargetListener = nullptr; return rv2;
}
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { bool requestSucceeded; if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) ||
!requestSucceeded) { // Bail out on this load, since it looks like we have an HTTP error page return NS_BINDING_ABORTED;
}
}
// Give this document its own loadgroup
nsCOMPtr<nsILoadGroup> newLoadGroup =
do_CreateInstance(NS_LOADGROUP_CONTRACTID);
NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY);
newLoadGroup->SetLoadGroup(loadGroup);
nsCOMPtr<nsIParser> parser = do_QueryInterface(listener); if (!parser) { /// We don't want to deal with the various fake documents yet return NS_ERROR_NOT_IMPLEMENTED;
}
// We can't handle HTML and other weird things here yet.
nsIContentSink* sink = parser->GetContentSink();
nsCOMPtr<nsIXMLContentSink> xmlSink = do_QueryInterface(sink); if (!xmlSink) { return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aStream,
uint64_t aOffset,
uint32_t aCount) { // mTargetListener might be null if SetupViewer or AddExternalResource failed.
NS_ENSURE_TRUE(mTargetListener, NS_ERROR_FAILURE); if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) { return NS_BINDING_ABORTED;
} return mTargetListener->OnDataAvailable(aRequest, aStream, aOffset, aCount);
}
NS_IMETHODIMP
ExternalResourceMap::PendingLoad::OnStopRequest(nsIRequest* aRequest,
nsresult aStatus) { // mTargetListener might be null if SetupViewer or AddExternalResource failed if (mTargetListener) {
nsCOMPtr<nsIStreamListener> listener;
mTargetListener.swap(listener); return listener->OnStopRequest(aRequest, aStatus);
}
return NS_OK;
}
nsresult ExternalResourceMap::PendingLoad::StartLoad(
nsIURI* aURI, nsIReferrerInfo* aReferrerInfo, nsINode* aRequestingNode) {
MOZ_ASSERT(aURI, "Must have a URI");
MOZ_ASSERT(aRequestingNode, "Must have a node");
MOZ_ASSERT(aReferrerInfo, "Must have a referrerInfo");
// If we ever have an nsIDocumentObserver notification for stylesheet title // changes we should update the list from that instead of overriding // EnsureFresh. class DOMStyleSheetSetList final : public DOMStringList { public: explicit DOMStyleSheetSetList(Document* aDocument);
void Disconnect() { mDocument = nullptr; }
virtualvoid EnsureFresh() override;
protected:
Document* mDocument; // Our document; weak ref. It'll let us know if it // dies.
};
DOMStyleSheetSetList::DOMStyleSheetSetList(Document* aDocument)
: mDocument(aDocument) {
NS_ASSERTION(mDocument, "Must have document!");
}
Document::Document(constchar* aContentType)
: nsINode(nullptr),
DocumentOrShadowRoot(this),
mCharacterSet(WINDOWS_1252_ENCODING),
mCharacterSetSource(0),
mParentDocument(nullptr),
mCachedRootElement(nullptr),
mNodeInfoManager(nullptr), #ifdef DEBUG
mStyledLinksCleared(false), #endif
mCachedStateObjectValid(false),
mBlockAllMixedContent(false),
mBlockAllMixedContentPreloads(false),
mUpgradeInsecureRequests(false),
mUpgradeInsecurePreloads(false),
mDevToolsWatchingDOMMutations(false),
mBidiEnabled(false),
mMayNeedFontPrefsUpdate(true),
mMathMLEnabled(false),
mIsInitialDocumentInWindow(false),
mIsEverInitialDocumentInWindow(false),
mIgnoreDocGroupMismatches(false),
mLoadedAsData(false),
mAddedToMemoryReportingAsDataDocument(false),
mMayStartLayout(true),
mHaveFiredTitleChange(false),
mIsShowing(false),
mVisible(true),
mRemovedFromDocShell(false), // mAllowDNSPrefetch starts true, so that we can always reliably && it // with various values that might disable it. Since we never prefetch // unless we get a window, and in that case the docshell value will get // &&-ed in, this is safe.
mAllowDNSPrefetch(true),
mIsStaticDocument(false),
mCreatingStaticClone(false),
mHasPrintCallbacks(false),
mInUnlinkOrDeletion(false),
mHasHadScriptHandlingObject(false),
mIsBeingUsedAsImage(false),
mChromeRulesEnabled(false),
mInChromeDocShell(false),
mIsSyntheticDocument(false),
mHasLinksToUpdateRunnable(false),
mFlushingPendingLinkUpdates(false),
mMayHaveDOMMutationObservers(false),
mMayHaveAnimationObservers(false),
mHasCSPDeliveredThroughHeader(false),
mBFCacheDisallowed(false),
mHasHadDefaultView(false),
mStyleSheetChangeEventsEnabled(false),
mDevToolsAnonymousAndShadowEventsEnabled(false),
mIsSrcdocDocument(false),
mHasDisplayDocument(false),
mFontFaceSetDirty(true),
mDidFireDOMContentLoaded(true),
mIsTopLevelContentDocument(false),
mIsContentDocument(false),
mDidCallBeginLoad(false),
mEncodingMenuDisabled(false),
mLinksEnabled(true),
mIsSVGGlyphsDocument(false),
mInDestructor(false),
mIsGoingAway(false),
mStyleSetFilled(false),
mQuirkSheetAdded(false),
mMayHaveTitleElement(false),
mDOMLoadingSet(false),
mDOMInteractiveSet(false),
mDOMCompleteSet(false),
mAutoFocusFired(false),
mScrolledToRefAlready(false),
mChangeScrollPosWhenScrollingToRef(false),
mDelayFrameLoaderInitialization(false),
mSynchronousDOMContentLoaded(false),
mMaybeServiceWorkerControlled(false),
mAllowZoom(false),
mValidScaleFloat(false),
mValidMinScale(false),
mValidMaxScale(false),
mWidthStrEmpty(false),
mParserAborted(false),
mReportedDocumentUseCounters(false),
mHasReportedShadowDOMUsage(false),
mHasDelayedRefreshEvent(false),
mLoadEventFiring(false),
mSkipLoadEventAfterClose(false),
mDisableCookieAccess(false),
mDisableDocWrite(false),
mTooDeepWriteRecursion(false),
mPendingMaybeEditingStateChanged(false),
mHasBeenEditable(false),
mIsRunningExecCommandByContent(false),
mIsRunningExecCommandByChromeOrAddon(false),
mSetCompleteAfterDOMContentLoaded(false),
mDidHitCompleteSheetCache(false),
mUseCountersInitialized(false),
mShouldReportUseCounters(false),
mShouldSendPageUseCounters(false),
mUserHasInteracted(false),
mHasUserInteractionTimerScheduled(false),
mShouldResistFingerprinting(false),
mIsInPrivateBrowsing(false),
mCloningForSVGUse(false),
mAllowDeclarativeShadowRoots(false),
mSuspendDOMNotifications(false),
mForceLoadAtTop(false),
mFireMutationEvents(true),
mHasPolicyWithRequireTrustedTypesForDirective(false),
mClipboardCopyTriggered(false),
mXMLDeclarationBits(0),
mOnloadBlockCount(0),
mWriteLevel(0),
mContentEditableCount(0),
mEditingState(EditingState::eOff),
mCompatMode(eCompatibility_FullStandards),
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
mAncestorIsLoading(false),
mVisibilityState(dom::VisibilityState::Hidden),
mType(eUnknown),
mDefaultElementType(0),
mAllowXULXBL(eTriUnset),
mSkipDTDSecurityChecks(false),
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
mSandboxFlags(0),
mPartID(0),
mMarkedCCGeneration(0),
mPresShell(nullptr),
mSubtreeModifiedDepth(0),
mPreloadPictureDepth(0),
mEventsSuppressed(0),
mIgnoreDestructiveWritesCounter(0),
mStaticCloneCount(0),
mWindow(nullptr),
mBFCacheEntry(nullptr),
mInSyncOperationCount(0),
mBlockDOMContentLoaded(0),
mUpdateNestLevel(0),
mHttpsOnlyStatus(nsILoadInfo::HTTPS_ONLY_UNINITIALIZED),
mViewportType(Unknown),
mViewportFit(ViewportFitType::Auto),
mInteractiveWidgetMode(
InteractiveWidgetUtils::DefaultInteractiveWidgetMode()),
mHeaderData(nullptr),
mServoRestyleRootDirtyBits(0),
mThrowOnDynamicMarkupInsertionCounter(0),
mIgnoreOpensDuringUnloadCounter(0),
mSavedResolution(1.0f),
mGeneration(0),
mCachedTabSizeGeneration(0),
mNextFormNumber(0),
mNextControlNumber(0),
mPreloadService(this),
mShouldNotifyFetchSuccess(false),
mShouldNotifyFormOrPasswordRemoved(false) {
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
SetIsInDocument();
SetIsConnected(true);
// Create these unconditionally, they will be used to warn about the `zoom` // property, even if use counters are disabled.
mStyleUseCounters.reset(Servo_UseCounters_Create());
SetContentType(nsDependentCString(aContentType));
// Start out mLastStyleSheetSet as null, per spec
SetDOMStringToNull(mLastStyleSheetSet);
// void state used to differentiate an empty source from an unselected source
mPreloadPictureFoundSource.SetIsVoid(true);
RecomputeLanguageFromCharset();
mPreloadReferrerInfo = new dom::ReferrerInfo(nullptr);
mReferrerInfo = new dom::ReferrerInfo(nullptr);
}
#ifndef ANDROID // unused by GeckoView staticbool IsAboutErrorPage(nsGlobalWindowInner* aWin, constchar* aSpec) { if (NS_WARN_IF(!aWin)) { returnfalse;
}
nsIURI* uri = aWin->GetDocumentURI(); if (NS_WARN_IF(!uri)) { returnfalse;
} // getSpec is an expensive operation, hence we first check the scheme // to see if the caller is actually an about: page. if (!uri->SchemeIs("about")) { returnfalse;
}
// Given an nsresult that is assumed to be synthesized by PSM and describes a // certificate or TLS error, attempts to convert it into a string // representation of the underlying NSS error. // `aErrorCodeString` will be an empty string if `aResult` is not an error from // PSM or it does not represent a valid NSS error. void GetErrorCodeStringFromNSResult(nsresult aResult,
nsAString& aErrorCodeString) {
aErrorCodeString.Truncate();
// We don't throw even if httpChannel is null, we just keep responseStatus and // responseStatusText empty if (httpChannel) {
uint32_t responseStatus;
nsAutoCString responseStatusText;
rv = httpChannel->GetResponseStatus(&responseStatus); if (NS_SUCCEEDED(rv)) {
aInfo.mResponseStatus = responseStatus;
}
rv = httpChannel->GetResponseStatusText(responseStatusText); if (NS_SUCCEEDED(rv)) {
aInfo.mResponseStatusText.AssignASCII(responseStatusText);
}
}
// If nsITransportSecurityInfo is not set, simply keep the remaining fields // empty (to make responseStatus and responseStatusText accessible). if (!tsi) { return;
}
bool Document::CallerIsTrustedAboutCertError(JSContext* aCx,
JSObject* aObject) {
nsGlobalWindowInner* win = xpc::WindowOrNull(aObject); #ifdef ANDROID // GeckoView uses data URLs for error pages, so for now just check for any // error page return win && win->GetDocument() && win->GetDocument()->IsErrorPage(); #else return win && IsAboutErrorPage(win, "certerror"); #endif
}
bool Document::CallerCanAccessPrivilegeSSA(JSContext* aCx, JSObject* aObject) {
RefPtr<BasePrincipal> principal =
BasePrincipal::Cast(nsContentUtils::SubjectPrincipal(aCx));
if (!principal) { returnfalse;
}
// We allow the privilege SSA to be called from system principal. if (principal->IsSystemPrincipal()) { returntrue;
}
// We only allow calling the privilege SSA from the content script of the // webcompat extension. if (auto* policy = principal->ContentScriptAddonPolicy()) {
nsAutoString addonID;
policy->GetId(addonID);
void Document::LoadEventFired() { // Object used to collect some telemetry data so we don't need to query for it // twice.
glean::perf::PageLoadExtra pageLoadEventData;
// Accumulate timing data located in each document's realm and report to // telemetry.
AccumulateJSTelemetry(pageLoadEventData);
// Record page load event
RecordPageLoadEventTelemetry(pageLoadEventData);
// Release the JS bytecode cache from its wait on the load event, and // potentially dispatch the encoding of the bytecode. if (ScriptLoader()) {
ScriptLoader()->LoadEventFired();
}
}
void Document::RecordPageLoadEventTelemetry(
glean::perf::PageLoadExtra& aEventTelemetryData) { // If the page load time is empty, then the content wasn't something we want // to report (i.e. not a top level document). if (!aEventTelemetryData.loadTime) { return;
}
MOZ_ASSERT(IsTopLevelContentDocument());
nsPIDOMWindowOuter* window = GetWindow(); if (!window) { return;
}
nsIDocShell* docshell = window->GetDocShell(); if (!docshell) { return;
}
nsAutoCString loadTypeStr; switch (docshell->GetLoadType()) { case LOAD_NORMAL: case LOAD_NORMAL_REPLACE: case LOAD_NORMAL_BYPASS_CACHE: case LOAD_NORMAL_BYPASS_PROXY: case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
loadTypeStr.Append("NORMAL"); break; case LOAD_HISTORY:
loadTypeStr.Append("HISTORY"); break; case LOAD_RELOAD_NORMAL: case LOAD_RELOAD_BYPASS_CACHE: case LOAD_RELOAD_BYPASS_PROXY: case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: case LOAD_REFRESH: case LOAD_REFRESH_REPLACE: case LOAD_RELOAD_CHARSET_CHANGE: case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE: case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
loadTypeStr.Append("RELOAD"); break; case LOAD_LINK:
loadTypeStr.Append("LINK"); break; case LOAD_STOP_CONTENT: case LOAD_STOP_CONTENT_AND_REPLACE:
loadTypeStr.Append("STOP"); break; case LOAD_ERROR_PAGE:
loadTypeStr.Append("ERROR"); break; default:
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.42 Sekunden
(vorverarbeitet)
¤
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.