Bug 1631405 - Move nsISecureBrowserUI to be owned by the canonical browsing context instead of docshell. r=nika,ckerschb,Gijs,webcompat-reviewers,twisniewski

This removes all docshell nsISecureBrowserUI and mixed content properties, and moves them into CanonicalBrowsingContext/WindowGlobalParent. It makes the mixed content blocker just compute the state for the current load, and then send the results to the parent process, where we update the security state accordingly.

I think we could in the future remove onSecurityChange entirely, and instead just fire an event to the <browser> element notifying it of changes to the queryable securityUI.

Unfortunately we have a lot of existing code that depends on specific ordering between onSecurityChange and onLocationChange, so I had to hook into the RemoteWebProgress implementation in BrowserParent to mimic the same timings.

Differential Revision: https://phabricator.services.mozilla.com/D75447
This commit is contained in:
Matt Woodrow 2020-05-26 21:17:01 +00:00
parent 5b64e9bae2
commit 240d417eb6
42 changed files with 475 additions and 932 deletions

View File

@ -148,8 +148,6 @@ class ReportSiteIssueHelperChild extends JSWindowActorChild {
case "GetBlockingStatus":
const { docShell } = this;
return {
hasMixedActiveContentBlocked: docShell.hasMixedActiveContentBlocked,
hasMixedDisplayContentBlocked: docShell.hasMixedDisplayContentBlocked,
hasTrackingContentBlocked: docShell.hasTrackingContentBlocked,
};
}

View File

