summaryrefslogtreecommitdiffstats
path: root/dom/base/nsDocument.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/nsDocument.cpp')
-rw-r--r--dom/base/nsDocument.cpp239
1 files changed, 46 insertions, 193 deletions
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 8acfd901a..6b8e11db0 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -25,7 +25,6 @@
#include "plstr.h"
#include "mozilla/Sprintf.h"
-#include "mozilla/Telemetry.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsILoadContext.h"
@@ -1396,63 +1395,6 @@ nsDocument::~nsDocument()
NS_ASSERTION(!mIsShowing, "Destroying a currently-showing document");
- if (IsTopLevelContentDocument()) {
- //don't report for about: pages
- if (!IsAboutPage()) {
- // Record the page load
- uint32_t pageLoaded = 1;
- Accumulate(Telemetry::MIXED_CONTENT_UNBLOCK_COUNTER, pageLoaded);
- // Record the mixed content status of the docshell in Telemetry
- enum {
- NO_MIXED_CONTENT = 0, // There is no Mixed Content on the page
- MIXED_DISPLAY_CONTENT = 1, // The page attempted to load Mixed Display Content
- MIXED_ACTIVE_CONTENT = 2, // The page attempted to load Mixed Active Content
- MIXED_DISPLAY_AND_ACTIVE_CONTENT = 3 // The page attempted to load Mixed Display & Mixed Active Content
- };
-
- bool mixedActiveLoaded = GetHasMixedActiveContentLoaded();
- bool mixedActiveBlocked = GetHasMixedActiveContentBlocked();
-
- bool mixedDisplayLoaded = GetHasMixedDisplayContentLoaded();
- bool mixedDisplayBlocked = GetHasMixedDisplayContentBlocked();
-
- bool hasMixedDisplay = (mixedDisplayBlocked || mixedDisplayLoaded);
- bool hasMixedActive = (mixedActiveBlocked || mixedActiveLoaded);
-
- uint32_t mixedContentLevel = NO_MIXED_CONTENT;
- if (hasMixedDisplay && hasMixedActive) {
- mixedContentLevel = MIXED_DISPLAY_AND_ACTIVE_CONTENT;
- } else if (hasMixedActive){
- mixedContentLevel = MIXED_ACTIVE_CONTENT;
- } else if (hasMixedDisplay) {
- mixedContentLevel = MIXED_DISPLAY_CONTENT;
- }
- Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
-
- // record mixed object subrequest telemetry
- if (mHasMixedContentObjectSubrequest) {
- /* mixed object subrequest loaded on page*/
- Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 1);
- } else {
- /* no mixed object subrequests loaded on page*/
- Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 0);
- }
-
- // record CSP telemetry on this document
- if (mHasCSP) {
- Accumulate(Telemetry::CSP_DOCUMENTS_COUNT, 1);
- }
- if (mHasUnsafeInlineCSP) {
- Accumulate(Telemetry::CSP_UNSAFE_INLINE_DOCUMENTS_COUNT, 1);
- }
- if (mHasUnsafeEvalCSP) {
- Accumulate(Telemetry::CSP_UNSAFE_EVAL_DOCUMENTS_COUNT, 1);
- }
- }
- }
-
- ReportUseCounters();
-
mInDestructor = true;
mInUnlinkOrDeletion = true;
@@ -1648,10 +1590,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDocument, tmp->mRefCnt.get())
}
- // Always need to traverse script objects, so do that before we check
- // if we're uncollectable.
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-
if (!nsINode::Traverse(tmp, cb)) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
@@ -1737,8 +1675,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnDemandBuiltInUASheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPreloadingImages)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntersectionObservers)
-
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSubImportLinks)
for (uint32_t i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
@@ -9286,19 +9222,23 @@ already_AddRefed<nsIURI>
nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
- const nsAString& aSizesAttr)
+ const nsAString& aSizesAttr,
+ bool *aIsImgSet)
{
nsString sourceURL;
+ bool isImgSet;
if (mPreloadPictureDepth == 1 && !mPreloadPictureFoundSource.IsVoid()) {
// We're in a <picture> element and found a URI from a source previous to
// this image, use it.
sourceURL = mPreloadPictureFoundSource;
+ isImgSet = true;
} else {
// Otherwise try to use this <img> as a source
HTMLImageElement::SelectSourceForTagWithAttrs(this, false, aSrcAttr,
aSrcsetAttr, aSizesAttr,
NullString(), NullString(),
sourceURL);
+ isImgSet = !aSrcsetAttr.IsEmpty();
}
// Empty sources are not loaded by <img> (i.e. not resolved to the baseURI)
@@ -9316,6 +9256,8 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
return nullptr;
}
+ *aIsImgSet = isImgSet;
+
// We don't clear mPreloadPictureFoundSource because subsequent <img> tags in
// this this <picture> share the same <sources> (though this is not valid per
// spec)
@@ -9324,16 +9266,12 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
void
nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
- ReferrerPolicy aReferrerPolicy)
+ ReferrerPolicy aReferrerPolicy, bool aIsImgSet)
{
// Early exit if the img is already present in the img-cache
// which indicates that the "real" load has already started and
// that we shouldn't preload it.
- int16_t blockingStatus;
- if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this)) ||
- !nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
- this, NodePrincipal(), &blockingStatus,
- nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) {
+ if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this))) {
return;
}
@@ -9352,6 +9290,10 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
MOZ_CRASH("Unknown CORS mode!");
}
+ nsContentPolicyType policyType =
+ aIsImgSet ? nsIContentPolicy::TYPE_IMAGESET :
+ nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD;
+
// Image not in cache - trigger preload
RefPtr<imgRequestProxy> request;
nsresult rv =
@@ -9365,7 +9307,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
loadFlags,
NS_LITERAL_STRING("img"),
getter_AddRefs(request),
- nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD);
+ policyType);
// Pin image-reference to avoid evicting it from the img-cache before
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
@@ -12007,7 +11949,8 @@ nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
&aWindowSizes->mLayoutPresShellSize,
&aWindowSizes->mLayoutStyleSetsSize,
&aWindowSizes->mLayoutTextRunsSize,
- &aWindowSizes->mLayoutPresContextSize);
+ &aWindowSizes->mLayoutPresContextSize,
+ &aWindowSizes->mLayoutFramePropertiesSize);
}
aWindowSizes->mPropertyTablesSize +=
@@ -12356,134 +12299,27 @@ nsIDocument::InlineScriptAllowedByCSP()
return allowsInlineScript;
}
-static bool
-MightBeAboutOrChromeScheme(nsIURI* aURI)
-{
- MOZ_ASSERT(aURI);
- bool isAbout = true;
- bool isChrome = true;
- aURI->SchemeIs("about", &isAbout);
- aURI->SchemeIs("chrome", &isChrome);
- return isAbout || isChrome;
-}
-
-void
-nsDocument::ReportUseCounters()
-{
- static const bool sDebugUseCounters = false;
- if (mReportedUseCounters) {
- return;
- }
-
- mReportedUseCounters = true;
-
- if (Telemetry::HistogramUseCounterCount > 0 &&
- (IsContentDocument() || IsResourceDoc())) {
- nsCOMPtr<nsIURI> uri;
- NodePrincipal()->GetURI(getter_AddRefs(uri));
- if (!uri || MightBeAboutOrChromeScheme(uri)) {
- return;
- }
-
- if (sDebugUseCounters) {
- nsCString spec = uri->GetSpecOrDefault();
-
- // URIs can be rather long for data documents, so truncate them to
- // some reasonable length.
- spec.Truncate(std::min(128U, spec.Length()));
- printf("-- Use counters for %s --\n", spec.get());
- }
-
- // We keep separate counts for individual documents and top-level
- // pages to more accurately track how many web pages might break if
- // certain features were removed. Consider the case of a single
- // HTML document with several SVG images and/or iframes with
- // sub-documents of their own. If we maintained a single set of use
- // counters and all the sub-documents use a particular feature, then
- // telemetry would indicate that we would be breaking N documents if
- // that feature were removed. Whereas with a document/top-level
- // page split, we can see that N documents would be affected, but
- // only a single web page would be affected.
-
- // The difference between the values of these two histograms and the
- // related use counters below tell us how many pages did *not* use
- // the feature in question. For instance, if we see that a given
- // session has destroyed 30 content documents, but a particular use
- // counter shows only a count of 5, we can infer that the use
- // counter was *not* used in 25 of those 30 documents.
- //
- // We do things this way, rather than accumulating a boolean flag
- // for each use counter, to avoid sending histograms for features
- // that don't get widely used. Doing things in this fashion means
- // smaller telemetry payloads and faster processing on the server
- // side.
- Telemetry::Accumulate(Telemetry::CONTENT_DOCUMENTS_DESTROYED, 1);
- if (IsTopLevelContentDocument()) {
- Telemetry::Accumulate(Telemetry::TOP_LEVEL_CONTENT_DOCUMENTS_DESTROYED, 1);
- }
-
- for (int32_t c = 0;
- c < eUseCounter_Count; ++c) {
- UseCounter uc = static_cast<UseCounter>(c);
-
- Telemetry::ID id =
- static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter + uc * 2);
- bool value = GetUseCounter(uc);
-
- if (value) {
- if (sDebugUseCounters) {
- const char* name = Telemetry::GetHistogramName(id);
- if (name) {
- printf(" %s", name);
- } else {
- printf(" #%d", id);
- }
- printf(": %d\n", value);
- }
-
- Telemetry::Accumulate(id, 1);
- }
-
- if (IsTopLevelContentDocument()) {
- id = static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter +
- uc * 2 + 1);
- value = GetUseCounter(uc) || GetChildDocumentUseCounter(uc);
-
- if (value) {
- if (sDebugUseCounters) {
- const char* name = Telemetry::GetHistogramName(id);
- if (name) {
- printf(" %s", name);
- } else {
- printf(" #%d", id);
- }
- printf(": %d\n", value);
- }
-
- Telemetry::Accumulate(id, 1);
- }
- }
- }
- }
-}
-
void
nsDocument::AddIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- NS_ASSERTION(mIntersectionObservers.IndexOf(aObserver) == nsTArray<int>::NoIndex,
- "Intersection observer already in the list");
- mIntersectionObservers.AppendElement(aObserver);
+ MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
+ "Intersection observer already in the list");
+ mIntersectionObservers.PutEntry(aObserver);
}
void
nsDocument::RemoveIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- mIntersectionObservers.RemoveElement(aObserver);
+ mIntersectionObservers.RemoveEntry(aObserver);
}
void
nsDocument::UpdateIntersectionObservations()
{
+ if (mIntersectionObservers.IsEmpty()) {
+ return;
+ }
+
DOMHighResTimeStamp time = 0;
if (nsPIDOMWindowInner* window = GetInnerWindow()) {
Performance* perf = window->GetPerformance();
@@ -12491,25 +12327,42 @@ nsDocument::UpdateIntersectionObservations()
time = perf->Now();
}
}
- for (const auto& observer : mIntersectionObservers) {
- observer->Update(this, time);
+ nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
+ for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Get()->GetKey();
+ observers.AppendElement(observer);
+ }
+ for (const auto& observer : observers) {
+ if (observer) {
+ observer->Update(this, time);
+ }
}
}
void
nsDocument::ScheduleIntersectionObserverNotification()
{
+ if (mIntersectionObservers.IsEmpty()) {
+ return;
+ }
+
nsCOMPtr<nsIRunnable> notification = NewRunnableMethod(this,
&nsDocument::NotifyIntersectionObservers);
- NS_DispatchToCurrentThread(notification);
+ NS_DispatchToCurrentThread(notification.forget());
}
void
nsDocument::NotifyIntersectionObservers()
{
- nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers);
+ nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
+ for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Get()->GetKey();
+ observers.AppendElement(observer);
+ }
for (const auto& observer : observers) {
- observer->Notify();
+ if (observer) {
+ observer->Notify();
+ }
}
}