fixes bug 261083 "Channels do not uniformly query their notification callbacks" r=biesi sr=bzbarsky

This commit is contained in:
darin%meer.net 2004-11-15 20:16:52 +00:00
Родитель a3df80a5ed
Коммит c79cfdbf74
32 изменённых файлов: 583 добавлений и 551 удалений

Просмотреть файл

@ -2300,12 +2300,8 @@ nsBookmarksService::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
schedule,
nsCaseInsensitiveStringComparator()))
{
nsCOMPtr<nsIInterfaceRequestor> interfaces;
nsCOMPtr<nsIPrompt> prompter;
channel->GetNotificationCallbacks(getter_AddRefs(interfaces));
if (interfaces)
interfaces->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompter));
NS_QueryNotificationCallbacks(channel, prompter);
if (!prompter)
{
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));

Просмотреть файл

@ -116,34 +116,6 @@ nsresult nsJSThunk::Init(nsIURI* uri)
return NS_OK;
}
static void
GetInterfaceFromChannel(nsIChannel* aChannel,
const nsIID &aIID,
void **aResult)
{
NS_PRECONDITION(aChannel, "Must have a channel");
NS_PRECONDITION(aResult, "Null out param");
*aResult = nsnull;
// Get an interface requestor from the channel callbacks.
nsCOMPtr<nsIInterfaceRequestor> callbacks;
aChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (callbacks) {
callbacks->GetInterface(aIID, aResult);
}
if (!*aResult) {
// Try the loadgroup
nsCOMPtr<nsILoadGroup> loadGroup;
aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (callbacks) {
callbacks->GetInterface(aIID, aResult);
}
}
}
}
nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
{
nsresult rv;
@ -157,8 +129,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
// The the global object owner from the channel
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner;
GetInterfaceFromChannel(aChannel, NS_GET_IID(nsIScriptGlobalObjectOwner),
getter_AddRefs(globalOwner));
NS_QueryNotificationCallbacks(aChannel, globalOwner);
NS_ASSERTION(globalOwner,
"Unable to get an nsIScriptGlobalObjectOwner from the "
"channel!");
@ -372,8 +343,7 @@ nsresult nsJSChannel::StopAll()
{
nsresult rv = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIWebNavigation> webNav;
GetInterfaceFromChannel(mStreamChannel, NS_GET_IID(nsIWebNavigation),
getter_AddRefs(webNav));
NS_QueryNotificationCallbacks(mStreamChannel, webNav);
NS_ASSERTION(webNav, "Can't get nsIWebNavigation from channel!");
if (webNav) {
@ -564,8 +534,7 @@ nsJSChannel::InternalOpen(PRBool aIsAsync, nsIStreamListener *aListener,
// ok. If so, stop all pending network loads.
nsCOMPtr<nsIDocShell> docShell;
GetInterfaceFromChannel(mStreamChannel, NS_GET_IID(nsIDocShell),
getter_AddRefs(docShell));
NS_QueryNotificationCallbacks(mStreamChannel, docShell);
if (docShell) {
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));

Просмотреть файл

@ -42,7 +42,7 @@
#include "nsIServiceManager.h"
#include "nsICookiePromptService.h"
#include "nsICookieManager2.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIURI.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
@ -108,31 +108,6 @@ IsFromMailNews(nsIURI *aURI)
}
#endif
static void
GetInterfaceFromChannel(nsIChannel *aChannel,
const nsIID &aIID,
void **aResult)
{
if (!aChannel)
return; // no context, no interface!
NS_ASSERTION(!*aResult, "result not initialized to null");
nsCOMPtr<nsIInterfaceRequestor> cbs;
aChannel->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
cbs->GetInterface(aIID, aResult);
if (!*aResult) {
// try load group's notification callbacks...
nsCOMPtr<nsILoadGroup> loadGroup;
aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
cbs->GetInterface(aIID, aResult);
}
}
}
NS_IMPL_ISUPPORTS2(nsCookiePermission,
nsICookiePermission,
nsIObserver)
@ -252,8 +227,7 @@ nsCookiePermission::CanAccess(nsIURI *aURI,
PRUint32 appType = nsIDocShell::APP_TYPE_UNKNOWN;
if (aChannel) {
nsCOMPtr<nsIDocShellTreeItem> item, parent;
GetInterfaceFromChannel(aChannel, NS_GET_IID(nsIDocShellTreeItem),
getter_AddRefs(parent));
NS_QueryNotificationCallbacks(aChannel, parent);
if (parent) {
do {
item = parent;
@ -381,8 +355,8 @@ nsCookiePermission::CanSetCookie(nsIURI *aURI,
// try to get a nsIDOMWindow from the channel...
nsCOMPtr<nsIDOMWindow> parent;
GetInterfaceFromChannel(aChannel, NS_GET_IID(nsIDOMWindow),
getter_AddRefs(parent));
if (aChannel)
NS_QueryNotificationCallbacks(aChannel, parent);
// get some useful information to present to the user:
// whether a previous cookie already exists, and how many cookies this host

Просмотреть файл

@ -189,9 +189,10 @@ nsDateTimeChannel::Open(nsIInputStream **_retval)
NS_IMETHODIMP
nsDateTimeChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
nsresult rv = NS_OK;
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
rv = NS_CheckPortSafety(mPort, "datetime");
nsresult rv = NS_CheckPortSafety(mPort, "datetime");
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQ;
@ -209,8 +210,7 @@ nsDateTimeChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
// not fatal if these fail
mTransport->SetSecurityCallbacks(mCallbacks);
// not fatal if this fails
mTransport->SetEventSink(this, eventQ);
//
@ -357,7 +357,6 @@ NS_IMETHODIMP
nsDateTimeChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
mProgressSink = do_GetInterface(mCallbacks);
return NS_OK;
}

Просмотреть файл

@ -208,9 +208,10 @@ nsFingerChannel::Open(nsIInputStream **_retval)
NS_IMETHODIMP
nsFingerChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
nsresult rv = NS_OK;
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
rv = NS_CheckPortSafety(mPort, "finger");
nsresult rv = NS_CheckPortSafety(mPort, "finger");
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQ;
@ -228,8 +229,7 @@ nsFingerChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
// not fatal if these fail
mTransport->SetSecurityCallbacks(mCallbacks);
// not fatal if this fails
mTransport->SetEventSink(this, eventQ);
rv = WriteRequest(mTransport);
@ -379,7 +379,6 @@ NS_IMETHODIMP
nsFingerChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
mProgressSink = do_GetInterface(mCallbacks);
return NS_OK;
}

Просмотреть файл

@ -141,30 +141,6 @@ MapGnomeVFSResult(GnomeVFSResult result)
//-----------------------------------------------------------------------------
// Query the channel for a nsIAuthPrompt reference (use the canonical method of
// searching the channel's notification callbacks first, and its loadgroup's
// callbacks seconds). XXX This should really live somewhere else.
static void
GetAuthPromptFromChannel(nsIChannel *channel, nsIAuthPrompt **result)
{
nsCOMPtr<nsIInterfaceRequestor> cbs;
channel->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
CallGetInterface(cbs.get(), result);
if (!*result)
{
nsCOMPtr<nsILoadGroup> loadGroup;
channel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup)
{
loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
CallGetInterface(cbs.get(), result);
}
}
}
static void
ProxiedAuthCallback(gconstpointer in,
gsize in_size,
@ -185,7 +161,7 @@ ProxiedAuthCallback(gconstpointer in,
return;
nsCOMPtr<nsIAuthPrompt> prompt;
GetAuthPromptFromChannel(channel, getter_AddRefs(prompt));
NS_QueryNotificationCallbacks(channel, prompt);
// If no auth prompt, then give up. We could failover to using the
// WindowWatcher service, but that might defeat a consumer's purposeful

Просмотреть файл

@ -55,8 +55,6 @@
#include "nsIFormControl.h"
#include "nsIDocShell.h"
#include "nsIDOMWindowInternal.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPrompt.h"
#include "nsIChannel.h"
#include "nsIWindowWatcher.h"
@ -65,6 +63,7 @@
#include "nsUnicharUtils.h"
#include "nsReadableUtils.h"
#include "nsICategoryManager.h"
#include "nsNetUtil.h"
// for making the leap from nsIDOMWindowInternal -> nsIPresShell
#include "nsIScriptGlobalObject.h"
@ -448,14 +447,11 @@ nsWalletlibService::OnStateChange(nsIWebProgress* aWebProgress,
if (nameString) {
nsAutoString value;
PRUnichar* valueString = NULL;
nsCOMPtr<nsIInterfaceRequestor> interfaces;
nsCOMPtr<nsIPrompt> prompter;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel)
channel->GetNotificationCallbacks(getter_AddRefs(interfaces));
if (interfaces)
interfaces->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompter));
NS_QueryNotificationCallbacks(channel, prompter);
if (!prompter) {
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
if (wwatch)

Просмотреть файл

@ -651,17 +651,6 @@ NS_IMETHODIMP
nsMsgProtocol::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
// Verify that the event sink is http
if (mCallbacks)
{
nsCOMPtr<nsIProgressEventSink> progressSink;
(void)mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink),
getter_AddRefs(progressSink));
// only replace our current progress event sink if we were given a new one..
if (progressSink) mProgressEventSink = progressSink;
}
return NS_OK;
}
@ -669,37 +658,40 @@ NS_IMETHODIMP
nsMsgProtocol::OnTransportStatus(nsITransport *transport, nsresult status,
PRUint32 progress, PRUint32 progressMax)
{
if (mProgressEventSink && !(mLoadFlags & LOAD_BACKGROUND))
if ((mLoadFlags & LOAD_BACKGROUND) || !m_url)
return NS_OK;
// these transport events should not generate any status messages
if (status == nsISocketTransport::STATUS_RECEIVING_FROM ||
status == nsISocketTransport::STATUS_SENDING_TO)
return NS_OK;
if (!mProgressEventSink)
{
// these transport events should not generate any status messages
if (status == nsISocketTransport::STATUS_RECEIVING_FROM ||
status == nsISocketTransport::STATUS_SENDING_TO)
NS_QueryNotificationCallbacks(mCallbacks, m_loadGroup, mProgressEventSink);
if (!mProgressEventSink)
return NS_OK;
}
nsCAutoString host;
m_url->GetHost(host);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url);
if (mailnewsUrl)
{
nsCOMPtr<nsIMsgIncomingServer> server;
mailnewsUrl->GetServer(getter_AddRefs(server));
if (server)
{
// do nothing....do NOT report socket transport progress bytes either
char *realHostName = nsnull;
server->GetRealHostName(&realHostName);
if (realHostName)
host.Adopt(realHostName);
}
else
{
nsCAutoString host;
if (m_url)
{
m_url->GetHost(host);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url);
if (mailnewsUrl)
{
nsCOMPtr<nsIMsgIncomingServer> server;
nsresult rv = mailnewsUrl->GetServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv) && server)
{
nsXPIDLCString realHostName;
rv = server->GetRealHostName(getter_Copies(realHostName));
if (NS_SUCCEEDED(rv))
host = realHostName;
}
}
mProgressEventSink->OnStatus(this, nsnull, status, NS_ConvertUTF8toUCS2(host).get());
}
}
}
}
mProgressEventSink->OnStatus(this, nsnull, status,
NS_ConvertUTF8toUTF16(host).get());
return NS_OK;
}