@ -31,6 +31,14 @@ this.tabExtras = class extends ExtensionAPI {
const promises = actors.map(actor => actor.sendQuery("GetLog"));
const logs = await Promise.all(promises);
const info = await actors[0].sendQuery("GetBlockingStatus");
info.hasMixedActiveContentBlocked = !!(
browsingContext.secureBrowserUI.state &
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT
);
info.hasMixedDisplayContentBlocked = !!(
browsingContext.secureBrowserUI.state &
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT
);
info.log = logs
.flat()
.sort((a, b) => a.timeStamp - b.timeStamp)

View File

@ -9,6 +9,7 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/BrowsingContextBinding.h"
#include "mozilla/dom/ContentChild.h"

View File

@ -26,6 +26,7 @@
#include "nsIWebBrowserChrome.h"
#include "nsNetUtil.h"
#include "nsSHistory.h"
#include "nsSecureBrowserUI.h"
using namespace mozilla::ipc;
@ -114,6 +115,23 @@ void CanonicalBrowsingContext::SetOwnerProcessId(uint64_t aProcessId) {
mProcessId = aProcessId;
}
nsISecureBrowserUI* CanonicalBrowsingContext::GetSecureBrowserUI() {
if (!IsTop()) {
return nullptr;
}
if (!mSecureBrowserUI) {
mSecureBrowserUI = new nsSecureBrowserUI(this);
}
return mSecureBrowserUI;
}
void CanonicalBrowsingContext::
UpdateSecurityStateForLocationOrMixedContentChange() {
if (mSecureBrowserUI) {
mSecureBrowserUI->UpdateForLocationOrMixedContentChange();
}
}
void CanonicalBrowsingContext::SetInFlightProcessId(uint64_t aProcessId) {
// We can't handle more than one in-flight process change at a time.
MOZ_ASSERT_IF(aProcessId, mInFlightProcessId == 0);

View File

@ -18,7 +18,9 @@
#include "nsHashKeys.h"
class nsISHistory;
#include "nsISecureBrowserUI.h"
class nsSecureBrowserUI;
namespace mozilla {
namespace net {
class DocumentLoadListener;
@ -141,6 +143,15 @@ class CanonicalBrowsingContext final : public BrowsingContext {
bool AttemptLoadURIInParent(nsDocShellLoadState* aLoadState,
uint32_t* aLoadIdentifier);
// Get or create a secure browser UI for this BrowsingContext
nsISecureBrowserUI* GetSecureBrowserUI();
// Called when the current URI changes (from an
// nsIWebProgressListener::OnLocationChange event, so that we
// can update our security UI for the new location, or when the
// mixed content state for our current window is changed.
void UpdateSecurityStateForLocationOrMixedContentChange();
protected:
// Called when the browsing context is being discarded.
void CanonicalDiscard();
@ -216,6 +227,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
nsTArray<SessionHistoryEntryAndId> mLoadingEntries;
RefPtr<SessionHistoryEntry> mActiveEntry;
RefPtr<nsSecureBrowserUI> mSecureBrowserUI;
};
} // namespace dom

View File

@ -218,6 +218,24 @@ void WindowContext::Discard() {
Group()->Unregister(this);
}
void WindowContext::AddMixedContentSecurityState(uint32_t aStateFlags) {
MOZ_ASSERT(TopWindowContext() == this);
MOZ_ASSERT((aStateFlags &
(nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT)) ==
aStateFlags,
"Invalid flags specified!");
if (XRE_IsParentProcess()) {
Canonical()->AddMixedContentSecurityState(aStateFlags);
} else {
ContentChild* child = ContentChild::GetSingleton();
child->SendAddMixedContentSecurityState(this, aStateFlags);
}
}
WindowContext::IPCInitializer WindowContext::GetIPCInitializer() {
IPCInitializer init;
init.mInnerWindowId = mInnerWindowId;

View File

@ -92,6 +92,12 @@ class WindowContext : public nsISupports, public nsWrapperCache {
static void CreateFromIPC(IPCInitializer&& aInit);
// Add new mixed content security state flags.
// These should be some of the four nsIWebProgressListener
// 'MIXED' state flags, and should only be called on the
// top window context.
void AddMixedContentSecurityState(uint32_t aStateFlags);
protected:
WindowContext(BrowsingContext* aBrowsingContext, uint64_t aInnerWindowId,
uint64_t aOuterWindowId, bool aInProcess, FieldTuple&& aFields);

View File

@ -501,7 +501,8 @@ already_AddRefed<nsDocShell> nsDocShell::Create(
// various methods via which nsDocLoader can be notified. Note that this
// holds an nsWeakPtr to |ds|, so it's ok.
rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
nsIWebProgress::NOTIFY_STATE_NETWORK);
nsIWebProgress::NOTIFY_STATE_NETWORK |
nsIWebProgress::NOTIFY_LOCATION);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
@ -1400,40 +1401,6 @@ void nsDocShell::GetParentCharset(const Encoding*& aCharset,
NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded) {
RefPtr<Document> doc(GetDocument());
*aHasMixedActiveContentLoaded = doc && doc->GetHasMixedActiveContentLoaded();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentBlocked(
bool* aHasMixedActiveContentBlocked) {
RefPtr<Document> doc(GetDocument());
*aHasMixedActiveContentBlocked =
doc && doc->GetHasMixedActiveContentBlocked();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedDisplayContentLoaded(
bool* aHasMixedDisplayContentLoaded) {
RefPtr<Document> doc(GetDocument());
*aHasMixedDisplayContentLoaded =
doc && doc->GetHasMixedDisplayContentLoaded();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedDisplayContentBlocked(
bool* aHasMixedDisplayContentBlocked) {
RefPtr<Document> doc(GetDocument());
*aHasMixedDisplayContentBlocked =
doc && doc->GetHasMixedDisplayContentBlocked();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
MOZ_ASSERT(aPromise);
@ -1974,20 +1941,6 @@ nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation,
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetSecurityUI(nsISecureBrowserUI** aSecurityUI) {
NS_IF_ADDREF(*aSecurityUI = mSecurityUI);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetSecurityUI(nsISecureBrowserUI* aSecurityUI) {
MOZ_ASSERT(!mIsBeingDestroyed);
mSecurityUI = aSecurityUI;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
@ -4348,9 +4301,6 @@ nsDocShell::Destroy() {
mChromeEventHandler = nullptr;
// required to break ref cycle
mSecurityUI = nullptr;
// Cancel any timers that were set for this docshell; this is needed
// to break the cycle between us and the timers.
CancelRefreshURITimers();
@ -5623,7 +5573,17 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
NS_IMETHODIMP
nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
nsIURI* aURI, uint32_t aFlags) {
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
if (XRE_IsParentProcess()) {
// Since we've now changed Documents, notify the BrowsingContext that we've
// changed. Ideally we'd just let the BrowsingContext do this when it
// changes the current window global, but that happens before this and we
// have a lot of tests that depend on the specific ordering of messages.
if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
GetBrowsingContext()
->Canonical()
->UpdateSecurityStateForLocationOrMixedContentChange();
}
}
return NS_OK;
}

View File

@ -1146,9 +1146,6 @@ class nsDocShell final : public nsDocLoader,
// Editor data, if this document is designMode or contentEditable.
mozilla::UniquePtr<nsDocShellEditorData> mEditorData;
// Secure browser UI object
nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
// The URI we're currently loading. This is only relevant during the
// firing of a pagehide/unload. The caller of FirePageHideNotification()
// is responsible for setting it and unsetting it. It may be null if the

View File

@ -353,12 +353,6 @@ interface nsIDocShell : nsIDocShellTreeItem
attribute nsILayoutHistoryState layoutHistoryState;
/**
* The SecureBrowserUI object for this docshell. This is set by XUL
* <browser> or nsWebBrowser for their root docshell.
*/
attribute nsISecureBrowserUI securityUI;
/**
* Object used to delegate URI loading to an upper context.
* Currently only set for GeckoView to allow handling of load requests
@ -466,45 +460,6 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
readonly attribute boolean isInUnload;
/**
* This attribute determines whether Mixed Active Content is loaded on the
* document. When it is true, mixed active content was not blocked and has
* loaded (or is about to load) on the page. When it is false, mixed active content
* has not loaded on 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).
*/
[infallible] 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.
*/
[infallible] readonly attribute boolean hasMixedActiveContentBlocked;
/**
* This attribute determines whether Mixed Display Content is loaded on the
* document. When it is true, mixed display content was not blocked and has
* loaded (or is about to load) on the page. Similar behavior to
* hasMixedActiveContentLoaded.
*/
[infallible] readonly attribute boolean hasMixedDisplayContentLoaded;
/**
* This attribute determines whether a document has Mixed Display Content
* that has been blocked from loading. Similar behavior to
* hasMixedActiveContentBlocked.
*/
[infallible] readonly attribute boolean hasMixedDisplayContentBlocked;
/**
* Disconnects this docshell's editor from its window, and stores the
* editor data in the open document's session history entry. This

View File

@ -1846,40 +1846,6 @@ Document::~Document() {
// don't report for about: pages
if (!IsAboutPage()) {
// Record the page load
uint32_t pageLoaded = 1;
Accumulate(Telemetry::MIXED_CONTENT_UNBLOCK_COUNTER, pageLoaded);
// Record the mixed content status of the docshell in Telemetry
enum {
NO_MIXED_CONTENT = 0, // There is no Mixed Content on the page
MIXED_DISPLAY_CONTENT =
1, // The page attempted to load Mixed Display Content
MIXED_ACTIVE_CONTENT =
2, // The page attempted to load Mixed Active Content
MIXED_DISPLAY_AND_ACTIVE_CONTENT =
3 // The page attempted to load Mixed Display & Mixed Active
// Content
};
bool mixedActiveLoaded = GetHasMixedActiveContentLoaded();
bool mixedActiveBlocked = GetHasMixedActiveContentBlocked();
bool mixedDisplayLoaded = GetHasMixedDisplayContentLoaded();
bool mixedDisplayBlocked = GetHasMixedDisplayContentBlocked();
bool hasMixedDisplay = (mixedDisplayBlocked || mixedDisplayLoaded);
bool hasMixedActive = (mixedActiveBlocked || mixedActiveLoaded);
uint32_t mixedContentLevel = NO_MIXED_CONTENT;
if (hasMixedDisplay && hasMixedActive) {
mixedContentLevel = MIXED_DISPLAY_AND_ACTIVE_CONTENT;
} else if (hasMixedActive) {
mixedContentLevel = MIXED_ACTIVE_CONTENT;
} else if (hasMixedDisplay) {
mixedContentLevel = MIXED_DISPLAY_CONTENT;
}
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
// record CSP telemetry on this document
if (mHasCSP) {
Accumulate(Telemetry::CSP_DOCUMENTS_COUNT, 1);

View File

@ -1050,96 +1050,6 @@ class Document : public nsINode,
*/
void SetBidiOptions(uint32_t aBidiOptions) { mBidiOptions = aBidiOptions; }
/**
* Get the has mixed active content loaded flag for this document.
*/
bool GetHasMixedActiveContentLoaded() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
/**
* Set the has mixed active content loaded flag for this document.
*/
void SetHasMixedActiveContentLoaded(bool aHasMixedActiveContentLoaded) {
if (aHasMixedActiveContentLoaded) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
}
/**
* Get mixed active content blocked flag for this document.
*/
bool GetHasMixedActiveContentBlocked() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
}
/**
* Set the mixed active content blocked flag for this document.
*/
void SetHasMixedActiveContentBlocked(bool aHasMixedActiveContentBlocked) {
if (aHasMixedActiveContentBlocked) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
}
}
/**
* Get the has mixed display content loaded flag for this document.
*/
bool GetHasMixedDisplayContentLoaded() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
/**
* Set the has mixed display content loaded flag for this document.
*/
void SetHasMixedDisplayContentLoaded(bool aHasMixedDisplayContentLoaded) {
if (aHasMixedDisplayContentLoaded) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
}
/**
* Get mixed display content blocked flag for this document.
*/
bool GetHasMixedDisplayContentBlocked() {
return mMixedContentFlags &
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
}
/**
* Set the mixed display content blocked flag for this document.
*/
void SetHasMixedDisplayContentBlocked(bool aHasMixedDisplayContentBlocked) {
if (aHasMixedDisplayContentBlocked) {
mMixedContentFlags |=
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
} else {
mMixedContentFlags &=
~nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
}
}
uint32_t GetMixedContentFlags() const { return mMixedContentFlags; }
void AddMixedContentFlags(uint32_t aMixedContentFlags) {
mMixedContentFlags |= aMixedContentFlags;
}
/**
* Set CSP flag for this document.
*/
@ -4390,8 +4300,6 @@ class Document : public nsINode,
// GetPermissionDelegateHandler
RefPtr<PermissionDelegateHandler> mPermissionDelegateHandler;
uint32_t mMixedContentFlags = 0;
// True if BIDI is enabled.
bool mBidiEnabled : 1;
// True if we may need to recompute the language prefs for this document.

View File

@ -1878,6 +1878,7 @@ addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
addExternalIface('nsIContentChild', nativeType='nsIContentChild', notflattened=True)
addExternalIface('nsIContentParent', nativeType='nsIContentParent', notflattened=True)
addExternalIface('nsIReferrerInfo', nativeType='nsIReferrerInfo', notflattened=True)
addExternalIface('nsISecureBrowserUI', nativeType='nsISecureBrowserUI', notflattened=True)
addExternalIface('nsIWebNavigation', nativeType='nsIWebNavigation', notflattened=True)
addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
interface nsIDocShell;
interface nsISecureBrowserUI;
interface mixin LoadContextMixin {
readonly attribute WindowProxy? associatedWindow;
@ -125,6 +126,8 @@ interface CanonicalBrowsingContext : BrowsingContext {
void notifyStartDelayedAutoplayMedia();
void notifyMediaMutedChanged(boolean muted);
readonly attribute nsISecureBrowserUI? secureBrowserUI;
static unsigned long countSiteOrigins(sequence<BrowsingContext> roots);
/**

View File

@ -160,20 +160,6 @@ interface nsIBrowser : nsISupports
in uint64_t aRequestContextID,
in AString aContentType);
/**
* Called by Gecko when a security chang event needs to update the event
* state stored in the security UI object stored in the parent process.
*
* @param aSecurityInfo the transport security information from the content
* process
* @param aState the flags from the OnSecurityChange event that triggered
* this method, as outlined in nsIWebProgressListener
* @param aIsSecureContext whether or not the context is secure
*/
void updateSecurityUIForSecurityChange(in nsITransportSecurityInfo aSecurityInfo,
in uint32_t aState,
in boolean aIsSecureContext);
/**
* Called by Gecko when it wants to change the process which is currently
* being used to render content in this tab.

View File

@ -3711,56 +3711,9 @@ NS_IMETHODIMP BrowserChild::OnStatusChange(nsIWebProgress* aWebProgress,
NS_IMETHODIMP BrowserChild::OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aState) {
if (!IPCOpen() || !mShouldSendWebProgressEventsToParent) {
return NS_OK;
}
Maybe<WebProgressData> webProgressData;
RequestData requestData;
MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData,
requestData));
Maybe<WebProgressSecurityChangeData> securityChangeData;
if (aWebProgress && webProgressData->isTopLevel()) {
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
if (!docShell) {
return NS_OK;
}
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
{
nsCOMPtr<nsISecureBrowserUI> securityUI;
MOZ_TRY(docShell->GetSecurityUI(getter_AddRefs(securityUI)));
if (securityUI) {
MOZ_TRY(securityUI->GetSecInfo(getter_AddRefs(securityInfo)));
}
}
bool isSecureContext = false;
{
nsCOMPtr<nsPIDOMWindowOuter> outerWindow = do_GetInterface(docShell);
if (!outerWindow) {
return NS_OK;
}
if (nsPIDOMWindowInner* window = outerWindow->GetCurrentInnerWindow()) {
isSecureContext = window->IsSecureContext();
} else {
return NS_OK;
}
}
securityChangeData.emplace();
securityChangeData->securityInfo() = ToRefPtr(std::move(securityInfo));
securityChangeData->isSecureContext() = isSecureContext;
}
Unused << SendOnSecurityChange(webProgressData, requestData, aState,
securityChangeData);
// Security changes are now handled entirely in the parent process
// so we don't need to worry about forwarding them (and we shouldn't
// be receiving any to forward).
return NS_OK;
}

View File

@ -116,6 +116,7 @@
#include "MMPrinter.h"
#include "SessionStoreFunctions.h"
#include "mozilla/dom/CrashReport.h"
#include "nsISecureBrowserUI.h"
#ifdef XP_WIN
# include "mozilla/plugins/PluginWidgetParent.h"
@ -2703,6 +2704,13 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnLocationChange(
Unused << managerAsListener->OnLocationChange(webProgress, request, aLocation,
aFlags);
// Since we've now changed Documents, notify the BrowsingContext that we've
// changed. Ideally we'd just let the BrowsingContext do this when it changes
// the current window global, but that happens before this and we have a lot
// of tests that depend on the specific ordering of messages.
if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
GetBrowsingContext()->UpdateSecurityStateForLocationOrMixedContentChange();
}
return IPC_OK();
}
@ -2734,36 +2742,6 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnStatusChange(
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserParent::RecvOnSecurityChange(
const Maybe<WebProgressData>& aWebProgressData,
const RequestData& aRequestData, const uint32_t aState,
const Maybe<WebProgressSecurityChangeData>& aSecurityChangeData) {
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return IPC_OK();
}
nsCOMPtr<nsIWebProgress> webProgress;
nsCOMPtr<nsIRequest> request;
ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
getter_AddRefs(webProgress),
getter_AddRefs(request));
if (aWebProgressData && aWebProgressData->isTopLevel() &&
aSecurityChangeData.isSome()) {
Unused << browser->UpdateSecurityUIForSecurityChange(
aSecurityChangeData->securityInfo(), aState,
aSecurityChangeData->isSecureContext());
}
Unused << managerAsListener->OnSecurityChange(webProgress, request, aState);
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserParent::RecvNavigationFinished() {
nsCOMPtr<nsIBrowser> browser =
mFrameElement ? mFrameElement->AsBrowser() : nullptr;

View File

@ -307,11 +307,6 @@ class BrowserParent final : public PBrowserParent,
const RequestData& aRequestData, const nsresult aStatus,
const nsString& aMessage);
mozilla::ipc::IPCResult RecvOnSecurityChange(
const Maybe<WebProgressData>& aWebProgressData,
const RequestData& aRequestData, const uint32_t aState,
const Maybe<WebProgressSecurityChangeData>& aSecurityChangeData);
mozilla::ipc::IPCResult RecvNotifyContentBlockingEvent(
const uint32_t& aEvent, const RequestData& aRequestData,
const bool aBlocked, const nsACString& aTrackingOrigin,

View File

@ -3573,6 +3573,16 @@ bool ContentParent::DeallocPParentToChildStreamParent(
return true;
}
mozilla::ipc::IPCResult ContentParent::RecvAddMixedContentSecurityState(
const MaybeDiscarded<WindowContext>& aContext, uint32_t aStateFlags) {
if (aContext.IsNullOrDiscarded()) {
return IPC_OK();
}
aContext.get()->AddMixedContentSecurityState(aStateFlags);
return IPC_OK();
}
already_AddRefed<PExternalHelperAppParent>
ContentParent::AllocPExternalHelperAppParent(
nsIURI* uri, const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,

View File

@ -1063,6 +1063,9 @@ class ContentParent final
const MaybeDiscarded<WindowContext>& aContext,
WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch);
mozilla::ipc::IPCResult RecvAddMixedContentSecurityState(
const MaybeDiscarded<WindowContext>& aContext, uint32_t aStateFlags);
mozilla::ipc::IPCResult RecvFirstIdle();
mozilla::ipc::IPCResult RecvDeviceReset();

View File

@ -6,6 +6,7 @@
#include "mozilla/dom/JSWindowActorBinding.h"
#include "mozilla/dom/JSWindowActorParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/MessageManagerBinding.h"

View File

@ -94,7 +94,6 @@ using mozilla::ScrollAxis from "mozilla/PresShellForwards.h";
using mozilla::ScrollFlags from "mozilla/PresShellForwards.h";
using struct InputFormData from "mozilla/dom/SessionStoreMessageUtils.h";
using struct CollectedInputDataValue from "mozilla/dom/SessionStoreMessageUtils.h";
using refcounted class nsITransportSecurityInfo from "nsITransportSecurityInfo.h";
using mozilla::ContentBlockingNotifier::StorageAccessGrantedReason from "mozilla/ContentBlockingNotifier.h";
using CallerType from "mozilla/dom/BindingDeclarations.h";
using mozilla::dom::EmbedderElementEventType from "mozilla/dom/TabMessageUtils.h";
@ -154,12 +153,6 @@ struct WebProgressLocationChangeData
uint64_t? requestContextID;
};
struct WebProgressSecurityChangeData
{
nsITransportSecurityInfo securityInfo;
bool isSecureContext;
};
/**
* A PBrowser manages a maximal locally connected subtree of BrowsingContexts
* in a content process.
@ -583,10 +576,6 @@ parent:
RequestData aRequestData, nsresult aStatus,
nsString aMessage);
async OnSecurityChange(WebProgressData? aWebProgressData,
RequestData aRequestData, uint32_t aState,
WebProgressSecurityChangeData? aSecurityChangeData);
async NotifyContentBlockingEvent(uint32_t aEvent, RequestData aRequestData,
bool aBlocked, nsCString aTrackingOrigin,
nsCString[] aTrackingFullHashes,

View File

@ -988,6 +988,8 @@ parent:
async OpenNotificationSettings(Principal principal);
async AddMixedContentSecurityState(MaybeDiscardedWindowContext aContext, uint32_t aStateFlags);
// Request that the ServiceWorkerManager in the parent process create a
// notification "click" or "close" event and dispatch it on the relevant
// ServiceWorker. This needs to happen because when a notification is

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include "mozilla/dom/DocShellMessageUtils.h";
include "mozilla/ipc/TransportSecurityInfoUtils.h";
include protocol PBrowser;
include protocol PInProcess;
@ -21,6 +22,7 @@ using nscolor from "nsColor.h";
using refcounted class nsDocShellLoadState from "nsDocShellLoadState.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
using refcounted class nsITransportSecurityInfo from "nsITransportSecurityInfo.h";
namespace mozilla {
namespace dom {
@ -114,6 +116,8 @@ parent:
// Update the document's HTTPS-Only Mode flags in this WindowGlobal.
async UpdateHttpsOnlyStatus(uint32_t aHttpsOnlyStatus);
async UpdateDocumentSecurityInfo(nsITransportSecurityInfo aSecurityInfo);
/// Send down initial document bit to the parent.
async SetIsInitialDocument(bool aIsInitialDocument);

View File

@ -129,11 +129,18 @@ WindowGlobalInit WindowGlobalActor::WindowInitializer(
true;
}
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
if (nsCOMPtr<nsIChannel> channel = doc->GetChannel()) {
nsCOMPtr<nsISupports> securityInfoSupports;
channel->GetSecurityInfo(getter_AddRefs(securityInfoSupports));
securityInfo = do_QueryInterface(securityInfoSupports);
}
init.securityInfo() = securityInfo;
// Most data here is specific to the Document, which can change without
// creating a new WindowGlobal. Anything new added here which fits that
// description should also be synchronized in
// WindowGlobalChild::OnNewDocument.
return init;
}

View File

@ -59,6 +59,20 @@ WindowGlobalChild::WindowGlobalChild(dom::WindowContext* aWindowContext,
if (!mDocumentURI) {
NS_NewURI(getter_AddRefs(mDocumentURI), "about:blank");
}
#ifdef MOZ_GECKO_PROFILER
// Registers a DOM Window with the profiler. It re-registers the same Inner
// Window ID with different URIs because when a Browsing context is first
// loaded, the first url loaded in it will be about:blank. This call keeps the
// first non-about:blank registration of window and discards the previous one.
uint64_t embedderInnerWindowID = 0;
if (BrowsingContext()->GetParent()) {
embedderInnerWindowID = BrowsingContext()->GetEmbedderInnerWindowId();
}
profiler_register_page(BrowsingContext()->Id(), InnerWindowId(),
aDocumentURI->GetSpecOrDefault(),
embedderInnerWindowID);
#endif
}
already_AddRefed<WindowGlobalChild> WindowGlobalChild::Create(
@ -165,6 +179,15 @@ void WindowGlobalChild::OnNewDocument(Document* aDocument) {
// FIXME: Perhaps these should be combined into a smaller number of messages?
SetDocumentURI(aDocument->GetDocumentURI());
SetDocumentPrincipal(aDocument->NodePrincipal());
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
if (nsCOMPtr<nsIChannel> channel = aDocument->GetChannel()) {
nsCOMPtr<nsISupports> securityInfoSupports;
channel->GetSecurityInfo(getter_AddRefs(securityInfoSupports));
securityInfo = do_QueryInterface(securityInfoSupports);
}
SendUpdateDocumentSecurityInfo(securityInfo);
SendUpdateDocumentCspSettings(aDocument->GetBlockAllMixedContent(false),
aDocument->GetUpgradeInsecureRequests(false));
SendUpdateSandboxFlags(aDocument->GetSandboxFlags());

View File

@ -41,6 +41,7 @@
#include "nsIBrowser.h"
#include "nsITransportSecurityInfo.h"
#include "nsISharePicker.h"
#include "mozilla/Telemetry.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
@ -93,6 +94,7 @@ already_AddRefed<WindowGlobalParent> WindowGlobalParent::CreateDisconnected(
wgp->mBlockAllMixedContent = aInit.blockAllMixedContent();
wgp->mUpgradeInsecureRequests = aInit.upgradeInsecureRequests();
wgp->mSandboxFlags = aInit.sandboxFlags();
wgp->mSecurityInfo = aInit.securityInfo();
net::CookieJarSettings::Deserialize(aInit.cookieJarSettings(),
getter_AddRefs(wgp->mCookieJarSettings));
MOZ_RELEASE_ASSERT(wgp->mDocumentPrincipal, "Must have a valid principal");
@ -594,6 +596,12 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvUpdateCookieJarSettings(
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvUpdateDocumentSecurityInfo(
nsITransportSecurityInfo* aSecurityInfo) {
mSecurityInfo = aSecurityInfo;
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvShare(
IPCWebShareData&& aData, WindowGlobalParent::ShareResolver&& aResolver) {
// Widget Layer handoff...
@ -717,6 +725,43 @@ already_AddRefed<Promise> WindowGlobalParent::GetSecurityInfo(
}
void WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy) {
if (GetBrowsingContext()->IsTopContent() &&
!mDocumentPrincipal->SchemeIs("about")) {
// Record the page load
uint32_t pageLoaded = 1;
Accumulate(Telemetry::MIXED_CONTENT_UNBLOCK_COUNTER, pageLoaded);
// Record the mixed content status of the docshell in Telemetry
enum {
NO_MIXED_CONTENT = 0, // There is no Mixed Content on the page
MIXED_DISPLAY_CONTENT =
1, // The page attempted to load Mixed Display Content
MIXED_ACTIVE_CONTENT =
2, // The page attempted to load Mixed Active Content
MIXED_DISPLAY_AND_ACTIVE_CONTENT = 3 // The page attempted to load Mixed
// Display & Mixed Active Content
};
bool hasMixedDisplay =
mMixedContentSecurityState &
(nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
bool hasMixedActive =
mMixedContentSecurityState &
(nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
uint32_t mixedContentLevel = NO_MIXED_CONTENT;
if (hasMixedDisplay && hasMixedActive) {
mixedContentLevel = MIXED_DISPLAY_AND_ACTIVE_CONTENT;
} else if (hasMixedActive) {
mixedContentLevel = MIXED_ACTIVE_CONTENT;
} else if (hasMixedDisplay) {
mixedContentLevel = MIXED_DISPLAY_CONTENT;
}
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
}
// If there are any non-discarded nested contexts when this WindowContext is
// destroyed, tear them down.
nsTArray<RefPtr<dom::BrowsingContext>> toDiscard;
@ -828,6 +873,28 @@ bool WindowGlobalParent::ShouldTrackSiteOriginTelemetry() {
return DocumentPrincipal()->GetIsContentPrincipal();
}
void WindowGlobalParent::AddMixedContentSecurityState(uint32_t aStateFlags) {
MOZ_ASSERT(TopWindowContext() == this);
MOZ_ASSERT((aStateFlags &
(nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT)) ==
aStateFlags,
"Invalid flags specified!");
if ((mMixedContentSecurityState & aStateFlags) ==
mMixedContentSecurityState) {
return;
}
mMixedContentSecurityState |= aStateFlags;
if (GetBrowsingContext()->GetCurrentWindowGlobal() == this) {
GetBrowsingContext()->UpdateSecurityStateForLocationOrMixedContentChange();
}
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(WindowGlobalParent, WindowContext,
mWindowActors)

View File

@ -15,7 +15,6 @@
#include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/PWindowGlobalParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/WindowContext.h"
#include "nsDataHashtable.h"
#include "nsRefPtrHashtable.h"
@ -38,6 +37,7 @@ class CrossProcessPaint;
namespace dom {
class BrowserParent;
class WindowGlobalChild;
class JSWindowActorParent;
class JSActorMessageMeta;
@ -190,6 +190,13 @@ class WindowGlobalParent final : public WindowContext,
uint32_t HttpsOnlyStatus() { return mHttpsOnlyStatus; }
// 'MIXED' state flags, and should only be called on the
// top window context.
void AddMixedContentSecurityState(uint32_t aStateFlags);
uint32_t GetMixedContentSecurityFlags() { return mMixedContentSecurityState; }
nsITransportSecurityInfo* GetSecurityInfo() { return mSecurityInfo; }
protected:
const nsAString& GetRemoteType() override;
JSActor::Type GetSide() override { return JSActor::Type::Parent; }
@ -216,6 +223,8 @@ class WindowGlobalParent final : public WindowContext,
mIsInitialDocument = aIsInitialDocument;
return IPC_OK();
}
mozilla::ipc::IPCResult RecvUpdateDocumentSecurityInfo(
nsITransportSecurityInfo* aSecurityInfo);
mozilla::ipc::IPCResult RecvSetHasBeforeUnload(bool aHasBeforeUnload);
mozilla::ipc::IPCResult RecvSetClientInfo(
const IPCClientInfo& aIPCClientInfo);
@ -266,9 +275,13 @@ class WindowGlobalParent final : public WindowContext,
// includes the activity log for all of the nested subdocuments as well.
ContentBlockingLog mContentBlockingLog;
uint32_t mMixedContentSecurityState = 0;
Maybe<ClientInfo> mClientInfo;
// Fields being mirrored from the corresponding document
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
uint32_t mSandboxFlags;
struct OriginCounter {

View File

@ -4,10 +4,13 @@
* 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 "mozilla/ipc/TransportSecurityInfoUtils.h";
include NeckoChannelParams;
include DOMTypes;
using mozilla::dom::WindowContextInitializer from "mozilla/dom/WindowContext.h";
using refcounted class nsITransportSecurityInfo from "nsITransportSecurityInfo.h";
namespace mozilla {
namespace dom {
@ -26,6 +29,7 @@ struct WindowGlobalInit
bool upgradeInsecureRequests;
uint32_t sandboxFlags;
CookieJarSettingsArgs cookieJarSettings;
nsITransportSecurityInfo securityInfo;
};
} // namespace dom

View File

@ -638,17 +638,14 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
// blocking if the subresource load uses http: and the CSP directive
// 'upgrade-insecure-requests' is present on the page.
nsCOMPtr<nsIDocShell> docShell =
NS_CP_GetDocShellFromContext(requestingContext);
// Carve-out: if we're in the parent and we're loading media, e.g. through
// webbrowserpersist, don't reject it if we can't find a docshell.
if (XRE_IsParentProcess() && !docShell &&
if (XRE_IsParentProcess() && !requestingWindow &&
(contentType == TYPE_IMAGE || contentType == TYPE_MEDIA)) {
*aDecision = ACCEPT;
return NS_OK;
}
// Otherwise, we must have a docshell
NS_ENSURE_TRUE(docShell, NS_OK);
// Otherwise, we must have a window
NS_ENSURE_TRUE(requestingWindow, NS_OK);
if (isHttpScheme && aLoadInfo->GetUpgradeInsecureRequests()) {
@ -720,44 +717,6 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
}
// Get the root document from the rootShell
nsCOMPtr<nsIDocShell> rootShell = topWC->GetBrowsingContext()->GetDocShell();
nsCOMPtr<Document> rootDoc = rootShell ? rootShell->GetDocument() : nullptr;
// TODO Fission: Bug 1631405: Make Mixed Content UI fission compatible
// At this point we know it's a mixed content load, which means we we would
// allow mixed passive content to load but only allow mixed active content
// if the user has updated prefs or overriden mixed content using the UI.
// In fission however, we might not have access to the rootShell or RootDoc
// so might not be able to access Mixed Content UI. Until we have fixed
// Bug 1631405 we assume default behavior and allow mixed passive content
// but block mixed active content in fission.
if (StaticPrefs::fission_autostart()) {
if (!rootShell || !rootDoc) {
if (classification == eMixedDisplay) {
*aDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
// some tests explicitly flip the allow active content pref, so
// let's make them work in fission mode.
if (!StaticPrefs::security_mixed_content_block_active_content()) {
*aDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
*aDecision = nsIContentPolicy::REJECT_REQUEST;
return NS_OK;
}
}
nsCOMPtr<nsISecureBrowserUI> securityUI;
rootShell->GetSecurityUI(getter_AddRefs(securityUI));
// If there is no securityUI, document doesn't have a security state.
// Allow load and return early.
if (!securityUI) {
*aDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
OriginAttributes originAttributes;
if (loadingPrincipal) {
originAttributes = loadingPrincipal->OriginAttributesRef();
@ -844,38 +803,9 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
: eUserOverride,
requestingLocation);
if (rootDoc->GetMixedContentFlags() == newState) {
return NS_OK;
}
// Copy the new state onto the Document flags.
rootDoc->AddMixedContentFlags(newState);
uint32_t state = nsIWebProgressListener::STATE_IS_BROKEN;
MOZ_ALWAYS_SUCCEEDS(securityUI->GetState(&state));
if (*aDecision == nsIContentPolicy::ACCEPT && rootHasSecureConnection) {
// reset state security flag
state = state >> 4 << 4;
// set state security flag to broken, since there is mixed content
state |= nsIWebProgressListener::STATE_IS_BROKEN;
// If mixed display content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedDisplayContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
// If mixed active content is loaded, make sure to include that in the
// state.
if (rootDoc->GetHasMixedActiveContentLoaded()) {
state |= nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
}
}
state |= newState;
nsDocShell* nativeDocShell = nsDocShell::Cast(docShell);
nativeDocShell->nsDocLoader::OnSecurityChange(requestingContext, state);
// Notify the top WindowContext of the flags we've computed, and it
// will handle updating any relevant security UI.
topWC->AddMixedContentSecurityState(newState);
return NS_OK;
}

View File

@ -6,14 +6,11 @@
#include "nsISupports.idl"
interface nsIDocShell;
interface nsITransportSecurityInfo;
[scriptable, uuid(718c662a-f810-4a80-a6c9-0b1810ecade2)]
[scriptable, builtinclass, uuid(718c662a-f810-4a80-a6c9-0b1810ecade2)]
interface nsISecureBrowserUI : nsISupports
{
void init(in nsIDocShell docShell);
readonly attribute unsigned long state;
readonly attribute bool isSecureContext;
readonly attribute nsITransportSecurityInfo secInfo;

View File

@ -29,12 +29,6 @@ Classes = [
'type': 'nsNSSVersion',
'headers': ['/security/manager/ssl/nsNSSVersion.h'],
},
{
'cid': '{cc75499a-1dd1-11b2-8a82-ca410ac907b8}',
'contract_ids': ['@mozilla.org/secure_browser_ui;1'],
'type': 'nsSecureBrowserUIImpl',
'headers': ['/security/manager/ssl/nsSecureBrowserUIImpl.h'],
},
{
'cid': '{47402be2-e653-45d0-8daa-9f0dce0ac148}',
'contract_ids': ['@mozilla.org/security/local-cert-service;1'],

View File

@ -73,6 +73,7 @@ EXPORTS += [
'nsNSSComponent.h',
'nsNSSHelper.h',
'nsRandomGenerator.h',
'nsSecureBrowserUI.h',
'nsSecurityHeaderParser.h',
'NSSErrorsService.h',
'nsSSLSocketProvider.h',
@ -130,7 +131,7 @@ UNIFIED_SOURCES += [
'nsPKCS12Blob.cpp',
'nsProtectedAuthThread.cpp',
'nsRandomGenerator.cpp',
'nsSecureBrowserUIImpl.cpp',
'nsSecureBrowserUI.cpp',
'nsSecurityHeaderParser.cpp',
'NSSErrorsService.cpp',
'nsSiteSecurityService.cpp',

View File

@ -31,7 +31,7 @@
#include "nsPK11TokenDB.h"
#include "nsPKCS11Slot.h"
#include "nsRandomGenerator.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsSecureBrowserUI.h"
#include "nsSiteSecurityService.h"
#include "nsXULAppAPI.h"

View File

@ -0,0 +1,223 @@
/* -*- 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 "nsGlobalWindow.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;
}
static bool GetWebProgressListener(CanonicalBrowsingContext* aBrowsingContext,
nsIBrowser** aOutBrowser,
nsIWebProgress** aOutManager,
nsIWebProgressListener** aOutListener) {
MOZ_ASSERT(aOutBrowser);
MOZ_ASSERT(aOutManager);
MOZ_ASSERT(aOutListener);
nsCOMPtr<nsIBrowser> browser;
RefPtr<Element> currentElement = aBrowsingContext->GetEmbedderElement();
// In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>,
// but we want the <xul:browser> that it is embedded in.
while (currentElement) {
browser = currentElement->AsBrowser();
if (browser) {
break;
}
BrowsingContext* browsingContext =
currentElement->OwnerDoc()->GetBrowsingContext();
currentElement =
browsingContext ? browsingContext->GetEmbedderElement() : nullptr;
}
if (!browser) {
return false;
}
nsCOMPtr<nsIWebProgress> manager;
nsresult rv = browser->GetRemoteWebProgressManager(getter_AddRefs(manager));
if (NS_FAILED(rv)) {
browser.forget(aOutBrowser);
return true;
}
nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(manager);
if (!listener) {
// We are no longer remote so we cannot forward this event.
browser.forget(aOutBrowser);
manager.forget(aOutManager);
return true;
}
browser.forget(aOutBrowser);
manager.forget(aOutManager);
listener.forget(aOutListener);
return true;
}
void nsSecureBrowserUI::UpdateForLocationOrMixedContentChange() {
// 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 the mixed content flags from the window
if (win) {
mState |= win->GetMixedContentSecurityFlags();
}
// 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;
}
// This is a bit painful, as we need to do different things for
// in-process docshells vs OOP ones.
// Ideally we'd just call a function on 'browser' which would
// handle sending an event to all listeners, and we wouldn't
// need to bother with onSecurityChange.
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(ctx, getter_AddRefs(browser),
getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return;
}
// Do we need to construct a fake webprogress and request instance?
// Should we split this API out of nsIWebProgressListener to avoid
// that?
if (managerAsListener) {
Unused << managerAsListener->OnSecurityChange(nullptr, nullptr, mState);
}
if (ctx->GetDocShell()) {
nsDocShell* nativeDocShell = nsDocShell::Cast(ctx->GetDocShell());
nativeDocShell->nsDocLoader::OnSecurityChange(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();
}

View File

@ -18,7 +18,9 @@ class nsIChannel;
namespace mozilla {
namespace dom {
class Document;
}
class WindowGlobalParent;
class CanonicalBrowsingContext;
} // namespace dom
} // namespace mozilla
#define NS_SECURE_BROWSER_UI_CID \
@ -28,32 +30,24 @@ class Document;
} \
}
class nsSecureBrowserUIImpl : public nsISecureBrowserUI,
public nsIWebProgressListener,
public nsSupportsWeakReference {
class nsSecureBrowserUI : public nsISecureBrowserUI,
public nsSupportsWeakReference {
public:
nsSecureBrowserUIImpl();
explicit nsSecureBrowserUI(
mozilla::dom::CanonicalBrowsingContext* aBrowsingContext);
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSISECUREBROWSERUI
protected:
virtual ~nsSecureBrowserUIImpl() = default;
void UpdateForLocationOrMixedContentChange();
already_AddRefed<mozilla::dom::Document> PrepareForContentChecks();
// Do mixed content checks. May update mState.
void CheckForMixedContent();
// Given some information about a request from an OnLocationChange event,
// update mState and mTopLevelSecurityInfo.
nsresult UpdateStateAndSecurityInfo(nsIChannel* channel, nsIURI* uri);
protected:
virtual ~nsSecureBrowserUI() = default;
mozilla::dom::WindowGlobalParent* GetCurrentWindow();
uint32_t mState;
uint32_t mEvent;
bool mIsSecureContext;
nsWeakPtr mDocShell;
nsWeakPtr mWebProgress;
nsCOMPtr<nsITransportSecurityInfo> mTopLevelSecurityInfo;
uint64_t mBrowsingContextId;
};
#endif // nsSecureBrowserUIImpl_h

View File

@ -1,395 +0,0 @@
/* -*- 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 "nsSecureBrowserUIImpl.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 "nsGlobalWindow.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsITransportSecurityInfo.h"
#include "nsIWebProgress.h"
#include "nsNetUtil.h"
using namespace mozilla;
LazyLogModule gSecureBrowserUILog("nsSecureBrowserUI");
nsSecureBrowserUIImpl::nsSecureBrowserUIImpl()
: mState(0), mEvent(0), mIsSecureContext(false) {
MOZ_ASSERT(NS_IsMainThread());
}
NS_IMPL_ISUPPORTS(nsSecureBrowserUIImpl, nsISecureBrowserUI,
nsIWebProgressListener, nsISupportsWeakReference)
NS_IMETHODIMP
nsSecureBrowserUIImpl::Init(nsIDocShell* aDocShell) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aDocShell);
aDocShell->SetSecurityUI(this);
// The Docshell will own the SecureBrowserUI object, we keep a weak ref.
nsresult rv;
mDocShell = do_GetWeakReference(aDocShell, &rv);
if (NS_FAILED(rv)) {
return rv;
}
// hook up to the webprogress notifications.
nsCOMPtr<nsIWebProgress> wp(do_GetInterface(aDocShell));
if (!wp) {
return NS_ERROR_FAILURE;
}
// Save this so we can compare it to the web progress in OnLocationChange.
mWebProgress = do_GetWeakReference(wp, &rv);
if (NS_FAILED(rv)) {
return rv;
}
return wp->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::GetState(uint32_t* aState) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aState);
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, ("GetState %p", this));
// With respect to mixed content and tracking protection, we won't know when
// the state of our document (or a subdocument) has changed, so we ask the
// docShell.
CheckForMixedContent();
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" mState: %x", mState));
*aState = mState;
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::GetIsSecureContext(bool* aIsSecureContext) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aIsSecureContext);
*aIsSecureContext = mIsSecureContext;
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::GetSecInfo(nsITransportSecurityInfo** result) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(result);
*result = mTopLevelSecurityInfo;
NS_IF_ADDREF(*result);
return NS_OK;
}
already_AddRefed<dom::Document>
nsSecureBrowserUIImpl::PrepareForContentChecks() {
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
if (!docShell) {
return nullptr;
}
// For content docShells, the mixed content security state is set on the root
// docShell.
if (docShell->ItemType() == nsIDocShellTreeItem::typeContent) {
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(docShell);
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
Unused << docShellTreeItem->GetInProcessSameTypeRootTreeItem(
getter_AddRefs(sameTypeRoot));
MOZ_ASSERT(
sameTypeRoot,
"No document shell root tree item from document shell tree item!");
docShell = do_QueryInterface(sameTypeRoot);
if (!docShell) {
return nullptr;
}
}
RefPtr<dom::Document> doc = docShell->GetDocument();
return doc.forget();
}
// Ask the docShell if we've blocked or loaded any mixed content.
void nsSecureBrowserUIImpl::CheckForMixedContent() {
RefPtr<dom::Document> doc = PrepareForContentChecks();
if (!doc) {
// If the docshell has no document, then there is no need to update mState.
return;
}
// Has mixed content been loaded or blocked in nsMixedContentBlocker?
// This only applies to secure documents even if they're affected by mixed
// content blocking in which case the STATE_IS_BROKEN bit would be set rather
// than STATE_IS_SECURE.
if (((mState & STATE_IS_SECURE) != 0) || ((mState & STATE_IS_BROKEN) != 0)) {
if (doc->GetHasMixedActiveContentLoaded()) {
mState |= STATE_IS_BROKEN | STATE_LOADED_MIXED_ACTIVE_CONTENT;
mState &= ~STATE_IS_SECURE;
}
if (doc->GetHasMixedDisplayContentLoaded()) {
mState |= STATE_IS_BROKEN | STATE_LOADED_MIXED_DISPLAY_CONTENT;
mState &= ~STATE_IS_SECURE;
}
if (doc->GetHasMixedActiveContentBlocked()) {
mState |= STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
}
if (doc->GetHasMixedDisplayContentBlocked()) {
mState |= STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
}
}
}
// Helper function to determine if the given URI can be considered secure.
// Essentially, only "https" URIs can be considered secure. However, the URI we
// have may be e.g. view-source:https://example.com, in which case we have to
// evaluate the innermost URI.
static nsresult URICanBeConsideredSecure(
nsIURI* uri, /* out */ bool& canBeConsideredSecure) {
MOZ_ASSERT(uri);
NS_ENSURE_ARG(uri);
canBeConsideredSecure = false;
nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(uri);
if (!innermostURI) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" couldn't get innermost URI"));
return NS_ERROR_FAILURE;
}
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" innermost URI is '%s'", innermostURI->GetSpecOrDefault().get()));
canBeConsideredSecure = innermostURI->SchemeIs("https");
return NS_OK;
}
// Helper function to get the securityInfo from a channel as a
// nsITransportSecurityInfo. The out parameter will be set to null if there is
// no securityInfo set.
static void GetSecurityInfoFromChannel(
nsIChannel* channel, nsITransportSecurityInfo** securityInfoOut) {
MOZ_ASSERT(channel);
MOZ_ASSERT(securityInfoOut);
NS_ENSURE_TRUE_VOID(channel);
NS_ENSURE_TRUE_VOID(securityInfoOut);
*securityInfoOut = nullptr;
nsCOMPtr<nsISupports> securityInfoSupports;
nsresult rv = channel->GetSecurityInfo(getter_AddRefs(securityInfoSupports));
// GetSecurityInfo may return an error, but it's not necessarily fatal - the
// underlying channel may simply not have a securityInfo.
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsITransportSecurityInfo> securityInfo(
do_QueryInterface(securityInfoSupports));
securityInfo.forget(securityInfoOut);
}
nsresult nsSecureBrowserUIImpl::UpdateStateAndSecurityInfo(nsIChannel* channel,
nsIURI* uri) {
MOZ_ASSERT(channel);
MOZ_ASSERT(uri);
NS_ENSURE_ARG(channel);
NS_ENSURE_ARG(uri);
mState = STATE_IS_INSECURE;
mTopLevelSecurityInfo = nullptr;
// 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).
bool canBeConsideredSecure;
nsresult rv = URICanBeConsideredSecure(uri, canBeConsideredSecure);
if (NS_FAILED(rv)) {
return rv;
}
if (!canBeConsideredSecure) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" URI can't be considered secure"));
return NS_OK;
}
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
GetSecurityInfoFromChannel(channel, getter_AddRefs(securityInfo));
if (securityInfo) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" we have a security info %p", securityInfo.get()));
rv = securityInfo->GetSecurityState(&mState);
if (NS_FAILED(rv)) {
return rv;
}
// If the security state is STATE_IS_INSECURE, the TLS handshake never
// completed. Don't set any further state.
if (mState == STATE_IS_INSECURE) {
return NS_OK;
}
mTopLevelSecurityInfo = securityInfo;
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" set mTopLevelSecurityInfo"));
bool isEV;
rv = mTopLevelSecurityInfo->GetIsExtendedValidation(&isEV);
if (NS_FAILED(rv)) {
return rv;
}
if (isEV) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is EV"));
mState |= STATE_IDENTITY_EV_TOPLEVEL;
}
// Proactively check for mixed content in case GetState() is never called
// (this can happen when loading from the BF cache).
CheckForMixedContent();
}
return NS_OK;
}
// We receive this notification for the nsIWebProgress we added ourselves to
// (i.e. the window we were passed in Init, which should be the top-level
// window or whatever corresponds to an <iframe mozbrowser> element). In some
// cases, we also receive it from nsIWebProgress instances that are children of
// that nsIWebProgress. We ignore notifications from children because they don't
// change the top-level state (if children load mixed or tracking content, the
// docShell will know and will tell us in GetState when we call
// CheckForMixedContent).
// When we receive a notification from the top-level nsIWebProgress, we extract
// any relevant security information and set our state accordingly. We then call
// OnSecurityChange on the docShell corresponding to the nsIWebProgress we were
// initialized with to notify any downstream listeners of the security state.
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, nsIURI* aLocation,
uint32_t aFlags) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aWebProgress);
NS_ENSURE_ARG(aLocation);
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
("%p OnLocationChange: %p %p %s %x", this, aWebProgress, aRequest,
aLocation->GetSpecOrDefault().get(), aFlags));
// Filter out events from children. See comment at the top of this function.
// It would be nice if the attribute isTopLevel worked for this, but that
// filters out events for <iframe mozbrowser> elements, which means they don't
// get OnSecurityChange events from this implementation. Instead, we check to
// see if the web progress we were handed here is the same one as we were
// initialized with.
nsCOMPtr<nsIWebProgress> originalWebProgress = do_QueryReferent(mWebProgress);
if (aWebProgress != originalWebProgress) {
return NS_OK;
}
// If this is a same-document location change, we don't need to update our
// state or notify anyone.
if (aFlags & LOCATION_CHANGE_SAME_DOCUMENT) {
return NS_OK;
}
mState = 0;
mEvent = 0;
mIsSecureContext = false;
mTopLevelSecurityInfo = nullptr;
if (aFlags & LOCATION_CHANGE_ERROR_PAGE) {
mState = STATE_IS_INSECURE;
mTopLevelSecurityInfo = nullptr;
} else {
// NB: aRequest may be null. It may also not be QI-able to nsIChannel.
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" we have a channel %p", channel.get()));
nsresult rv = UpdateStateAndSecurityInfo(channel, aLocation);
// Even if this failed, we still want to notify downstream so that we
// don't leave a stale security indicator. We set everything to "not
// secure" to be safe.
if (NS_WARN_IF(NS_FAILED(rv))) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" Failed to update security info. "
"Setting everything to 'not secure' to be safe."));
mState = STATE_IS_INSECURE;
mTopLevelSecurityInfo = nullptr;
}
}
nsCOMPtr<mozIDOMWindowProxy> domWindow;
aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
if (domWindow) {
nsPIDOMWindowOuter* outerWindow = nsPIDOMWindowOuter::From(domWindow);
if (outerWindow) {
nsGlobalWindowInner* innerWindow =
nsGlobalWindowInner::Cast(outerWindow->GetCurrentInnerWindow());
if (innerWindow) {
mIsSecureContext = innerWindow->IsSecureContext();
}
}
}
}
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
if (docShell) {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
(" calling OnSecurityChange %p %x", aRequest, mState));
nsDocShell::Cast(docShell)->nsDocLoader::OnSecurityChange(aRequest, mState);
} else {
MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" no docShell?"));
}
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress*, nsIRequest*, uint32_t,
nsresult) {
MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()");
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnProgressChange(nsIWebProgress*, nsIRequest*, int32_t,
int32_t, int32_t, int32_t) {
MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()");
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnStatusChange(nsIWebProgress*, nsIRequest*, nsresult,
const char16_t*) {
MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()");
return NS_OK;
}
nsresult nsSecureBrowserUIImpl::OnSecurityChange(nsIWebProgress*, nsIRequest*,
uint32_t) {
MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()");
return NS_OK;
}
nsresult nsSecureBrowserUIImpl::OnContentBlockingEvent(nsIWebProgress*,
nsIRequest*, uint32_t) {
MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()");
return NS_OK;
}

View File

@ -160,17 +160,6 @@ already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
NS_ENSURE_SUCCESS(docShellAsWin->Create(), nullptr);
// Hook into the OnSecurityChange() notification for lock/unlock icon
// updates
// this works because the implementation of nsISecureBrowserUI
// (nsSecureBrowserUIImpl) calls docShell->SetSecurityUI(this);
nsCOMPtr<nsISecureBrowserUI> securityUI =
do_CreateInstance(NS_SECURE_BROWSER_UI_CONTRACTID);
if (NS_WARN_IF(!securityUI)) {
return nullptr;
}
securityUI->Init(docShell);
docShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0)
docShellTreeOwner->AddChromeListeners();

View File

@ -361,8 +361,6 @@
this._unselectedTabHoverMessageListenerCount = 0;
this._securityUI = null;
this.urlbarChangeTracker = {
_startedLoadSinceLastUserTyping: false,
@ -894,36 +892,7 @@
}
get securityUI() {
if (this.isRemoteBrowser) {
if (!this._securityUI) {
// Don't attempt to create the remote web progress if the
// messageManager has already gone away
if (!this.messageManager) {
return null;
}
let jsm = "resource://gre/modules/RemoteSecurityUI.jsm";
let RemoteSecurityUI = ChromeUtils.import(jsm, {}).RemoteSecurityUI;
this._securityUI = new RemoteSecurityUI();
}
// We want to double-wrap the JS implemented interface, so that QI and instanceof works.
var ptr = Cc[
"@mozilla.org/supports-interface-pointer;1"
].createInstance(Ci.nsISupportsInterfacePointer);
ptr.data = this._securityUI;
return ptr.data.QueryInterface(Ci.nsISecureBrowserUI);
}
if (!this.docShell.securityUI) {
const SECUREBROWSERUI_CONTRACTID = "@mozilla.org/secure_browser_ui;1";
var securityUI = Cc[SECUREBROWSERUI_CONTRACTID].createInstance(
Ci.nsISecureBrowserUI
);
securityUI.init(this.docShell);
}
return this.docShell.securityUI;
return this.browsingContext.secureBrowserUI;
}
set userTypedValue(val) {
@ -1349,16 +1318,6 @@
}
}
updateSecurityUIForSecurityChange(aSecurityInfo, aState, aIsSecureContext) {
if (this.isRemoteBrowser && this.messageManager) {
// Invoking this getter triggers the generation of the underlying object,
// which we need to access with ._securityUI, because .securityUI returns
// a wrapper that makes _update inaccessible.
void this.securityUI;
this._securityUI._update(aSecurityInfo, aState, aIsSecureContext);
}
}
get remoteWebProgressManager() {
return this._remoteWebProgressManager;
}

