зеркало из https://github.com/mozilla/pjs.git
merge after backing out 38140c8a8327
This commit is contained in:
Коммит
eca57915a5
|
@ -807,7 +807,7 @@ nsHttpConnection::GetInterface(const nsIID &iid, void **result)
|
||||||
// the socket transport thread. If that weren't the case, then we'd
|
// the socket transport thread. If that weren't the case, then we'd
|
||||||
// have to worry about the possibility of mTransaction going away
|
// have to worry about the possibility of mTransaction going away
|
||||||
// part-way through this function call. See CloseTransaction.
|
// part-way through this function call. See CloseTransaction.
|
||||||
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
|
NS_ASSERTION(PR_GetCurrentThread() != gSocketThread, "wrong thread");
|
||||||
|
|
||||||
if (mTransaction) {
|
if (mTransaction) {
|
||||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||||
|
|
|
@ -190,7 +190,8 @@ nsSecureBrowserUIImpl::~nsSecureBrowserUIImpl()
|
||||||
PR_DestroyMonitor(mMonitor);
|
PR_DestroyMonitor(mMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS6(nsSecureBrowserUIImpl, nsISecureBrowserUI,
|
NS_IMPL_THREADSAFE_ISUPPORTS6(nsSecureBrowserUIImpl,
|
||||||
|
nsISecureBrowserUI,
|
||||||
nsIWebProgressListener,
|
nsIWebProgressListener,
|
||||||
nsIFormSubmitObserver,
|
nsIFormSubmitObserver,
|
||||||
nsIObserver,
|
nsIObserver,
|
||||||
|
|
|
@ -222,15 +222,12 @@ nsNSSSocketInfo::nsNSSSocketInfo()
|
||||||
mPort(0)
|
mPort(0)
|
||||||
{
|
{
|
||||||
mThreadData = new nsSSLSocketThreadData;
|
mThreadData = new nsSSLSocketThreadData;
|
||||||
mCallbacksLock = nsAutoLock::NewLock("nsNSSSocketInfo::mCallbacksLock");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsNSSSocketInfo::~nsNSSSocketInfo()
|
nsNSSSocketInfo::~nsNSSSocketInfo()
|
||||||
{
|
{
|
||||||
delete mThreadData;
|
delete mThreadData;
|
||||||
|
|
||||||
nsAutoLock::DestroyLock(mCallbacksLock);
|
|
||||||
|
|
||||||
nsNSSShutDownPreventionLock locker;
|
nsNSSShutDownPreventionLock locker;
|
||||||
if (isAlreadyShutDown())
|
if (isAlreadyShutDown())
|
||||||
return;
|
return;
|
||||||
|
@ -331,192 +328,119 @@ PRBool nsNSSSocketInfo::GetHasCleartextPhase()
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSSSocketInfo::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks)
|
nsNSSSocketInfo::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISupports> supports;
|
*aCallbacks = mCallbacks;
|
||||||
{
|
NS_IF_ADDREF(*aCallbacks);
|
||||||
nsAutoLock lock(mCallbacksLock);
|
|
||||||
supports = mCallbacks;
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIInterfaceRequestor> callbacks(do_QueryInterface(supports));
|
|
||||||
callbacks.forget(aCallbacks);
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
|
nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISupports> callbacks(do_QueryInterface(aCallbacks));
|
if (!aCallbacks) {
|
||||||
|
mCallbacks = nsnull;
|
||||||
nsAutoLock lock(mCallbacksLock);
|
return NS_OK;
|
||||||
|
|
||||||
callbacks.swap(mCallbacks);
|
|
||||||
if (mCallbacks) {
|
|
||||||
mDocShellDependentStuffKnown = PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCallbacks = aCallbacks;
|
||||||
|
mDocShellDependentStuffKnown = PR_FALSE;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
class nsGatherDocshellInfoForPSMRunnable : public nsRunnable
|
nsresult
|
||||||
|
nsNSSSocketInfo::EnsureDocShellDependentStuffKnown()
|
||||||
{
|
{
|
||||||
public:
|
if (mDocShellDependentStuffKnown)
|
||||||
nsGatherDocshellInfoForPSMRunnable(nsIInterfaceRequestor* aCallbacks,
|
return NS_OK;
|
||||||
PRBool* aExternalReporting,
|
|
||||||
nsIX509Cert** aPreviousCert)
|
|
||||||
: mCallbacks(aCallbacks), mExternalReporting(aExternalReporting),
|
|
||||||
mPreviousCert(aPreviousCert)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(aCallbacks, "Null pointer!");
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHOD Run()
|
if (!mCallbacks || nsSSLThread::exitRequested())
|
||||||
{
|
return NS_ERROR_FAILURE;
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Must run only on the main thread!");
|
|
||||||
|
|
||||||
*mExternalReporting = PR_FALSE;
|
mDocShellDependentStuffKnown = PR_TRUE;
|
||||||
*mPreviousCert = nsnull;
|
|
||||||
|
nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
|
||||||
|
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
|
||||||
|
NS_GET_IID(nsIInterfaceRequestor),
|
||||||
|
static_cast<nsIInterfaceRequestor*>(mCallbacks),
|
||||||
|
NS_PROXY_SYNC,
|
||||||
|
getter_AddRefs(proxiedCallbacks));
|
||||||
|
|
||||||
// Are we running within a context that wants external SSL error reporting?
|
// Are we running within a context that wants external SSL error reporting?
|
||||||
// We'll look at the presence of a security UI object inside docshell.
|
// We'll look at the presence of a security UI object inside docshell.
|
||||||
// If the docshell wants the lock icon, you'll get the ssl error pages, too.
|
// If the docshell wants the lock icon, you'll get the ssl error pages, too.
|
||||||
// This is helpful to distinguish from all other contexts, like mail
|
// This is helpful to distinguish from all other contexts, like mail windows,
|
||||||
// windows, or any other SSL connections running in the background.
|
// or any other SSL connections running in the background.
|
||||||
// We must query it now and remember, because fatal SSL errors will come
|
// We must query it now and remember, because fatal SSL errors will come
|
||||||
// with a socket close, and the socket transport might detach the callbacks
|
// with a socket close, and the socket transport might detach the callbacks
|
||||||
// instance prior to our error reporting.
|
// instance prior to our error reporting.
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(mCallbacks));
|
nsCOMPtr<nsIDocShell> docshell;
|
||||||
if (!item)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> proxiedItem;
|
||||||
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
||||||
item->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
|
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
|
||||||
|
NS_GET_IID(nsIDocShellTreeItem),
|
||||||
|
item.get(),
|
||||||
|
NS_PROXY_SYNC,
|
||||||
|
getter_AddRefs(proxiedItem));
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShell> docshell(do_QueryInterface(rootItem));
|
proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
|
||||||
|
docshell = do_QueryInterface(rootItem);
|
||||||
NS_ASSERTION(docshell, "rootItem do_QI is null");
|
NS_ASSERTION(docshell, "rootItem do_QI is null");
|
||||||
if (!docshell)
|
}
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsISecureBrowserUI> secureUI;
|
if (docshell)
|
||||||
docshell->GetSecurityUI(getter_AddRefs(secureUI));
|
{
|
||||||
if (!secureUI)
|
nsCOMPtr<nsIDocShell> proxiedDocShell;
|
||||||
return NS_OK;
|
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
|
||||||
|
NS_GET_IID(nsIDocShell),
|
||||||
*mExternalReporting = PR_TRUE;
|
docshell.get(),
|
||||||
|
NS_PROXY_SYNC,
|
||||||
|
getter_AddRefs(proxiedDocShell));
|
||||||
|
nsISecureBrowserUI* secureUI;
|
||||||
|
proxiedDocShell->GetSecurityUI(&secureUI);
|
||||||
|
if (secureUI)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
|
||||||
|
NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
|
||||||
|
mExternalErrorReporting = PR_TRUE;
|
||||||
|
|
||||||
// If this socket is associated to a docshell, let's try to remember
|
// If this socket is associated to a docshell, let's try to remember
|
||||||
// the currently used cert. If this socket gets a notification from NSS
|
// the currently used cert. If this socket gets a notification from NSS
|
||||||
// having the same raw socket, we can keep the PSM wrapper object
|
// having the same raw socket, we can keep the PSM wrapper object
|
||||||
// and all the data it has cached (like verification results).
|
// and all the data it has cached (like verification results).
|
||||||
nsCOMPtr<nsISSLStatusProvider> statprov(do_QueryInterface(secureUI));
|
nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
|
||||||
if (!statprov)
|
if (statprov) {
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> isup_stat;
|
nsCOMPtr<nsISupports> isup_stat;
|
||||||
statprov->GetSSLStatus(getter_AddRefs(isup_stat));
|
statprov->GetSSLStatus(getter_AddRefs(isup_stat));
|
||||||
|
if (isup_stat) {
|
||||||
|
nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
|
||||||
|
if (sslstat) {
|
||||||
|
sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsISSLStatus> sslstat(do_QueryInterface(isup_stat));
|
|
||||||
if (!sslstat)
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
sslstat->GetServerCert(mPreviousCert);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsIInterfaceRequestor* mCallbacks;
|
|
||||||
PRBool* mExternalReporting;
|
|
||||||
nsIX509Cert** mPreviousCert;
|
|
||||||
};
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsNSSSocketInfo::EnsureDocShellDependentStuffKnown(PRBool* aExternalReporting,
|
|
||||||
nsIX509Cert** aPreviousCert)
|
|
||||||
{
|
|
||||||
do {
|
|
||||||
nsCOMPtr<nsISupports> origCallbacks;
|
|
||||||
{
|
|
||||||
nsAutoLock lock(mCallbacksLock);
|
|
||||||
|
|
||||||
if (mDocShellDependentStuffKnown) {
|
|
||||||
if (aExternalReporting) {
|
|
||||||
*aExternalReporting = mExternalErrorReporting;
|
|
||||||
}
|
|
||||||
if (aPreviousCert) {
|
|
||||||
NS_IF_ADDREF(*aPreviousCert = mPreviousCert);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
origCallbacks = mCallbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsSSLThread::exitRequested() || !origCallbacks) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIInterfaceRequestor> callbacks(do_QueryInterface(origCallbacks));
|
|
||||||
NS_ASSERTION(callbacks, "How does this not QI to nsIInterfaceRequestor?!");
|
|
||||||
|
|
||||||
// We're about to touch the docshell which we know to be main-thread-only.
|
|
||||||
nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
|
|
||||||
NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
PRBool externalReporting = PR_FALSE;
|
|
||||||
nsCOMPtr<nsIX509Cert> previousCert;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
|
||||||
new nsGatherDocshellInfoForPSMRunnable(callbacks, &externalReporting,
|
|
||||||
getter_AddRefs(previousCert));
|
|
||||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
|
|
||||||
nsresult rv = mainThread->Dispatch(runnable, NS_DISPATCH_SYNC);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
{
|
|
||||||
nsAutoLock lock(mCallbacksLock);
|
|
||||||
|
|
||||||
// Check to see if anyone replaced mCallbacks while the runnable was
|
|
||||||
// queued. This is why we store nsISupports in mCallbacks - otherwise we'd
|
|
||||||
// have to QI inside this lock.
|
|
||||||
if (mCallbacks == origCallbacks) {
|
|
||||||
// No one reset this out from under us, so go ahead and update our data.
|
|
||||||
mDocShellDependentStuffKnown = PR_TRUE;
|
|
||||||
mExternalErrorReporting = externalReporting;
|
|
||||||
previousCert.swap(mPreviousCert);
|
|
||||||
|
|
||||||
if (aExternalReporting) {
|
|
||||||
*aExternalReporting = mExternalErrorReporting;
|
|
||||||
}
|
|
||||||
if (aPreviousCert) {
|
|
||||||
NS_IF_ADDREF(*aPreviousCert = mPreviousCert);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Someone replaced mCallbacks while we were running, try again.
|
|
||||||
NS_WARNING("Contention for mCallbacks, trying again");
|
|
||||||
|
|
||||||
} while(1); // Loop until we don't have contention.
|
|
||||||
|
|
||||||
NS_NOTREACHED("Should never get here");
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsNSSSocketInfo::GetExternalErrorReporting(PRBool* state)
|
nsNSSSocketInfo::GetExternalErrorReporting(PRBool* state)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(state);
|
nsresult rv = EnsureDocShellDependentStuffKnown();
|
||||||
nsresult rv = EnsureDocShellDependentStuffKnown(state);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
*state = mExternalErrorReporting;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsNSSSocketInfo::SetExternalErrorReporting(PRBool aState)
|
nsNSSSocketInfo::SetExternalErrorReporting(PRBool aState)
|
||||||
{
|
{
|
||||||
nsAutoLock lock(mCallbacksLock);
|
|
||||||
mExternalErrorReporting = aState;
|
mExternalErrorReporting = aState;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -620,33 +544,27 @@ nsNSSSocketInfo::SetErrorMessage(const PRUnichar* aText) {
|
||||||
/* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
|
/* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
|
||||||
NS_IMETHODIMP nsNSSSocketInfo::GetInterface(const nsIID & uuid, void * *result)
|
NS_IMETHODIMP nsNSSSocketInfo::GetInterface(const nsIID & uuid, void * *result)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISupports> callbacks;
|
nsresult rv;
|
||||||
|
if (!mCallbacks) {
|
||||||
|
nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
|
||||||
|
if (!ir)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
{
|
rv = ir->GetInterface(uuid, result);
|
||||||
nsAutoLock lock(mCallbacksLock);
|
} else {
|
||||||
callbacks = mCallbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callbacks) {
|
|
||||||
// XXX Shouldn't we check this even if callbacks is null?
|
|
||||||
if (nsSSLThread::exitRequested())
|
if (nsSSLThread::exitRequested())
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
|
nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
|
||||||
nsresult rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
|
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
|
||||||
NS_GET_IID(nsIInterfaceRequestor),
|
NS_GET_IID(nsIInterfaceRequestor),
|
||||||
callbacks,
|
mCallbacks,
|
||||||
NS_PROXY_SYNC,
|
NS_PROXY_SYNC,
|
||||||
getter_AddRefs(proxiedCallbacks));
|
getter_AddRefs(proxiedCallbacks));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return proxiedCallbacks->GetInterface(uuid, result);
|
rv = proxiedCallbacks->GetInterface(uuid, result);
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
|
|
||||||
NS_ENSURE_TRUE(ir, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
|
|
||||||
return ir->GetInterface(uuid, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -795,9 +713,12 @@ nsresult nsNSSSocketInfo::SetFileDescPtr(PRFileDesc* aFilePtr)
|
||||||
nsresult nsNSSSocketInfo::GetPreviousCert(nsIX509Cert** _result)
|
nsresult nsNSSSocketInfo::GetPreviousCert(nsIX509Cert** _result)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(_result);
|
NS_ENSURE_ARG_POINTER(_result);
|
||||||
nsresult rv = EnsureDocShellDependentStuffKnown(nsnull, _result);
|
nsresult rv = EnsureDocShellDependentStuffKnown();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
*_result = mPreviousCert;
|
||||||
|
NS_IF_ADDREF(*_result);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
|
|
||||||
#include "prtypes.h"
|
#include "prtypes.h"
|
||||||
#include "prio.h"
|
#include "prio.h"
|
||||||
#include "prlock.h"
|
|
||||||
#include "certt.h"
|
#include "certt.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsIInterfaceRequestor.h"
|
#include "nsIInterfaceRequestor.h"
|
||||||
|
@ -202,7 +201,7 @@ public:
|
||||||
PRStatus CloseSocketAndDestroy();
|
PRStatus CloseSocketAndDestroy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsCOMPtr<nsISupports> mCallbacks;
|
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||||
PRFileDesc* mFd;
|
PRFileDesc* mFd;
|
||||||
nsCOMPtr<nsIX509Cert> mCert;
|
nsCOMPtr<nsIX509Cert> mCert;
|
||||||
nsCOMPtr<nsIX509Cert> mPreviousCert; // DocShellDependent
|
nsCOMPtr<nsIX509Cert> mPreviousCert; // DocShellDependent
|
||||||
|
@ -236,13 +235,7 @@ protected:
|
||||||
|
|
||||||
nsSSLSocketThreadData *mThreadData;
|
nsSSLSocketThreadData *mThreadData;
|
||||||
|
|
||||||
// This lock will protect mCallbacks, mDocShellDependentStuffKnown,
|
nsresult EnsureDocShellDependentStuffKnown();
|
||||||
// mExternalErrorReporting, and mPreviousCert from concurrent changes.
|
|
||||||
PRLock* mCallbacksLock;
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
EnsureDocShellDependentStuffKnown(PRBool* aExternalReporting = nsnull,
|
|
||||||
nsIX509Cert** aPreviousCert = nsnull);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void virtualDestroyNSSReference();
|
virtual void virtualDestroyNSSReference();
|
||||||
|
|
|
@ -219,8 +219,8 @@ nsDocLoader::~nsDocLoader()
|
||||||
/*
|
/*
|
||||||
* Implementation of ISupports methods...
|
* Implementation of ISupports methods...
|
||||||
*/
|
*/
|
||||||
NS_IMPL_ADDREF(nsDocLoader)
|
NS_IMPL_THREADSAFE_ADDREF(nsDocLoader)
|
||||||
NS_IMPL_RELEASE(nsDocLoader)
|
NS_IMPL_THREADSAFE_RELEASE(nsDocLoader)
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN(nsDocLoader)
|
NS_INTERFACE_MAP_BEGIN(nsDocLoader)
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver)
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче