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
authorTanvi Vyas <tvyas@mozilla.com>
Wed, 30 Jan 2013 00:04:31 -0800
changeset 120333 4068ef6c54a6355d23893c56afa69b8de4d4b320
parent 120332 a74d6901fd71bb53de89ea97a797d367a6f9c476
child 120334 a704f2af8bf37e9f7172829f4c9de974ca46b0fa
push id22162
push usertvyas@mozilla.com
push dateWed, 30 Jan 2013 08:05:01 +0000
treeherdermozilla-inbound@8da4794af394 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs822367
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
content/base/public/nsIDocument.h
content/base/src/nsMixedContentBlocker.cpp
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsDocShellLoadTypes.h
docshell/base/nsIDocShell.idl
docshell/base/nsIDocShellLoadInfo.idl
docshell/base/nsIWebNavigation.idl
docshell/shistory/src/nsSHistory.cpp
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -97,18 +97,18 @@ class HTMLBodyElement;
 class Link;
 class ProcessingInstruction;
 class UndoManager;
 template<typename> class Sequence;
 } // namespace dom
 } // 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)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -441,16 +441,31 @@ public:
   /**
    * Set the has mixed active content loaded flag for this document.
    */
   void SetHasMixedActiveContentLoaded(bool aHasMixedActiveContentLoaded)
   {
     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.
    * @see nsSandboxFlags.h for the possible flags
    */
   uint32_t GetSandboxFlags() const
   {
     return mSandboxFlags;
@@ -2161,16 +2176,19 @@ protected:
   bool mNeedStyleFlush;
 
   // True if a DOMMutationObserver is perhaps attached to a node in the document.
   bool mMayHaveDOMMutationObservers;
 
   // 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;
 
   // If true, we have an input encoding.  If this is false, then the
   // document was created entirely in memory
   bool mHaveInputEncoding;
 
   // The document's script global object, the object from which the
--- a/content/base/src/nsMixedContentBlocker.cpp
+++ b/content/base/src/nsMixedContentBlocker.cpp
@@ -16,16 +16,19 @@
 #include "nsNetUtil.h"
 #include "nsIRequest.h"
 #include "nsIDocument.h"
 #include "nsIContentViewer.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannel.h"
 #include "mozilla/Preferences.h"
 #include "nsIScriptObjectPrincipal.h"
+#include "nsISecureBrowserUI.h"
+#include "nsIDocumentLoader.h"
+#include "nsLoadGroup.h"
 
 #include "prlog.h"
 
 using namespace mozilla;
 
 // Is mixed script blocking (fonts, plugin content, scripts, stylesheets,
 // iframes, websockets, XHR) enabled?
 bool nsMixedContentBlocker::sBlockMixedScript = false;
@@ -69,17 +72,17 @@ public:
     // now get the document from sameTypeRoot
     nsCOMPtr<nsIDocument> rootDoc = do_GetInterface(sameTypeRoot);
     NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");
 
 
     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);
       }
 
     } else {
         if (mType == eMixedDisplay) {
           //Do Nothing for now; state will already be set STATE_IS_BROKEN
@@ -319,21 +322,87 @@ nsMixedContentBlocker::ShouldLoad(uint32
     return NS_OK;
   }
   if (!parentIsHttps) {
     *aDecision = ACCEPT;
     return NS_OK;
   }
 
   // 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.
 
     // Fire the event from a script runner as it is unsafe to run script
     // from within ShouldLoad
     nsContentUtils::AddScriptRunner(
       new nsMixedContentEvent(aRequestingContext, classification));
     return NS_OK;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -69,16 +69,18 @@
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsIScriptChannel.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsITimedChannel.h"
 #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"
 #include "mozilla/Telemetry.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Attributes.h"
 
 // we want to explore making the document own the load group
@@ -1140,16 +1142,19 @@ ConvertDocShellLoadInfoToLoadType(nsDocS
         loadType = LOAD_STOP_CONTENT_AND_REPLACE;
         break;
     case nsIDocShellLoadInfo::loadPushState:
         loadType = LOAD_PUSHSTATE;
         break;
     case nsIDocShellLoadInfo::loadReplaceBypassCache:
         loadType = LOAD_REPLACE_BYPASS_CACHE;
         break;
+    case nsIDocShellLoadInfo::loadMixedContent:
+        loadType = LOAD_MIXED_CONTENT;
+        break;
     default:
         NS_NOTREACHED("Unexpected nsDocShellInfoLoadType value");
     }
 
     return loadType;
 }
 
 
@@ -1211,16 +1216,19 @@ nsDocShell::ConvertLoadTypeToDocShellLoa
         docShellLoadType = nsIDocShellLoadInfo::loadStopContentAndReplace;
         break;
     case LOAD_PUSHSTATE:
         docShellLoadType = nsIDocShellLoadInfo::loadPushState;
         break;
     case LOAD_REPLACE_BYPASS_CACHE:
         docShellLoadType = nsIDocShellLoadInfo::loadReplaceBypassCache;
         break;
+    case LOAD_MIXED_CONTENT:
+        docShellLoadType = nsIDocShellLoadInfo::loadMixedContent;
+        break;
     default:
         NS_NOTREACHED("Unexpected load type value");
     }
 
     return docShellLoadType;
 }                                                                               
 
 //*****************************************************************************
