e10s HTTPS: securityInfo. sr=biesi.
☠☠ backed out by 0c5db3a42fb6 ☠ ☠
authorHonza Bambas <honzab.moz@firemni.cz>
Wed, 30 Jun 2010 09:17:51 -0700
changeset 46945 9cfe0ace0e9588e4cfff87f978e88fe896d0a87d
parent 46944 17bd6f89d86c3989a7f53746a93e173147f2ab56
child 46946 d1dc03b03aefd307243d25b26fe07af0a637cf86
child 46951 0c5db3a42fb6ff37bc0c9976bdef4bf62b75b928
push idunknown
push userunknown
push dateunknown
reviewersbiesi
milestone2.0b2pre
e10s HTTPS: securityInfo. sr=biesi.
dom/ipc/Makefile.in
dom/ipc/PIFrameEmbedding.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/PHttpChannel.ipdl
security/manager/boot/src/nsSecureBrowserUIImpl.cpp
security/manager/ssl/public/nsIAssociatedContentSecurity.idl
security/manager/ssl/src/nsNSSIOLayer.cpp
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -76,13 +76,14 @@ include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
 		-I$(srcdir)/../../content/base/src \
 		-I$(srcdir)/../../content/events/src \
 		-I$(srcdir)/../src/geolocation \
 		-I$(topsrcdir)/chrome/src \
+		-I$(srcdir)/../../netwerk/base/src \
 		$(NULL)
 
 CXXFLAGS += $(TK_CFLAGS)
 
 DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -85,17 +85,20 @@ parent:
                          PRInt64 curTotalProgress,
                          PRInt64 maxTotalProgress);
 
     notifyLocationChange(nsCString uri);
 
     notifyStatusChange(nsresult status,
                        nsString message);
 
-    notifySecurityChange(PRUint32 aState);
+    notifySecurityChange(PRUint32 aState,
+                         PRBool aUseSSLStatusObject,
+                         nsString aTooltip,
+                         nsCString aSecInfoAsString);
 
     sync refreshAttempted(nsCString uri, PRInt32 millis,
                           bool sameURI) returns (bool retval);
 
 
     rpc createWindow() returns (PIFrameEmbedding window);
 
     sync sendSyncMessageToParent(nsString aMessage, nsString aJSON)
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -40,16 +40,18 @@
 #include "mozilla/dom/PContentProcessChild.h"
 #include "mozilla/dom/PContentDialogChild.h"
 
 #include "nsIWebBrowser.h"
 #include "nsEmbedCID.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIBaseWindow.h"
 #include "nsIDOMWindow.h"
+#include "nsIWebProgress.h"
+#include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsThreadUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/ipc/DocumentRendererShmemChild.h"
 #include "mozilla/ipc/DocumentRendererNativeIDChild.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsPIDOMWindow.h"
@@ -71,16 +73,19 @@
 #include "nsScriptLoader.h"
 #include "nsPIWindowRoot.h"
 #include "nsIScriptContext.h"
 #include "nsInterfaceHashtable.h"
 #include "nsPresContext.h"
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsWeakReference.h"
+#include "nsISecureBrowserUI.h"
+#include "nsISSLStatusProvider.h"
+#include "nsSerializationHelper.h"
 
 #ifdef MOZ_WIDGET_QT
 #include <QX11EmbedWidget>
 #include <QGraphicsView>
 #include <QGraphicsWidget>
 #endif
 
 #ifdef MOZ_WIDGET_GTK2
