fix 165094, Compressed PDF doesn't render in Acrobat Plugin, r=peterl, sr=darin

This commit is contained in:
serge%netscape.com 2002-09-12 19:12:56 +00:00
parent 0261bf1849
commit 0f8e1c47d0
2 changed files with 97 additions and 109 deletions

View File

@ -345,13 +345,11 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
// prepare NPP_ calls params
NPP npp;
mInst->GetNPP(&npp);
pluginInfo->GetURL(&mNPStream.url);
pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified));
PRInt32 streamOffset;
pluginInfo->GetStreamOffset(&streamOffset);
mPosition = streamOffset;
streamOffset += length;
streamOffset += length;
// Set new stream offset for the next ODA call
// regardless of how following NPP_Write call will behave
// we pretend to consume all data from the input stream.
@ -362,6 +360,12 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
// should be temporarily stopped if NPP_WriteReady returns 0 (bug #89270)
pluginInfo->SetStreamOffset(streamOffset);
// set new end in case the content is compressed
// initial end is less than end of decompressed stream
// and some plugins (e.g. acrobat) can fail.
if ((PRInt32)mNPStream.end < streamOffset)
mNPStream.end = streamOffset;
PRUint32 bytesToRead = mStreamBufferSize;
if (length < mStreamBufferSize) {
// do not read more that supplier wants us to read
@ -467,7 +471,7 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
} // end of for(;;)
} while ((PRInt32)(length) > 0);
return rv;
return rv == NS_BASE_STREAM_WOULD_BLOCK ? NS_OK:rv;
}
///////////////////////////////////////////////////////////////////////////////
@ -478,19 +482,13 @@ ns4xPluginStreamListener::OnFileAvailable(nsIPluginStreamInfo* pluginInfo,
if(!mInst || !mInst->IsStarted())
return NS_ERROR_FAILURE;
NPP npp;
const NPPluginFuncs *callbacks = nsnull;
mInst->GetCallbacks(&callbacks);
mInst->GetNPP(&npp);
if(!callbacks)
if(!callbacks && !callbacks->asfile)
return NS_ERROR_FAILURE;
pluginInfo->GetURL(&mNPStream.url);
if (callbacks->asfile == NULL)
return NS_OK;
NPP npp;
mInst->GetNPP(&npp);
PRLibrary* lib = nsnull;
lib = mInst->fLibrary;
@ -516,11 +514,6 @@ ns4xPluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo,
if(!mInst || !mInst->IsStarted())
return NS_ERROR_FAILURE;
if(pluginInfo) {
pluginInfo->GetURL(&mNPStream.url);
pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified));
}
// check if the stream is of seekable type and later its destruction
// see bug 91140
nsresult rv = NS_OK;

View File

