fixes bug 293350 "Allow dynamic changes to notification callbacks" r=biesi sr=bzbarsky

This commit is contained in:
darin%meer.net 2005-09-10 00:20:02 +00:00
Родитель d5a752d6a5
Коммит 7c7704b82f
13 изменённых файлов: 164 добавлений и 126 удалений

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

@ -189,9 +189,6 @@ nsDateTimeChannel::Open(nsIInputStream **_retval)
NS_IMETHODIMP
nsDateTimeChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
nsresult rv = NS_CheckPortSafety(mPort, "datetime");
if (NS_FAILED(rv)) return rv;
@ -327,6 +324,7 @@ NS_IMETHODIMP
nsDateTimeChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
@ -357,6 +355,7 @@ NS_IMETHODIMP
nsDateTimeChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
mProgressSink = nsnull;
return NS_OK;
}
@ -419,6 +418,9 @@ NS_IMETHODIMP
nsDateTimeChannel::OnTransportStatus(nsITransport *trans, nsresult status,
PRUint64 progress, PRUint64 progressMax)
{
if (!mProgressSink)
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
// suppress status notification if channel is no longer pending!
if (mProgressSink && NS_SUCCEEDED(mStatus) && mPump && !(mLoadFlags & LOAD_BACKGROUND)) {
NS_ConvertUTF8toUTF16 host(mHost);

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

@ -208,9 +208,6 @@ nsFingerChannel::Open(nsIInputStream **_retval)
NS_IMETHODIMP
nsFingerChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
nsresult rv = NS_CheckPortSafety(mPort, "finger");
if (NS_FAILED(rv)) return rv;
@ -349,6 +346,7 @@ NS_IMETHODIMP
nsFingerChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
@ -379,6 +377,7 @@ NS_IMETHODIMP
nsFingerChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
mProgressSink = nsnull;
return NS_OK;
}
@ -441,6 +440,9 @@ NS_IMETHODIMP
nsFingerChannel::OnTransportStatus(nsITransport *trans, nsresult status,
PRUint64 progress, PRUint64 progressMax)
{
if (!mProgressSink)
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
// suppress status notification if channel is no longer pending!
if (mProgressSink && NS_SUCCEEDED(mStatus) && mPump && !(mLoadFlags & LOAD_BACKGROUND)) {
mProgressSink->OnStatus(this, nsnull, status,

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

@ -90,19 +90,20 @@ interface nsIChannel : nsIRequest
* The notification callbacks for the channel. This is set by clients, who
* wish to provide a means to receive progress, status and protocol-specific
* notifications. If this value is NULL, the channel implementation may use
* the notification callbacks from its load group.
* the notification callbacks from its load group. The channel may also
* query the notification callbacks from its load group if its notification
* callbacks do not supply the requested interface.
*
* 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.
*
* When the channel is done, it must not continue holding references to
* this object.
*
* NOTE: A channel implementation should take care when "caching" an
* interface pointer queried from its notification callbacks. If the
* notification callbacks are changed, then a cached interface pointer may
* become invalid and may therefore need to be re-queried.
*/
attribute nsIInterfaceRequestor notificationCallbacks;
@ -169,7 +170,9 @@ interface nsIChannel : nsIRequest
/**
* Asynchronously open this channel. Data is fed to the specified stream
* listener as it becomes available.
* listener as it becomes available. The stream listener's methods are
* called on the thread that calls asyncOpen and are not called until
* after asyncOpen returns.
*
* @param aListener the nsIStreamListener implementation
* @param aContext an opaque parameter forwarded to aListener's methods

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

@ -163,6 +163,7 @@ NS_IMETHODIMP
nsInputStreamChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
@ -217,6 +218,7 @@ NS_IMETHODIMP
nsInputStreamChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = nsnull;
return NS_OK;
}
@ -294,9 +296,6 @@ 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
@ -392,6 +391,9 @@ nsInputStreamChannel::OnDataAvailable(nsIRequest *req, nsISupports *ctx,
rv = mListener->OnDataAvailable(this, mListenerContext, stream, offset, count);
if (!mProgressSink)
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
// XXX need real 64-bit math here! (probably needs new streamlistener and
// channel ifaces)
if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND))

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

@ -214,6 +214,7 @@ NS_IMETHODIMP
nsFileChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
@ -271,6 +272,7 @@ NS_IMETHODIMP
nsFileChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = nsnull;
return NS_OK;
}
@ -371,9 +373,6 @@ 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;
@ -579,6 +578,9 @@ NS_IMETHODIMP
nsFileChannel::OnTransportStatus(nsITransport *trans, nsresult status,
PRUint64 progress, PRUint64 progressMax)
{
if (!mProgressSink)
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
// suppress status notification if channel is no longer pending!
if (mProgressSink && NS_SUCCEEDED(mStatus) && mRequest && !(mLoadFlags & LOAD_BACKGROUND)) {
// file channel does not send OnStatus events!

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

@ -304,20 +304,6 @@ 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;
@ -365,26 +351,47 @@ nsFTPChannel::AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
// XXX this function must not fail since we have already called AddRequest!
}
void
nsFTPChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
{
if (!mFTPEventSink) {
nsCOMPtr<nsIFTPEventSink> ftpSink;
GetCallback(ftpSink);
if (ftpSink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIFTPEventSink),
ftpSink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mFTPEventSink));
}
aResult = mFTPEventSink;
}
void
nsFTPChannel::InitProgressSink()
{
// 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> progressSink;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, progressSink);
if (progressSink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIProgressEventSink),
progressSink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mProgressSink));
}
nsresult
nsFTPChannel::SetupState(PRUint64 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,
prompt,
authPrompt,
ftpEventSink,
nsresult rv = mFTPState->Init(this,
mCacheEntry,
mProxyInfo,
startPos,
@ -478,6 +485,8 @@ NS_IMETHODIMP
nsFTPChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
mFTPEventSink = nsnull;
return NS_OK;
}
@ -507,6 +516,8 @@ NS_IMETHODIMP
nsFTPChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
mProgressSink = nsnull;
mFTPEventSink = nsnull;
return NS_OK;
}
@ -519,7 +530,7 @@ nsFTPChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
// nsIInterfaceRequestor method
NS_IMETHODIMP
nsFTPChannel::GetInterface(const nsIID &aIID, void **aResult )
nsFTPChannel::GetInterface(const nsIID &aIID, void **aResult)
{
// capture the progress event sink stuff. pass the rest through.
if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
@ -536,6 +547,9 @@ NS_IMETHODIMP
nsFTPChannel::OnStatus(nsIRequest *request, nsISupports *aContext,
nsresult aStatus, const PRUnichar* aStatusArg)
{
if (!mProgressSink)
InitProgressSink();
if (aStatus == NS_NET_STATUS_CONNECTED_TO)
{
// The state machine needs to know that the data connection
@ -547,24 +561,27 @@ nsFTPChannel::OnStatus(nsIRequest *request, nsISupports *aContext,
NS_ERROR("ftp state is null.");
}
if (!mEventSink || (mLoadFlags & LOAD_BACKGROUND) || !mIsPending || NS_FAILED(mStatus))
if (!mProgressSink || (mLoadFlags & LOAD_BACKGROUND) || !mIsPending || NS_FAILED(mStatus))
return NS_OK;
nsCAutoString host;
mURL->GetHost(host);
return mEventSink->OnStatus(this, mUserContext, aStatus,
NS_ConvertUTF8toUTF16(host).get());
return mProgressSink->OnStatus(this, mUserContext, aStatus,
NS_ConvertUTF8toUTF16(host).get());
}
NS_IMETHODIMP
nsFTPChannel::OnProgress(nsIRequest *request, nsISupports* aContext,
PRUint64 aProgress, PRUint64 aProgressMax)
{
if (!mEventSink || (mLoadFlags & LOAD_BACKGROUND) || !mIsPending)
if (!mProgressSink)
InitProgressSink();
if (!mProgressSink || (mLoadFlags & LOAD_BACKGROUND) || !mIsPending)
return NS_OK;
return mEventSink->OnProgress(this, mUserContext,
aProgress, aProgressMax);
return mProgressSink->OnProgress(this, mUserContext,
aProgress, aProgressMax);
}
@ -612,8 +629,9 @@ nsFTPChannel::OnStopRequest(nsIRequest *request, nsISupports* aContext,
mIsPending = PR_FALSE;
// Drop notification callbacks to prevent cycles.
mCallbacks = 0;
mEventSink = 0;
mCallbacks = nsnull;
mProgressSink = nsnull;
mFTPEventSink = nsnull;
return rv;
}

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

@ -111,6 +111,18 @@ public:
nsresult AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
PRUint64 startPos, const nsACString& entityID);
// Helper function to simplify getting notification callbacks.
template <class T>
void GetCallback(nsCOMPtr<T> &aResult) {
GetInterface(NS_GET_IID(T), getter_AddRefs(aResult));
}
// Helper function for getting the nsIFTPEventSink.
void GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult);
protected:
void InitProgressSink();
protected:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURL;
@ -118,7 +130,8 @@ protected:
nsCOMPtr<nsIInputStream> mUploadStream;
// various callback interfaces
nsCOMPtr<nsIProgressEventSink> mEventSink;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRBool mIsPending;

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

@ -564,8 +564,10 @@ nsFtpState::OnDataAvailable(nsIRequest *request,
mState = mNextState;
}
if (mFTPEventSink)
mFTPEventSink->OnFTPControlLog(PR_TRUE, mResponseMsg.get());
nsCOMPtr<nsIFTPEventSink> ftpSink;
mChannel->GetFTPEventSink(ftpSink);
if (ftpSink)
ftpSink->OnFTPControlLog(PR_TRUE, mResponseMsg.get());
rv = Process();
mResponseMsg.Truncate();
@ -1026,7 +1028,11 @@ nsFtpState::S_user() {
usernameStr.AppendLiteral("anonymous");
} else {
if (mUsername.IsEmpty()) {
if (!mAuthPrompter) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIAuthPrompt> prompter;
mChannel->GetCallback(prompter);
if (!prompter)
return NS_ERROR_NOT_INITIALIZED;
nsXPIDLString user, passwd;
PRBool retval;
nsCAutoString prePath;
@ -1046,13 +1052,13 @@ nsFtpState::S_user() {
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordFor").get(),
formatStrings, 1,
getter_Copies(formatedString));
rv = mAuthPrompter->PromptUsernameAndPassword(nsnull,
formatedString,
prePathU.get(),
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(user),
getter_Copies(passwd),
&retval);
rv = prompter->PromptUsernameAndPassword(nsnull,
formatedString,
prePathU.get(),
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(user),
getter_Copies(passwd),
&retval);
// if the user canceled or didn't supply a username we want to fail
if (!retval || (user && !*user) )
@ -1125,7 +1131,10 @@ nsFtpState::S_pass() {
}
} else {
if (mPassword.IsEmpty() || mRetryPass) {
if (!mAuthPrompter) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIAuthPrompt> prompter;
mChannel->GetCallback(prompter);
if (!prompter)
return NS_ERROR_NOT_INITIALIZED;
nsXPIDLString passwd;
PRBool retval;
@ -1148,11 +1157,11 @@ nsFtpState::S_pass() {
getter_Copies(formatedString));
if (NS_FAILED(rv)) return rv;
rv = mAuthPrompter->PromptPassword(nsnull,
formatedString,
prePathU.get(),
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(passwd), &retval);
rv = prompter->PromptPassword(nsnull,
formatedString,
prePathU.get(),
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(passwd), &retval);
// we want to fail if the user canceled. Note here that if they want
// a blank password, we will pass it along.
@ -1297,9 +1306,11 @@ nsFtpState::R_syst() {
nsMemory::Free(ucs2Response);
if (NS_FAILED(rv)) return FTP_ERROR;
NS_ASSERTION(mPrompter, "no prompter!");
if (mPrompter)
(void) mPrompter->Alert(nsnull, formatedString.get());
// XXX(darin): this code should not be dictating UI like this!
nsCOMPtr<nsIPrompt> prompter;
mChannel->GetCallback(prompter);
if (prompter)
prompter->Alert(nsnull, formatedString.get());
// since we just alerted the user, clear mResponseMsg,
// which is displayed to the user.
@ -2164,27 +2175,12 @@ nsFtpState::CanReadEntry()
nsresult
nsFtpState::Init(nsFTPChannel* aChannel,
nsIPrompt* aPrompter,
nsIAuthPrompt* aAuthPrompter,
nsIFTPEventSink* sink,
nsICacheEntryDescriptor* cacheEntry,
nsIProxyInfo* proxyInfo,
PRUint64 startPos,
const nsACString& entity)
{
// 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;
mAuthPrompter = aAuthPrompter;
mCacheEntry = cacheEntry;
mProxyInfo = proxyInfo;
mStartPos = startPos;
@ -2396,14 +2392,16 @@ nsFtpState::StopProcessing()
printf("FTP Stopped: [response code %d] [response msg follows:]\n%s\n", mResponseCode, mResponseMsg.get());
#endif
if ( NS_FAILED(mInternalError) && !mResponseMsg.IsEmpty())
if (NS_FAILED(mInternalError) && !mResponseMsg.IsEmpty())
{
// check to see if the control status is bad.
// web shell wont throw an alert. we better:
NS_ASSERTION(mPrompter, "no prompter!");
if (mPrompter)
(void) mPrompter->Alert(nsnull, NS_ConvertASCIItoUCS2(mResponseMsg).get());
// XXX(darin): this code should not be dictating UI like this!
nsCOMPtr<nsIPrompt> prompter;
mChannel->GetCallback(prompter);
if (prompter)
prompter->Alert(nsnull, NS_ConvertASCIItoUCS2(mResponseMsg).get());
}
nsresult broadcastErrorCode = mControlStatus;
@ -2445,8 +2443,6 @@ nsFtpState::StopProcessing()
// Release the Observers
mWriteStream = 0; // should this call close before setting to null?
mPrompter = 0;
mAuthPrompter = 0;
mChannel = 0;
mProxyInfo = 0;
@ -2519,8 +2515,11 @@ nsFtpState::SendFTPCommand(nsCString& command)
logcmd = "PASS xxxxx";
LOG(("(%x)(dwait=%d) Writing \"%s\"\n", this, mWaitingForDConn, logcmd.get()));
if (mFTPEventSink)
mFTPEventSink->OnFTPControlLog(PR_FALSE, logcmd.get());
nsCOMPtr<nsIFTPEventSink> ftpSink;
mChannel->GetFTPEventSink(ftpSink);
if (ftpSink)
ftpSink->OnFTPControlLog(PR_FALSE, logcmd.get());
if (mControlConnection) {
return mControlConnection->Write(command, mWaitingForDConn);

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

@ -119,9 +119,6 @@ public:
virtual ~nsFtpState();
nsresult Init(nsFTPChannel *aChannel,
nsIPrompt *aPrompter,
nsIAuthPrompt *aAuthPrompter,
nsIFTPEventSink *sink,
nsICacheEntryDescriptor* cacheEntry,
nsIProxyInfo* proxyInfo,
PRUint64 startPos,
@ -229,9 +226,6 @@ private:
nsCOMPtr<nsIInputStream> mWriteStream; // This stream is written to the server.
PRUint32 mWriteCount;
PRPackedBool mIPv6Checked;
nsCOMPtr<nsIPrompt> mPrompter;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;
nsCOMPtr<nsIAuthPrompt> mAuthPrompter;
static PRUint32 mSessionStartTime;

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

@ -262,9 +262,6 @@ nsGopherChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
// get callback interfaces...
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mPrompter);
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
nsresult rv;
PRInt32 port;
@ -470,6 +467,7 @@ NS_IMETHODIMP
nsGopherChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
@ -499,6 +497,7 @@ NS_IMETHODIMP
nsGopherChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = nsnull;
return NS_OK;
}
@ -550,7 +549,6 @@ nsGopherChannel::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
// Drop notification callbacks to prevent cycles.
mCallbacks = 0;
mPrompter = 0;
mProgressSink = 0;
return NS_OK;
@ -593,7 +591,9 @@ nsGopherChannel::SendRequest()
if (pos == -1) {
// We require a query string here - if we don't have one,
// then we need to ask the user
if (!mPrompter) {
nsCOMPtr<nsIPrompt> prompter;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, prompter);
if (!prompter) {
NS_ERROR("We need a prompter!");
return NS_ERROR_FAILURE;
}
@ -630,7 +630,7 @@ nsGopherChannel::SendRequest()
nsXPIDLString search;
PRBool res;
mPrompter->Prompt(promptTitle.get(),
prompter->Prompt(promptTitle.get(),
promptText.get(),
getter_Copies(search),
NULL,
@ -727,6 +727,9 @@ NS_IMETHODIMP
nsGopherChannel::OnTransportStatus(nsITransport *trans, nsresult status,
PRUint64 progress, PRUint64 progressMax)
{
if (!mProgressSink)
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
// suppress status notification if channel is no longer pending!
if (mProgressSink && NS_SUCCEEDED(mStatus) && mPump && !(mLoadFlags & LOAD_BACKGROUND)) {
NS_ConvertUTF8toUTF16 host(mHost);

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

@ -81,7 +81,6 @@ public:
protected:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIPrompt> mPrompter;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIStreamListener> mListener;

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

@ -2059,19 +2059,23 @@ nsHttpChannel::ProcessRedirection(PRUint32 redirectType)
if (NS_FAILED(rv)) return rv;
// call out to the event sink to notify it of this redirection.
if (mHttpEventSink) {
// Note: mHttpEventSink is only kept for compatibility with pre-1.8
nsCOMPtr<nsIHttpEventSink> httpEventSink;
GetCallback(httpEventSink);
if (httpEventSink) {
// NOTE: nsIHttpEventSink is only used for compatibility with pre-1.8
// versions.
rv = mHttpEventSink->OnRedirect(this, newChannel);
rv = httpEventSink->OnRedirect(this, newChannel);
if (NS_FAILED(rv)) return rv;
}
if (mChannelEventSink) {
nsCOMPtr<nsIChannelEventSink> channelEventSink;
GetCallback(channelEventSink);
if (channelEventSink) {
PRUint32 flags;
if (redirectType == 301) // Moved Permanently
flags = nsIChannelEventSink::REDIRECT_PERMANENT;
else
flags = nsIChannelEventSink::REDIRECT_TEMPORARY;
rv = mChannelEventSink->OnChannelRedirect(this, newChannel, flags);
rv = channelEventSink->OnChannelRedirect(this, newChannel, flags);
if (NS_FAILED(rv)) return rv;
}
// XXX we used to talk directly with the script security manager, but that
@ -3100,6 +3104,7 @@ NS_IMETHODIMP
nsHttpChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
@ -3176,6 +3181,7 @@ NS_IMETHODIMP
nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor *callbacks)
{
mCallbacks = callbacks;
mProgressSink = nsnull;
return NS_OK;
}
@ -3294,11 +3300,6 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
nsresult rv;
// Initialize callback interfaces
GetCallback(mHttpEventSink);
GetCallback(mChannelEventSink);
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.
@ -4093,8 +4094,6 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
mLoadGroup->RemoveRequest(this, nsnull, status);
mCallbacks = nsnull;
mHttpEventSink = nsnull;
mChannelEventSink = nsnull;
mProgressSink = nsnull;
mEventQ = nsnull;
@ -4177,6 +4176,10 @@ NS_IMETHODIMP
nsHttpChannel::OnTransportStatus(nsITransport *trans, nsresult status,
PRUint64 progress, PRUint64 progressMax)
{
// cache the progress sink so we don't have to query for it each time.
if (!mProgressSink)
GetCallback(mProgressSink);
// block socket status event after Cancel or OnStopRequest has been called.
if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending && !(mLoadFlags & LOAD_BACKGROUND)) {
LOG(("sending status notification [this=%x status=%x progress=%llu/%llu]\n",

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

@ -218,8 +218,6 @@ private:
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIHttpEventSink> mHttpEventSink;
nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
nsCOMPtr<nsIInputStream> mUploadStream;
nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsISupports> mSecurityInfo;