Просмотреть файл

@ -325,6 +325,9 @@ void nsSmtpProtocol::Initialize(nsIURI * aURL)
PR_LOG(SMTPLogModule, PR_LOG_ALWAYS, ("SMTP Connecting to: %s", hostName.get()));
#endif
// When we are making a secure connection, we need to make sure that we
// pass an interface requestor down to the socket transport so that PSM can
// retrieve a nsIPrompt instance if needed.
nsCOMPtr<nsIInterfaceRequestor> callbacks;
nsCOMPtr<nsISmtpUrl> smtpUrl(do_QueryInterface(aURL));
if (smtpUrl)

Просмотреть файл

@ -695,6 +695,21 @@ nsImapProtocol::SetupSinkProxy()
NS_ASSERTION(NS_SUCCEEDED(res), "couldn't get proxies");
}
static void SetSecurityCallbacksFromChannel(nsISocketTransport* aTrans, nsIChannel* aChannel)
{
nsCOMPtr<nsIInterfaceRequestor> callbacks;
aChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
nsCOMPtr<nsILoadGroup> loadGroup;
aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
nsCOMPtr<nsIInterfaceRequestor> securityCallbacks;
NS_NewNotificationCallbacksAggregation(callbacks, loadGroup,
getter_AddRefs(securityCallbacks));
if (securityCallbacks)
aTrans->SetSecurityCallbacks(securityCallbacks);
}
// Setup With Url is intended to set up data which is held on a PER URL basis and not
// a per connection basis. If you have data which is independent of the url we are currently
// running, then you should put it in Initialize().
@ -808,10 +823,7 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer)
if (m_transport)
{
// Ensure that the socket can get the notification callbacks
nsCOMPtr<nsIInterfaceRequestor> callbacks;
m_mockChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (callbacks)
m_transport->SetSecurityCallbacks(callbacks);
SetSecurityCallbacksFromChannel(m_transport, m_mockChannel);
// open buffered, blocking input stream
rv = m_transport->OpenInputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(m_inputStream));
@ -832,10 +844,7 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer)
m_transport->GetSecurityInfo(getter_AddRefs(securityInfo));
m_mockChannel->SetSecurityInfo(securityInfo);
nsCOMPtr<nsIInterfaceRequestor> callbacks;
m_mockChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (callbacks && m_transport)
m_transport->SetSecurityCallbacks(callbacks);
SetSecurityCallbacksFromChannel(m_transport, m_mockChannel);
nsCOMPtr<nsITransportEventSink> sink = do_QueryInterface(m_mockChannel);
if (sink) {
@ -4536,7 +4545,7 @@ nsImapProtocol::AlertUserEvent(const char * message)
{
nsCOMPtr<nsIMsgWindow> msgWindow;
GetMsgWindow(getter_AddRefs(msgWindow));
m_imapServerSink->FEAlert(NS_ConvertASCIItoUCS2(message).get(), msgWindow);
m_imapServerSink->FEAlert(NS_ConvertASCIItoUTF16(message).get(), msgWindow);
}
}
@ -8430,17 +8439,6 @@ NS_IMETHODIMP
nsImapMockChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
// Verify that the event sink is http
if (mCallbacks)
{
nsCOMPtr<nsIProgressEventSink> progressSink;
(void)mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink),
getter_AddRefs(progressSink));
// only replace our current progress event sink if we were given a new one..
if (progressSink) mProgressEventSink = progressSink;
}
return NS_OK;
}
@ -8448,36 +8446,39 @@ NS_IMETHODIMP
nsImapMockChannel::OnTransportStatus(nsITransport *transport, nsresult status,
PRUint32 progress, PRUint32 progressMax)
{
if (mProgressEventSink && NS_SUCCEEDED(m_cancelStatus) && !(mLoadFlags & LOAD_BACKGROUND))
if (NS_FAILED(m_cancelStatus) || (mLoadFlags & LOAD_BACKGROUND) || !m_url)
return NS_OK;
// these transport events should not generate any status messages
if (status == nsISocketTransport::STATUS_RECEIVING_FROM ||
status == nsISocketTransport::STATUS_SENDING_TO)
return NS_OK;
if (!mProgressEventSink)
{
// these transport events should not generate any status messages
if (status == nsISocketTransport::STATUS_RECEIVING_FROM ||
status == nsISocketTransport::STATUS_SENDING_TO)
NS_QueryNotificationCallbacks(mCallbacks, m_loadGroup, mProgressEventSink);
if (!mProgressEventSink)
return NS_OK;
}
nsCAutoString host;
m_url->GetHost(host);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url);
if (mailnewsUrl)
{
nsCOMPtr<nsIMsgIncomingServer> server;
mailnewsUrl->GetServer(getter_AddRefs(server));
if (server)
{
// do nothing....do NOT report socket transport progress bytes either
char *realHostName = nsnull;
server->GetRealHostName(&realHostName);
if (realHostName)
host.Adopt(realHostName);
}
else
{
nsCAutoString host;
if (m_url)
{
m_url->GetHost(host);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url);
if (mailnewsUrl)
{
nsCOMPtr<nsIMsgIncomingServer> server;
nsresult rv = mailnewsUrl->GetServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv) && server)
{
nsXPIDLCString realHostName;
rv = server->GetRealHostName(getter_Copies(realHostName));
if (NS_SUCCEEDED(rv))
host = realHostName;
}
}
mProgressEventSink->OnStatus(this, nsnull, status, NS_ConvertUTF8toUCS2(host).get());
}
}
}
}
mProgressEventSink->OnStatus(this, nsnull, status,
NS_ConvertUTF8toUTF16(host).get());
return NS_OK;
}

Просмотреть файл

@ -565,14 +565,20 @@ nsresult nsPop3Protocol::Initialize(nsIURI * aURL)
m_url = do_QueryInterface(aURL);
// When we are making a secure connection, we need to make sure that we
// pass an interface requestor down to the socket transport so that PSM can
// retrieve a nsIPrompt instance if needed.
nsCOMPtr<nsIInterfaceRequestor> ir;
nsCOMPtr<nsIMsgWindow> msgwin;
mailnewsUrl->GetMsgWindow(getter_AddRefs(msgwin));
if (msgwin)
if (isSecure)
{
nsCOMPtr<nsIMsgWindow> msgwin;
mailnewsUrl->GetMsgWindow(getter_AddRefs(msgwin));
if (msgwin)
{
nsCOMPtr<nsIDocShell> docshell;
msgwin->GetRootDocShell(getter_AddRefs(docshell));
ir = do_QueryInterface(docshell);
}
}
PRInt32 port = 0;

Просмотреть файл

