Bug 822367 - Plumbing needed to show user Mixed Content Blocker Doorhanger when Mixed Active Content is Blocked and allow user an option to load the inseucre content anyway. r=smaug

This commit is contained in:
Tanvi Vyas 2013-01-30 00:04:31 -08:00
Родитель 7d786d459c
Коммит c3eedfc7b5
9 изменённых файлов: 248 добавлений и 19 удалений

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

@ -102,8 +102,8 @@ template<typename> class Sequence;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x2df7f766, 0xf70b, 0x4de4, \
{ 0xb0, 0xba, 0x78, 0x25, 0x07, 0x41, 0xd6, 0xce } }
{ 0x4e6f7d97, 0x091e, 0x4eda, \
{ 0xb7, 0xd6, 0xfe, 0xb0, 0xb8, 0x01, 0x2a, 0x93 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -446,6 +446,21 @@ public:
mHasMixedActiveContentLoaded = aHasMixedActiveContentLoaded;
}
/**
* Get mixed active content blocked flag for this document.
*/
bool GetHasMixedActiveContentBlocked()
{
return mHasMixedActiveContentBlocked;
}
/**
* Set the mixed active content blocked flag for this document.
*/
void SetHasMixedActiveContentBlocked(bool aHasMixedActiveContentBlocked)
{
mHasMixedActiveContentBlocked = aHasMixedActiveContentBlocked;
}
/**
* Get the sandbox flags for this document.
@ -2166,6 +2181,9 @@ protected:
// True if a document has loaded Mixed Active Script (see nsMixedContentBlocker.cpp)
bool mHasMixedActiveContentLoaded;
// True if a document has blocked Mixed Active Script (see nsMixedContentBlocker.cpp)
bool mHasMixedActiveContentBlocked;
// True if DisallowBFCaching has been called on this document.
bool mBFCacheDisallowed;

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

@ -21,6 +21,9 @@
#include "nsIHttpChannel.h"
#include "mozilla/Preferences.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsISecureBrowserUI.h"
#include "nsIDocumentLoader.h"
#include "nsLoadGroup.h"
#include "prlog.h"
@ -74,7 +77,7 @@ public:
if (mType == eMixedScript) {
rootDoc->SetHasMixedActiveContentLoaded(true);
// Update the security UI in the tab with the blocked mixed content
// Update the security UI in the tab with the allowed mixed content
nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell);
if (eventSink) {
eventSink->OnSecurityChange(mContext, nsIWebProgressListener::STATE_IS_BROKEN);
@ -324,11 +327,77 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
}
// If we are here we have mixed content.
// Determine if the rootDoc is https and if the user decided to allow Mixed Content
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
NS_ENSURE_TRUE(docShell, NS_OK);
bool rootHasSecureConnection = false;
bool allowMixedContent = false;
rv = docShell->GetAllowMixedContentAndConnectionData(&rootHasSecureConnection, &allowMixedContent);
if (NS_FAILED(rv)) {
return rv;
}
// Get the root document from the docshell
nsCOMPtr<nsIDocShellTreeItem> currentDocShellTreeItem(do_QueryInterface(docShell));
NS_ASSERTION(currentDocShellTreeItem, "No DocShellTreeItem from docshell");
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
currentDocShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
nsCOMPtr<nsIDocument> rootDoc = do_GetInterface(sameTypeRoot);
NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");
// If the content is display content, and the pref says display content should be blocked, block it.
// If the content is mixed content, and the pref says mixed content should be blocked, block it.
if ( (sBlockMixedDisplay && classification == eMixedDisplay) || (sBlockMixedScript && classification == eMixedScript) ) {
*aDecision = nsIContentPolicy::REJECT_REQUEST;
if (sBlockMixedDisplay && classification == eMixedDisplay) {
if (allowMixedContent) {
*aDecision = nsIContentPolicy::ACCEPT;
rootDoc->SetHasMixedActiveContentLoaded(true);
} else {
*aDecision = nsIContentPolicy::REJECT_REQUEST;
}
return NS_OK;
} else if (sBlockMixedScript && 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 (allowMixedContent) {
*aDecision = nsIContentPolicy::ACCEPT;
rootDoc->SetHasMixedActiveContentLoaded(true);
} else {
*aDecision = nsIContentPolicy::REJECT_REQUEST;
rootDoc->SetHasMixedActiveContentBlocked(true);
}
// Call eventsink to invoke the Mixed Content UI
nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell);
if (eventSink) {
if (!allowMixedContent) {
// The user has not overriden the pref, so make sure they still have an option by calling eventSink
// which will invoke the doorhanger
nsCOMPtr<nsIDocShell> rootShell = do_GetInterface(sameTypeRoot);
NS_ASSERTION(rootShell, "No root docshell from document shell root tree item.");
uint32_t State;
nsCOMPtr<nsISecureBrowserUI> SecurityUI;
rootShell->GetSecurityUI(getter_AddRefs(SecurityUI));
if (SecurityUI) {
nsresult rv = SecurityUI->GetState(&State);
if (NS_SUCCEEDED(rv)) {
eventSink->OnSecurityChange(aRequestingContext, State);
}
}
return NS_OK;
} else if (rootHasSecureConnection) {
// User has decided to override the pref and the root is https, so change the Security State.
eventSink->OnSecurityChange(aRequestingContext, nsIWebProgressListener::STATE_IS_BROKEN);
return NS_OK;
} else if (!rootHasSecureConnection) {
// User has already overriden the pref and the root is not https;
// mixed content was allowed on an https subframe.
// In this case, we do nothing since we don't need a doorhanger and we don't want
// to change the Security UI of an http page
return NS_OK;
}
}
} else {
// The content is not blocked by the mixed content prefs.

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

@ -74,6 +74,8 @@
#include "nsIPrivacyTransitionObserver.h"
#include "nsCPrefetchService.h"
#include "nsJSON.h"
#include "nsIDocShellTreeItem.h"
#include "nsIChannel.h"
#include "IHistory.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
@ -1145,6 +1147,9 @@ ConvertDocShellLoadInfoToLoadType(nsDocShellInfoLoadType aDocShellLoadType)
case nsIDocShellLoadInfo::loadReplaceBypassCache:
loadType = LOAD_REPLACE_BYPASS_CACHE;
break;
case nsIDocShellLoadInfo::loadMixedContent:
loadType = LOAD_MIXED_CONTENT;
break;
default:
NS_NOTREACHED("Unexpected nsDocShellInfoLoadType value");
}
@ -1216,6 +1221,9 @@ nsDocShell::ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType)
case LOAD_REPLACE_BYPASS_CACHE:
docShellLoadType = nsIDocShellLoadInfo::loadReplaceBypassCache;
break;
case LOAD_MIXED_CONTENT:
docShellLoadType = nsIDocShellLoadInfo::loadMixedContent;
break;
default:
NS_NOTREACHED("Unexpected load type value");
}
@ -1960,13 +1968,21 @@ nsDocShell::GetChannelIsUnsafe(bool *aUnsafe)
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentLoaded(bool *aHasMixedActiveContentLoaded)
nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded)
{
nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
*aHasMixedActiveContentLoaded = doc && doc->GetHasMixedActiveContentLoaded();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentBlocked(bool* aHasMixedActiveContentBlocked)
{
nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
*aHasMixedActiveContentBlocked = doc && doc->GetHasMixedActiveContentBlocked();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetAllowPlugins(bool * aAllowPlugins)
{
@ -5310,6 +5326,68 @@ nsDocShell::GetSandboxFlags(uint32_t *aSandboxFlags)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetMixedContentChannel(nsIChannel* aMixedContentChannel)
{
#ifdef DEBUG
// Get the root docshell.
nsCOMPtr<nsIDocShellTreeItem> root;
GetSameTypeRootTreeItem(getter_AddRefs(root));
NS_WARN_IF_FALSE(
root.get() == static_cast<nsIDocShellTreeItem *>(this),
"Setting mMixedContentChannel on a docshell that is not the root docshell"
);
#endif
mMixedContentChannel = aMixedContentChannel;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetMixedContentChannel(nsIChannel **aMixedContentChannel)
{
NS_ENSURE_ARG_POINTER(aMixedContentChannel);
NS_IF_ADDREF(*aMixedContentChannel = mMixedContentChannel);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetAllowMixedContentAndConnectionData(bool* aRootHasSecureConnection, bool* aAllowMixedContent)
{
*aRootHasSecureConnection = false;
*aAllowMixedContent = false;
nsCOMPtr<nsIDocShellTreeItem> currentDocShellTreeItem = static_cast<nsIDocShellTreeItem *>(this);
NS_ASSERTION(currentDocShellTreeItem, "No DocShellTreeItem from docshell");
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
currentDocShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
// now get the document from sameTypeRoot
nsCOMPtr<nsIDocument> rootDoc = do_GetInterface(sameTypeRoot);
NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");
// nsCOMPtr<nsIScriptObjectPrincipal> prin = do_QueryInterface(rootDoc);
// nsCOMPtr<nsIPrincipal> rootPrincipal = prin->GetPrincipal();
nsCOMPtr<nsIPrincipal> rootPrincipal = rootDoc->NodePrincipal();
NS_ASSERTION(rootPrincipal, "No root principal from root document");
nsCOMPtr<nsIURI> rootUri;
rootPrincipal->GetURI(getter_AddRefs(rootUri));
NS_ASSERTION(rootUri, "No root uri from root principal");
nsresult rv = rootUri->SchemeIs("https", aRootHasSecureConnection);
NS_ENSURE_SUCCESS(rv, rv);
// Check the root doc's channel against the root docShell's mMixedContentChannel to see
// if they are the same. If they are the same, the user has overriden
// the block.
nsCOMPtr<nsIDocShell> rootDocShell = do_GetInterface(sameTypeRoot);
nsCOMPtr<nsIChannel> mixedChannel;
rootDocShell->GetMixedContentChannel(getter_AddRefs(mixedChannel));
*aAllowMixedContent = mixedChannel && (mixedChannel == rootDoc->GetChannel());
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetVisibility(bool aVisibility)
{
@ -9328,6 +9406,14 @@ nsDocShell::DoURILoad(nsIURI * aURI,
}
}
if (mLoadType == LOAD_MIXED_CONTENT) {
rv = SetMixedContentChannel(channel);
NS_ENSURE_SUCCESS(rv, rv);
} else {
rv = SetMixedContentChannel(nullptr);
NS_ENSURE_SUCCESS(rv, rv);
}
//hack
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(channel));

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

@ -745,6 +745,10 @@ protected:
nsCOMPtr<nsIChannel> mFailedChannel;
uint32_t mFailedLoadType;
// Set in DoURILoad when the LOAD_MIXED_CONTENT flag is set.
// Checked in nsMixedContentBlocker, to see if the channels match.
nsCOMPtr<nsIChannel> mMixedContentChannel;
// WEAK REFERENCES BELOW HERE.
// Note these are intentionally not addrefd. Doing so will create a cycle.
// For that reasons don't use nsCOMPtr.

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

@ -28,8 +28,7 @@
* above 0xffff (e.g. LOAD_FLAGS_BYPASS_CLASSIFIER), since MAKE_LOAD_TYPE would
* just shift them out anyway.
*/
#define EXTRA_LOAD_FLAGS (LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | \
LOAD_FLAGS_FIRST_LOAD | \
#define EXTRA_LOAD_FLAGS (LOAD_FLAGS_FIRST_LOAD | \
LOAD_FLAGS_ALLOW_POPUPS | \
0xffff0000)
@ -61,6 +60,7 @@ enum LoadType {
LOAD_STOP_CONTENT_AND_REPLACE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT | nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY),
LOAD_PUSHSTATE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_PUSHSTATE, nsIWebNavigation::LOAD_FLAGS_NONE),
LOAD_REPLACE_BYPASS_CACHE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY | nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE),
LOAD_MIXED_CONTENT = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_ALLOW_MIXED_CONTENT),
/**
* Load type for an error page. These loads are never triggered by users of
* Docshell. Instead, Docshell triggers the load itself when a
@ -93,6 +93,7 @@ static inline bool IsValidLoadType(uint32_t aLoadType)
case LOAD_STOP_CONTENT_AND_REPLACE:
case LOAD_PUSHSTATE:
case LOAD_REPLACE_BYPASS_CACHE:
case LOAD_MIXED_CONTENT:
case LOAD_ERROR_PAGE:
return true;
}

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

@ -39,7 +39,7 @@ interface nsIWebBrowserPrint;
interface nsIVariant;
interface nsIPrivacyTransitionObserver;
[scriptable, builtinclass, uuid(ca15d803-1330-4154-b3f9-063fb2b443e7)]
[scriptable, builtinclass, uuid(5ea80008-a166-4692-8a7e-39690dd192c6)]
interface nsIDocShell : nsISupports
{
/**
@ -476,6 +476,18 @@ interface nsIDocShell : nsISupports
*/
readonly attribute boolean hasMixedActiveContentLoaded;
/**
* This attribute determines whether a document has Mixed Active Content
* that has been blocked from loading. When it is true, there is definitely
* mixed active content on a page that has been blocked by
* nsMixedContentBlocker. When it is false, there may or may not be mixed
* active content on a page, but if there is, it will load. Note that if the
* about:config setting security.mixed_content.block_active_content is set
* false, this boolean will be false, since blocking active content has been
* disabled.
*/
readonly attribute boolean hasMixedActiveContentBlocked;
/**
* Disconnects this docshell's editor from its window, and stores the
* editor data in the open document's session history entry. This
@ -703,6 +715,34 @@ interface nsIDocShell : nsISupports
*/
attribute unsigned long sandboxFlags;
/**
* This member variable determines whether a document has Mixed Active Content that
* was initially blocked from loading, but the user has choosen to override the
* block and allow the content to load. mMixedContentChannel is set to the document's
* channel when the user allows mixed content. The nsMixedContentBlocker content policy
* checks if the document's root channel matches the mMixedContentChannel. If it matches,
* then Mixed Content is loaded. If it does match, mixed content is blocked.
*
* A match implies that there is definitely mixed active content on a page that was
* initially blocked by nsMixedContentBlocker and then allowed and loaded by the user.
* A miss imples that IF there is mixed active content on the page AND it was
* blocked by nsMixedContentBlocker.cpp, the user has not choosen to override
* the block. Note that if the about:config setting
* security.mixed_content.block_active_content is set to false, this boolean
* will be false, mMixedContentChannel will remain null since blocking active content has
* been disabled and hence mMixedContentChannel will never be set.
*/
attribute nsIChannel mixedContentChannel;
/**
* Checks whether the channel associated with the root docShell is equal to
* mMixedContentChannel. If they are the same, allowMixedContent is set to true.
* Checks if the root document has a secure connection. If it is, sets
* rootHasSecureConnection to true.
*/
void GetAllowMixedContentAndConnectionData(out boolean rootHasSecureConnection, out boolean allowMixedContent);
/**
* Are plugins allowed in the current document loaded in this docshell ?
* (if there is one). This depends on whether plugins are allowed by this

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

@ -17,7 +17,7 @@ interface nsISHEntry;
typedef long nsDocShellInfoLoadType;
[scriptable, uuid(92a0a637-373e-4647-9476-ead11e005c75)]
[scriptable, uuid(5b041ea4-6655-434c-b3d3-cbbc9441f86a)]
interface nsIDocShellLoadInfo : nsISupports
{
/** This is the referrer for the load. */
@ -61,6 +61,7 @@ interface nsIDocShellLoadInfo : nsISupports
const long loadNormalBypassProxyAndCache = 16;
const long loadPushState = 17; // history.pushState or replaceState
const long loadReplaceBypassCache = 18;
const long loadMixedContent = 19;
/** Contains a load type as specified by the load* constants */
attribute nsDocShellInfoLoadType loadType;

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