@@ -516,17 +521,67 @@ TabChild::OnStatusChange(nsIWebProgress 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChild::OnSecurityChange(nsIWebProgress *aWebProgress,
                            nsIRequest *aRequest,
                            PRUint32 aState)
 {
-  SendnotifySecurityChange(aState);
+  nsCString secInfoAsString;
+  if (aState & nsIWebProgressListener::STATE_IS_SECURE) {
+    nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+    if (channel) {
+      nsCOMPtr<nsISupports> secInfoSupports;
+      channel->GetSecurityInfo(getter_AddRefs(secInfoSupports));
+
+      nsCOMPtr<nsISerializable> secInfoSerializable =
+          do_QueryInterface(secInfoSupports);
+      NS_SerializeToString(secInfoSerializable, secInfoAsString);
+    }
+  }
+
+  PRBool useSSLStatusObject = PR_FALSE;
+  nsAutoString securityTooltip;
+  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aWebProgress);
+  if (docShell) {
+    nsCOMPtr<nsISecureBrowserUI> secureUI;
+    docShell->GetSecurityUI(getter_AddRefs(secureUI));
+    if (secureUI) {
+      secureUI->GetTooltipText(securityTooltip);
+      nsCOMPtr<nsISupports> supports;
+      nsCOMPtr<nsISSLStatusProvider> provider =
+        do_QueryInterface(secureUI);
+      nsresult rv = provider->GetSSLStatus(getter_AddRefs(supports));
+      if (NS_SUCCEEDED(rv) && supports) {
+        /*
+         * useSSLStatusObject: Security UI internally holds 4 states: secure, mixed,
+         * broken, no security.  In cases of secure, mixed and broken it holds reference
+         * to a valid SSL status object.  But, in case of the 'broken' state it doesn't
+         * return the SSL status object (returns null), in contrary to the 'mixed' state
+         * for which it returns.
+         * 
+         * However, mixed and broken states are both reported to the upper level
+         * as nsIWebProgressListener::STATE_IS_BROKEN, i.e. states are merged,
+         * so we cannot determine, if to return the status object or not.
+         *
+         * TabParent is extracting the SSL status object from the security info
+         * serialization (string). SSL status object is always present there
+         * even security UI implementation doesn't present it.  This argument 
+         * tells the parent if the SSL status object is being presented by 
+         * the security UI here, on the child process, and so if it has to be
+         * presented also on the parent process.
+         */
+        useSSLStatusObject = PR_TRUE;
+      }
+    }
+  }
+
+  SendnotifySecurityChange(aState, useSSLStatusObject, securityTooltip,
+                           secInfoAsString);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChild::OnLocationChange(nsIWebProgress *aWebProgress,
                            nsIRequest *aRequest,
                            nsIURI *aLocation)
 {
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -48,46 +48,50 @@
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMElement.h"
 #include "nsEventDispatcher.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIWindowWatcher.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
+#include "nsIIdentityInfo.h"
 #include "TabChild.h"
 #include "nsIDOMEvent.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIWebProgressListener2.h"
 #include "nsFrameLoader.h"
 #include "nsNetUtil.h"
 #include "jsarray.h"
 #include "nsContentUtils.h"
 #include "nsGeolocationOOP.h"
 #include "nsIDOMNSHTMLFrameElement.h"
 #include "nsIDialogCreator.h"
 #include "nsThreadUtils.h"
 #include "nsIPromptFactory.h"
 #include "nsIContent.h"
+#include "nsSerializationHelper.h"
 
 using mozilla::ipc::DocumentRendererParent;
 using mozilla::ipc::DocumentRendererShmemParent;
 using mozilla::ipc::DocumentRendererNativeIDParent;
 using mozilla::dom::ContentProcessParent;
 
 // The flags passed by the webProgress notifications are 16 bits shifted
 // from the ones registered by webProgressListeners.
 #define NOTIFY_FLAG_SHIFT 16
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIWebProgress, nsIAuthPromptProvider)
+NS_IMPL_ISUPPORTS5(TabParent, nsITabParent, nsIWebProgress, nsIAuthPromptProvider, 
+                   nsISecureBrowserUI, nsISSLStatusProvider)
 
 TabParent::TabParent()
+  : mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE)
 {
 }
 
 TabParent::~TabParent()
 {
 }
 
 void
@@ -279,42 +283,71 @@ TabParent::RecvnotifyStatusChange(const 
 
     listener->OnStatusChange(this, nsnull, status, message.BeginReading());
   }
 
   return true;
 }
 
 bool