@ -481,8 +481,11 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI * aURL, nsIMsgWindow *aMsgWindow
if (!m_socketIsOpen)
{
// When we are making a secure connection, we need to make sure that we
// pass an interface requestor down to the socket transport so that PSM can
// retrieve a nsIPrompt instance if needed.
nsCOMPtr<nsIInterfaceRequestor> ir;
if (aMsgWindow) {
if (isSecure && aMsgWindow) {
nsCOMPtr<nsIDocShell> docShell;
aMsgWindow->GetRootDocShell(getter_AddRefs(docShell));
ir = do_QueryInterface(docShell);
@ -502,10 +505,7 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI * aURL, nsIMsgWindow *aMsgWindow
rv = NS_ExamineForProxy("nntp", hostName.get(), port, getter_AddRefs(proxyInfo));
if (NS_FAILED(rv)) proxyInfo = nsnull;
if (isSecure)
rv = OpenNetworkSocketWithInfo(hostName.get(), port, "ssl", proxyInfo, ir);
else
rv = OpenNetworkSocketWithInfo(hostName.get(), port, nsnull, proxyInfo, ir);
rv = OpenNetworkSocketWithInfo(hostName.get(), port, isSecure ? "ssl" : nsnull, proxyInfo, ir);
NS_ENSURE_SUCCESS(rv,rv);
m_nextState = NNTP_LOGIN_RESPONSE;

Просмотреть файл

@ -484,7 +484,6 @@ NS_IMETHODIMP
nsJARChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = do_GetInterface(mCallbacks);
return NS_OK;
}
@ -603,6 +602,9 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
nsresult rv = EnsureJarInput(PR_FALSE);
if (NS_FAILED(rv)) return rv;

Просмотреть файл

@ -94,6 +94,12 @@ interface nsIChannel : nsIRequest
*
* Interfaces commonly requested include: nsIProgressEventSink, nsIPrompt,
* and nsIAuthPrompt.
*
* NOTE: channels generally query this attribute when they are opened and
* retain references to the resulting interfaces until they are done. A
* channel may ignore changes to the notificationCallbacks attribute after
* it has been opened. This rule also applies to notificationCallbacks
* queried from the channel's loadgroup.
*/
attribute nsIInterfaceRequestor notificationCallbacks;

Просмотреть файл

@ -83,6 +83,7 @@
#include "nsIAsyncStreamCopier.h"
#include "nsIPersistentProperties2.h"
#include "nsISyncStreamListener.h"
#include "nsInterfaceRequestorAgg.h"
// Helper, to simplify getting the I/O service.
inline const nsGetServiceByCID
@ -903,4 +904,97 @@ NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **result,
return rv;
}
/**
* NS_QueryNotificationCallbacks implements the canonical algorithm for
* querying interfaces from a channel's notification callbacks. It first
* searches the channel's notificationCallbacks attribute, and if the interface
* is not found there, then it inspects the notificationCallbacks attribute of
* the channel's loadGroup.
*/
inline void
NS_QueryNotificationCallbacks(nsIChannel *aChannel,
const nsIID &aIID,
void **aResult)
{
NS_PRECONDITION(aChannel, "null channel");
*aResult = nsnull;
nsCOMPtr<nsIInterfaceRequestor> cbs;
aChannel->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
cbs->GetInterface(aIID, aResult);
if (!*aResult) {
// try load group's notification callbacks...
nsCOMPtr<nsILoadGroup> loadGroup;
aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
cbs->GetInterface(aIID, aResult);
}
}
}
/* template helper */
template <class T> inline void
NS_QueryNotificationCallbacks(nsIChannel *aChannel,
nsCOMPtr<T> &aResult)
{
NS_QueryNotificationCallbacks(aChannel, NS_GET_IID(T),
getter_AddRefs(aResult));
}
/**
* Alternate form of NS_QueryNotificationCallbacks designed for use by
* nsIChannel implementations.
*/
inline void
NS_QueryNotificationCallbacks(nsIInterfaceRequestor *aCallbacks,
nsILoadGroup *aLoadGroup,
const nsIID &aIID,
void **aResult)
{
NS_PRECONDITION(aChannel, "null channel");
*aResult = nsnull;
if (aCallbacks)
aCallbacks->GetInterface(aIID, aResult);
if (!*aResult) {
// try load group's notification callbacks...
if (aLoadGroup) {
nsCOMPtr<nsIInterfaceRequestor> cbs;
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
cbs->GetInterface(aIID, aResult);
}
}
}
/* template helper */
template <class T> inline void
NS_QueryNotificationCallbacks(nsIInterfaceRequestor *aCallbacks,
nsILoadGroup *aLoadGroup,
nsCOMPtr<T> &aResult)
{
NS_QueryNotificationCallbacks(aCallbacks, aLoadGroup,
NS_GET_IID(T),
getter_AddRefs(aResult));
}
/**
* This function returns a nsIInterfaceRequestor instance that returns the
* same result as NS_QueryNotificationCallbacks when queried. It is useful
* as the value for nsISocketTransport::securityCallbacks.
*/
inline nsresult
NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *aCallbacks,
nsILoadGroup *aLoadGroup,
nsIInterfaceRequestor **aResult)
{
nsCOMPtr<nsIInterfaceRequestor> cbs;
if (aLoadGroup)
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
return NS_NewInterfaceRequestorAggregation(aCallbacks, cbs, aResult);
}
#endif // !nsNetUtil_h__

Просмотреть файл

@ -217,7 +217,6 @@ NS_IMETHODIMP
nsInputStreamChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = do_GetInterface(mCallbacks);
return NS_OK;
}
@ -295,6 +294,9 @@ nsInputStreamChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
NS_ENSURE_TRUE(mContentStream, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS);
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
// if content length is unknown, then we must guess... in this case, we
// assume the stream can tell us. if the stream is a pipe, then this will
// not work. in that case, we hope that the user of this interface would

Просмотреть файл

@ -265,7 +265,6 @@ NS_IMETHODIMP
nsFileChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = do_GetInterface(mCallbacks);
return NS_OK;
}
@ -366,6 +365,9 @@ nsFileChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
{
NS_ENSURE_TRUE(!mRequest, NS_ERROR_IN_PROGRESS);
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
nsCOMPtr<nsIStreamListener> grip;
nsCOMPtr<nsIEventQueue> currentEventQ;
nsresult rv;

Просмотреть файл

@ -84,7 +84,6 @@ nsFTPChannel::nsFTPChannel()
mAmount(0),
mContentLength(-1),
mFTPState(nsnull),
mLock(nsnull),
mStatus(NS_OK),
mCanceled(PR_FALSE),
mStartPos(LL_MaxUint())
@ -99,7 +98,6 @@ nsFTPChannel::~nsFTPChannel()
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFTPChannel() for %s", spec.get()));
#endif
NS_IF_RELEASE(mFTPState);
if (mLock) PR_DestroyLock(mLock);
}
NS_IMPL_ADDREF(nsFTPChannel)
@ -140,11 +138,6 @@ nsFTPChannel::Init(nsIURI* uri, nsIProxyInfo* proxyInfo, nsICacheSession* sessio
rv = mURL->GetAsciiHost(mHost);
if (NS_FAILED(rv)) return rv;
if (!mLock) {
mLock = PR_NewLock();
if (!mLock) return NS_ERROR_OUT_OF_MEMORY;
}
mIOService = do_GetIOService(&rv);
if (NS_FAILED(rv)) return rv;
@ -191,7 +184,6 @@ nsFTPChannel::Cancel(nsresult status) {
this, status, mCanceled));
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
nsAutoLock lock(mLock);
if (mCanceled)
return NS_OK;
@ -212,7 +204,6 @@ nsFTPChannel::Suspend(void) {
PR_LOG(gFTPLog, PR_LOG_DEBUG,
("nsFTPChannel::Suspend() called [this=%x]\n", this));
nsAutoLock lock(mLock);
if (mFTPState) {
return mFTPState->Suspend();
}
@ -225,7 +216,6 @@ nsFTPChannel::Resume(void) {
PR_LOG(gFTPLog, PR_LOG_DEBUG,
("nsFTPChannel::Resume() called [this=%x]\n", this));
nsAutoLock lock(mLock);
if (mFTPState) {
return mFTPState->Resume();
}
@ -324,14 +314,26 @@ nsFTPChannel::AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::AsyncOpen() called\n"));
// Initialize mEventSink
//
// Build a proxy for the progress event sink since we may need to call it
// while we are deep inside some of our state logic, and we wouldn't want
// to worry about some weird re-entrancy scenario.
nsCOMPtr<nsIProgressEventSink> sink;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, sink);
if (sink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIProgressEventSink),
sink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mEventSink));
mListener = listener;
mUserContext = ctxt;
// Add this request to the load group
if (mLoadGroup) {
rv = mLoadGroup->AddRequest(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
if (mLoadGroup)
mLoadGroup->AddRequest(this, nsnull);
PRBool offline;
// If we're starting from the beginning, then its OK to use the cache,
@ -361,7 +363,8 @@ nsFTPChannel::AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
rv = mCacheSession->AsyncOpenCacheEntry(cacheKey.get(),
accessRequested,
this);
if (NS_SUCCEEDED(rv)) return rv;
if (NS_SUCCEEDED(rv))
return rv;
// If we failed to use the cache, try without
PR_LOG(gFTPLog, PR_LOG_DEBUG,
@ -369,20 +372,29 @@ nsFTPChannel::AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
}
return SetupState(startPos, entityID);
// XXX this function must not fail since we have already called AddRequest!
}
nsresult
nsFTPChannel::SetupState(PRUint32 startPos, const nsACString& entityID)
{
nsCOMPtr<nsIPrompt> prompt;
nsCOMPtr<nsIAuthPrompt> authPrompt;
nsCOMPtr<nsIFTPEventSink> ftpEventSink;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, ftpEventSink);
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, prompt);
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, authPrompt);
if (!mFTPState) {
NS_NEWXPCOM(mFTPState, nsFtpState);
if (!mFTPState) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mFTPState);
}
nsresult rv = mFTPState->Init(this,
mPrompter,
mAuthPrompter,
mFTPEventSink,
prompt,
authPrompt,
ftpEventSink,
mCacheEntry,
mProxyInfo,
startPos,
@ -418,8 +430,6 @@ nsFTPChannel::SetLoadFlags(PRUint32 aLoadFlags)
NS_IMETHODIMP
nsFTPChannel::GetContentType(nsACString &aContentType)
{
nsAutoLock lock(mLock);
if (mContentType.IsEmpty()) {
aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
} else {
@ -433,7 +443,6 @@ nsFTPChannel::GetContentType(nsACString &aContentType)
NS_IMETHODIMP
nsFTPChannel::SetContentType(const nsACString &aContentType)
{
nsAutoLock lock(mLock);
NS_ParseContentType(aContentType, mContentType, mContentCharset);
return NS_OK;
}
@ -455,7 +464,6 @@ nsFTPChannel::SetContentCharset(const nsACString &aContentCharset)
NS_IMETHODIMP
nsFTPChannel::GetContentLength(PRInt32 *aContentLength)
{
nsAutoLock lock(mLock);
*aContentLength = mContentLength;
return NS_OK;
}
@ -463,7 +471,6 @@ nsFTPChannel::GetContentLength(PRInt32 *aContentLength)
NS_IMETHODIMP
nsFTPChannel::SetContentLength(PRInt32 aContentLength)
{
nsAutoLock lock(mLock);
mContentLength = aContentLength;
return NS_OK;
}
@ -509,61 +516,6 @@ NS_IMETHODIMP
nsFTPChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
if (mCallbacks) {
// nsIProgressEventSink
nsCOMPtr<nsIProgressEventSink> sink;
(void)mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink),
getter_AddRefs(sink));
if (sink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIProgressEventSink),
sink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mEventSink));
// nsIFTPEventSink
nsCOMPtr<nsIFTPEventSink> ftpSink;
(void)mCallbacks->GetInterface(NS_GET_IID(nsIFTPEventSink),
getter_AddRefs(ftpSink));
if (ftpSink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIFTPEventSink),
sink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mFTPEventSink));
// nsIPrompt
nsCOMPtr<nsIPrompt> prompt;
(void)mCallbacks->GetInterface(NS_GET_IID(nsIPrompt),
getter_AddRefs(prompt));
NS_ASSERTION ( prompt, "Channel doesn't have a prompt!!!" );
if (prompt)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIPrompt),
prompt,
PROXY_SYNC,
getter_AddRefs(mPrompter));
// nsIAuthPrompt
nsCOMPtr<nsIAuthPrompt> aPrompt;
(void)mCallbacks->GetInterface(NS_GET_IID(nsIAuthPrompt),
getter_AddRefs(aPrompt));
if (aPrompt)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIAuthPrompt),
aPrompt,
PROXY_SYNC,
getter_AddRefs(mAuthPrompter));
}
return NS_OK;
}
@ -576,15 +528,16 @@ nsFTPChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
// nsIInterfaceRequestor method
NS_IMETHODIMP
nsFTPChannel::GetInterface(const nsIID &anIID, void **aResult ) {
nsFTPChannel::GetInterface(const nsIID &aIID, void **aResult )
{
// capture the progress event sink stuff. pass the rest through.
if (anIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
*aResult = NS_STATIC_CAST(nsIProgressEventSink*, this);
NS_ADDREF(this);
return NS_OK;
} else {
return mCallbacks ? mCallbacks->GetInterface(anIID, aResult) : NS_ERROR_NO_INTERFACE;
}
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, aIID, aResult);
return aResult ? NS_OK : NS_ERROR_NO_INTERFACE;
}
// nsIProgressEventSink methods