@ -16,7 +16,7 @@ interface nsIURI;
* location, stop or restart an in process load, or determine where the object
* has previously gone.
*/
[scriptable, uuid(F5D9E7B0-D930-11d3-B057-00A024FFC08C)]
[scriptable, uuid(28404f7e-0f17-4dc3-a21a-2074d8659b02)]
interface nsIWebNavigation : nsISupports
{
/**
@ -145,13 +145,12 @@ interface nsIWebNavigation : nsISupports
* A hint this load was prompted by an external program: take care!
*/
const unsigned long LOAD_FLAGS_FROM_EXTERNAL = 0x1000;
/**
* This flag specifies that the URI may be submitted to a third-party
* server for correction. This should only be applied to non-sensitive
* URIs entered by users. This flag must not be passed to Reload.
*/
const unsigned long LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 0x2000;
This flag is set when a user explicitly disables the Mixed Content
Blocker, and allows Mixed Content to load on an https page.
*/
const unsigned long LOAD_FLAGS_ALLOW_MIXED_CONTENT = 0x2000;
/**
* This flag specifies that this is the first load in this object.
@ -190,6 +189,13 @@ interface nsIWebNavigation : nsISupports
*/
const unsigned long LOAD_FLAGS_URI_IS_UTF8 = 0x80000;
/**
* This flag specifies that the URI may be submitted to a third-party
* server for correction. This should only be applied to non-sensitive
* URIs entered by users. This flag must not be passed to Reload.
*/
const unsigned long LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 0x100000;
/**
* Loads a given URI. This will give priority to loading the requested URI
* in the object implementing this interface. If it can't be loaded here

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

@ -874,11 +874,15 @@ nsSHistory::Reload(uint32_t aReloadFlags)
{
loadType = nsIDocShellLoadInfo::loadReloadCharsetChange;
}
else if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_MIXED_CONTENT)
{
loadType = nsIDocShellLoadInfo::loadMixedContent;
}
else
{
loadType = nsIDocShellLoadInfo::loadReloadNormal;
}
// We are reloading. Send Reload notifications.
// nsDocShellLoadFlagType is not public, where as nsIWebNavigation
// is public. So send the reload notifications with the