-TabParent::RecvnotifySecurityChange(const PRUint32& aState)
+TabParent::RecvnotifySecurityChange(const PRUint32& aState,
+                                    const PRBool& aUseSSLStatusObject,
+                                    const nsString& aTooltip,
+                                    const nsCString& aSecInfoAsString)
 {
   /*                                                                           
    * First notify any listeners of the new state info...
    *
    * Operate the elements from back to front so that if items get
    * get removed from the list it won't affect our iteration
    */
 
+  mSecurityState = aState;
+  mSecurityTooltipText = aTooltip;
+
+  if (!aSecInfoAsString.IsEmpty()) {
+    nsCOMPtr<nsISupports> secInfoSupports;
+    nsresult rv = NS_DeserializeObject(aSecInfoAsString, getter_AddRefs(secInfoSupports));
+
+    if (NS_SUCCEEDED(rv)) {
+      nsCOMPtr<nsIIdentityInfo> idInfo = do_QueryInterface(secInfoSupports);
+      if (idInfo) {
+        PRBool isEV;
+        if (NS_SUCCEEDED(idInfo->GetIsExtendedValidation(&isEV)) && isEV)
+          mSecurityState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
+      }
+    }
+
+    mSecurityStatusObject = nsnull;
+    if (aUseSSLStatusObject)
+    {
+      nsCOMPtr<nsISSLStatusProvider> sslStatusProvider =
+        do_QueryInterface(secInfoSupports);
+      if (sslStatusProvider)
+        sslStatusProvider->GetSSLStatus(getter_AddRefs(mSecurityStatusObject));
+    }
+  }
+
   nsCOMPtr<nsIWebProgressListener> listener;
   PRUint32 count = mListenerInfoList.Length();
 
   while (count-- > 0) {
     TabParentListenerInfo *info = &mListenerInfoList[count];
     if (!(info->mNotifyMask & nsIWebProgress::NOTIFY_SECURITY)) {
       continue;
     }
 
     listener = do_QueryReferent(info->mWeakListener);
     if (!listener) {
       // the listener went away. gracefully pull it out of the list.
       mListenerInfoList.RemoveElementAt(count);
       continue;
     }
 
-    listener->OnSecurityChange(this, nsnull, aState);
+    listener->OnSecurityChange(this, nsnull, mSecurityState);
   }
 
   return true;
 }
 
 bool
 TabParent::RecvrefreshAttempted(const nsCString& aURI, const PRInt32& aMillis, 
                                 const bool& aSameURI, bool* refreshAllowed)
@@ -613,16 +646,44 @@ TabParent::GetDOMWindow(nsIDOMWindow **a
 }
 
 NS_IMETHODIMP
 TabParent::GetIsLoadingDocument(PRBool *aIsLoadingDocument)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+TabParent::Init(nsIDOMWindow *window)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TabParent::GetState(PRUint32 *aState)
