Bug 1384741 - Part 1: Add facility to buffer up CSP violation reports. r?bholley
MozReview-Commit-ID: G4JLTmP1wD7
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1348,16 +1348,17 @@ nsIDocument::nsIDocument()
mGetUserFontSetCalled(false),
mPostedFlushUserFontSet(false),
mDidFireDOMContentLoaded(true),
mHasScrollLinkedEffect(false),
mFrameRequestCallbacksScheduled(false),
mIsTopLevelContentDocument(false),
mIsContentDocument(false),
mMightHaveStaleServoData(false),
+ mBufferingCSPViolations(false),
mIsScopedStyleEnabled(eScopedStyle_Unknown),
mCompatMode(eCompatibility_FullStandards),
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
mStyleBackendType(StyleBackendType::None),
#ifdef MOZILLA_INTERNAL_API
mVisibilityState(dom::VisibilityState::Hidden),
#else
mDummy(0),
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -831,16 +831,62 @@ public:
* @see nsSandboxFlags.h for the possible flags
*/
void SetSandboxFlags(uint32_t sandboxFlags)
{
mSandboxFlags = sandboxFlags;
}
/**
+ * After calling this function, any CSP violation reports will be buffered up
+ * by the document (by calling ReportCSPViolation) instead of being sent
+ * immediately.
+ *
+ * This facility is used by the user font cache, which wants to pre-emptively
+ * check whether a given font load would violate CSP directives, and so
+ * shouldn't immediately send the report.
+ */
+ void StartBufferingCSPViolations()
+ {
+ MOZ_ASSERT(!mBufferingCSPViolations);
+ mBufferingCSPViolations = true;
+ }
+
+ /**
+ * Stops buffering CSP violation reports, and stores any buffered reports in
+ * aResult.
+ */
+ void StopBufferingCSPViolations(nsTArray<nsCOMPtr<nsIRunnable>>& aResult)
+ {
+ MOZ_ASSERT(mBufferingCSPViolations);
+ mBufferingCSPViolations = false;
+
+ aResult.SwapElements(mBufferedCSPViolations);
+ mBufferedCSPViolations.Clear();
+ }
+
+ /**
+ * Returns whether we are currently buffering CSP violation reports.
+ */
+ bool ShouldReportCSPViolationsToDocument() const
+ {
+ return mBufferingCSPViolations;
+ }
+
+ /**
+ * Called when a CSP violation is encountered that would generate a report
+ * while buffering is enabled.
+ */
+ void ReportCSPViolation(nsIRunnable* aReportingRunnable)
+ {
+ MOZ_ASSERT(mBufferingCSPViolations);
+ mBufferedCSPViolations.AppendElement(aReportingRunnable);
+ }
+
+ /**
* Access HTTP header data (this may also get set from other
* sources, like HTML META tags).
*/
virtual void GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const = 0;
virtual void SetHeaderData(nsIAtom* aheaderField, const nsAString& aData) = 0;
/**
* Create a new presentation shell that will use aContext for its
@@ -3301,16 +3347,20 @@ protected:
bool mIsTopLevelContentDocument : 1;
bool mIsContentDocument : 1;
// True if there may be Servo element data on Elements in the document that
// were created for a pres shell that no longer exists.
bool mMightHaveStaleServoData : 1;
+ // True if any CSP violation reports for this doucment will be buffered in
+ // mBufferedCSPViolations instead of being sent immediately.
+ bool mBufferingCSPViolations : 1;
+
// Whether <style scoped> support is enabled in this document.
enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
unsigned int mIsScopedStyleEnabled : 2;
// Compatibility mode
nsCompatibility mCompatMode;
// Our readyState
@@ -3481,16 +3531,20 @@ protected:
mozilla::TimeStamp mPageUnloadingEventTimeStamp;
RefPtr<mozilla::dom::DocGroup> mDocGroup;
// The set of all the tracking script URLs. URLs are added to this set by
// calling NoteScriptTrackingStatus(). Currently we assume that a URL not
// existing in the set means the corresponding script isn't a tracking script.
nsTHashtable<nsCStringHashKey> mTrackingScripts;
+
+ // CSP violation reports that have been buffered up due to a call to
+ // StartBufferingCSPViolations.
+ nsTArray<nsCOMPtr<nsIRunnable>> mBufferedCSPViolations;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
/**
* mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
* event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
* object is deleted.
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -1232,16 +1232,24 @@ nsCSPContext::AsyncReportViolation(nsISu
mPolicies[aViolatedPolicyIndex]->getReportOnlyFlag(),
aViolatedDirective,
aObserverSubject,
aSourceFile,
aScriptSample,
aLineNum,
this);
+ // If the document is currently buffering up CSP violation reports, send the
+ // runnable to it instead of dispatching it immediately.
+ nsCOMPtr<nsIDocument> doc = do_QueryReferent(mLoadingContext);
+ if (doc && doc->ShouldReportCSPViolationsToDocument()) {
+ doc->ReportCSPViolation(task);
+ return NS_OK;
+ }
+
if (XRE_IsContentProcess()) {
if (mEventTarget) {
mEventTarget->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
return NS_OK;
}
}
NS_DispatchToMainThread(task.forget());