diff options
Diffstat (limited to 'security/manager/ssl/nsSecureBrowserUI.cpp')
-rw-r--r-- | security/manager/ssl/nsSecureBrowserUI.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/security/manager/ssl/nsSecureBrowserUI.cpp b/security/manager/ssl/nsSecureBrowserUI.cpp new file mode 100644 index 0000000000..4f56d7319f --- /dev/null +++ b/security/manager/ssl/nsSecureBrowserUI.cpp @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsSecureBrowserUI.h" + +#include "mozilla/Assertions.h" +#include "mozilla/Logging.h" +#include "mozilla/Unused.h" +#include "mozilla/dom/Document.h" +#include "nsContentUtils.h" +#include "nsIChannel.h" +#include "nsDocShell.h" +#include "nsIDocShellTreeItem.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsITransportSecurityInfo.h" +#include "nsIWebProgress.h" +#include "nsNetUtil.h" +#include "mozilla/dom/CanonicalBrowsingContext.h" +#include "mozilla/dom/WindowGlobalParent.h" +#include "mozilla/dom/Element.h" +#include "nsIBrowser.h" + +using namespace mozilla; +using namespace mozilla::dom; + +LazyLogModule gSecureBrowserUILog("nsSecureBrowserUI"); + +nsSecureBrowserUI::nsSecureBrowserUI(CanonicalBrowsingContext* aBrowsingContext) + : mState(0) { + MOZ_ASSERT(NS_IsMainThread()); + + // The BrowsingContext will own the SecureBrowserUI object, we keep a weak + // ref. + mBrowsingContextId = aBrowsingContext->Id(); +} + +NS_IMPL_ISUPPORTS(nsSecureBrowserUI, nsISecureBrowserUI, + nsISupportsWeakReference) + +NS_IMETHODIMP +nsSecureBrowserUI::GetState(uint32_t* aState) { + MOZ_ASSERT(NS_IsMainThread()); + NS_ENSURE_ARG(aState); + + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, + ("GetState %p mState: %x", this, mState)); + *aState = mState; + return NS_OK; +} + +void nsSecureBrowserUI::RecomputeSecurityFlags() { + // Our BrowsingContext either has a new WindowGlobalParent, or the + // existing one has mutated its security state. + // Recompute our security state and fire notifications to listeners + + RefPtr<WindowGlobalParent> win = GetCurrentWindow(); + mState = nsIWebProgressListener::STATE_IS_INSECURE; + + // Only https is considered secure (it is possible to have e.g. an http URI + // with a channel that has a securityInfo that indicates the connection is + // secure - e.g. h2/alt-svc or by visiting an http URI over an https proxy). + nsCOMPtr<nsITransportSecurityInfo> securityInfo; + if (win && win->GetIsSecure()) { + securityInfo = win->GetSecurityInfo(); + if (securityInfo) { + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, + (" we have a security info %p", securityInfo.get())); + + nsresult rv = securityInfo->GetSecurityState(&mState); + + // If the security state is STATE_IS_INSECURE, the TLS handshake never + // completed. Don't set any further state. + if (NS_SUCCEEDED(rv) && + mState != nsIWebProgressListener::STATE_IS_INSECURE) { + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, + (" set mTopLevelSecurityInfo")); + bool isEV; + rv = securityInfo->GetIsExtendedValidation(&isEV); + if (NS_SUCCEEDED(rv) && isEV) { + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is EV")); + mState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL; + } + } + } + } + + // Add upgraded-state flags when request has been + // upgraded with HTTPS-Only Mode + if (win) { + // Check if top-level load has been upgraded + uint32_t httpsOnlyStatus = win->HttpsOnlyStatus(); + if (!(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UNINITIALIZED) && + !(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_EXEMPT)) { + mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED; + } + if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST) { + if (win->GetDocumentURI()->SchemeIs("https")) { + mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED_FIRST; + } else { + mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADE_FAILED; + } + } + // Add the secruity flags from the window + mState |= win->GetSecurityFlags(); + } + + // If we have loaded mixed content and this is a secure page, + // then clear secure flags and add broken instead. + static const uint32_t kLoadedMixedContentFlags = + nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT | + nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT; + if (win && win->GetIsSecure() && (mState & kLoadedMixedContentFlags)) { + // reset state security flag + mState = mState >> 4 << 4; + // set state security flag to broken, since there is mixed content + mState |= nsIWebProgressListener::STATE_IS_BROKEN; + } + + RefPtr<CanonicalBrowsingContext> ctx = + CanonicalBrowsingContext::Get(mBrowsingContextId); + if (!ctx) { + return; + } + + if (ctx->GetDocShell()) { + nsDocShell* nativeDocShell = nsDocShell::Cast(ctx->GetDocShell()); + nativeDocShell->nsDocLoader::OnSecurityChange(nullptr, mState); + } else if (ctx->GetWebProgress()) { + ctx->GetWebProgress()->OnSecurityChange(nullptr, nullptr, mState); + } +} + +NS_IMETHODIMP +nsSecureBrowserUI::GetIsSecureContext(bool* aIsSecureContext) { + MOZ_ASSERT(NS_IsMainThread()); + NS_ENSURE_ARG(aIsSecureContext); + + if (WindowGlobalParent* parent = GetCurrentWindow()) { + *aIsSecureContext = parent->GetIsSecureContext(); + } else { + *aIsSecureContext = false; + } + return NS_OK; +} + +NS_IMETHODIMP +nsSecureBrowserUI::GetSecInfo(nsITransportSecurityInfo** result) { + MOZ_ASSERT(NS_IsMainThread()); + NS_ENSURE_ARG_POINTER(result); + + if (WindowGlobalParent* parent = GetCurrentWindow()) { + *result = parent->GetSecurityInfo(); + } + NS_IF_ADDREF(*result); + + return NS_OK; +} + +WindowGlobalParent* nsSecureBrowserUI::GetCurrentWindow() { + RefPtr<CanonicalBrowsingContext> ctx = + CanonicalBrowsingContext::Get(mBrowsingContextId); + if (!ctx) { + return nullptr; + } + return ctx->GetCurrentWindowGlobal(); +} |