Backed out 9 changesets (bug 1637487) for bustages on nsMixedContentBlocker.cpp . CLOSED TREE

Backed out changeset 5633cc2aaa9b (bug 1637487)
Backed out changeset c4f0c757cae0 (bug 1637487)
Backed out changeset 65bb1114df87 (bug 1637487)
Backed out changeset 1a64ef10e773 (bug 1637487)
Backed out changeset d1709ebb7f46 (bug 1637487)
Backed out changeset 286e5ee6517f (bug 1637487)
Backed out changeset 83362625c297 (bug 1637487)
Backed out changeset ab9df2f2d11f (bug 1637487)
Backed out changeset b83f49bc11b0 (bug 1637487)
This commit is contained in:
Narcis Beleuzu 2020-05-14 02:41:40 +03:00
Родитель 5a8efe4876
Коммит 53167b2819
3 изменённых файлов: 297 добавлений и 99 удалений

Просмотреть файл

@ -1251,6 +1251,10 @@ Document::Document(const char* aContentType)
mFlushingPendingLinkUpdates(false),
mMayHaveDOMMutationObservers(false),
mMayHaveAnimationObservers(false),
mHasMixedActiveContentLoaded(false),
mHasMixedActiveContentBlocked(false),
mHasMixedDisplayContentLoaded(false),
mHasMixedDisplayContentBlocked(false),
mHasCSP(false),
mHasUnsafeEvalCSP(false),
mHasUnsafeInlineCSP(false),

Просмотреть файл

