From e3a990319e4db7f2233f3aa704078973cf8ff3f6 Mon Sep 17 00:00:00 2001 From: "edburns%acm.org" Date: Wed, 20 Sep 2000 09:27:54 +0000 Subject: [PATCH] a=beard, waterson r=av bug=52963 Tested on win32. Tested to build on win32 and solaris. This patch fixes bug 52963, bug 52965, and bug 52973. This patch contributed by Stanley Ho 52963: nsIPluginStreamListener::OnStartBinding isn't always called: Added new ivar, mStartBinding: * Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has * been called. Checked in ::OnStopRequest so we can call the * plugin's OnStartBinding if, for some reason, it has not already * been called. 52965: Length isn't always set: rv = channel->GetContentLength(&length); // it's possible for the server to not send a Content-Length. We should // still work in this case. if (NS_FAILED(rv)) { mPluginStreamInfo->SetLength(-1); } else { mPluginStreamInfo->SetLength(length); } 52973: nsIHTTPHeaderListener called before nsIPluginStreamListener::NewStream This fix required rolling back Andrei Volkov's change to the signature of nsPluginStreamListenerPeer::SetUpStreamListener(). In order to call the plugin with the headers before the NewStream is sent, we need the nsIChannel. files in this fix: M modules/plugin/nglsrc/nsPluginHostImpl.cpp --- modules/plugin/base/src/nsPluginHostImpl.cpp | 97 ++++++++++++++------ modules/plugin/nglsrc/nsPluginHostImpl.cpp | 97 ++++++++++++++------ 2 files changed, 134 insertions(+), 60 deletions(-) diff --git a/modules/plugin/base/src/nsPluginHostImpl.cpp b/modules/plugin/base/src/nsPluginHostImpl.cpp index 05d4e19acf2..105b17f5fe9 100644 --- a/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -859,7 +859,7 @@ public: private: nsresult SetUpCache(nsIURI* aURL); - nsresult SetUpStreamListener(nsIURI* aURL); + nsresult SetUpStreamListener(nsIChannel *channel, nsIURI* aURL); nsIURI *mURL; nsIPluginInstanceOwner *mOwner; @@ -867,7 +867,18 @@ private: nsIPluginStreamListener *mPStreamListener; nsPluginStreamInfo *mPluginStreamInfo; - PRBool mSetUpListener; + PRBool mSetUpListener; + + /* + + * Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has + * been called. Checked in ::OnStopRequest so we can call the + * plugin's OnStartBinding if, for some reason, it has not already + * been called. + + */ + + PRBool mStartBinding; // these get passed to the plugin stream listener char *mMIMEType; @@ -960,6 +971,7 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer() mSetUpListener = PR_FALSE; mHost = nsnull; mStreamType = nsPluginStreamType_Normal; + mStartBinding = PR_FALSE; } nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() @@ -1162,10 +1174,18 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIChannel* channel, nsISupports* aCo PRInt32 length; rv = channel->GetContentLength(&length); - if (NS_FAILED(rv)) return rv; - mPluginStreamInfo->SetLength(length); - rv = SetUpStreamListener(aURL); + // it's possible for the server to not send a Content-Length. We should + // still work in this case. + if (NS_FAILED(rv)) { + mPluginStreamInfo->SetLength(-1); + } + else { + mPluginStreamInfo->SetLength(length); + } + + + rv = SetUpStreamListener(channel, aURL); if (NS_FAILED(rv)) return rv; return rv; @@ -1208,24 +1228,6 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIChannel* channel, mPluginStreamInfo->SetURL(urlString); nsCRT::free(urlString); - /* - - * Assumption - - * By the time nsPluginStreamListenerPeer::OnDataAvailable() gets - * called, all the headers have been read. - - */ - - nsCOMPtr headerListener = - do_QueryInterface(mPStreamListener); - if (headerListener) { - nsCOMPtr httpChannel = do_QueryInterface(channel); - if (httpChannel) { - ReadHeadersFromChannelAndPostToListener(httpChannel, headerListener); - } - } - // if the plugin has requested an AsFileOnly stream, then don't // call OnDataAvailable if(mStreamType != nsPluginStreamType_AsFileOnly) @@ -1282,7 +1284,17 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIChannel* channel, nsCRT::free(urlString); } - mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + if (mStartBinding) + { + // On start binding has been called + mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + } + else + { + // OnStartBinding hasn't been called, so complete the action. + mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo); + mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + } } return rv; @@ -1298,7 +1310,8 @@ nsresult nsPluginStreamListenerPeer::SetUpCache(nsIURI* aURL) return NS_OpenURI(cacheListener, nsnull, aURL, nsnull); } -nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIURI* aURL) +nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIChannel* channel, + nsIURI* aURL) { nsresult rv = NS_OK; @@ -1316,6 +1329,26 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIURI* aURL) if(mPStreamListener == nsnull) return NS_ERROR_NULL_POINTER; + + /* + + * Assumption + + * By the time nsPluginStreamListenerPeer::OnDataAvailable() gets + * called, all the headers have been read. + + */ + + nsCOMPtr headerListener = + do_QueryInterface(mPStreamListener); + if (headerListener) { + nsCOMPtr httpChannel = do_QueryInterface(channel); + if (httpChannel) { + ReadHeadersFromChannelAndPostToListener(httpChannel, headerListener); + } + } + + mSetUpListener = PR_TRUE; mPluginStreamInfo->SetSeekable(PR_FALSE); //mPluginStreamInfo->SetModified(??); @@ -1327,6 +1360,8 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIURI* aURL) rv = mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo); + mStartBinding = PR_TRUE; + if(rv == NS_OK) { mPStreamListener->GetStreamType(&mStreamType); @@ -3343,8 +3378,6 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, channel->SetOwner(principal); } - rv = channel->AsyncRead(listenerPeer, nsnull); - // deal with headers and post data nsCOMPtr httpChannel(do_QueryInterface(channel)); if(httpChannel) @@ -3380,16 +3413,20 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, httpChannel->SetRequestMethod(method); httpChannel->SetUploadStream(postDataStream); } + if (aHeadersData) { rv = AddHeadersToChannel(aHeadersData, aHeadersDataLen, httpChannel); - } + } + } - } + + rv = channel->AsyncRead(listenerPeer, nsnull); + } + NS_RELEASE(listenerPeer); } - return rv; } diff --git a/modules/plugin/nglsrc/nsPluginHostImpl.cpp b/modules/plugin/nglsrc/nsPluginHostImpl.cpp index 05d4e19acf2..105b17f5fe9 100644 --- a/modules/plugin/nglsrc/nsPluginHostImpl.cpp +++ b/modules/plugin/nglsrc/nsPluginHostImpl.cpp @@ -859,7 +859,7 @@ public: private: nsresult SetUpCache(nsIURI* aURL); - nsresult SetUpStreamListener(nsIURI* aURL); + nsresult SetUpStreamListener(nsIChannel *channel, nsIURI* aURL); nsIURI *mURL; nsIPluginInstanceOwner *mOwner; @@ -867,7 +867,18 @@ private: nsIPluginStreamListener *mPStreamListener; nsPluginStreamInfo *mPluginStreamInfo; - PRBool mSetUpListener; + PRBool mSetUpListener; + + /* + + * Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has + * been called. Checked in ::OnStopRequest so we can call the + * plugin's OnStartBinding if, for some reason, it has not already + * been called. + + */ + + PRBool mStartBinding; // these get passed to the plugin stream listener char *mMIMEType; @@ -960,6 +971,7 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer() mSetUpListener = PR_FALSE; mHost = nsnull; mStreamType = nsPluginStreamType_Normal; + mStartBinding = PR_FALSE; } nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() @@ -1162,10 +1174,18 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIChannel* channel, nsISupports* aCo PRInt32 length; rv = channel->GetContentLength(&length); - if (NS_FAILED(rv)) return rv; - mPluginStreamInfo->SetLength(length); - rv = SetUpStreamListener(aURL); + // it's possible for the server to not send a Content-Length. We should + // still work in this case. + if (NS_FAILED(rv)) { + mPluginStreamInfo->SetLength(-1); + } + else { + mPluginStreamInfo->SetLength(length); + } + + + rv = SetUpStreamListener(channel, aURL); if (NS_FAILED(rv)) return rv; return rv; @@ -1208,24 +1228,6 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIChannel* channel, mPluginStreamInfo->SetURL(urlString); nsCRT::free(urlString); - /* - - * Assumption - - * By the time nsPluginStreamListenerPeer::OnDataAvailable() gets - * called, all the headers have been read. - - */ - - nsCOMPtr headerListener = - do_QueryInterface(mPStreamListener); - if (headerListener) { - nsCOMPtr httpChannel = do_QueryInterface(channel); - if (httpChannel) { - ReadHeadersFromChannelAndPostToListener(httpChannel, headerListener); - } - } - // if the plugin has requested an AsFileOnly stream, then don't // call OnDataAvailable if(mStreamType != nsPluginStreamType_AsFileOnly) @@ -1282,7 +1284,17 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIChannel* channel, nsCRT::free(urlString); } - mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + if (mStartBinding) + { + // On start binding has been called + mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + } + else + { + // OnStartBinding hasn't been called, so complete the action. + mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo); + mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + } } return rv; @@ -1298,7 +1310,8 @@ nsresult nsPluginStreamListenerPeer::SetUpCache(nsIURI* aURL) return NS_OpenURI(cacheListener, nsnull, aURL, nsnull); } -nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIURI* aURL) +nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIChannel* channel, + nsIURI* aURL) { nsresult rv = NS_OK; @@ -1316,6 +1329,26 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIURI* aURL) if(mPStreamListener == nsnull) return NS_ERROR_NULL_POINTER; + + /* + + * Assumption + + * By the time nsPluginStreamListenerPeer::OnDataAvailable() gets + * called, all the headers have been read. + + */ + + nsCOMPtr headerListener = + do_QueryInterface(mPStreamListener); + if (headerListener) { + nsCOMPtr httpChannel = do_QueryInterface(channel); + if (httpChannel) { + ReadHeadersFromChannelAndPostToListener(httpChannel, headerListener); + } + } + + mSetUpListener = PR_TRUE; mPluginStreamInfo->SetSeekable(PR_FALSE); //mPluginStreamInfo->SetModified(??); @@ -1327,6 +1360,8 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIURI* aURL) rv = mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo); + mStartBinding = PR_TRUE; + if(rv == NS_OK) { mPStreamListener->GetStreamType(&mStreamType); @@ -3343,8 +3378,6 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, channel->SetOwner(principal); } - rv = channel->AsyncRead(listenerPeer, nsnull); - // deal with headers and post data nsCOMPtr httpChannel(do_QueryInterface(channel)); if(httpChannel) @@ -3380,16 +3413,20 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, httpChannel->SetRequestMethod(method); httpChannel->SetUploadStream(postDataStream); } + if (aHeadersData) { rv = AddHeadersToChannel(aHeadersData, aHeadersDataLen, httpChannel); - } + } + } - } + + rv = channel->AsyncRead(listenerPeer, nsnull); + } + NS_RELEASE(listenerPeer); } - return rv; }