Просмотреть файл

@ -117,9 +117,6 @@ protected:
// various callback interfaces
nsCOMPtr<nsIProgressEventSink> mEventSink;
nsCOMPtr<nsIPrompt> mPrompter;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;
nsCOMPtr<nsIAuthPrompt> mAuthPrompter;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRBool mIsPending;
@ -138,7 +135,6 @@ protected:
nsFtpState* mFTPState;
nsCString mHost;
PRLock* mLock;
nsCOMPtr<nsISupports> mUserContext;
nsresult mStatus;
PRPackedBool mCanceled;

Просмотреть файл

@ -84,8 +84,20 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
#endif /* PR_LOGGING */
#define LOG(args) PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
#define LOG_ALWAYS(args) PR_LOG(gFTPLog, PR_LOG_ALWAYS, args)
#else
#define LOG(args)
#define LOG_ALWAYS(args)
#endif
/**
* This object observes status from a control connection. For control
* connections, we don't worry about reporting transfer progress.
*
* The OnTransportStatus events are delivered to the main thread.
*/
class TransportEventForwarder : public nsITransportEventSink
{
public:
@ -93,6 +105,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSITRANSPORTEVENTSINK
private:
nsCOMPtr<nsIProgressEventSink> mSink;
};
@ -116,6 +129,9 @@ TransportEventForwarder::OnTransportStatus(nsITransport *transport, nsresult sta
}
/**
* This object observes events for a data connection.
*/
class DataRequestForwarder : public nsIFTPChannel,
public nsIStreamListener,
public nsIResumableChannel,
@ -123,7 +139,7 @@ class DataRequestForwarder : public nsIFTPChannel,
{
public:
DataRequestForwarder();
virtual ~DataRequestForwarder();
nsresult Init(nsIRequest *request);
nsresult SetStreamListener(nsIStreamListener *listener);
@ -179,21 +195,17 @@ NS_IMPL_THREADSAFE_ISUPPORTS7(DataRequestForwarder,
DataRequestForwarder::DataRequestForwarder()
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder CREATED\n", this));
LOG(("(%x) DataRequestForwarder CREATED\n", this));
mBytesTransfered = 0;
mBytesToUpload = 0;
mRetrying = mUploading = mDelayedOnStartFired = PR_FALSE;
}
DataRequestForwarder::~DataRequestForwarder()
{
}
nsresult
DataRequestForwarder::Init(nsIRequest *request)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder Init [request=%x]\n", this, request));
LOG(("(%x) DataRequestForwarder Init [request=%x]\n", this, request));
NS_ENSURE_ARG(request);
@ -248,7 +260,7 @@ DataRequestForwarder::SetCacheEntry(nsICacheEntryDescriptor *cacheEntry, PRBool
nsresult
DataRequestForwarder::SetStreamListener(nsIStreamListener *listener)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder SetStreamListener [listener=%x]\n", this, listener));
LOG(("(%x) DataRequestForwarder SetStreamListener [listener=%x]\n", this, listener));
mListener = listener;
if (!mListener)
@ -287,7 +299,7 @@ DataRequestForwarder::ResumeAt(PRUint64,
nsresult
DataRequestForwarder::DelayedOnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder DelayedOnStartRequest \n", this));
LOG(("(%x) DataRequestForwarder DelayedOnStartRequest \n", this));
return mListener->OnStartRequest(this, ctxt);
}
@ -297,7 +309,7 @@ DataRequestForwarder::SetRetrying(PRBool retry)
// The problem here is that if we send a second PASV, our listener would
// get an OnStop from the socket transport, and fail. So we temporarily
// suspend notifications
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder SetRetrying [retry=%d]\n", this, retry));
LOG(("(%x) DataRequestForwarder SetRetrying [retry=%d]\n", this, retry));
mRetrying = retry;
mDelayedOnStartFired = PR_FALSE;
@ -307,7 +319,7 @@ NS_IMETHODIMP
DataRequestForwarder::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
NS_ASSERTION(mListener, "No Listener Set.");
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder OnStartRequest \n[mRetrying=%d]", this, mRetrying));
LOG(("(%x) DataRequestForwarder OnStartRequest \n[mRetrying=%d]", this, mRetrying));
if (!mListener)
return NS_ERROR_NOT_INITIALIZED;
@ -319,7 +331,7 @@ DataRequestForwarder::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
NS_IMETHODIMP
DataRequestForwarder::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) DataRequestForwarder OnStopRequest [status=%x, mRetrying=%d]\n", this, statusCode, mRetrying));
LOG(("(%x) DataRequestForwarder OnStopRequest [status=%x, mRetrying=%d]\n", this, statusCode, mRetrying));
if (mRetrying) {
mRetrying = PR_FALSE;
@ -390,7 +402,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsFtpState,
nsFtpState::nsFtpState()
{
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpState created", this));
LOG_ALWAYS(("(%x) nsFtpState created", this));
// bool init
mRETRFailed = PR_FALSE;
mWaitingForDConn = mTryingCachedControl = mRetryPass = PR_FALSE;
@ -422,7 +435,7 @@ nsFtpState::nsFtpState()
nsFtpState::~nsFtpState()
{
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpState destroyed", this));
LOG_ALWAYS(("(%x) nsFtpState destroyed", this));
if (mIPv6ServerAddress) nsMemory::Free(mIPv6ServerAddress);
NS_IF_RELEASE(mDRequestForwarder);
@ -469,7 +482,7 @@ nsFtpState::OnDataAvailable(nsIRequest *request,
nsresult rv = aInStream->Read(buffer, aCount, &aCount);
if (NS_FAILED(rv))
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) nsFtpState - error reading %x\n", this, rv));
LOG(("(%x) nsFtpState - error reading %x\n", this, rv));
nsMemory::Free(buffer);
return NS_ERROR_FAILURE;
}
@ -478,7 +491,7 @@ nsFtpState::OnDataAvailable(nsIRequest *request,
nsXPIDLCString data;
data.Adopt(buffer);
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) reading %d bytes: \"%s\"", this, aCount, buffer));
LOG(("(%x) reading %d bytes: \"%s\"", this, aCount, buffer));
// Sometimes we can get two responses in the same packet, eg from LIST.
// So we need to parse the response line by line
@ -571,8 +584,7 @@ nsFtpState::OnStartRequest(nsIRequest *request, nsISupports *aContext)
nsCAutoString spec;
(void)mURL->GetAsciiSpec(spec);
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) nsFtpState::OnStartRequest() (spec =%s)\n",
this, spec.get()));
LOG(("(%x) nsFtpState::OnStartRequest() (spec =%s)\n", this, spec.get()));
#endif
return NS_OK;
}
@ -581,13 +593,13 @@ NS_IMETHODIMP
nsFtpState::OnStopRequest(nsIRequest *request, nsISupports *aContext,
nsresult aStatus)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) nsFtpState::OnStopRequest() rv=%x\n", this, aStatus));
LOG(("(%x) nsFtpState::OnStopRequest() rv=%x\n", this, aStatus));
mControlStatus = aStatus;
// HACK. This may not always work. I am assuming that I can mask the OnStopRequest
// notification since I created it via the control connection.
if (mTryingCachedControl && NS_FAILED(aStatus) && NS_SUCCEEDED(mInternalError)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) nsFtpState::OnStopRequest() cache connect failed. Reconnecting...\n", this, aStatus));
LOG(("(%x) nsFtpState::OnStopRequest() cache connect failed. Reconnecting...\n", this, aStatus));
mTryingCachedControl = PR_FALSE;
Connect();
return NS_OK;
@ -604,7 +616,7 @@ nsFtpState::EstablishControlConnection()
{
nsresult rv;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) trying cached control\n", this));
LOG(("(%x) trying cached control\n", this));
nsFtpControlConnection* connection;
(void) gFtpHandler->RemoveConnection(mURL, &connection);
@ -638,12 +650,12 @@ nsFtpState::EstablishControlConnection()
}
else
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) isAlive return false\n", this));
LOG(("(%x) isAlive return false\n", this));
NS_RELEASE(mControlConnection);
}
}
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) creating control\n", this));
LOG(("(%x) creating control\n", this));
mState = FTP_READ_BUF;
mNextState = FTP_S_USER;
@ -669,7 +681,7 @@ nsFtpState::MoveToNextState(FTP_STATE nextState)
if (NS_FAILED(mInternalError))
{
mState = FTP_ERROR;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) FAILED (%x)\n", this, mInternalError));
LOG(("(%x) FAILED (%x)\n", this, mInternalError));
}
else
{
@ -690,18 +702,18 @@ nsFtpState::Process()
{
case FTP_COMMAND_CONNECT:
KillControlConnection();
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) Establishing control connection...", this));
LOG(("(%x) Establishing control connection...", this));
mInternalError = EstablishControlConnection(); // sets mState
if (NS_FAILED(mInternalError)) {
mState = FTP_ERROR;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) FAILED\n", this));
LOG(("(%x) FAILED\n", this));
}
else
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) SUCCEEDED\n", this));
LOG(("(%x) SUCCEEDED\n", this));
break;
case FTP_READ_BUF:
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) Waiting for control data (%x)...", this, rv));
LOG(("(%x) Waiting for control data (%x)...", this, rv));
processingRead = PR_FALSE;
break;
@ -723,7 +735,7 @@ nsFtpState::Process()
// that the max number of users has been reached...
mState = FTP_COMMAND_CONNECT;
} else {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) FTP_ERROR - Calling StopProcessing\n", this));
LOG(("(%x) FTP_ERROR - Calling StopProcessing\n", this));
rv = StopProcessing();
NS_ASSERTION(NS_SUCCEEDED(rv), "StopProcessing failed.");
processingRead = PR_FALSE;
@ -731,7 +743,7 @@ nsFtpState::Process()
break;
case FTP_COMPLETE:
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) COMPLETE\n", this));
LOG(("(%x) COMPLETE\n", this));
rv = StopProcessing();
NS_ASSERTION(NS_SUCCEEDED(rv), "StopProcessing failed.");
processingRead = PR_FALSE;
@ -1509,7 +1521,7 @@ nsFtpState::R_list() {
if (mResponseCode/100 == 1) {
nsresult rv = mDPipeRequest->Resume();
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) dataPipe->Resume (rv=%x)\n", this, rv));
LOG(("(%x) dataPipe->Resume (rv=%x)\n", this, rv));
return FTP_ERROR;
}
return FTP_READ_BUF;
@ -1559,7 +1571,7 @@ nsFtpState::R_retr() {
}
nsresult rv = mDPipeRequest->Resume();
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) dataPipe->Resume (rv=%x)\n", this, rv));
LOG(("(%x) dataPipe->Resume (rv=%x)\n", this, rv));
return FTP_ERROR;
}
return FTP_READ_BUF;
@ -1647,7 +1659,7 @@ nsFtpState::R_stor() {
}
if (mResponseCode/100 == 1) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) writing on Data Transport\n", this));
LOG(("(%x) writing on Data Transport\n", this));
return FTP_READ_BUF;
}
@ -1663,8 +1675,7 @@ nsFtpState::S_pasv() {
// Find IPv6 socket address, if server is IPv6
mIPv6Checked = PR_TRUE;
PR_ASSERT(mIPv6ServerAddress == 0);
nsCOMPtr<nsITransport> controlSocket;
mControlConnection->GetTransport(getter_AddRefs(controlSocket));
nsITransport *controlSocket = mControlConnection->Transport();
if (!controlSocket) return FTP_ERROR;
nsCOMPtr<nsISocketTransport> sTrans = do_QueryInterface(controlSocket, &rv);
@ -1818,7 +1829,7 @@ nsFtpState::R_pasv() {
getter_AddRefs(mDPipe)); // the data socket
if (NS_FAILED(rv)) return FTP_ERROR;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) Created Data Transport (%s:%x)\n", this, hostStr, port));
LOG(("(%x) Created Data Transport (%s:%x)\n", this, hostStr, port));
if (!mDRequestForwarder) {
mDRequestForwarder = new DataRequestForwarder;
@ -1827,7 +1838,7 @@ nsFtpState::R_pasv() {
rv = mDRequestForwarder->Init(mChannel);
if (NS_FAILED(rv)){
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) forwarder->Init failed (rv=%x)\n", this, rv));
LOG(("(%x) forwarder->Init failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
}
@ -1838,12 +1849,12 @@ nsFtpState::R_pasv() {
nsCOMPtr<nsIEventQueue> eventQ;
rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
if (NS_FAILED(rv)){
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) NS_GetCurrentEventQ failed (rv=%x)\n", this, rv));
LOG(("(%x) NS_GetCurrentEventQ failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
rv = mDPipe->SetEventSink(NS_STATIC_CAST(nsITransportEventSink*, mDRequestForwarder), eventQ);
if (NS_FAILED(rv)){
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) forwarder->SetEventSink failed (rv=%x)\n", this, rv));
LOG(("(%x) forwarder->SetEventSink failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
@ -1896,7 +1907,7 @@ nsFtpState::R_pasv() {
FTP_DATA_CHANNEL_SEG_COUNT,
getter_AddRefs(input));
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) OpenInputStream failed (rv=%x)\n", this, rv));
LOG(("(%x) OpenInputStream failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
@ -1904,13 +1915,13 @@ nsFtpState::R_pasv() {
nsCOMPtr<nsIInputStreamPump> pump;
rv = NS_NewInputStreamPump(getter_AddRefs(pump), input, -1, -1, 0, 0, PR_TRUE);
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) NS_NewInputStreamPump failed (rv=%x)\n", this, rv));
LOG(("(%x) NS_NewInputStreamPump failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
rv = pump->AsyncRead(mDRequestForwarder, nsnull);
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) AsyncRead failed (rv=%x)\n", this, rv));
LOG(("(%x) AsyncRead failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
@ -1923,7 +1934,7 @@ nsFtpState::R_pasv() {
// onstop as if it was from the real data connection
rv = mDPipeRequest->Suspend();
if (NS_FAILED(rv)){
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) dataPipe->Suspend failed (rv=%x)\n", this, rv));
LOG(("(%x) dataPipe->Suspend failed (rv=%x)\n", this, rv));
return FTP_ERROR;
}
}
@ -1949,13 +1960,10 @@ nsFtpState::IsPending(PRBool *result)
nsresult rv = NS_OK;
*result = PR_FALSE;
nsCOMPtr<nsIRequest> request;
mControlConnection->GetReadRequest(getter_AddRefs(request));
if (request) {
nsIRequest *request = mControlConnection->ReadRequest();
if (request)
rv = request->IsPending(result);
if (NS_FAILED(rv)) return rv;
}
return rv;
}
@ -1970,7 +1978,7 @@ NS_IMETHODIMP
nsFtpState::Cancel(nsresult status)
{
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) nsFtpState::Cancel() rv=%x\n", this, status));
LOG(("(%x) nsFtpState::Cancel() rv=%x\n", this, status));
// we should try to recover the control connection....
if (NS_SUCCEEDED(mControlStatus))
@ -1997,18 +2005,14 @@ nsFtpState::Suspend(void)
mSuspendCount++;
// only worry about the read request.
nsCOMPtr<nsIRequest> request;
mControlConnection->GetReadRequest(getter_AddRefs(request));
nsIRequest *request = mControlConnection->ReadRequest();
if (request) {
rv = request->Suspend();
if (NS_FAILED(rv)) return rv;
}
if (mDPipeRequest) {
if (mDPipeRequest)
rv = mDPipeRequest->Suspend();
if (NS_FAILED(rv)) return rv;
}
}
return rv;
@ -2031,8 +2035,7 @@ nsFtpState::Resume(void)
if (mDPipe && dataAlive && mControlConnection->IsAlive())
{
nsCOMPtr<nsIRequest> controlRequest;
mControlConnection->GetReadRequest(getter_AddRefs(controlRequest));
nsIRequest *controlRequest = mControlConnection->ReadRequest();
NS_ASSERTION(controlRequest, "where did my request go!");
controlRequest->Resume();
@ -2159,21 +2162,18 @@ nsFtpState::Init(nsIFTPChannel* aChannel,
PRUint32 startPos,
const nsACString& entity)
{
nsresult rv = NS_OK;
// Build a proxy for the FTP event sink since we may need to call
// it while we are deep inside some of our state logic, and we
// wouldn't want to worry about some wierd re-entrancy scenario.
if (sink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIFTPEventSink),
sink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mFTPEventSink));
mKeepRunning = PR_TRUE;
mPrompter = aPrompter;
if (!mPrompter) {
nsCOMPtr<nsILoadGroup> ldGrp;
aChannel->GetLoadGroup(getter_AddRefs(ldGrp));
if (ldGrp) {
nsCOMPtr<nsIInterfaceRequestor> cbs;
rv = ldGrp->GetNotificationCallbacks(getter_AddRefs(cbs));
if (NS_SUCCEEDED(rv))
mPrompter = do_GetInterface(cbs);
}
}
mFTPEventSink = sink;
mAuthPrompter = aAuthPrompter;
mCacheEntry = cacheEntry;
mProxyInfo = proxyInfo;
@ -2185,8 +2185,9 @@ nsFtpState::Init(nsIFTPChannel* aChannel,
mChannel = aChannel; // a straight com ptr to the channel
rv = aChannel->GetURI(getter_AddRefs(mURL));
if (NS_FAILED(rv)) return rv;
nsresult rv = aChannel->GetURI(getter_AddRefs(mURL));
if (NS_FAILED(rv))
return rv;
if (mCacheEntry) {
if (CanReadEntry()) {
@ -2310,15 +2311,17 @@ nsFtpState::Connect()
// check for errors.
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("-- Connect() on Control Connect FAILED with rv = %x\n", rv));
LOG(("-- Connect() on Control Connect FAILED with rv = %x\n", rv));
mInternalError = NS_ERROR_FAILURE;
mState = FTP_ERROR;
}
return rv;
}
nsresult
nsFtpState::SetWriteStream(nsIInputStream* aInStream) {
nsFtpState::SetWriteStream(nsIInputStream* aInStream)
{
if (!aInStream)
return NS_OK;
@ -2329,7 +2332,8 @@ nsFtpState::SetWriteStream(nsIInputStream* aInStream) {
}
void
nsFtpState::KillControlConnection() {
nsFtpState::KillControlConnection()
{
mControlReadCarryOverBuf.Truncate(0);
NS_IF_RELEASE(mDRequestForwarder);
@ -2355,7 +2359,7 @@ nsFtpState::KillControlConnection() {
NS_SUCCEEDED(mControlStatus) &&
mControlConnection->IsAlive()) {
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpState caching control connection", this));
LOG_ALWAYS(("(%x) nsFtpState caching control connection", this));
// Store connection persistant data
mControlConnection->mServerType = mServerType;
@ -2374,8 +2378,9 @@ nsFtpState::KillControlConnection() {
}
nsresult
nsFtpState::StopProcessing() {
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpState stopping", this));
nsFtpState::StopProcessing()
{
LOG_ALWAYS(("(%x) nsFtpState stopping", this));
#ifdef DEBUG_dougt
printf("FTP Stopped: [response code %d] [response msg follows:]\n%s\n", mResponseCode, mResponseMsg.get());
@ -2464,7 +2469,7 @@ nsFtpState::BuildStreamConverter(nsIStreamListener** convertStreamListener)
mURL,
getter_AddRefs(converterListener));
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) scs->AsyncConvertData failed (rv=%x)\n", this, rv));
LOG(("(%x) scs->AsyncConvertData failed (rv=%x)\n", this, rv));
return rv;
}
@ -2475,7 +2480,7 @@ nsFtpState::BuildStreamConverter(nsIStreamListener** convertStreamListener)
void
nsFtpState::DataConnectionEstablished()
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) Data Connection established.", this));
LOG(("(%x) Data Connection established.", this));
mWaitingForDConn = PR_FALSE;
@ -2488,10 +2493,9 @@ nsFtpState::DataConnectionEstablished()
void
nsFtpState::DataConnectionComplete()
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) Data Connection complete.", this));
LOG(("(%x) Data Connection complete.", this));
if (mDPipe) {
mDPipe->SetSecurityCallbacks(nsnull);
mDPipe->SetEventSink(nsnull, nsnull);
mDPipe->Close(NS_ERROR_ABORT);
mDPipe = 0;
@ -2508,7 +2512,7 @@ nsFtpState::SendFTPCommand(nsCString& command)
if (StringBeginsWith(command, NS_LITERAL_CSTRING("PASS ")))
logcmd = "PASS xxxxx";
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x)(dwait=%d) Writing \"%s\"\n", this, mWaitingForDConn, logcmd.get()));
LOG(("(%x)(dwait=%d) Writing \"%s\"\n", this, mWaitingForDConn, logcmd.get()));
if (mFTPEventSink)
mFTPEventSink->OnFTPControlLog(PR_FALSE, logcmd.get());
@ -2532,8 +2536,8 @@ nsFtpState::ConvertFilespecToVMS(nsCString& fileString)
fileStringCopy = fileString;
t = nsCRT::strtok(fileStringCopy.BeginWriting(), "/", &nextToken);
if (t) while (nsCRT::strtok(nextToken, "/", &nextToken)) ntok++; // count number of terms (tokens)
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertFilespecToVMS ntok: %d\n", this, ntok));
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertFilespecToVMS from: \"%s\"\n", this, fileString.get()));
LOG(("(%x) ConvertFilespecToVMS ntok: %d\n", this, ntok));
LOG(("(%x) ConvertFilespecToVMS from: \"%s\"\n", this, fileString.get()));
if (fileString.First() == '/') {
// absolute filespec
@ -2601,7 +2605,7 @@ nsFtpState::ConvertFilespecToVMS(nsCString& fileString)
fileString.Append(nsCRT::strtok(nextToken, "/", &nextToken));
}
}
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertFilespecToVMS to: \"%s\"\n", this, fileString.get()));
LOG(("(%x) ConvertFilespecToVMS to: \"%s\"\n", this, fileString.get()));
}
// Convert a unix-style dirspec to VMS format
@ -2612,7 +2616,7 @@ nsFtpState::ConvertFilespecToVMS(nsCString& fileString)
void
nsFtpState::ConvertDirspecToVMS(nsCString& dirSpec)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertDirspecToVMS from: \"%s\"\n", this, dirSpec.get()));
LOG(("(%x) ConvertDirspecToVMS from: \"%s\"\n", this, dirSpec.get()));
if (!dirSpec.IsEmpty()) {
if (dirSpec.Last() != '/')
dirSpec.Append("/");
@ -2621,14 +2625,14 @@ nsFtpState::ConvertDirspecToVMS(nsCString& dirSpec)
ConvertFilespecToVMS(dirSpec);
dirSpec.Truncate(dirSpec.Length()-1);
}
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertDirspecToVMS to: \"%s\"\n", this, dirSpec.get()));
LOG(("(%x) ConvertDirspecToVMS to: \"%s\"\n", this, dirSpec.get()));
}
// Convert an absolute VMS style dirspec to UNIX format
void
nsFtpState::ConvertDirspecFromVMS(nsCString& dirSpec)
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertDirspecFromVMS from: \"%s\"\n", this, dirSpec.get()));
LOG(("(%x) ConvertDirspecFromVMS from: \"%s\"\n", this, dirSpec.get()));
if (dirSpec.IsEmpty()) {
dirSpec.Insert('.', 0);
}
@ -2638,5 +2642,5 @@ nsFtpState::ConvertDirspecFromVMS(nsCString& dirSpec)
dirSpec.ReplaceChar('.', '/');
dirSpec.ReplaceChar(']', '/');
}
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) ConvertDirspecFromVMS to: \"%s\"\n", this, dirSpec.get()));
LOG(("(%x) ConvertDirspecFromVMS to: \"%s\"\n", this, dirSpec.get()));
}