@ -1048,91 +1048,55 @@ class Document : public nsINode,
/**
* Get the has mixed active content loaded flag for this document.
*/
bool GetHasMixedActiveContentLoaded() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
bool GetHasMixedActiveContentLoaded() { return mHasMixedActiveContentLoaded; }
/**
* Set the has mixed active content loaded flag for this document.
*/
void SetHasMixedActiveContentLoaded(bool aHasMixedActiveContentLoaded) {
if (aHasMixedActiveContentLoaded) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
mHasMixedActiveContentLoaded = aHasMixedActiveContentLoaded;
}
/**
* Get mixed active content blocked flag for this document.
*/
bool GetHasMixedActiveContentBlocked() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
return mHasMixedActiveContentBlocked;
}
/**
* Set the mixed active content blocked flag for this document.
*/
void SetHasMixedActiveContentBlocked(bool aHasMixedActiveContentBlocked) {
if (aHasMixedActiveContentBlocked) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
}
mHasMixedActiveContentBlocked = aHasMixedActiveContentBlocked;
}
/**
* Get the has mixed display content loaded flag for this document.
*/
bool GetHasMixedDisplayContentLoaded() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
return mHasMixedDisplayContentLoaded;
}
/**
* Set the has mixed display content loaded flag for this document.
*/
void SetHasMixedDisplayContentLoaded(bool aHasMixedDisplayContentLoaded) {
if (aHasMixedDisplayContentLoaded) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
mHasMixedDisplayContentLoaded = aHasMixedDisplayContentLoaded;
}
/**
* Get mixed display content blocked flag for this document.
*/
bool GetHasMixedDisplayContentBlocked() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
return mHasMixedDisplayContentBlocked;
}
/**
* Set the mixed display content blocked flag for this document.
*/
void SetHasMixedDisplayContentBlocked(bool aHasMixedDisplayContentBlocked) {
if (aHasMixedDisplayContentBlocked) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
}
}
uint32_t GetMixedContentFlags() const { return mMixedContentFlags; }
void AddMixedContentFlags(uint32_t aMixedContentFlags) {
mMixedContentFlags |= aMixedContentFlags;
mHasMixedDisplayContentBlocked = aHasMixedDisplayContentBlocked;
}
/**
@ -4380,8 +4344,6 @@ class Document : public nsINode,
// GetPermissionDelegateHandler
RefPtr<PermissionDelegateHandler> mPermissionDelegateHandler;
uint32_t mMixedContentFlags = 0;
// True if BIDI is enabled.
bool mBidiEnabled : 1;
// True if we may need to recompute the language prefs for this document.
@ -4475,6 +4437,22 @@ class Document : public nsINode,
// document.
bool mMayHaveAnimationObservers : 1;
// True if a document has loaded Mixed Active Script (see
// nsMixedContentBlocker.cpp)
bool mHasMixedActiveContentLoaded : 1;
// True if a document has blocked Mixed Active Script (see
// nsMixedContentBlocker.cpp)
bool mHasMixedActiveContentBlocked : 1;
// True if a document has loaded Mixed Display/Passive Content (see
// nsMixedContentBlocker.cpp)
bool mHasMixedDisplayContentLoaded : 1;
// True if a document has blocked Mixed Display/Passive Content (see
// nsMixedContentBlocker.cpp)
bool mHasMixedDisplayContentBlocked : 1;
// True if a document load has a CSP attached.
bool mHasCSP : 1;

Просмотреть файл

@ -62,6 +62,151 @@ enum MixedContentHSTSState {
MCB_HSTS_ACTIVE_WITH_HSTS = 3
};
// Fired at the document that attempted to load mixed content. The UI could
// handle this event, for example, by displaying an info bar that offers the
// choice to reload the page with mixed content permitted.
class nsMixedContentEvent : public Runnable {
public:
nsMixedContentEvent(nsISupports* aContext, MixedContentTypes aType,
bool aRootHasSecureConnection)
: mozilla::Runnable("nsMixedContentEvent"),
mContext(aContext),
mType(aType),
mRootHasSecureConnection(aRootHasSecureConnection) {}
NS_IMETHOD Run() override {
NS_ASSERTION(mContext,
"You can't call this runnable without a requesting context");
// To update the security UI in the tab with the blocked mixed content, call
// nsDocLoader::OnSecurityChange.
// Mixed content was allowed and is about to load; get the document and
// set the approriate flag to true if we are about to load Mixed Active
// Content.
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(mContext);
if (!docShell) {
return NS_OK;
}
nsCOMPtr<nsIDocShell> rootShell =
docShell->GetBrowsingContext()->Top()->GetDocShell();
if (!rootShell) {
return NS_OK;
}
// now get the document from sameTypeRoot
nsCOMPtr<Document> rootDoc = rootShell->GetDocument();
NS_ASSERTION(rootDoc,
"No root document from document shell root tree item.");
nsDocShell* nativeDocShell = nsDocShell::Cast(docShell);
uint32_t state = nsIWebProgressListener::STATE_IS_BROKEN;
nsCOMPtr<nsISecureBrowserUI> securityUI;
rootShell->GetSecurityUI(getter_AddRefs(securityUI));
// If there is no securityUI, document doesn't have a security state to
// update. But we still want to set the document flags, so we don't return
// early.
nsresult stateRV = NS_ERROR_FAILURE;
if (securityUI) {
stateRV = securityUI->GetState(&state);
}
if (mType == eMixedScript) {
// See if the pref will change here. If it will, only then do we need to
// call OnSecurityChange() to update the UI.
if (rootDoc->GetHasMixedActiveContentLoaded()) {
return NS_OK;
}
rootDoc->SetHasMixedActiveContentLoaded(true);
// Update the security UI in the tab with the allowed mixed active content
if (securityUI) {
// Bug 1182551 - before changing the security state to broken, check
// that the root is actually secure.
if (mRootHasSecureConnection) {
// reset state security flag
state = state >> 4 << 4;
// set state security flag to broken, since there is mixed content
state |= nsIWebProgressListener::STATE_IS_BROKEN;
// If mixed display content is loaded, make sure to include that in
// the state.
if (rootDoc->GetHasMixedDisplayContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
nativeDocShell->nsDocLoader::OnSecurityChange(
mContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
} else {
// root not secure, mixed active content loaded in an https subframe
if (NS_SUCCEEDED(stateRV)) {
nativeDocShell->nsDocLoader::OnSecurityChange(
mContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
}
}
}
} else if (mType == eMixedDisplay) {
// See if the pref will change here. If it will, only then do we need to
// call OnSecurityChange() to update the UI.
if (rootDoc->GetHasMixedDisplayContentLoaded()) {
return NS_OK;
}
rootDoc->SetHasMixedDisplayContentLoaded(true);
// Update the security UI in the tab with the allowed mixed display
// content.
if (securityUI) {
// Bug 1182551 - before changing the security state to broken, check
// that the root is actually secure.
if (mRootHasSecureConnection) {
// reset state security flag
state = state >> 4 << 4;
// set state security flag to broken, since there is mixed content
state |= nsIWebProgressListener::STATE_IS_BROKEN;
// If mixed active content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedActiveContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
nativeDocShell->nsDocLoader::OnSecurityChange(
mContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
} else {
// root not secure, mixed display content loaded in an https subframe
if (NS_SUCCEEDED(stateRV)) {
nativeDocShell->nsDocLoader::OnSecurityChange(
mContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
}
}
}
}
return NS_OK;
}
private:
// The requesting context for the content load. Generally, a DOM node from
// the document that caused the load.
nsCOMPtr<nsISupports> mContext;
// The type of mixed content detected, e.g. active or display
const MixedContentTypes mType;
// Indicates whether the top level load is https or not.
bool mRootHasSecureConnection;
};
nsMixedContentBlocker::~nsMixedContentBlocker() = default;
NS_IMPL_ISUPPORTS(nsMixedContentBlocker, nsIContentPolicy, nsIChannelEventSink)
@ -749,6 +894,11 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
}
uint64_t topInnerWindowID =
docShell->GetBrowsingContext()->GetTopWindowContext()->Id();
nsDocShell* nativeDocShell = nsDocShell::Cast(docShell);
uint32_t state = nsIWebProgressListener::STATE_IS_BROKEN;
nsCOMPtr<nsISecureBrowserUI> securityUI;
rootShell->GetSecurityUI(getter_AddRefs(securityUI));
// If there is no securityUI, document doesn't have a security state.
@ -757,6 +907,7 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
*aDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
nsresult stateRV = securityUI->GetState(&state);
OriginAttributes originAttributes;
if (loadingPrincipal) {
@ -804,79 +955,144 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
}
uint32_t newState = 0;
// If the content is display content, and the pref says display content should
// be blocked, block it.
if (classification == eMixedDisplay) {
if (!StaticPrefs::security_mixed_content_block_display_content() ||
allowMixedContent) {
if (StaticPrefs::security_mixed_content_block_display_content() &&
classification == eMixedDisplay) {
if (allowMixedContent) {
LogMixedContentMessage(classification, aContentLocation, topInnerWindowID,
eUserOverride, requestingLocation);
*aDecision = nsIContentPolicy::ACCEPT;
// User has overriden the pref and the root is not https;
// mixed display content was allowed on an https subframe.
newState |= nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
// See if mixed display content has already loaded on the page or if the
// state needs to be updated here. If mixed display hasn't loaded
// previously, then we need to call OnSecurityChange() to update the UI.
if (rootDoc->GetHasMixedDisplayContentLoaded()) {
return NS_OK;
}
rootDoc->SetHasMixedDisplayContentLoaded(true);
if (rootHasSecureConnection) {
// reset state security flag
state = state >> 4 << 4;
// set state security flag to broken, since there is mixed content
state |= nsIWebProgressListener::STATE_IS_BROKEN;
// If mixed active content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedActiveContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
nativeDocShell->nsDocLoader::OnSecurityChange(
requestingContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
} else {
// User has overriden the pref and the root is not https;
// mixed display content was allowed on an https subframe.
if (NS_SUCCEEDED(stateRV)) {
nativeDocShell->nsDocLoader::OnSecurityChange(
requestingContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
}
}
} else {
*aDecision = nsIContentPolicy::REJECT_REQUEST;
newState |= nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
LogMixedContentMessage(classification, aContentLocation, topInnerWindowID,
eBlocked, requestingLocation);
if (!rootDoc->GetHasMixedDisplayContentBlocked() &&
NS_SUCCEEDED(stateRV)) {
rootDoc->SetHasMixedDisplayContentBlocked(true);
nativeDocShell->nsDocLoader::OnSecurityChange(
requestingContext,
(state |
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT));
}
}
} else {
MOZ_ASSERT(classification == eMixedScript);
return NS_OK;
} else if (StaticPrefs::security_mixed_content_block_active_content() &&
classification == eMixedScript) {
// If the content is active content, and the pref says active content should
// be blocked, block it unless the user has choosen to override the pref
if (!StaticPrefs::security_mixed_content_block_active_content() ||
allowMixedContent) {
if (allowMixedContent) {
LogMixedContentMessage(classification, aContentLocation, topInnerWindowID,
eUserOverride, requestingLocation);
*aDecision = nsIContentPolicy::ACCEPT;
// User has already overriden the pref and the root is not https;
// mixed active content was allowed on an https subframe.
newState |= nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
// See if the state will change here. If it will, only then do we need to
// call OnSecurityChange() to update the UI.
if (rootDoc->GetHasMixedActiveContentLoaded()) {
return NS_OK;
}
rootDoc->SetHasMixedActiveContentLoaded(true);
if (rootHasSecureConnection) {
// reset state security flag
state = state >> 4 << 4;
// set state security flag to broken, since there is mixed content
state |= nsIWebProgressListener::STATE_IS_BROKEN;
// If mixed display content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedDisplayContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
nativeDocShell->nsDocLoader::OnSecurityChange(
requestingContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
return NS_OK;
} else {
// User has already overriden the pref and the root is not https;
// mixed active content was allowed on an https subframe.
if (NS_SUCCEEDED(stateRV)) {
nativeDocShell->nsDocLoader::OnSecurityChange(
requestingContext,
(state |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
}
return NS_OK;
}
} else {
// User has not overriden the pref by Disabling protection. Reject the
// request and update the security state.
*aDecision = nsIContentPolicy::REJECT_REQUEST;
LogMixedContentMessage(classification, aContentLocation, topInnerWindowID,
eBlocked, requestingLocation);
// See if the pref will change here. If it will, only then do we need to
// call OnSecurityChange() to update the UI.
if (rootDoc->GetHasMixedActiveContentBlocked()) {
return NS_OK;
}
rootDoc->SetHasMixedActiveContentBlocked(true);
// The user has not overriden the pref, so make sure they still have an
// option by calling nativeDocShell which will invoke the doorhanger
newState |= nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
if (NS_SUCCEEDED(stateRV)) {
nativeDocShell->nsDocLoader::OnSecurityChange(
requestingContext,
(state |
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT));
}
return NS_OK;
}
}
} else {
// The content is not blocked by the mixed content prefs.
LogMixedContentMessage(classification, aContentLocation, topWC->Id(),
(*aDecision == nsIContentPolicy::REJECT_REQUEST)
? eBlocked
: eUserOverride,
requestingLocation);
// Log a message that we are loading mixed content.
LogMixedContentMessage(classification, aContentLocation, topInnerWindowID,
eUserOverride, requestingLocation);
if (rootDoc->GetMixedContentFlags() == newState) {
// Fire the event from a script runner as it is unsafe to run script
// from within ShouldLoad
nsContentUtils::AddScriptRunner(new nsMixedContentEvent(
requestingContext, classification, rootHasSecureConnection));
*aDecision = ACCEPT;
return NS_OK;
}
// Copy the new state onto the Document flags.
rootDoc->AddMixedContentFlags(newState);
uint32_t state = nsIWebProgressListener::STATE_IS_BROKEN;
MOZ_ALWAYS_SUCCEEDS(securityUI->GetState(&state));
if (*aDecision == nsIContentPolicy::ACCEPT && rootHasSecureConnection) {
// reset state security flag
state = state >> 4 << 4;
// set state security flag to broken, since there is mixed content
state |= nsIWebProgressListener::STATE_IS_BROKEN;
// If mixed display content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedDisplayContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
// If mixed active content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedActiveContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
}
state |= newState;
nsDocShell* nativeDocShell = nsDocShell::Cast(docShell);
nativeDocShell->nsDocLoader::OnSecurityChange(requestingContext, state);
return NS_OK;
}
bool nsMixedContentBlocker::URISafeToBeLoadedInSecureContext(nsIURI* aURI) {