@ -1266,7 +1266,10 @@ public:
MakeByteRangeString(nsByteRange* aRangeList, nsACString &string, PRInt32 *numRequests);
PRBool
UseExistingPluginCacheFile(nsPluginStreamInfo* psi, nsIFile* file);
UseExistingPluginCacheFile(nsPluginStreamInfo* psi);
void
SetStreamComplete(const PRBool complete);
private:
@ -1278,6 +1281,7 @@ private:
nsIPluginInstance * mPluginInstance;
nsPluginStreamListenerPeer * mPluginStreamListenerPeer;
PRInt32 mStreamOffset;
PRBool mStreamComplete;
};
@ -1327,7 +1331,6 @@ private:
nsIPluginInstance *mInstance;
nsIPluginStreamListener *mPStreamListener;
nsPluginStreamInfo *mPluginStreamInfo;
PRPackedBool mSetUpListener;
// Set to PR_TRUE if we request failed (like with a HTTP response of 404)
PRPackedBool mRequestFailed;
@ -1394,6 +1397,7 @@ nsPluginStreamInfo::nsPluginStreamInfo()
mLength = 0;
mModified = 0;
mStreamOffset = 0;
mStreamComplete = PR_FALSE;
}
@ -1764,7 +1768,6 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
mInstance = nsnull;
mPStreamListener = nsnull;
mPluginStreamInfo = nsnull;
mSetUpListener = PR_FALSE;
mHost = nsnull;
mStreamType = nsPluginStreamType_Normal;
mStartBinding = PR_FALSE;
@ -1990,7 +1993,7 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
if (lp->mLocalCachedFile &&
lp->mPluginStreamInfo &&
(useExistingCacheFile =
lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo,lp->mLocalCachedFile)))
lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo)))
{
NS_ADDREF(mLocalCachedFile = lp->mLocalCachedFile);
}
@ -2198,7 +2201,7 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo
// it's possible for the server to not send a Content-Length. We should
// still work in this case.
if (NS_FAILED(rv)) {
if (NS_FAILED(rv) || length == -1) {
mPluginStreamInfo->SetLength(PRUint32(0));
}
else {
@ -2463,6 +2466,9 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
if (NS_SUCCEEDED(aStatus))
mPluginStreamInfo->SetStreamComplete(PR_TRUE);
return NS_OK;
}
@ -2497,6 +2503,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
if(mPStreamListener == nsnull)
return NS_ERROR_NULL_POINTER;
PRBool useLocalCache = PR_FALSE;
// get httpChannel to retrieve some info we need for nsIPluginStreamInfo setup
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
@ -2507,44 +2514,52 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
* By the time nsPluginStreamListenerPeer::OnDataAvailable() gets
* called, all the headers have been read.
*/
if (httpChannel)
if (httpChannel) {
httpChannel->VisitResponseHeaders(this);
mSetUpListener = PR_TRUE;
// set seekability (seekable if the stream has a known length and if the
// http server accepts byte ranges).
PRBool bSeekable = PR_FALSE;
PRUint32 length = PRUint32(-1);
mPluginStreamInfo->GetLength(&length);
if ((length != PRUint32(-1)) && httpChannel)
{
nsCAutoString range;
if(NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("accept-ranges"), range)))
{
if (range.Equals(NS_LITERAL_CSTRING("bytes"), nsCaseInsensitiveCStringComparator()))
bSeekable = PR_TRUE;
// set seekability (seekable if the stream has a known length and if the
// http server accepts byte ranges).
PRBool bSeekable = PR_FALSE;
PRUint32 length;
mPluginStreamInfo->GetLength(&length);
if (length) {
// first we look for a content-encoding header. If we find one,
// we tell the plugin that stream is not seekable,
// because range request on compressed content is irrelevant,
// so we force the plugin to use nsPluginStreamType_AsFile stream type
// and we have to save decompressed file into local plugin cache,
// because necko cache contains original compressed file.
nsCAutoString contentEncoding;
if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
contentEncoding))) {
useLocalCache = PR_TRUE;
} else {
nsCAutoString range;
if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("accept-ranges"), range)) &&
range.Equals(NS_LITERAL_CSTRING("bytes"), nsCaseInsensitiveCStringComparator())) {
bSeekable = PR_TRUE;
// nsPluginStreamInfo.mSeekable intitialized by PR_FALSE in ctor of nsPluginStreamInfo
// so we reset it only here.
mPluginStreamInfo->SetSeekable(bSeekable);
}
}
// we require a content len
// get Last-Modified header for plugin info
nsCAutoString lastModified;
if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("last-modified"), lastModified)) &&
!lastModified.IsEmpty())
{
PRTime time64;
PR_ParseTimeString(lastModified.get(), PR_TRUE, &time64); //convert string time to interger time
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
double fpTime;
LL_L2D(fpTime, time64);
mPluginStreamInfo->SetLastModified((PRUint32)(fpTime * 1e-6 + 0.5));
}
}
}
mPluginStreamInfo->SetSeekable(bSeekable);
// we require a content len
// get Last-Modified header for plugin info
if (httpChannel)
{
nsCAutoString lastModified;
if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("last-modified"), lastModified)) &&
!lastModified.IsEmpty())
{
PRTime time64;
PR_ParseTimeString(lastModified.get(), PR_TRUE, &time64); //convert string time to interger time
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
double fpTime;
LL_L2D(fpTime, time64);
mPluginStreamInfo->SetLastModified((PRUint32)(fpTime * 1e-6 + 0.5));
}
}
rv = mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo);
@ -2554,39 +2569,23 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
return rv;
mPStreamListener->GetStreamType(&mStreamType);
// now lets figure out if we have to save the file into plugin local cache
PRBool useLocalCache = PR_FALSE;
if (httpChannel) {
// Now we look for a content-encoding header. If we find one,
// we have to use the local cache, it'll have decoded copy of file
nsCAutoString contentEncoding;
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
contentEncoding);
if (NS_SUCCEEDED(rv) &&
!contentEncoding.Equals("identity",nsCaseInsensitiveCStringComparator())) {
useLocalCache = PR_TRUE;
} else if (mStreamType >= nsPluginStreamType_AsFile) {
// if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly
// check out if browser's cache is avalable
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(httpChannel);
if (cacheChannel && NS_FAILED(cacheChannel->SetCacheAsFile(PR_TRUE))) {
useLocalCache = PR_TRUE; // we'll use local cache
if (!useLocalCache && mStreamType >= nsPluginStreamType_AsFile) {
// check it out if this is not a file channel.
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request);
if (!fileChannel) {
// and browser cache is not available
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
if (!(cacheChannel && (NS_SUCCEEDED(cacheChannel->SetCacheAsFile(PR_TRUE))))) {
useLocalCache = PR_TRUE;
}
#if !defined(CACHE_SUPPOPTS_FILE_EXTENSION)
// until bug 90558 got fixed
// and necko cache starts to support file extension
// we'll force to copy the file+ext into local plugin cache
// becase several plugins (e.g. acrobat, quick time) do not work w/o file extension
useLocalCache = PR_TRUE;
#endif
}
if (useLocalCache) {
SetupPluginCacheFile(httpChannel);
}
}
if (useLocalCache) {
SetupPluginCacheFile(channel);
}
return NS_OK;
}
@ -6501,18 +6500,18 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
mPluginStreamInfo->SetSeekable(0);
mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo);
mPluginStreamInfo->SetStreamOffset(0);
// force the plugin use stream as file
mStreamType = nsPluginStreamType_AsFile;
#if !defined(CACHE_SUPPOPTS_FILE_EXTENSION)
// close & tear down existing cached stream
mFileCacheOutputStream = nsnull;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
if (httpChannel) {
SetupPluginCacheFile(channel);
// then check it out if browser cache is not available
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
if (!(cacheChannel && (NS_SUCCEEDED(cacheChannel->SetCacheAsFile(PR_TRUE))))) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (channel) {
SetupPluginCacheFile(channel);
}
}
#endif
// unset mPendingRequests
mPendingRequests = 0;
@ -6627,27 +6626,23 @@ nsPluginByteRangeStreamListener::OnDataAvailable(nsIRequest *request, nsISupport
}
PRBool
nsPluginStreamInfo::UseExistingPluginCacheFile(nsPluginStreamInfo* psi, nsIFile* file)
nsPluginStreamInfo::UseExistingPluginCacheFile(nsPluginStreamInfo* psi)
{
NS_ENSURE_ARG_POINTER(psi);
if ( psi->mLength == mLength &&
psi->mModified == mModified &&
mStreamComplete &&
!PL_strcmp(psi->mURL, mURL))
{
if (psi->mLength != (PRUint32) mStreamOffset) { //lets check a file size
PRInt64 size;
if (NS_FAILED(file->GetFileSize(&size)))
return PR_FALSE;
PRUint32 fs = nsInt64(size);
if (psi->mLength != fs) {
return PR_FALSE;
}
}
return PR_TRUE;
}
return PR_FALSE;
}
void
nsPluginStreamInfo::SetStreamComplete(PRBool complete)
{
mStreamComplete = complete;
}