Просмотреть файл

@ -47,9 +47,16 @@
#include "nsEventQueueUtils.h"
#include "nsCRT.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
#endif /* PR_LOGGING */
#define LOG(args) PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
#define LOG_ALWAYS(args) PR_LOG(gFTPLog, PR_LOG_ALWAYS, args)
#else
#define LOG(args)
#define LOG_ALWAYS(args)
#endif
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
@ -61,25 +68,19 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsFtpControlConnection,
nsIStreamListener,
nsIRequestObserver)
nsFtpControlConnection::nsFtpControlConnection(const char* host,
PRUint32 port)
nsFtpControlConnection::nsFtpControlConnection(const char* host, PRUint32 port)
: mServerType(0), mPort(port)
{
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpControlConnection created", this));
LOG_ALWAYS(("(%x) nsFtpControlConnection created", this));
mHost.Adopt(nsCRT::strdup(host));
mLock = PR_NewLock();
NS_ASSERTION(mLock, "null lock");
mHost.Assign(host);
}
nsFtpControlConnection::~nsFtpControlConnection()
{
if (mLock) PR_DestroyLock(mLock);
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpControlConnection destroyed", this));
LOG_ALWAYS(("(%x) nsFtpControlConnection destroyed", this));
}
PRBool
nsFtpControlConnection::IsAlive()
{
@ -105,6 +106,7 @@ nsFtpControlConnection::Connect(nsIProxyInfo* proxyInfo,
getter_AddRefs(mCPipe)); // the command transport
if (NS_FAILED(rv)) return rv;
// proxy transport events back to current thread
if (eventSink) {
nsCOMPtr<nsIEventQueue> eventQ;
rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
@ -146,7 +148,7 @@ nsFtpControlConnection::Disconnect(nsresult status)
{
if (!mCPipe) return NS_ERROR_FAILURE;
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("(%x) nsFtpControlConnection disconnecting (%x)", this, status));
LOG_ALWAYS(("(%x) nsFtpControlConnection disconnecting (%x)", this, status));
if (NS_FAILED(status)) {
// break cyclic reference!
@ -182,66 +184,31 @@ nsFtpControlConnection::Write(nsCString& command, PRBool suspend)
return NS_OK;
}
nsresult
nsFtpControlConnection::GetTransport(nsITransport** controlTransport)
{
NS_IF_ADDREF(*controlTransport = mCPipe);
return NS_OK;
}
nsresult
nsFtpControlConnection::SetStreamListener(nsIStreamListener *aListener)
{
nsAutoLock lock(mLock);
mListener = aListener;
return NS_OK;
}
NS_IMETHODIMP
nsFtpControlConnection::OnStartRequest(nsIRequest *request, nsISupports *aContext)
{
if (!mCPipe)
return NS_OK;
// we do not care about notifications from the write channel.
// a non null context indicates that this is a write notification.
if (aContext != nsnull)
if (!mListener)
return NS_OK;
PR_Lock(mLock);
nsCOMPtr<nsIStreamListener> myListener = mListener;
PR_Unlock(mLock);
if (!myListener)
return NS_OK;
return myListener->OnStartRequest(request, aContext);
return mListener->OnStartRequest(request, aContext);
}
NS_IMETHODIMP
nsFtpControlConnection::OnStopRequest(nsIRequest *request, nsISupports *aContext,
nsresult aStatus)
{
if (!mCPipe)
return NS_OK;
// we do not care about successful notifications from the write channel.
// a non null context indicates that this is a write notification.
if (aContext != nsnull && NS_SUCCEEDED(aStatus))
return NS_OK;
PR_Lock(mLock);
nsCOMPtr<nsIStreamListener> myListener = mListener;
PR_Unlock(mLock);
if (!myListener)
if (!mListener)
return NS_OK;
return myListener->OnStopRequest(request, aContext, aStatus);
return mListener->OnStopRequest(request, aContext, aStatus);
}
NS_IMETHODIMP
nsFtpControlConnection::OnDataAvailable(nsIRequest *request,
nsISupports *aContext,
@ -252,14 +219,9 @@ nsFtpControlConnection::OnDataAvailable(nsIRequest *request,
if (!mCPipe)
return NS_OK;
PR_Lock(mLock);
nsCOMPtr<nsIStreamListener> myListener = mListener;
PR_Unlock(mLock);
if (!myListener)
if (!mListener)
return NS_OK;
return myListener->OnDataAvailable(request, aContext, aInStream,
return mListener->OnDataAvailable(request, aContext, aInStream,
aOffset, aCount);
}

Просмотреть файл

@ -53,7 +53,7 @@
class nsIProxyInfo;
class nsITransportEventSink;
class nsFtpControlConnection : public nsIStreamListener
class nsFtpControlConnection : public nsIStreamListener
{
public:
NS_DECL_ISUPPORTS
@ -61,18 +61,18 @@ public:
NS_DECL_NSIREQUESTOBSERVER
nsFtpControlConnection(const char* host, PRUint32 port);
virtual ~nsFtpControlConnection();
~nsFtpControlConnection();
nsresult Connect(nsIProxyInfo* proxyInfo, nsITransportEventSink* eventSink);
nsresult Disconnect(nsresult status);
nsresult Write(nsCString& command, PRBool suspend);
void GetReadRequest(nsIRequest** request) { NS_IF_ADDREF(*request=mReadRequest); }
PRBool IsAlive();
nsresult GetTransport(nsITransport** controlTransport);
nsresult SetStreamListener(nsIStreamListener *aListener);
PRBool IsAlive();
nsIRequest *ReadRequest() { return mReadRequest; }
nsITransport *Transport() { return mCPipe; }
void SetStreamListener(nsIStreamListener *l) { mListener = l; }
PRUint32 mServerType; // what kind of server is it.
nsString mPassword;
@ -80,12 +80,8 @@ public:
nsCString mPwd;
private:
PRLock* mLock; // protects mListener.
nsXPIDLCString mHost;
PRUint32 mPort;
nsCString mHost;
PRUint32 mPort;
nsCOMPtr<nsIRequest> mReadRequest;
nsCOMPtr<nsISocketTransport> mCPipe;
@ -93,5 +89,4 @@ private:
nsCOMPtr<nsIStreamListener> mListener;
};
#endif

Просмотреть файл

@ -260,6 +260,11 @@ nsGopherChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
PR_LOG(gGopherLog, PR_LOG_DEBUG, ("nsGopherChannel::AsyncOpen() called [this=%x]\n",
this));
// get callback interfaces...
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mPrompter);
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
nsresult rv;
PRInt32 port;
@ -295,7 +300,6 @@ nsGopherChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
if (eventQ)
mTransport->SetEventSink(this, eventQ);
}
mTransport->SetSecurityCallbacks(mCallbacks);
// open buffered, asynchronous socket input stream, and use a input stream
// pump to read from it.
@ -411,17 +415,15 @@ nsGopherChannel::GetContentType(nsACString &aContentType)
NS_IMETHODIMP
nsGopherChannel::SetContentType(const nsACString &aContentType)
{
if (mIsPending) {
// only changes mContentCharset if a charset is parsed
NS_ParseContentType(aContentType, mContentType, mContentCharset);
} else {
// We are being given a content-type hint. Since we have no ways of
// determining a charset on our own, just set mContentCharset from the
// charset part of this.
nsCAutoString charsetBuf;
NS_ParseContentType(aContentType, mContentTypeHint, mContentCharset);
}
// If AsyncOpen has been called, then treat this value as a content-type
// override. Otherwise, treat it as a content-type hint.
//
// In the case in which we are being given a content-type hint, we have no
// ways of determining a charset on our own, so just set mContentCharset
// from the charset part of this.
nsCString *contentType = mIsPending ? &mContentType : &mContentTypeHint;
NS_ParseContentType(aContentType, *contentType, mContentCharset);
return NS_OK;
}
@ -486,25 +488,16 @@ nsGopherChannel::SetOwner(nsISupports* aOwner)
}
NS_IMETHODIMP
nsGopherChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
nsGopherChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
{
*aNotificationCallbacks = mCallbacks.get();
NS_IF_ADDREF(*aNotificationCallbacks);
NS_IF_ADDREF(*aCallbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP
nsGopherChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
nsGopherChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
{
mCallbacks = aNotificationCallbacks;
if (mCallbacks) {
mPrompter = do_GetInterface(mCallbacks);
mProgressSink = do_GetInterface(mCallbacks);
}
else {
mPrompter = 0;
mProgressSink = 0;
}
mCallbacks = aCallbacks;
return NS_OK;
}
@ -594,16 +587,8 @@ nsGopherChannel::SendRequest()
// We require a query string here - if we don't have one,
// then we need to ask the user
if (!mPrompter) {
if (mLoadGroup) {
nsCOMPtr<nsIInterfaceRequestor> cbs;
rv = mLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
if (NS_SUCCEEDED(rv))
mPrompter = do_GetInterface(cbs);
}
if (!mPrompter) {
NS_ERROR("We need a prompter!");
return NS_ERROR_FAILURE;
}
NS_ERROR("We need a prompter!");
return NS_ERROR_FAILURE;
}
if (!mStringBundle) {

Просмотреть файл

@ -568,6 +568,13 @@ nsHttpChannel::SetupTransaction()
}
}
// create wrapper for this channel's notification callbacks
nsCOMPtr<nsIInterfaceRequestor> callbacks;
NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
getter_AddRefs(callbacks));
if (!callbacks)
return NS_ERROR_OUT_OF_MEMORY;
// create the transaction object
mTransaction = new nsHttpTransaction();
if (!mTransaction)
@ -577,7 +584,7 @@ nsHttpChannel::SetupTransaction()
nsCOMPtr<nsIAsyncInputStream> responseStream;
rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead,
mUploadStream, mUploadStreamHasHeaders,
mEventQ, mCallbacks, this,
mEventQ, callbacks, this,
getter_AddRefs(responseStream));
if (NS_FAILED(rv)) return rv;
@ -846,22 +853,6 @@ nsHttpChannel::ProcessNormal()
return rv;
}
void
nsHttpChannel::GetCallback(const nsIID &aIID, void **aResult)
{
NS_ASSERTION(aResult && !*aResult, "invalid argument in GetCallback");
if (mCallbacks)
mCallbacks->GetInterface(aIID, aResult);
if (!*aResult && mLoadGroup) {
nsCOMPtr<nsIInterfaceRequestor> cbs;
mLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
if (cbs)
cbs->GetInterface(aIID, aResult);
}
}
nsresult
nsHttpChannel::PromptTempRedirect()
{
@ -881,7 +872,7 @@ nsHttpChannel::PromptTempRedirect()
PRBool repost = PR_FALSE;
nsCOMPtr<nsIPrompt> prompt;
GetCallback(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt));
GetCallback(prompt);
if (!prompt)
return NS_ERROR_NO_INTERFACE;
@ -2476,17 +2467,18 @@ nsHttpChannel::PromptForIdentity(const char *scheme,
nsCOMPtr<nsIAuthPromptProvider> authPromptProvider;
nsCOMPtr<nsIAuthPrompt> authPrompt;
GetCallback(NS_GET_IID(nsIAuthPromptProvider), getter_AddRefs(authPromptProvider));
GetCallback(authPromptProvider);
if (authPromptProvider) {
PRUint32 promptReason;
if (proxyAuth)
promptReason = nsIAuthPromptProvider::PROMPT_PROXY;
else
promptReason = nsIAuthPromptProvider::PROMPT_NORMAL;
(void) authPromptProvider->GetAuthPrompt(promptReason, getter_AddRefs(authPrompt));
authPromptProvider->GetAuthPrompt(promptReason,
getter_AddRefs(authPrompt));
}
else
GetCallback(NS_GET_IID(nsIAuthPrompt), getter_AddRefs(authPrompt));
GetCallback(authPrompt);
if (!authPrompt)
return NS_ERROR_NO_INTERFACE;
@ -2622,7 +2614,7 @@ nsHttpChannel::ConfirmAuth(const nsString &bundleKey, PRBool doYesNoPrompt)
return PR_TRUE;
nsCOMPtr<nsIPrompt> prompt;
GetCallback(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt));
GetCallback(prompt);
if (!prompt)
return PR_TRUE;
@ -2962,18 +2954,13 @@ nsHttpChannel::SetOwner(nsISupports *owner)
NS_IMETHODIMP
nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor **callbacks)
{
NS_ENSURE_ARG_POINTER(callbacks);
*callbacks = mCallbacks;
NS_IF_ADDREF(*callbacks);
NS_IF_ADDREF(*callbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor *callbacks)
{
mCallbacks = callbacks;
mHttpEventSink = do_GetInterface(mCallbacks);
mProgressSink = do_GetInterface(mCallbacks);
return NS_OK;
}
@ -3089,6 +3076,10 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
nsresult rv;
// Initialize callback interfaces
GetCallback(mHttpEventSink);
GetCallback(mProgressSink);
// we want to grab a reference to the calling thread's event queue at
// this point. we will proxy all events back to the current thread via
// this event queue.
@ -3613,7 +3604,7 @@ nsHttpChannel::SetCookie(const char *aCookieHeader)
NS_ENSURE_TRUE(cs, NS_ERROR_FAILURE);
nsCOMPtr<nsIPrompt> prompt;
GetCallback(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt));
GetCallback(prompt);
return cs->SetCookieStringFromHttp(mURI,
mDocumentURI ? mDocumentURI : mOriginalURI,

Просмотреть файл

@ -117,6 +117,15 @@ public: /* internal; workaround lame compilers */
typedef void (nsHttpChannel:: *nsAsyncCallback)(void);
private:
// Helper function to simplify getting notification callbacks.
template <class T>
void GetCallback(nsCOMPtr<T> &aResult)
{
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(T),
getter_AddRefs(aResult));
}
//
// AsyncCall may be used to call a member function asynchronously.
//
@ -138,7 +147,6 @@ private:
nsresult ProcessNotModified();
nsresult ProcessRedirection(PRUint32 httpStatus);
nsresult ProcessAuthentication(PRUint32 httpStatus);
void GetCallback(const nsIID &aIID, void **aResult);
PRBool ResponseWouldVary();
// redirection specific methods

Просмотреть файл

@ -78,6 +78,7 @@
#include "nsIFormSubmitObserver.h"
#include "nsISecurityWarningDialogs.h"
#include "nsIProxyObjectManager.h"
#include "nsNetUtil.h"
#include "nsCRT.h"
#define SECURITY_STRING_BUNDLE_URL "chrome://communicator/locale/security.properties"
@ -912,13 +913,7 @@ nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
void nsSecureBrowserUIImpl::ObtainEventSink(nsIChannel *channel)
{
if (!mToplevelEventSink)
{
nsCOMPtr<nsIInterfaceRequestor> requestor;
channel->GetNotificationCallbacks(getter_AddRefs(requestor));
if (requestor)
mToplevelEventSink = do_GetInterface(requestor);
}
NS_QueryNotificationCallbacks(channel, mToplevelEventSink);
}
nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest)

Просмотреть файл

@ -52,9 +52,7 @@
#include "nsIPrefService.h"
#include "nsIPrompt.h"
#include "nsEventQueueUtils.h"
#include "nsIChannel.h"
#include "nsNetCID.h"
#include "netCore.h"
#include "nsNetUtil.h"
// used to dispatch urls to default protocol handlers
#include "nsCExternalHandlerService.h"
@ -90,6 +88,7 @@ private:
nsresult mStatus;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsILoadGroup> mLoadGroup;
};
NS_IMPL_THREADSAFE_ADDREF(nsExtProtocolChannel)
@ -110,26 +109,25 @@ nsExtProtocolChannel::~nsExtProtocolChannel()
NS_IMETHODIMP nsExtProtocolChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
{
*aLoadGroup = nsnull;
return NS_OK;
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
NS_IMETHODIMP nsExtProtocolChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
{
NS_PRECONDITION(aNotificationCallbacks, "No out param?");
*aNotificationCallbacks = mCallbacks;
NS_IF_ADDREF(*aNotificationCallbacks);
NS_IF_ADDREF(*aCallbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
NS_IMETHODIMP nsExtProtocolChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
{
mCallbacks = aNotificationCallbacks;
mCallbacks = aCallbacks;
return NS_OK;
}
@ -182,11 +180,7 @@ nsresult nsExtProtocolChannel::OpenURL()
// get an nsIPrompt from the channel if we can
nsCOMPtr<nsIPrompt> prompt;
if (mCallbacks)
{
mCallbacks->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt));
}
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, prompt);
return extProtService->LoadURI(mUrl, prompt);
}
return NS_ERROR_FAILURE;

