mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 18:47:53 +00:00
Bug 1555963 - Add WindowGlobalParent.getSecurityInfo(). r=nika,mconley
This adds an API for fetching security info per frame, no matter if we have a certificate error or a valid certificate. I tried to make this work in a Fission-compatible way, let me know if this is the right approach. Differential Revision: https://phabricator.services.mozilla.com/D34354 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
a494b08766
commit
90ecafd3e1
@ -42,6 +42,10 @@ tags = mcb
|
||||
support-files =
|
||||
file_csp_block_all_mixedcontent.html
|
||||
file_csp_block_all_mixedcontent.js
|
||||
[browser_deprecatedTLSVersions.js]
|
||||
[browser_getSecurityInfo.js]
|
||||
support-files =
|
||||
dummy_iframe_page.html
|
||||
[browser_identity_UI.js]
|
||||
[browser_identityBlock_focus.js]
|
||||
support-files = ../permissions/permissions.html
|
||||
@ -115,4 +119,3 @@ support-files =
|
||||
support-files =
|
||||
file_mixedPassiveContent.html
|
||||
file_bug1045809_1.html
|
||||
[browser_deprecatedTLSVersions.js]
|
||||
|
@ -0,0 +1,57 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const MOZILLA_PKIX_ERROR_BASE = Ci.nsINSSErrorsService.MOZILLA_PKIX_ERROR_BASE;
|
||||
const MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT = MOZILLA_PKIX_ERROR_BASE + 14;
|
||||
|
||||
const IFRAME_PAGE = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com") + "dummy_iframe_page.html";
|
||||
|
||||
// Tests the getSecurityInfo() function exposed on WindowGlobalParent.
|
||||
add_task(async function test() {
|
||||
await BrowserTestUtils.withNewTab("about:blank", async function(browser) {
|
||||
let loaded = BrowserTestUtils.waitForErrorPage(browser);
|
||||
await BrowserTestUtils.loadURI(browser, "https://self-signed.example.com");
|
||||
await loaded;
|
||||
|
||||
let securityInfo = await browser.browsingContext.currentWindowGlobal.getSecurityInfo();
|
||||
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
ok(securityInfo, "Found some security info");
|
||||
ok(securityInfo.failedCertChain, "Has a failed cert chain");
|
||||
is(securityInfo.errorCode, MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT, "Has the correct error code");
|
||||
is(securityInfo.serverCert.commonName, "self-signed.example.com", "Has the correct certificate");
|
||||
|
||||
loaded = BrowserTestUtils.browserLoaded(browser);
|
||||
await BrowserTestUtils.loadURI(browser, "http://example.com");
|
||||
await loaded;
|
||||
|
||||
securityInfo = await browser.browsingContext.currentWindowGlobal.getSecurityInfo();
|
||||
is(securityInfo, null, "Found no security info");
|
||||
|
||||
loaded = BrowserTestUtils.browserLoaded(browser);
|
||||
await BrowserTestUtils.loadURI(browser, "https://example.com");
|
||||
await loaded;
|
||||
|
||||
securityInfo = await browser.browsingContext.currentWindowGlobal.getSecurityInfo();
|
||||
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
ok(securityInfo, "Found some security info");
|
||||
ok(securityInfo.succeededCertChain, "Has a succeeded cert chain");
|
||||
is(securityInfo.errorCode, 0, "Has no error code");
|
||||
is(securityInfo.serverCert.commonName, "example.com", "Has the correct certificate");
|
||||
|
||||
loaded = BrowserTestUtils.browserLoaded(browser);
|
||||
await BrowserTestUtils.loadURI(browser, IFRAME_PAGE);
|
||||
await loaded;
|
||||
|
||||
// Get the info of the parent, which is HTTP.
|
||||
securityInfo = await browser.browsingContext.currentWindowGlobal.getSecurityInfo();
|
||||
is(securityInfo, null, "Found no security info");
|
||||
|
||||
// Get the info of the frame, which is HTTPS.
|
||||
securityInfo = await browser.browsingContext.getChildren()[0].currentWindowGlobal.getSecurityInfo();
|
||||
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
ok(securityInfo, "Found some security info");
|
||||
ok(securityInfo.succeededCertChain, "Has a succeeded cert chain");
|
||||
is(securityInfo.errorCode, 0, "Has no error code");
|
||||
is(securityInfo.serverCert.commonName, "example.com", "Has the correct certificate");
|
||||
});
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Dummy iframe test page</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="https://example.org"></iframe>
|
||||
<p>Dummy test page</p>
|
||||
</body>
|
||||
</html>
|
@ -7,6 +7,7 @@ interface Principal;
|
||||
interface URI;
|
||||
interface nsIDocShell;
|
||||
interface RemoteTab;
|
||||
interface nsITransportSecurityInfo;
|
||||
|
||||
[Exposed=Window, ChromeOnly]
|
||||
interface WindowGlobalParent {
|
||||
@ -54,6 +55,18 @@ interface WindowGlobalParent {
|
||||
Promise<unsigned long long> changeFrameRemoteness(
|
||||
BrowsingContext? bc, DOMString remoteType,
|
||||
unsigned long long pendingSwitchId);
|
||||
|
||||
/**
|
||||
* Fetches the securityInfo object for this window. This function will
|
||||
* look for failed and successful channels to find the security info,
|
||||
* thus it will work on regular HTTPS pages as well as certificate
|
||||
* error pages.
|
||||
*
|
||||
* This returns a Promise which resolves to an nsITransportSecurity
|
||||
* object with certificate data or undefined if no security info is available.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<nsITransportSecurityInfo> getSecurityInfo();
|
||||
};
|
||||
|
||||
[Exposed=Window, ChromeOnly]
|
||||
|
@ -40,6 +40,11 @@ child:
|
||||
uint64_t aSwitchId)
|
||||
returns (nsresult rv, nullable PBrowserBridge bridge);
|
||||
|
||||
/**
|
||||
* Returns the serialized security info associated with this window.
|
||||
*/
|
||||
async GetSecurityInfo() returns(nsCString? serializedSecInfo);
|
||||
|
||||
both:
|
||||
async RawMessage(JSWindowActorMessageMeta aMetadata, ClonedMessageData aData);
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsGlobalWindowInner.h"
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
|
||||
#include "mozilla/dom/JSWindowActorBinding.h"
|
||||
#include "mozilla/dom/JSWindowActorChild.h"
|
||||
@ -253,6 +254,36 @@ IPCResult WindowGlobalChild::RecvChangeFrameRemoteness(
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WindowGlobalChild::RecvGetSecurityInfo(
|
||||
GetSecurityInfoResolver&& aResolve) {
|
||||
Maybe<nsCString> result;
|
||||
|
||||
if (nsCOMPtr<Document> doc = mWindowGlobal->GetDoc()) {
|
||||
nsCOMPtr<nsISupports> secInfo;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// First check if there's a failed channel, in case of a certificate
|
||||
// error.
|
||||
if (nsIChannel* failedChannel = doc->GetFailedChannel()) {
|
||||
rv = failedChannel->GetSecurityInfo(getter_AddRefs(secInfo));
|
||||
} else {
|
||||
// When there's no failed channel we should have a regular
|
||||
// security info on the document. In some cases there's no
|
||||
// security info at all, i.e. on HTTP sites.
|
||||
secInfo = doc->GetSecurityInfo();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && secInfo) {
|
||||
nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfo);
|
||||
result.emplace();
|
||||
NS_SerializeToString(secInfoSer, result.ref());
|
||||
}
|
||||
}
|
||||
|
||||
aResolve(result);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult WindowGlobalChild::RecvRawMessage(
|
||||
const JSWindowActorMessageMeta& aMeta, const ClonedMessageData& aData) {
|
||||
StructuredCloneData data;
|
||||
|
@ -103,6 +103,9 @@ class WindowGlobalChild final : public WindowGlobalActor,
|
||||
dom::BrowsingContext* aBc, const nsString& aRemoteType,
|
||||
uint64_t aPendingSwitchId, ChangeFrameRemotenessResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetSecurityInfo(
|
||||
GetSecurityInfoResolver&& aResolve);
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "nsGlobalWindowInner.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsITransportSecurityInfo.h"
|
||||
|
||||
#include "mozilla/dom/JSWindowActorBinding.h"
|
||||
#include "mozilla/dom/JSWindowActorParent.h"
|
||||
@ -319,6 +321,45 @@ already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> WindowGlobalParent::GetSecurityInfo(
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
||||
if (NS_WARN_IF(!browserParent)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIGlobalObject* global = xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SendGetSecurityInfo(
|
||||
[promise](Maybe<nsCString>&& aResult) {
|
||||
if (aResult) {
|
||||
nsCOMPtr<nsISupports> infoObj;
|
||||
nsresult rv =
|
||||
NS_DeserializeObject(aResult.value(), getter_AddRefs(infoObj));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
}
|
||||
nsCOMPtr<nsITransportSecurityInfo> info = do_QueryInterface(infoObj);
|
||||
if (!info) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
}
|
||||
promise->MaybeResolve(info);
|
||||
} else {
|
||||
promise->MaybeResolveWithUndefined();
|
||||
}
|
||||
},
|
||||
[promise](ResponseRejectReason&& aReason) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
});
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
mIPCClosed = true;
|
||||
gWindowGlobalParentsById->Remove(mInnerWindowId);
|
||||
|
@ -107,6 +107,8 @@ class WindowGlobalParent final : public WindowGlobalActor,
|
||||
uint64_t aPendingSwitchId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetSecurityInfo(ErrorResult& aRv);
|
||||
|
||||
// Create a WindowGlobalParent from over IPC. This method should not be called
|
||||
// from outside of the IPC constructors.
|
||||
WindowGlobalParent(const WindowGlobalInit& aInit, bool aInProcess);
|
||||
|
Loading…
Reference in New Issue
Block a user