Bug 1124076 - Properly detect certs when loaded and prompt to import them. r=sworkman/dkeeler

--HG--
extra : rebase_source : 00240091ae66180390a76a9613a4215cf591401d
This commit is contained in:
Blake Kaplan 2015-04-21 14:56:00 +02:00
parent 5841b01411
commit 3a94be560c
10 changed files with 494 additions and 178 deletions

View File

@ -38,6 +38,7 @@
#include "mozilla/dom/asmjscache/AsmJSCache.h"
#include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
#include "mozilla/dom/nsIContentChild.h"
#include "mozilla/psm/PSMContentListener.h"
#include "mozilla/hal_sandbox/PHalChild.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
@ -203,6 +204,7 @@ using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
using namespace mozilla::jsipc;
using namespace mozilla::psm;
using namespace mozilla::widget;
#if defined(MOZ_WIDGET_GONK)
using namespace mozilla::system;
@ -1623,6 +1625,22 @@ ContentChild::DeallocPScreenManagerChild(PScreenManagerChild* aService)
return true;
}
PPSMContentDownloaderChild*
ContentChild::AllocPPSMContentDownloaderChild(const uint32_t& aCertType)
{
// NB: We don't need aCertType in the child actor.
nsRefPtr<PSMContentDownloaderChild> child = new PSMContentDownloaderChild();
return child.forget().take();
}
bool
ContentChild::DeallocPPSMContentDownloaderChild(PPSMContentDownloaderChild* aListener)
{
auto* listener = static_cast<PSMContentDownloaderChild*>(aListener);
nsRefPtr<PSMContentDownloaderChild> child = dont_AddRef(listener);
return true;
}
PExternalHelperAppChild*
ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
const nsCString& aMimeContentType,

View File

@ -232,6 +232,10 @@ public:
bool* aSuccess) override;
virtual bool DeallocPScreenManagerChild(PScreenManagerChild*) override;
virtual PPSMContentDownloaderChild* AllocPPSMContentDownloaderChild(
const uint32_t& aCertType) override;
virtual bool DeallocPPSMContentDownloaderChild(PPSMContentDownloaderChild* aDownloader) override;
virtual PExternalHelperAppChild *AllocPExternalHelperAppChild(
const OptionalURIParams& uri,
const nsCString& aMimeContentType,

View File

@ -156,6 +156,7 @@
#include "prio.h"
#include "private/pprio.h"
#include "ContentProcessManager.h"
#include "mozilla/psm/PSMContentListener.h"
#include "nsIBidiKeyboard.h"
@ -249,6 +250,7 @@ using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
using namespace mozilla::jsipc;
using namespace mozilla::psm;
using namespace mozilla::widget;
#ifdef ENABLE_TESTS
@ -3665,6 +3667,22 @@ ContentParent::DeallocPScreenManagerParent(PScreenManagerParent* aActor)
return true;
}
PPSMContentDownloaderParent*
ContentParent::AllocPPSMContentDownloaderParent(const uint32_t& aCertType)
{
nsRefPtr<PSMContentDownloaderParent> downloader =
new PSMContentDownloaderParent(aCertType);
return downloader.forget().take();
}
bool
ContentParent::DeallocPPSMContentDownloaderParent(PPSMContentDownloaderParent* aListener)
{
auto* listener = static_cast<PSMContentDownloaderParent*>(aListener);
nsRefPtr<PSMContentDownloaderParent> downloader = dont_AddRef(listener);
return true;
}
PExternalHelperAppParent*
ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
const nsCString& aMimeContentType,

View File