View File

@ -1,33 +0,0 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
var EXPORTED_SYMBOLS = ["RemoteSecurityUI"];
function RemoteSecurityUI() {
this._secInfo = null;
this._state = 0;
this._isSecureContext = false;
}
RemoteSecurityUI.prototype = {
QueryInterface: ChromeUtils.generateQI([Ci.nsISecureBrowserUI]),
// nsISecureBrowserUI
get state() {
return this._state;
},
get secInfo() {
return this._secInfo;
},
get isSecureContext() {
return this._isSecureContext;
},
_update(aSecInfo, aState, aIsSecureContext) {
this._secInfo = aSecInfo;
this._state = aState;
this._isSecureContext = aIsSecureContext;
},
};

View File

@ -117,9 +117,6 @@ with Files('PrivateBrowsingUtils.jsm'):
with Files('Promise*.jsm'):
BUG_COMPONENT = ('Toolkit', 'Async Tooling')
with Files('RemoteSecurityUI.jsm'):
BUG_COMPONENT = ('Firefox', 'Tabbed Browser')
with Files('RemoteWebProgress.jsm'):
BUG_COMPONENT = ('Core', 'DOM: Navigation')
@ -212,7 +209,6 @@ EXTRA_JS_MODULES += [
'PromiseUtils.jsm',
'Region.jsm',
'RemotePageAccessManager.jsm',
'RemoteSecurityUI.jsm',
'RemoteWebProgress.jsm',
'ResetProfile.jsm',
'ResponsivenessMonitor.jsm',

View File

@ -26,6 +26,7 @@
#include "nsISupportsPrimitives.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/Preferences.h"
#include "mozilla/SchedulerGroup.h"