+{
+  NS_ENSURE_ARG(aState);
+  *aState = mSecurityState;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TabParent::GetTooltipText(nsAString & aTooltipText)
+{
+  aTooltipText = mSecurityTooltipText;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TabParent::GetSSLStatus(nsISupports ** aStatus)
+{
+  NS_IF_ADDREF(*aStatus = mSecurityStatusObject);
+  return NS_OK;
+}
+
 // nsIAuthPromptProvider
 
 // This method is largely copied from nsDocShell::GetAuthPrompt
 NS_IMETHODIMP
 TabParent::GetAuthPrompt(PRUint32 aPromptReason, const nsIID& iid,
                           void** aResult)
 {
   // a priority prompt request will override a false mAllowAuth setting
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -47,16 +47,18 @@
 #include "nsCOMPtr.h"
 #include "nsITabParent.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIWebProgress.h"
 #include "nsIWebProgressListener.h"
 #include "nsWeakReference.h"
 #include "nsIDialogParamBlock.h"
 #include "nsIAuthPromptProvider.h"
+#include "nsISecureBrowserUI.h"
+#include "nsISSLStatusProvider.h"
 
 class nsIURI;
 class nsIDOMElement;
 class gfxMatrix;
 
 struct JSContext;
 struct JSObject;
 
@@ -86,16 +88,18 @@ bool operator==(const TabParentListenerI
 }
 
 class ContentDialogParent : public PContentDialogParent {};
 
 class TabParent : public PIFrameEmbeddingParent 
                 , public nsITabParent 
                 , public nsIWebProgress
                 , public nsIAuthPromptProvider
+                , public nsISecureBrowserUI
+                , public nsISSLStatusProvider
 {
 public:
     TabParent();
     virtual ~TabParent();
     void SetOwnerElement(nsIDOMElement* aElement) { mFrameElement = aElement; }
     void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
         mBrowserDOMWindow = aBrowserDOMWindow;
     }
@@ -106,17 +110,20 @@ public:
                                           const PRInt64& aProgressMax,
                                           const PRInt64& aTotalProgress,
                                           const PRInt64& aMaxTotalProgress);
     virtual bool RecvnotifyStateChange(const PRUint32& aStateFlags,
                                        const nsresult& aStatus);
     virtual bool RecvnotifyLocationChange(const nsCString& aUri);
     virtual bool RecvnotifyStatusChange(const nsresult& status,
                                         const nsString& message);
-    virtual bool RecvnotifySecurityChange(const PRUint32& aState);
+    virtual bool RecvnotifySecurityChange(const PRUint32& aState,
+                                          const PRBool& aUseSSLStatusObject,
+                                          const nsString& aTooltip,
+                                          const nsCString& aSecInfoAsString);
     virtual bool RecvrefreshAttempted(const nsCString& aURI,
                                       const PRInt32& aMillis,
                                       const bool& aSameURI,
                                       bool* aAllowRefresh);
 
     virtual bool AnswercreateWindow(PIFrameEmbeddingParent** retval);
     virtual bool RecvsendSyncMessageToParent(const nsString& aMessage,
                                              const nsString& aJSON,
@@ -182,31 +189,37 @@ public:
     virtual PGeolocationRequestParent* AllocPGeolocationRequest(const IPC::URI& uri);
     virtual bool DeallocPGeolocationRequest(PGeolocationRequestParent* actor);
 
     JSBool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBPROGRESS
     NS_DECL_NSIAUTHPROMPTPROVIDER
+    NS_DECL_NSISECUREBROWSERUI
+    NS_DECL_NSISSLSTATUSPROVIDER
 
     void HandleDelayedDialogs();
 protected:
     bool ReceiveMessage(const nsString& aMessage,
                         PRBool aSync,
                         const nsString& aJSON,
                         nsTArray<nsString>* aJSONRetVal = nsnull);
 
     TabParentListenerInfo* GetListenerInfo(nsIWebProgressListener *aListener);
 
     void ActorDestroy(ActorDestroyReason why);
 
     nsIDOMElement* mFrameElement;
     nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
 
+    PRUint32 mSecurityState;
+    nsString mSecurityTooltipText;
+    nsCOMPtr<nsISupports> mSecurityStatusObject;
+
     nsTArray<TabParentListenerInfo> mListenerInfoList;
 
     struct DelayedDialogData
     {
       DelayedDialogData(PContentDialogParent* aDialog, PRUint32 aType,
                         const nsCString& aName,
                         const nsCString& aFeatures,
                         nsIDialogParamBlock* aParams)
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -43,16 +43,17 @@
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/HttpChannelChild.h"
 
 #include "nsStringStream.h"
 #include "nsHttpHandler.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
+#include "nsSerializationHelper.h"
 
 namespace mozilla {
 namespace net {
 
 // C++ file contents
 HttpChannelChild::HttpChannelChild()
   : mIsFromCache(PR_FALSE)
   , mCacheEntryAvailable(PR_FALSE)
@@ -94,39 +95,46 @@ NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
   NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
   NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
   NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
   NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
   NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
   NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAssociatedContentSecurity, GetAssociatedContentSecurity())
 NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
 
 //-----------------------------------------------------------------------------
 // HttpChannelChild::PHttpChannelChild
 //-----------------------------------------------------------------------------
 
 bool 
 HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
                                      const PRBool& useResponseHead,
                                      const PRBool& isFromCache,
                                      const PRBool& cacheEntryAvailable,
                                      const PRUint32& cacheExpirationTime,
-                                     const nsCString& cachedCharset)
+                                     const nsCString& cachedCharset,
+                                     const nsCString& securityInfoSerialization)
 {
   LOG(("HttpChannelChild::RecvOnStartRequest [this=%x]\n", this));
 
   mState = HCC_ONSTART;
 
   if (useResponseHead)
     mResponseHead = new nsHttpResponseHead(responseHead);
   else
     mResponseHead = nsnull;
  
+  if (!securityInfoSerialization.IsEmpty())
+    NS_DeserializeObject(securityInfoSerialization, getter_AddRefs(mSecurityInfo));
+  else
+    mSecurityInfo = nsnull;
+
   mIsFromCache = isFromCache;
   mCacheEntryAvailable = cacheEntryAvailable;
   mCacheExpirationTime = cacheExpirationTime;
   mCachedCharset = cachedCharset;
 
   nsresult rv = mListener->OnStartRequest(this, mListenerContext);
   if (NS_FAILED(rv)) {
     // TODO: Cancel request: (bug 536317)
@@ -275,19 +283,18 @@ HttpChannelChild::Resume()
 
 //-----------------------------------------------------------------------------
 // HttpChannelChild::nsIChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
 {
-  // FIXME: Stub for bug 536301 .
   NS_ENSURE_ARG_POINTER(aSecurityInfo);
-  *aSecurityInfo = 0;
+  NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
 {
   LOG(("HttpChannelChild::AsyncOpen [this=%x uri=%s]\n", this, mSpec.get()));
 
@@ -595,12 +602,133 @@ HttpChannelChild::GetChooseApplicationCa
 }
 NS_IMETHODIMP
 HttpChannelChild::SetChooseApplicationCache(PRBool aChooseApplicationCache)
 {
   // FIXME: Browser calls this early, so stub OK for now. Fix in bug 536295.  
   return NS_OK;
 }
 
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIAssociatedContentSecurity
+//-----------------------------------------------------------------------------
+
+bool
+HttpChannelChild::GetAssociatedContentSecurity(nsIAssociatedContentSecurity** _result)
+{
+  if (!mSecurityInfo)
+    return false;
+
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc =
+      do_QueryInterface(mSecurityInfo);
+  if (!assoc)
+    return false;
+
+  if (_result)
+    assoc.forget(_result);
+  return true;
+}
+
+/* attribute unsigned long countSubRequestsHighSecurity; */
+NS_IMETHODIMP
+HttpChannelChild::GetCountSubRequestsHighSecurity(PRInt32 *aSubRequestsHighSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->GetCountSubRequestsHighSecurity(aSubRequestsHighSecurity);
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCountSubRequestsHighSecurity(PRInt32 aSubRequestsHighSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->SetCountSubRequestsHighSecurity(aSubRequestsHighSecurity);
+}
+
+/* attribute unsigned long countSubRequestsLowSecurity; */
+NS_IMETHODIMP
+HttpChannelChild::GetCountSubRequestsLowSecurity(PRInt32 *aSubRequestsLowSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->GetCountSubRequestsLowSecurity(aSubRequestsLowSecurity);
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCountSubRequestsLowSecurity(PRInt32 aSubRequestsLowSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->SetCountSubRequestsLowSecurity(aSubRequestsLowSecurity);
+}
+
+/* attribute unsigned long countSubRequestsBrokenSecurity; */
+NS_IMETHODIMP HttpChannelChild::GetCountSubRequestsBrokenSecurity(PRInt32 *aSubRequestsBrokenSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->GetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
+}
+NS_IMETHODIMP HttpChannelChild::SetCountSubRequestsBrokenSecurity(PRInt32 aSubRequestsBrokenSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->SetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
+}
+
+/* attribute unsigned long countSubRequestsNoSecurity; */
+NS_IMETHODIMP
+HttpChannelChild::GetCountSubRequestsNoSecurity(PRInt32 *aSubRequestsNoSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->GetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCountSubRequestsNoSecurity(PRInt32 aSubRequestsNoSecurity)
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  return assoc->SetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
+}
+
+NS_IMETHODIMP
+HttpChannelChild::Flush()
+{
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc;
+  if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
+    return NS_OK;
+
+  nsresult rv;
+  PRInt32 hi, low, broken, no;
+
+  rv = assoc->GetCountSubRequestsHighSecurity(&hi);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = assoc->GetCountSubRequestsLowSecurity(&low);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = assoc->GetCountSubRequestsBrokenSecurity(&broken);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = assoc->GetCountSubRequestsNoSecurity(&no);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  SendUpdateAssociatedContentSecurity(hi, low, broken, no);
+
+  return NS_OK;
+}
 
 //------------------------------------------------------------------------------
 }} // mozilla::net
 
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -53,16 +53,17 @@
 #include "nsICacheInfoChannel.h"
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIEncodedChannel.h"
 #include "nsIUploadChannel2.h"
 #include "nsIResumableChannel.h"
 #include "nsIProxiedChannel.h"
 #include "nsITraceableChannel.h"
+#include "nsIAssociatedContentSecurity.h"
 
 namespace mozilla {
 namespace net {
 
 // TODO: replace with IPDL states: bug 536319
 enum HttpChannelChildState {
   HCC_NEW,
   HCC_OPENED,
@@ -75,26 +76,28 @@ enum HttpChannelChildState {
 class HttpChannelChild : public PHttpChannelChild
                        , public HttpBaseChannel
                        , public nsICacheInfoChannel
                        , public nsIEncodedChannel
                        , public nsIResumableChannel
                        , public nsIProxiedChannel
                        , public nsITraceableChannel
                        , public nsIApplicationCacheChannel
+                       , public nsIAssociatedContentSecurity
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICACHEINFOCHANNEL
   NS_DECL_NSIENCODEDCHANNEL
   NS_DECL_NSIRESUMABLECHANNEL
   NS_DECL_NSIPROXIEDCHANNEL
   NS_DECL_NSITRACEABLECHANNEL
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
   NS_DECL_NSIAPPLICATIONCACHECHANNEL
+  NS_DECL_NSIASSOCIATEDCONTENTSECURITY
 
   HttpChannelChild();
   virtual ~HttpChannelChild();
 
   // Methods HttpBaseChannel didn't implement for us or that we override.
   //
   // nsIRequest
   NS_IMETHOD Cancel(nsresult status);
@@ -114,26 +117,30 @@ public:
 
 protected:
   void RefcountHitZero();
   bool RecvOnStartRequest(const nsHttpResponseHead& responseHead,
                           const PRBool& useResponseHead,
                           const PRBool& isFromCache,
                           const PRBool& cacheEntryAvailable,
                           const PRUint32& cacheExpirationTime,
-                          const nsCString& cachedCharset);
+                          const nsCString& cachedCharset,
+                          const nsCString& securityInfoSerialization);
   bool RecvOnDataAvailable(const nsCString& data, 
                            const PRUint32& offset,
                            const PRUint32& count);
   bool RecvOnStopRequest(const nsresult& statusCode);
   bool RecvOnProgress(const PRUint64& progress, const PRUint64& progressMax);
   bool RecvOnStatus(const nsresult& status, const nsString& statusArg);
 
+  bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** _result = nsnull);
+
 private:
   RequestHeaderTuples mRequestHeaders;
+  nsCOMPtr<nsISupports> mSecurityInfo;
 
   PRPackedBool mIsFromCache;
   PRPackedBool mCacheEntryAvailable;
   PRUint32     mCacheExpirationTime;
   nsCString    mCachedCharset;
 
   // FIXME: replace with IPDL states (bug 536319) 
   enum HttpChannelChildState mState;
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -43,16 +43,19 @@
 #include "nsHttpChannel.h"
 #include "nsHttpHandler.h"
 #include "nsNetUtil.h"
 #include "nsISupportsPriority.h"
 #include "nsIAuthPromptProvider.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIBadCertListener2.h"
 #include "nsICacheEntryDescriptor.h"
+#include "nsSerializationHelper.h"
+#include "nsISerializable.h"
+#include "nsIAssociatedContentSecurity.h"
 
 namespace mozilla {
 namespace net {
 
 // C++ file contents
 HttpChannelParent::HttpChannelParent(PIFrameEmbeddingParent* iframeEmbedding)
 : mIPCClosed(false)
 {
@@ -193,16 +196,39 @@ HttpChannelParent::RecvSetCacheTokenCach
 
 bool
 HttpChannelParent::RecvOnStopRequestCompleted()
 {
   mCacheDescriptor = nsnull;
   return true;
 }
 
+bool
+HttpChannelParent::RecvUpdateAssociatedContentSecurity(const PRInt32& high,
+                                                       const PRInt32& low,
+                                                       const PRInt32& broken,
+                                                       const PRInt32& no)
+{
+  nsHttpChannel *chan = static_cast<nsHttpChannel *>(mChannel.get());
+
+  nsCOMPtr<nsISupports> secInfo;
+  chan->GetSecurityInfo(getter_AddRefs(secInfo));
+
+  nsCOMPtr<nsIAssociatedContentSecurity> assoc = do_QueryInterface(secInfo);
+  if (!assoc)
+    return true;
+
+  assoc->SetCountSubRequestsHighSecurity(high);
+  assoc->SetCountSubRequestsLowSecurity(low);
+  assoc->SetCountSubRequestsBrokenSecurity(broken);
+  assoc->SetCountSubRequestsNoSecurity(no);
+
+  return true;
+}
+
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIRequestObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
 {
   LOG(("HttpChannelParent::OnStartRequest [this=%x]\n", this));
@@ -216,21 +242,30 @@ HttpChannelParent::OnStartRequest(nsIReq
   chan->GetCacheTokenExpirationTime(&expirationTime);
   nsCString cachedCharset;
   chan->GetCacheTokenCachedCharset(cachedCharset);
 
   // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
   // It could be already released by nsHttpChannel at that time.
   chan->GetCacheToken(getter_AddRefs(mCacheDescriptor));
 
+  nsCOMPtr<nsISupports> secInfoSupp;
+  chan->GetSecurityInfo(getter_AddRefs(secInfoSupp));
+
+  nsCOMPtr<nsISerializable> secInfoSer =
+      do_QueryInterface(secInfoSupp);
+
+  nsCString secInfoSerialization;
+  NS_SerializeToString(secInfoSer, secInfoSerialization);
+
   if (mIPCClosed || 
       !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(), 
                           !!responseHead, isFromCache,
                           mCacheDescriptor ? PR_TRUE : PR_FALSE,
-                          expirationTime, cachedCharset)) {
+                          expirationTime, cachedCharset, secInfoSerialization)) {
     return NS_ERROR_UNEXPECTED; 
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpChannelParent::OnStopRequest(nsIRequest *aRequest, 
                                  nsISupports *aContext, 
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -86,16 +86,20 @@ protected:
                              const PRUint16&            priority,
                              const PRUint8&             redirectionLimit,
                              const PRBool&              allowPipelining,
                              const PRBool&              forceAllowThirdPartyCookie);
 
   virtual bool RecvSetPriority(const PRUint16& priority);
   virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset);
   virtual bool RecvOnStopRequestCompleted();
+  virtual bool RecvUpdateAssociatedContentSecurity(const PRInt32& high,
+                                                   const PRInt32& low,
+                                                   const PRInt32& broken,
+                                                   const PRInt32& no);
 
   virtual void ActorDestroy(ActorDestroyReason why);
 
 private:
   nsCOMPtr<nsITabParent> mTabParent;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsICacheEntryDescriptor> mCacheDescriptor;
   bool mIPCClosed;                // PHttpChannel actor has been Closed()
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -77,23 +77,29 @@ parent:
             PRBool              forceAllowThirdPartyCookie);
 
   SetPriority(PRUint16 priority);
 
   SetCacheTokenCachedCharset(nsCString charset);
 
   OnStopRequestCompleted();
 
+  UpdateAssociatedContentSecurity(PRInt32 high,
+                                  PRInt32 low,
+                                  PRInt32 broken,
+                                  PRInt32 no);
+
 child:
   OnStartRequest(nsHttpResponseHead responseHead,
                  PRBool             useResponseHead,
                  PRBool             isFromCache,
                  PRBool             cacheEntryAvailable,
                  PRUint32           cacheExpirationTime,
-                 nsCString          cachedCharset);
+                 nsCString          cachedCharset,
+                 nsCString          securityInfoSerialization);
 
   OnDataAvailable(nsCString data, 
                   PRUint32  offset, 
                   PRUint32  count);
 
   OnStopRequest(nsresult statusCode);
 
   OnProgress(PRUint64 progress, PRUint64 progressMax);
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -562,17 +562,22 @@ nsSecureBrowserUIImpl::EvaluateAndUpdate
       mSSLStatus = temp_SSLStatus;
     }
     if (updateTooltip) {
       mInfoTooltip = temp_InfoTooltip;
     }
     PR_LOG(gSecureDocLog, PR_LOG_DEBUG,
            ("SecureUI:%p: remember securityInfo %p\n", this,
             info));
-    mCurrentToplevelSecurityInfo = info;
+    nsCOMPtr<nsIAssociatedContentSecurity> associatedContentSecurityFromRequest =
+        do_QueryInterface(aRequest);
+    if (associatedContentSecurityFromRequest)
+        mCurrentToplevelSecurityInfo = aRequest;
+    else
+        mCurrentToplevelSecurityInfo = info;
   }
 
   return UpdateSecurityState(aRequest, withNewLocation, 
                              updateStatus, updateTooltip);
 }
 
 void
 nsSecureBrowserUIImpl::UpdateSubrequestMembers(nsISupports *securityInfo)
@@ -1101,16 +1106,17 @@ nsSecureBrowserUIImpl::OnStateChange(nsI
                 ));
   
         // before resetting our state, let's save information about
         // sub element loads, so we can restore it later
         prevContentSecurity->SetCountSubRequestsHighSecurity(saveSubHigh);
         prevContentSecurity->SetCountSubRequestsLowSecurity(saveSubLow);
         prevContentSecurity->SetCountSubRequestsBrokenSecurity(saveSubBroken);
         prevContentSecurity->SetCountSubRequestsNoSecurity(saveSubNo);
+        prevContentSecurity->Flush();
       }
 
       PRBool retrieveAssociatedState = PR_FALSE;
 
       if (securityInfo &&
           (aProgressStateFlags & nsIWebProgressListener::STATE_RESTORING) != 0) {
         retrieveAssociatedState = PR_TRUE;
       } else {
--- a/security/manager/ssl/public/nsIAssociatedContentSecurity.idl
+++ b/security/manager/ssl/public/nsIAssociatedContentSecurity.idl
@@ -41,16 +41,17 @@
  *
  * Some optimizations like bfcaching removes these callback notifications
  * and therefor the subcontent state could not be determined. In such
  * a case it is loaded from this object stored in nsIChannel.securityInfo.
  */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(8DB92DDE-799F-4d33-80F7-459CAC800DC9)]
+[scriptable, uuid(6AC9A699-D12A-45dc-9B02-9E5E0DD831B9)]
 interface nsIAssociatedContentSecurity : nsISupports
 {
   attribute long countSubRequestsHighSecurity;
   attribute long countSubRequestsLowSecurity;
   attribute long countSubRequestsBrokenSecurity;
   attribute long countSubRequestsNoSecurity;
+  void flush();
 };
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -506,16 +506,20 @@ NS_IMETHODIMP nsNSSSocketInfo::GetCountS
   *aSubRequestsNoSecurity = mSubRequestsNoSecurity;
   return NS_OK;
 }
 NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsNoSecurity(PRInt32 aSubRequestsNoSecurity)
 {
   mSubRequestsNoSecurity = aSubRequestsNoSecurity;
   return NS_OK;
 }
+NS_IMETHODIMP nsNSSSocketInfo::Flush()
+{
+  return NS_OK;
+}
 
 NS_IMETHODIMP
 nsNSSSocketInfo::GetShortSecurityDescription(PRUnichar** aText) {
   if (mShortDesc.IsEmpty())
     *aText = nsnull;
   else {
     *aText = ToNewUnicode(mShortDesc);
     NS_ENSURE_TRUE(*aText, NS_ERROR_OUT_OF_MEMORY);