@ -606,6 +606,10 @@ private:
virtual bool DeallocPNeckoParent(PNeckoParent* necko) override;
virtual PPSMContentDownloaderParent* AllocPPSMContentDownloaderParent(
const uint32_t& aCertType) override;
virtual bool DeallocPPSMContentDownloaderParent(PPSMContentDownloaderParent* aDownloader) override;
virtual PExternalHelperAppParent* AllocPExternalHelperAppParent(
const OptionalURIParams& aUri,
const nsCString& aMimeContentType,

View File

@ -16,6 +16,7 @@ include protocol PContentPermissionRequest;
include protocol PCycleCollectWithLogs;
include protocol PCrashReporter;
include protocol PDocAccessible;
include protocol PPSMContentDownloader;
include protocol PExternalHelperApp;
include protocol PDeviceStorageRequest;
include protocol PFileDescriptorSet;
@ -388,6 +389,7 @@ prio(normal upto urgent) sync protocol PContent
manages PDocAccessible;
manages PDeviceStorageRequest;
manages PFileSystemRequest;
manages PPSMContentDownloader;
manages PExternalHelperApp;
manages PFileDescriptorSet;
manages PFMRadio;
@ -756,6 +758,8 @@ parent:
CloseAlert(nsString name, Principal principal);
PPSMContentDownloader(uint32_t aCertType);
PExternalHelperApp(OptionalURIParams uri,
nsCString aMimeContentType,
nsCString aContentDisposition,

View File

@ -0,0 +1,28 @@
/* vim: set sw=2 sts=2 ts=2 et tw=80 ft=cpp: */
/* 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 protocol PContent;
include protocol PChannelDiverter;
namespace mozilla {
namespace psm {
protocol PPSMContentDownloader
{
manager PContent;
parent:
OnStartRequest(uint32_t contentLength);
OnDataAvailable(nsCString data, uint64_t offset, uint32_t count);
OnStopRequest(nsresult code);
DivertToParentUsing(PChannelDiverter diverter);
child:
__delete__();
};
} // namespace psm
} // namespace mozilla

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set sw=2 sts=2 ts=2 et tw=80:
*
* 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
@ -6,16 +7,22 @@
#include "PSMContentListener.h"
#include "nsIDivertableChannel.h"
#include "nsIStreamListener.h"
#include "nsIX509CertDB.h"
#include "nsIXULAppInfo.h"
#include "mozilla/Casting.h"
#include "mozilla/Services.h"
#include "mozilla/unused.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/net/ChannelDiverterParent.h"
#include "mozilla/net/ChannelDiverterChild.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#include "nsNSSHelper.h"
#include "nsNSSShutDown.h"
#include "prlog.h"
@ -27,139 +34,158 @@ namespace mozilla { namespace psm {
namespace {
class PSMContentDownloader : public nsIStreamListener
{
public:
PSMContentDownloader() {NS_ASSERTION(false, "don't use this constructor."); }
explicit PSMContentDownloader(uint32_t type);
void setSilentDownload(bool flag);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
enum {UNKNOWN_TYPE = 0};
enum {X509_CA_CERT = 1};
enum {X509_USER_CERT = 2};
enum {X509_EMAIL_CERT = 3};
enum {X509_SERVER_CERT = 4};
protected:
virtual ~PSMContentDownloader();
char* mByteData;
int32_t mBufferOffset;
int32_t mBufferSize;
uint32_t mType;
nsCOMPtr<nsIURI> mURI;
};
PSMContentDownloader::PSMContentDownloader(uint32_t type)
: mByteData(nullptr),
mType(type)
{
}
PSMContentDownloader::~PSMContentDownloader()
{
if (mByteData)
free(mByteData);
}
NS_IMPL_ISUPPORTS(PSMContentDownloader, nsIStreamListener, nsIRequestObserver)
const int32_t kDefaultCertAllocLength = 2048;
NS_IMETHODIMP
PSMContentDownloader::OnStartRequest(nsIRequest* request, nsISupports* context)
{
nsresult rv;
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStartRequest\n"));
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
if (!channel) return NS_ERROR_FAILURE;
enum {
UNKNOWN_TYPE = 0,
X509_CA_CERT = 1,
X509_USER_CERT = 2,
X509_EMAIL_CERT = 3,
X509_SERVER_CERT = 4
};
// Get the URI //
channel->GetURI(getter_AddRefs(mURI));
/* other mime types that we should handle sometime:
application/x-pkcs7-mime
application/pkcs7-signature
application/pre-encrypted
*/
uint32_t
getPSMContentType(const char* aContentType)
{
// Don't forget to update the registration of content listeners in nsNSSModule.cpp
// for every supported content type.
if (!nsCRT::strcasecmp(aContentType, "application/x-x509-ca-cert"))
return X509_CA_CERT;
if (!nsCRT::strcasecmp(aContentType, "application/x-x509-server-cert"))
return X509_SERVER_CERT;
if (!nsCRT::strcasecmp(aContentType, "application/x-x509-user-cert"))
return X509_USER_CERT;
if (!nsCRT::strcasecmp(aContentType, "application/x-x509-email-cert"))
return X509_EMAIL_CERT;
return UNKNOWN_TYPE;
}
int64_t
ComputeContentLength(nsIRequest* request)
{
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
if (!channel) {
return -1;
}
int64_t contentLength;
rv = channel->GetContentLength(&contentLength);
if (NS_FAILED(rv) || contentLength <= 0)
contentLength = kDefaultCertAllocLength;
if (contentLength > INT32_MAX)
return NS_ERROR_OUT_OF_MEMORY;
mBufferOffset = 0;
mBufferSize = 0;
mByteData = (char*)moz_xmalloc(AssertedCast<size_t>(contentLength));
if (!mByteData)
return NS_ERROR_OUT_OF_MEMORY;
mBufferSize = int32_t(contentLength);
nsresult rv = channel->GetContentLength(&contentLength);
if (NS_FAILED(rv) || contentLength <= 0) {
return kDefaultCertAllocLength;
}
if (contentLength > INT32_MAX) {
return -1;
}
return contentLength;
}
class ImportCertRunnable : public nsRunnable
{
public:
ImportCertRunnable(PSMContentStreamListener* streamer)
: mStreamer(streamer)
{
}
NS_IMETHOD Run()
{
mStreamer->ImportCertificate();
return NS_OK;
}
private:
nsRefPtr<PSMContentStreamListener> mStreamer;
};
} // unnamed namespace
/* ------------------------
* PSMContentStreamListener
* ------------------------ */
PSMContentStreamListener::PSMContentStreamListener(uint32_t type)
: mType(type)
{
}
PSMContentStreamListener::~PSMContentStreamListener()
{
}
NS_IMPL_ISUPPORTS(PSMContentStreamListener, nsIStreamListener, nsIRequestObserver)
NS_IMETHODIMP
PSMContentStreamListener::OnStartRequest(nsIRequest* request, nsISupports* context)
{
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStartRequest\n"));
int64_t contentLength = ComputeContentLength(request);
if (contentLength < 0) {
return NS_ERROR_FAILURE;
}
mByteData.SetCapacity(contentLength);
return NS_OK;
}
NS_IMETHODIMP
PSMContentDownloader::OnDataAvailable(nsIRequest* request,
nsISupports* context,
nsIInputStream *aIStream,
uint64_t aSourceOffset,
uint32_t aLength)
PSMContentStreamListener::OnDataAvailable(nsIRequest* request,
nsISupports* context,
nsIInputStream* aIStream,
uint64_t aSourceOffset,
uint32_t aLength)
{
if (!mByteData)
return NS_ERROR_OUT_OF_MEMORY;
uint32_t amt;
nsresult err;
//Do a check to see if we need to allocate more memory.
if ((mBufferOffset + (int32_t)aLength) > mBufferSize) {
size_t newSize = (mBufferOffset + aLength) *2; // grow some more than needed
char *newBuffer;
newBuffer = (char*)moz_xrealloc(mByteData, newSize);
if (!newBuffer) {
return NS_ERROR_OUT_OF_MEMORY;
}
mByteData = newBuffer;
mBufferSize = newSize;
}
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnDataAvailable\n"));
do {
err = aIStream->Read(mByteData+mBufferOffset,
aLength, &amt);
if (NS_FAILED(err)) return err;
if (amt == 0) break;
aLength -= amt;
mBufferOffset += amt;
} while (aLength > 0);
nsCString chunk;
nsresult rv = NS_ReadInputStreamToString(aIStream, chunk, aLength);
if (NS_FAILED(rv)) {
return rv;
}
mByteData.Append(chunk);
return NS_OK;
}
NS_IMETHODIMP
PSMContentDownloader::OnStopRequest(nsIRequest* request,
nsISupports* context,
nsresult aStatus)
PSMContentStreamListener::OnStopRequest(nsIRequest* request,
nsISupports* context,
nsresult aStatus)
{
nsNSSShutDownPreventionLock locker;
//Check if the download succeeded - it might have failed due to
//network issues, etc.
if (NS_FAILED(aStatus)){
return aStatus;
}
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStopRequest\n"));
// Because importing the cert can spin the event loop (via alerts), we can't
// do it here. Do it off the event loop instead.
nsCOMPtr<nsIRunnable> r = new ImportCertRunnable(this);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
return NS_OK;
}
void
PSMContentStreamListener::ImportCertificate()
{
nsCOMPtr<nsIX509CertDB> certdb;
nsresult rv;
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
switch (mType) {
case PSMContentDownloader::X509_CA_CERT:
case PSMContentDownloader::X509_USER_CERT:
case PSMContentDownloader::X509_EMAIL_CERT:
case X509_CA_CERT:
case X509_USER_CERT:
case X509_EMAIL_CERT:
certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
break;
@ -167,48 +193,172 @@ PSMContentDownloader::OnStopRequest(nsIRequest* request,
break;
}
if (!certdb) {
return;
}
switch (mType) {
case PSMContentDownloader::X509_CA_CERT:
return certdb->ImportCertificates((uint8_t*)mByteData, mBufferOffset, mType, ctx);
case PSMContentDownloader::X509_USER_CERT:
return certdb->ImportUserCertificate((uint8_t*)mByteData, mBufferOffset, ctx);
case PSMContentDownloader::X509_EMAIL_CERT:
return certdb->ImportEmailCertificate((uint8_t*)mByteData, mBufferOffset, ctx);
case X509_CA_CERT:
certdb->ImportCertificates(reinterpret_cast<uint8_t*>(mByteData.BeginWriting()),
mByteData.Length(), mType, ctx);
break;
case X509_USER_CERT:
certdb->ImportUserCertificate(reinterpret_cast<uint8_t*>(mByteData.BeginWriting()),
mByteData.Length(), ctx);
break;
case X509_EMAIL_CERT:
certdb->ImportEmailCertificate(reinterpret_cast<uint8_t*>(mByteData.BeginWriting()),
mByteData.Length(), ctx);
break;
default:
rv = NS_ERROR_FAILURE;
break;
}
}
/* ------------------------
* PSMContentDownloaderParent
* ------------------------ */
PSMContentDownloaderParent::PSMContentDownloaderParent(uint32_t type)
: PSMContentStreamListener(type)
, mIPCOpen(true)
{
}
PSMContentDownloaderParent::~PSMContentDownloaderParent()
{
}
bool
PSMContentDownloaderParent::RecvOnStartRequest(const uint32_t& contentLength)
{
mByteData.SetCapacity(contentLength);
return true;
}
bool
PSMContentDownloaderParent::RecvOnDataAvailable(const nsCString& data,
const uint64_t& offset,
const uint32_t& count)
{
mByteData.Append(data);
return true;
}
bool
PSMContentDownloaderParent::RecvOnStopRequest(const nsresult& code)
{
if (NS_SUCCEEDED(code)) {
// See also PSMContentStreamListener::OnStopRequest. In this case, we don't
// have to dispatch ImportCertificate off of an event because we don't have
// to worry about Necko sending "clean up" events and destroying us if
// ImportCertificate spins the event loop.
ImportCertificate();
}
if (mIPCOpen) {
mozilla::unused << Send__delete__(this);
}
return true;
}
NS_IMETHODIMP
PSMContentDownloaderParent::OnStopRequest(nsIRequest* request, nsISupports* context, nsresult code)
{
nsresult rv = PSMContentStreamListener::OnStopRequest(request, context, code);
if (mIPCOpen) {
mozilla::unused << Send__delete__(this);
}
return rv;
}
/* other mime types that we should handle sometime:
application/x-pkcs7-mime
application/pkcs7-signature
application/pre-encrypted
*/
uint32_t
getPSMContentType(const char * aContentType)
{
// Don't forget to update the registration of content listeners in nsNSSModule.cpp
// for every supported content type.
if (!nsCRT::strcasecmp(aContentType, "application/x-x509-ca-cert"))
return PSMContentDownloader::X509_CA_CERT;
else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-server-cert"))
return PSMContentDownloader::X509_SERVER_CERT;
else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-user-cert"))
return PSMContentDownloader::X509_USER_CERT;
else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-email-cert"))
return PSMContentDownloader::X509_EMAIL_CERT;
return PSMContentDownloader::UNKNOWN_TYPE;
bool
PSMContentDownloaderParent::RecvDivertToParentUsing(mozilla::net::PChannelDiverterParent* diverter)
{
MOZ_ASSERT(diverter);
auto p = static_cast<mozilla::net::ChannelDiverterParent*>(diverter);
p->DivertTo(this);
mozilla::unused << p->Send__delete__(p);
return true;
}
} // unnamed namespace
void
PSMContentDownloaderParent::ActorDestroy(ActorDestroyReason why)
{
mIPCOpen = false;
}
/* ------------------------
* PSMContentDownloaderChild
* ------------------------ */
NS_IMPL_ISUPPORTS(PSMContentDownloaderChild, nsIStreamListener)
PSMContentDownloaderChild::PSMContentDownloaderChild()
{
}
PSMContentDownloaderChild::~PSMContentDownloaderChild()
{
}
NS_IMETHODIMP
PSMContentDownloaderChild::OnStartRequest(nsIRequest* request, nsISupports* context)
{
nsCOMPtr<nsIDivertableChannel> divertable = do_QueryInterface(request);
if (divertable) {
mozilla::net::ChannelDiverterChild* diverter = nullptr;
nsresult rv = divertable->DivertToParent(&diverter);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_ASSERT(diverter);
return SendDivertToParentUsing(diverter) ? NS_OK : NS_ERROR_FAILURE;
}
int64_t contentLength = ComputeContentLength(request);
if (contentLength < 0) {
return NS_ERROR_FAILURE;
}
mozilla::unused << SendOnStartRequest(contentLength);
return NS_OK;
}
NS_IMETHODIMP
PSMContentDownloaderChild::OnDataAvailable(nsIRequest* request,
nsISupports* context,
nsIInputStream* aIStream,
uint64_t aSourceOffset,
uint32_t aLength)
{
nsCString chunk;
nsresult rv = NS_ReadInputStreamToString(aIStream, chunk, aLength);
if (NS_FAILED(rv)) {
return rv;
}
mozilla::unused << SendOnDataAvailable(chunk, aSourceOffset, aLength);
return NS_OK;
}
NS_IMETHODIMP
PSMContentDownloaderChild::OnStopRequest(nsIRequest* request,
nsISupports* context,
nsresult aStatus)
{
mozilla::unused << SendOnStopRequest(aStatus);
return NS_OK;
}
/* ------------------------
* PSMContentListener
* ------------------------ */
NS_IMPL_ISUPPORTS(PSMContentListener,
nsIURIContentListener,
@ -231,7 +381,7 @@ PSMContentListener::init()
}
NS_IMETHODIMP
PSMContentListener::OnStartURIOpen(nsIURI *aURI, bool *aAbortOpen)
PSMContentListener::OnStartURIOpen(nsIURI* aURI, bool* aAbortOpen)
{
//if we don't want to handle the URI, return true in
//*aAbortOpen
@ -239,73 +389,77 @@ PSMContentListener::OnStartURIOpen(nsIURI *aURI, bool *aAbortOpen)
}
NS_IMETHODIMP
PSMContentListener::IsPreferred(const char * aContentType,
char ** aDesiredContentType,
bool * aCanHandleContent)
PSMContentListener::IsPreferred(const char* aContentType,
char** aDesiredContentType,
bool* aCanHandleContent)
{
return CanHandleContent(aContentType, true,
aDesiredContentType, aCanHandleContent);
}
NS_IMETHODIMP
PSMContentListener::CanHandleContent(const char * aContentType,
PSMContentListener::CanHandleContent(const char* aContentType,
bool aIsContentPreferred,
char ** aDesiredContentType,
bool * aCanHandleContent)
char** aDesiredContentType,
bool* aCanHandleContent)
{
uint32_t type;
type = getPSMContentType(aContentType);
if (type == PSMContentDownloader::UNKNOWN_TYPE) {
*aCanHandleContent = false;
} else {
*aCanHandleContent = true;
}
uint32_t type = getPSMContentType(aContentType);
*aCanHandleContent = (type != UNKNOWN_TYPE);
return NS_OK;
}
NS_IMETHODIMP
PSMContentListener::DoContent(const nsACString & aContentType,
PSMContentListener::DoContent(const nsACString& aContentType,
bool aIsContentPreferred,
nsIRequest * aRequest,
nsIStreamListener ** aContentHandler,
bool * aAbortProcess)
nsIRequest* aRequest,
nsIStreamListener** aContentHandler,
bool* aAbortProcess)
{
uint32_t type;
type = getPSMContentType(PromiseFlatCString(aContentType).get());
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("PSMContentListener::DoContent\n"));
if (type != PSMContentDownloader::UNKNOWN_TYPE) {
nsRefPtr<PSMContentDownloader> downLoader = new PSMContentDownloader(type);
downLoader.forget(aContentHandler);
if (gPIPNSSLog) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("PSMContentListener::DoContent\n"));
}
if (type != UNKNOWN_TYPE) {
nsCOMPtr<nsIStreamListener> downloader;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
downloader = new PSMContentStreamListener(type);
} else {
downloader = static_cast<PSMContentDownloaderChild*>(
dom::ContentChild::GetSingleton()->SendPPSMContentDownloaderConstructor(type));
}
downloader.forget(aContentHandler);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
PSMContentListener::GetLoadCookie(nsISupports * *aLoadCookie)
PSMContentListener::GetLoadCookie(nsISupports** aLoadCookie)
{
*aLoadCookie = mLoadCookie;
NS_IF_ADDREF(*aLoadCookie);
nsCOMPtr<nsISupports> loadCookie(mLoadCookie);
loadCookie.forget(aLoadCookie);
return NS_OK;
}
NS_IMETHODIMP
PSMContentListener::SetLoadCookie(nsISupports * aLoadCookie)
PSMContentListener::SetLoadCookie(nsISupports* aLoadCookie)
{
mLoadCookie = aLoadCookie;
return NS_OK;
}
NS_IMETHODIMP
PSMContentListener::GetParentContentListener(nsIURIContentListener ** aContentListener)
PSMContentListener::GetParentContentListener(nsIURIContentListener** aContentListener)
{
*aContentListener = mParentContentListener;
NS_IF_ADDREF(*aContentListener);
nsCOMPtr<nsIURIContentListener> listener(mParentContentListener);
listener.forget(aContentListener);
return NS_OK;
}
NS_IMETHODIMP
PSMContentListener::SetParentContentListener(nsIURIContentListener * aContentListener)
PSMContentListener::SetParentContentListener(nsIURIContentListener* aContentListener)
{
mParentContentListener = aContentListener;
return NS_OK;

View File

@ -10,12 +10,84 @@
#include "nsCOMPtr.h"
#include "nsIURIContentListener.h"
#include "nsWeakReference.h"
#include "mozilla/psm/PPSMContentDownloaderChild.h"
#include "mozilla/psm/PPSMContentDownloaderParent.h"
#define NS_PSMCONTENTLISTEN_CID {0xc94f4a30, 0x64d7, 0x11d4, {0x99, 0x60, 0x00, 0xb0, 0xd0, 0x23, 0x54, 0xa0}}
#define NS_PSMCONTENTLISTEN_CONTRACTID "@mozilla.org/security/psmdownload;1"
namespace mozilla {
namespace net {
class PChannelDiverterParent;
}
}
namespace mozilla { namespace psm {
// PSMContentStreamListener for parent-process downloading.
class PSMContentStreamListener : public nsIStreamListener
{
public:
explicit PSMContentStreamListener(uint32_t type);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
void ImportCertificate();
protected:
virtual ~PSMContentStreamListener();
nsCString mByteData;
uint32_t mType;
};
// Parent actor for importing a remote cert when the load was started by the
// child.
class PSMContentDownloaderParent : public PPSMContentDownloaderParent
, public PSMContentStreamListener
{
public:
explicit PSMContentDownloaderParent(uint32_t type);
virtual bool RecvOnStartRequest(const uint32_t &contentLength) override;
virtual bool RecvOnDataAvailable(const nsCString &data,
const uint64_t &offset,
const uint32_t &count) override;
virtual bool RecvOnStopRequest(const nsresult &code) override;
// We inherit most of nsIStreamListener from PSMContentStreamListener, but
// we have to override OnStopRequest to know when we're done with our IPC
// ref.
NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports *aContext, nsresult code) override;
virtual bool RecvDivertToParentUsing(mozilla::net::PChannelDiverterParent *diverter) override;
protected:
virtual ~PSMContentDownloaderParent();
virtual void ActorDestroy(ActorDestroyReason why) override;
bool mIPCOpen;
};
// Child actor for importing a cert.
class PSMContentDownloaderChild : public nsIStreamListener
, public PPSMContentDownloaderChild
{
public:
PSMContentDownloaderChild();
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
private:
~PSMContentDownloaderChild();
};
class PSMContentListener : public nsIURIContentListener,
public nsSupportsWeakReference
{

View File

@ -23,6 +23,10 @@ EXPORTS.mozilla += [
'PublicSSL.h',
]
EXPORTS.mozilla.psm += [
'PSMContentListener.h',
]
UNIFIED_SOURCES += [
'CryptoTask.cpp',
'nsCertOverrideService.cpp',
@ -74,6 +78,10 @@ SOURCES += [
'nsNSSCertificateDB.cpp',
]
IPDL_SOURCES += [
'PPSMContentDownloader.ipdl',
]
LOCAL_INCLUDES += [
'/security/manager/boot/src',
]

View File

@ -135,14 +135,20 @@ _InstanceClassChrome##Constructor(nsISupports *aOuter, REFNSIID aIID, \
{ \
nsresult rv; \
\
*aResult = nullptr; \
if (nullptr != aOuter) { \
*aResult = nullptr; \
if (nullptr != aOuter) { \
rv = NS_ERROR_NO_AGGREGATION; \
return rv; \
} \
\
if (!EnsureNSSInitialized(ensureOperator)) \
if (!NS_IS_PROCESS_DEFAULT && \
ensureOperator == nssEnsureChromeOrContent) { \
if (!EnsureNSSInitializedChromeOrContent()) { \
return NS_ERROR_FAILURE; \
} \
} else if (!EnsureNSSInitialized(ensureOperator)) { \
return NS_ERROR_FAILURE; \
} \
\
if (NS_IS_PROCESS_DEFAULT) \
NS_NSS_INSTANTIATE_INIT(ensureOperator, \
@ -182,7 +188,7 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsTLSSocketProvider)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsSecretDecoderRing)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsPK11TokenDB)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsPKCS11ModuleDB)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, PSMContentListener, init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(PSMContentListener, init)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_BYPROCESS(nssEnsureOnChromeOnly,
nsNSSCertificate,
nsNSSCertificateFakeTransport)