@@ -1955,24 +1963,32 @@ nsDocShell::GetChannelIsUnsafe(bool *aUn
     if (!jarChannel) {
         return NS_OK;
     }
 
     return jarChannel->GetIsUnsafe(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)
 {
     NS_ENSURE_ARG_POINTER(aAllowPlugins);
 
     *aAllowPlugins = mAllowPlugins;
     if (!mAllowPlugins) {
         return NS_OK;
     }
@@ -5306,16 +5322,78 @@ nsDocShell::SetSandboxFlags(uint32_t aSa
 NS_IMETHODIMP
 nsDocShell::GetSandboxFlags(uint32_t  *aSandboxFlags)
 {
     *aSandboxFlags = mSandboxFlags;
     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)
 {
     if (!mContentViewer)
         return NS_OK;
     if (aVisibility) {
         mContentViewer->Show();
     }
     else {
@@ -9323,16 +9401,24 @@ nsDocShell::DoURILoad(nsIURI * aURI,
         rv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
         NS_ENSURE_SUCCESS(rv, rv);
         if (!aFileName.IsEmpty()) {
             rv = channel->SetContentDispositionFilename(aFileName);
             NS_ENSURE_SUCCESS(rv, rv);
         }
     }
 
+    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));
     if (httpChannelInternal) {
       if (aForceAllowCookies) {
         httpChannelInternal->SetForceAllowThirdPartyCookie(true);
       } 
       if (aFirstParty) {
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -740,16 +740,20 @@ protected:
 
     // Set in LoadErrorPage from the method argument and used later
     // in CreateContentViewer. We have to delay an shistory entry creation
     // for which these objects are needed.
     nsCOMPtr<nsIURI>           mFailedURI;
     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.
 
     nsIDocShellTreeOwner *     mTreeOwner; // Weak Reference
     nsIDOMEventTarget *       mChromeEventHandler; //Weak Reference
 
     eCharsetReloadState        mCharsetReloadState;
--- a/docshell/base/nsDocShellLoadTypes.h
+++ b/docshell/base/nsDocShellLoadTypes.h
@@ -23,18 +23,17 @@
 #define LOAD_TYPE_HAS_FLAGS(type, flags) ((type) & ((flags) << 16))
 
 /**
  * These are flags that confuse ConvertLoadTypeToDocShellLoadInfo and should
  * not be passed to MAKE_LOAD_TYPE.  In particular this includes all flags
  * 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)
 
 
 
 /* load types are legal combinations of load commands and flags 
  *  
  * NOTE:
@@ -56,16 +55,17 @@ enum LoadType {
     LOAD_LINK = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_IS_LINK),
     LOAD_REFRESH = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_IS_REFRESH),
     LOAD_RELOAD_CHARSET_CHANGE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_RELOAD, nsIWebNavigation::LOAD_FLAGS_CHARSET_CHANGE),
     LOAD_BYPASS_HISTORY = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_BYPASS_HISTORY),
     LOAD_STOP_CONTENT = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT),
     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
      * consumer-triggered load failed.
      */
     LOAD_ERROR_PAGE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, LOAD_FLAGS_ERROR_PAGE)
 
     // NOTE: Adding a new value? Remember to update IsValidLoadType!
@@ -88,16 +88,17 @@ static inline bool IsValidLoadType(uint3
     case LOAD_LINK:
     case LOAD_REFRESH:
     case LOAD_RELOAD_CHARSET_CHANGE:
     case LOAD_BYPASS_HISTORY:
     case LOAD_STOP_CONTENT:
     case LOAD_STOP_CONTENT_AND_REPLACE:
     case LOAD_PUSHSTATE:
     case LOAD_REPLACE_BYPASS_CACHE:
+    case LOAD_MIXED_CONTENT:
     case LOAD_ERROR_PAGE:
         return true;
     }
     return false;
 }
 
 #endif // MOZILLA_INTERNAL_API
 #endif 
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -34,17 +34,17 @@ interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 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
 {
   /**
    * 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
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -471,16 +471,28 @@ interface nsIDocShell : nsISupports
    * the page, either because there was no mixed active content requests on the page
    * or such requests were blocked by nsMixedContentBlocker.
    * This boolean is set to true in nsMixedContentBlocker if Mixed Active Content
    * is allowed (either explicitly on the page by the user or when the about:config
    * setting security.mixed_content.block_active_content is set to false).
    */
   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
    * should be called only during page transitions.
    */
   [noscript, notxpcom] void DetachEditorFromWindow();
 
   /**
@@ -699,16 +711,44 @@ interface nsIDocShell : nsISupports
    * loaded.
    * The sandbox flags of a document depend on the sandbox flags on its
    * docshell and of its parent document, if any.
    * See nsSandboxFlags.h for the possible flags.
    */
   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
    * docshell itself or if the document is sandboxed and hence plugins should
    * not be allowed.
    */
   [noscript, notxpcom] bool pluginsAllowedInCurrentDoc();
   
 
--- a/docshell/base/nsIDocShellLoadInfo.idl
+++ b/docshell/base/nsIDocShellLoadInfo.idl
@@ -12,17 +12,17 @@
  */
  
 interface nsIURI;
 interface nsIInputStream;
 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. */
     attribute nsIURI referrer;
 
     /** The owner of the load, that is, the entity responsible for 
      *  causing the load to occur. This should be a nsIPrincipal typically.
      */
@@ -56,16 +56,17 @@ interface nsIDocShellLoadInfo : nsISuppo
     const long loadStopContent = 11;
     const long loadStopContentAndReplace = 12;
     const long loadNormalExternal = 13;
     const long loadNormalBypassCache = 14;
     const long loadNormalBypassProxy = 15;
     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;
 
     /** SHEntry for this page */
     attribute nsISHEntry SHEntry;
 
     /** Target for load, like _content, _blank etc. */
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -11,17 +11,17 @@ interface nsISHistory;
 interface nsIURI;
 
 /**
  * The nsIWebNavigation interface defines an interface for navigating the web.
  * It provides methods and attributes to direct an object to navigate to a new
  * 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
 {
   /**
    * Indicates if the object can go back.  If true this indicates that
    * there is back session history available for navigation.
    */
   readonly attribute boolean canGoBack;
 
@@ -140,23 +140,22 @@ interface nsIWebNavigation : nsISupports
    * STOP_CONTENT flag to Stop(), in addition to the STOP_NETWORK flag.
    */
   const unsigned long LOAD_FLAGS_STOP_CONTENT    = 0x0800;
 
   /**
    * 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.
    * Set with care, since setting incorrectly can cause us to assume that
    * nothing was actually loaded in this object if the load ends up being 
    * handled by an external application.  This flag must not be passed to
    * Reload.
    */
@@ -186,16 +185,23 @@ interface nsIWebNavigation : nsISupports
   const unsigned long LOAD_FLAGS_DISALLOW_INHERIT_OWNER = 0x40000;
 
   /**
    * Assume the URI is encoded in UTF-8.
    */
   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
    * however, the URI dispatcher will go through its normal process of content
    * loading.
    *
    * @param aURI
    *        The URI string to load.  For HTTP and FTP URLs and possibly others,
    *        characters above U+007F will be converted to UTF-8 and then URL-
--- a/docshell/shistory/src/nsSHistory.cpp
+++ b/docshell/shistory/src/nsSHistory.cpp
@@ -869,21 +869,25 @@ nsSHistory::Reload(uint32_t aReloadFlags
   else if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE)
   {
     loadType = nsIDocShellLoadInfo::loadReloadBypassCache;
   }
   else if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_CHARSET_CHANGE)
   {
     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
   // nsIWebNavigation flags.
   bool canNavigate = true;
   nsCOMPtr<nsIURI> currentURI;
   rv = GetCurrentURI(getter_AddRefs(currentURI));
   NOTIFY_LISTENERS_CANCELABLE(OnHistoryReload, canNavigate,