nsSecureBrowserUI.cpp (6359B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "nsSecureBrowserUI.h" 7 8 #include "mozilla/Assertions.h" 9 #include "mozilla/Logging.h" 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/dom/nsMixedContentBlocker.h" 12 #include "nsContentUtils.h" 13 #include "nsIChannel.h" 14 #include "nsDocShell.h" 15 #include "nsIDocShellTreeItem.h" 16 #include "nsIInterfaceRequestorUtils.h" 17 #include "nsITransportSecurityInfo.h" 18 #include "nsIWebProgress.h" 19 #include "nsNetUtil.h" 20 #include "mozilla/dom/CanonicalBrowsingContext.h" 21 #include "mozilla/dom/WindowGlobalParent.h" 22 #include "mozilla/dom/Element.h" 23 #include "nsIBrowser.h" 24 25 using namespace mozilla; 26 using namespace mozilla::dom; 27 28 LazyLogModule gSecureBrowserUILog("nsSecureBrowserUI"); 29 30 nsSecureBrowserUI::nsSecureBrowserUI(CanonicalBrowsingContext* aBrowsingContext) 31 : mState(0) { 32 MOZ_ASSERT(NS_IsMainThread()); 33 34 // The BrowsingContext will own the SecureBrowserUI object, we keep a weak 35 // ref. 36 mBrowsingContextId = aBrowsingContext->Id(); 37 } 38 39 NS_IMPL_ISUPPORTS(nsSecureBrowserUI, nsISecureBrowserUI, 40 nsISupportsWeakReference) 41 42 NS_IMETHODIMP 43 nsSecureBrowserUI::GetState(uint32_t* aState) { 44 MOZ_ASSERT(NS_IsMainThread()); 45 NS_ENSURE_ARG(aState); 46 47 MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, 48 ("GetState %p mState: %x", this, mState)); 49 *aState = mState; 50 return NS_OK; 51 } 52 53 void nsSecureBrowserUI::RecomputeSecurityFlags() { 54 // Our BrowsingContext either has a new WindowGlobalParent, or the 55 // existing one has mutated its security state. 56 // Recompute our security state and fire notifications to listeners 57 58 RefPtr<WindowGlobalParent> win = GetCurrentWindow(); 59 mState = nsIWebProgressListener::STATE_IS_INSECURE; 60 61 // Only https is considered secure (it is possible to have e.g. an http URI 62 // with a channel that has a securityInfo that indicates the connection is 63 // secure - e.g. h2/alt-svc or by visiting an http URI over an https proxy). 64 nsCOMPtr<nsITransportSecurityInfo> securityInfo; 65 if (win && win->GetIsSecure()) { 66 securityInfo = win->GetSecurityInfo(); 67 if (securityInfo) { 68 MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, 69 (" we have a security info %p", securityInfo.get())); 70 71 nsresult rv = securityInfo->GetSecurityState(&mState); 72 73 // If the security state is STATE_IS_INSECURE, the TLS handshake never 74 // completed. Don't set any further state. 75 if (NS_SUCCEEDED(rv) && 76 mState != nsIWebProgressListener::STATE_IS_INSECURE) { 77 MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, 78 (" set mTopLevelSecurityInfo")); 79 bool isEV; 80 rv = securityInfo->GetIsExtendedValidation(&isEV); 81 if (NS_SUCCEEDED(rv) && isEV) { 82 MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is EV")); 83 mState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL; 84 } 85 } 86 } 87 88 // any protocol routed over tor is secure 89 if (!(mState & nsIWebProgressListener::STATE_IS_SECURE)) { 90 nsCOMPtr<nsIURI> innerDocURI = NS_GetInnermostURI(win->GetDocumentURI()); 91 if (innerDocURI && 92 nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(innerDocURI)) { 93 MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is onion")); 94 mState = (mState & ~nsIWebProgressListener::STATE_IS_INSECURE) | 95 nsIWebProgressListener::STATE_IS_SECURE; 96 } 97 } 98 } 99 100 // Add upgraded-state flags when request has been 101 // upgraded with HTTPS-Only Mode 102 if (win) { 103 // Check if top-level load has been upgraded 104 uint32_t httpsOnlyStatus = win->HttpsOnlyStatus(); 105 if (!(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UNINITIALIZED) && 106 !(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_EXEMPT)) { 107 mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED; 108 } 109 if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST) { 110 if (win->GetDocumentURI()->SchemeIs("https")) { 111 mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED_FIRST; 112 } else { 113 mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADE_FAILED; 114 } 115 } 116 // Add the secruity flags from the window 117 mState |= win->GetSecurityFlags(); 118 } 119 120 // If we have loaded mixed content and this is a secure page, 121 // then clear secure flags and add broken instead. 122 static const uint32_t kLoadedMixedContentFlags = 123 nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT | 124 nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT; 125 if (win && win->GetIsSecure() && (mState & kLoadedMixedContentFlags)) { 126 // reset state security flag 127 mState = mState >> 4 << 4; 128 // set state security flag to broken, since there is mixed content 129 mState |= nsIWebProgressListener::STATE_IS_BROKEN; 130 } 131 132 RefPtr<CanonicalBrowsingContext> ctx = 133 CanonicalBrowsingContext::Get(mBrowsingContextId); 134 if (!ctx) { 135 return; 136 } 137 138 if (ctx->GetDocShell()) { 139 nsDocShell* nativeDocShell = nsDocShell::Cast(ctx->GetDocShell()); 140 nativeDocShell->nsDocLoader::OnSecurityChange(nullptr, mState); 141 } else if (ctx->GetWebProgress()) { 142 ctx->GetWebProgress()->OnSecurityChange(ctx->GetWebProgress(), nullptr, 143 mState); 144 } 145 } 146 147 NS_IMETHODIMP 148 nsSecureBrowserUI::GetIsSecureContext(bool* aIsSecureContext) { 149 MOZ_ASSERT(NS_IsMainThread()); 150 NS_ENSURE_ARG(aIsSecureContext); 151 152 if (WindowGlobalParent* parent = GetCurrentWindow()) { 153 *aIsSecureContext = parent->GetIsSecureContext(); 154 } else { 155 *aIsSecureContext = false; 156 } 157 return NS_OK; 158 } 159 160 NS_IMETHODIMP 161 nsSecureBrowserUI::GetSecInfo(nsITransportSecurityInfo** result) { 162 MOZ_ASSERT(NS_IsMainThread()); 163 NS_ENSURE_ARG_POINTER(result); 164 165 if (WindowGlobalParent* parent = GetCurrentWindow()) { 166 *result = parent->GetSecurityInfo(); 167 } 168 NS_IF_ADDREF(*result); 169 170 return NS_OK; 171 } 172 173 WindowGlobalParent* nsSecureBrowserUI::GetCurrentWindow() { 174 RefPtr<CanonicalBrowsingContext> ctx = 175 CanonicalBrowsingContext::Get(mBrowsingContextId); 176 if (!ctx) { 177 return nullptr; 178 } 179 return ctx->GetCurrentWindowGlobal(); 180 }