Просмотреть файл

@ -60,6 +60,7 @@ CPPSRCS = \
nsID.cpp \
nsMemoryImpl.cpp \
nsTraceRefcntImpl.cpp \
nsInterfaceRequestorAgg.cpp \
$(NULL)
ifdef GC_LEAK_DETECTOR
@ -78,6 +79,7 @@ EXPORTS = \
nsISupportsObsolete.h \
nsTraceRefcntImpl.h \
nsWeakPtr.h \
nsInterfaceRequestorAgg.h \
$(NULL)
ifeq ($(OS_ARCH),WINNT)

Просмотреть файл

@ -0,0 +1,78 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by IBM Corporation are Copyright (C) 2004
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsInterfaceRequestorAgg.h"
#include "nsCOMPtr.h"
class nsInterfaceRequestorAgg : public nsIInterfaceRequestor
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
nsInterfaceRequestorAgg(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond)
: mFirst(aFirst)
, mSecond(aSecond) {}
nsCOMPtr<nsIInterfaceRequestor> mFirst, mSecond;
};
// XXX This needs to support threadsafe refcounting until we fix bug 243591.
NS_IMPL_THREADSAFE_ISUPPORTS1(nsInterfaceRequestorAgg, nsIInterfaceRequestor)
NS_IMETHODIMP
nsInterfaceRequestorAgg::GetInterface(const nsIID &aIID, void **aResult)
{
nsresult rv = NS_ERROR_NO_INTERFACE;
if (mFirst)
rv = mFirst->GetInterface(aIID, aResult);
if (mSecond && NS_FAILED(rv))
rv = mSecond->GetInterface(aIID, aResult);
return rv;
}
nsresult
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond,
nsIInterfaceRequestor **aResult)
{
*aResult = new nsInterfaceRequestorAgg(aFirst, aSecond);
if (!aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,54 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by IBM Corporation are Copyright (C) 2004
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsInterfaceRequestorAgg_h__
#define nsInterfaceRequestorAgg_h__
#include "nsIInterfaceRequestor.h"
/**
* This function returns an instance of nsIInterfaceRequestor that aggregates
* two nsIInterfaceRequestor instances. It's GetInterface method queries
* aFirst for the requested interface and will query aSecond only if aFirst
* failed to supply the requested interface. Both aFirst and aSecond may
* be null.
*/
extern NS_COM nsresult
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond,
nsIInterfaceRequestor **aResult);
#endif // !defined( nsInterfaceRequestorAgg_h__ )

Просмотреть файл

@ -90,6 +90,7 @@
#include "nsStreamUtils.h"
#include "nsNativeCharsetUtils.h"
#include "nsComponentManagerObsolete.h"
#include "nsInterfaceRequestorAgg.h"
void XXXNeverCalled()
{
@ -193,4 +194,5 @@ void XXXNeverCalled()
nsServiceManager::GetGlobalServiceManager(nsnull);
}
NS_NewInterfaceRequestorAggregation(nsnull, nsnull, nsnull);
}

Просмотреть файл

@ -2353,12 +2353,8 @@ nsBookmarksService::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
schedule,
nsCaseInsensitiveStringComparator()))
{
nsCOMPtr<nsIInterfaceRequestor> interfaces;
nsCOMPtr<nsIPrompt> prompter;
channel->GetNotificationCallbacks(getter_AddRefs(interfaces));
if (interfaces)
interfaces->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompter));
NS_QueryNotificationCallbacks(channel, prompter);
if (!prompter)
{
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));