Merge backout of bug 548217 because of topcrash bug 549112

This commit is contained in:
Benjamin Smedberg 2010-02-27 17:40:03 -05:00
Родитель cb4d2d7494 e2c7ae2b80
Коммит f057b7256f
5 изменённых файлов: 329 добавлений и 137 удалений

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

@ -63,13 +63,6 @@ interface nsIPluginInstanceOwner : nsISupports
*/
void getInstance(in nsIPluginInstanceRef aInstance);
%{C++
// make getter_AddRefs work
inline nsresult GetInstance(nsIPluginInstance** aInstance) {
return GetInstance(*aInstance);
}
%}
/**
* Get a handle to the window structure of the owner.
* This pointer cannot be made persistent by the caller.

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

@ -2379,13 +2379,8 @@ _requestread(NPStream *pstream, NPByteRange *rangeList)
if (streamtype != NP_SEEK)
return NPERR_STREAM_NOT_SEEKABLE;
if (!streamlistener->mStreamInfo)
return NPERR_GENERIC_ERROR;
nsresult rv = streamlistener->mStreamInfo
->RequestRead((NPByteRange *)rangeList);
if (NS_FAILED(rv))
return NPERR_GENERIC_ERROR;
if (streamlistener->mStreamInfo)
streamlistener->mStreamInfo->RequestRead((NPByteRange *)rangeList);
return NS_OK;
}

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

@ -256,20 +256,9 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason)
if (mStreamCleanedUp)
return NS_OK;
mStreamCleanedUp = PR_TRUE;
StopDataPump();
// Seekable streams have an extra addref when they are created which must
// be matched here.
if (NP_SEEK == mStreamType)
NS_RELEASE_THIS();
if (!mInst || !mInst->IsRunning())
return rv;
mStreamInfo = NULL;
PluginDestructionGuard guard(mInst);
const NPPluginFuncs *callbacks = nsnull;
@ -296,7 +285,10 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason)
rv = NS_OK;
}
mStreamStarted = PR_FALSE;
mStreamCleanedUp = PR_TRUE;
mStreamStarted = PR_FALSE;
StopDataPump();
// fire notification back to plugin, just like before
CallURLNotify(reason);
@ -393,12 +385,6 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
break;
case NP_SEEK:
mStreamType = NP_SEEK;
// Seekable streams should continue to exist even after OnStopRequest
// is fired, so we AddRef ourself an extra time and Release when the
// plugin calls NPN_DestroyStream (CleanUpStream). If the plugin never
// calls NPN_DestroyStream the stream will be destroyed before the plugin
// instance is destroyed.
NS_ADDREF_THIS();
break;
default:
return NS_ERROR_FAILURE;
@ -808,13 +794,19 @@ nsNPAPIPluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo,
// check if the stream is of seekable type and later its destruction
// see bug 91140
nsresult rv = NS_OK;
NPReason reason = NS_FAILED(status) ? NPRES_NETWORK_ERR : NPRES_DONE;
if (mStreamType != NP_SEEK ||
(NP_SEEK == mStreamType && NS_BINDING_ABORTED == status)) {
if (mStreamType != NP_SEEK) {
NPReason reason = NPRES_DONE;
if (NS_FAILED(status))
reason = NPRES_NETWORK_ERR; // since the stream failed, we need to tell the plugin that
rv = CleanUpStream(reason);
}
return rv;
if (rv != NPERR_NO_ERROR)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
@ -1019,7 +1011,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Stop()
// clean up open streams
for (nsInstanceStream *is = mStreams; is != nsnull;) {
nsRefPtr<nsNPAPIPluginStreamListener> listener = is->mPluginStreamListener;
nsNPAPIPluginStreamListener * listener = is->mPluginStreamListener;
nsInstanceStream *next = is->mNext;
delete is;

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

@ -138,7 +138,7 @@
#include "nsPluginManifestLineReader.h"
#include "nsDefaultPlugin.h"
#include "nsIWeakReferenceUtils.h"
#include "nsWeakReference.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLObjectElement.h"
#include "nsIDOMHTMLEmbedElement.h"
@ -345,11 +345,97 @@ nsresult nsPluginHost::PostPluginUnloadEvent(PRLibrary* aLibrary)
return NS_ERROR_FAILURE;
}
class nsPluginStreamListenerPeer;
class nsPluginStreamInfo : public nsINPAPIPluginStreamInfo
{
public:
nsPluginStreamInfo();
virtual ~nsPluginStreamInfo();
NS_DECL_ISUPPORTS
// nsINPAPIPluginStreamInfo interface
NS_IMETHOD
GetContentType(char **result);
NS_IMETHOD
IsSeekable(PRBool* result);
NS_IMETHOD
GetLength(PRUint32* result);
NS_IMETHOD
GetLastModified(PRUint32* result);
NS_IMETHOD
GetURL(const char** result);
NS_IMETHOD
RequestRead(NPByteRange* rangeList);
NS_IMETHOD
GetStreamOffset(PRInt32 *result);
NS_IMETHOD
SetStreamOffset(PRInt32 result);
// local methods
void
SetContentType(const char* contentType);
void
SetSeekable(const PRBool seekable);
void
SetLength(const PRUint32 length);
void
SetLastModified(const PRUint32 modified);
void
SetURL(const char* url);
void
SetPluginInstance(nsIPluginInstance * aPluginInstance);
void
SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer);
void
MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, PRInt32 *numRequests);
PRBool
UseExistingPluginCacheFile(nsPluginStreamInfo* psi);
void
SetStreamComplete(const PRBool complete);
void
SetRequest(nsIRequest *request)
{
mRequest = request;
}
private:
char* mContentType;
char* mURL;
PRBool mSeekable;
PRUint32 mLength;
PRUint32 mModified;
nsIPluginInstance * mPluginInstance;
nsPluginStreamListenerPeer * mPluginStreamListenerPeer;
PRInt32 mStreamOffset;
PRBool mStreamComplete;
};
class nsPluginStreamListenerPeer : public nsIStreamListener,
public nsIProgressEventSink,
public nsIHttpHeaderVisitor,
public nsSupportsWeakReference,
public nsINPAPIPluginStreamInfo
public nsSupportsWeakReference
{
public:
nsPluginStreamListenerPeer();
@ -361,15 +447,6 @@ public:
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIHTTPHEADERVISITOR
// nsINPAPIPluginStreamInfo interface
NS_DECL_NSIPLUGINSTREAMINFO
// Called by RequestRead
void
MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, PRInt32 *numRequests);
PRBool UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi);
// Called by GetURL and PostURL (via NewStream)
nsresult Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
@ -392,11 +469,11 @@ private:
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
nsresult SetupPluginCacheFile(nsIChannel* channel);
nsCOMPtr<nsIURI> mURL;
nsCString mURLSpec; // Have to keep this member because GetURL hands out char*
nsCOMPtr<nsIPluginInstanceOwner> mOwner;
nsCOMPtr<nsIPluginInstance> mInstance;
nsCOMPtr<nsIPluginStreamListener> mPStreamListener;
nsIURI *mURL;
nsIPluginInstanceOwner *mOwner;
nsIPluginInstance *mInstance;
nsIPluginStreamListener *mPStreamListener;
nsRefPtr<nsPluginStreamInfo> mPluginStreamInfo;
// Set to PR_TRUE if we request failed (like with a HTTP response of 404)
PRPackedBool mRequestFailed;
@ -410,22 +487,16 @@ private:
PRPackedBool mStartBinding;
PRPackedBool mHaveFiredOnStartRequest;
// these get passed to the plugin stream listener
char *mMIMEType;
PRUint32 mLength;
PRInt32 mStreamType;
// local cached file, we save the content into local cache if browser cache is not available,
// or plugin asks stream as file and it expects file extension until bug 90558 got fixed
nsCOMPtr<nsIFile> mLocalCachedFile;
nsIFile *mLocalCachedFile;
nsCOMPtr<nsIOutputStream> mFileCacheOutputStream;
nsHashtable *mDataForwardToRequest;
nsCString mContentType;
PRBool mSeekable;
PRUint32 mModified;
nsCOMPtr<nsIPluginInstance> mPluginInstance;
PRInt32 mStreamOffset;
PRBool mStreamComplete;
public:
PRBool mAbort;
PRInt32 mPendingRequests;
@ -448,44 +519,70 @@ private:
PRBool mRemoveMagicNumber;
};
NS_IMETHODIMP
nsPluginStreamListenerPeer::GetContentType(char** result)
nsPluginStreamInfo::nsPluginStreamInfo()
{
*result = const_cast<char*>(mContentType.get());
mPluginInstance = nsnull;
mPluginStreamListenerPeer = nsnull;
mContentType = nsnull;
mURL = nsnull;
mSeekable = PR_FALSE;
mLength = 0;
mModified = 0;
mStreamOffset = 0;
mStreamComplete = PR_FALSE;
}
nsPluginStreamInfo::~nsPluginStreamInfo()
{
if (mContentType)
PL_strfree(mContentType);
if (mURL)
PL_strfree(mURL);
NS_IF_RELEASE(mPluginInstance);
}
NS_IMPL_ISUPPORTS2(nsPluginStreamInfo, nsIPluginStreamInfo,
nsINPAPIPluginStreamInfo)
NS_IMETHODIMP
nsPluginStreamInfo::GetContentType(char **result)
{
*result = mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::IsSeekable(PRBool* result)
nsPluginStreamInfo::IsSeekable(PRBool* result)
{
*result = mSeekable;
return NS_OK;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::GetLength(PRUint32* result)
nsPluginStreamInfo::GetLength(PRUint32* result)
{
*result = mLength;
return NS_OK;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::GetLastModified(PRUint32* result)
nsPluginStreamInfo::GetLastModified(PRUint32* result)
{
*result = mModified;
return NS_OK;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::GetURL(const char** result)
nsPluginStreamInfo::GetURL(const char** result)
{
*result = mURLSpec.get();
*result = mURL;
return NS_OK;
}
void
nsPluginStreamListenerPeer::MakeByteRangeString(NPByteRange* aRangeList, nsACString &rangeRequest,
PRInt32 *numRequests)
nsPluginStreamInfo::MakeByteRangeString(NPByteRange* aRangeList, nsACString &rangeRequest, PRInt32 *numRequests)
{
rangeRequest.Truncate();
*numRequests = 0;
@ -520,22 +617,36 @@ nsPluginStreamListenerPeer::MakeByteRangeString(NPByteRange* aRangeList, nsACStr
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
nsPluginStreamInfo::RequestRead(NPByteRange* rangeList)
{
nsCAutoString rangeString;
PRInt32 numRequests;
//first of all lets see if mPluginStreamListenerPeer is still alive
nsCOMPtr<nsISupportsWeakReference> suppWeakRef(
do_QueryInterface((nsISupportsWeakReference *)(mPluginStreamListenerPeer)));
if (!suppWeakRef)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIWeakReference> pWeakRefPluginStreamListenerPeer =
do_GetWeakReference(suppWeakRef);
if (!pWeakRefPluginStreamListenerPeer)
return NS_ERROR_FAILURE;
MakeByteRangeString(rangeList, rangeString, &numRequests);
if (numRequests == 0)
return NS_ERROR_FAILURE;
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> url;
nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks);
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup);
rv = NS_NewURI(getter_AddRefs(url), nsDependentCString(mURL));
nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mPluginStreamListenerPeer->mWeakPtrChannelCallbacks);
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mPluginStreamListenerPeer->mWeakPtrChannelLoadGroup);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel), mURL, nsnull, loadGroup, callbacks);
rv = NS_NewChannel(getter_AddRefs(channel), url, nsnull, loadGroup, callbacks);
if (NS_FAILED(rv))
return rv;
@ -545,29 +656,28 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, PR_FALSE);
mAbort = PR_TRUE; // instruct old stream listener to cancel
// the request on the next ODA.
mPluginStreamListenerPeer->mAbort = PR_TRUE; // instruct old stream listener to cancel
// the request on the next ODA.
nsCOMPtr<nsIStreamListener> converter;
if (numRequests == 1) {
converter = this;
converter = mPluginStreamListenerPeer;
// set current stream offset equal to the first offset in the range list
// it will work for single byte range request
// for multy range we'll reset it in ODA
SetStreamOffset(rangeList->offset);
} else {
nsWeakPtr weakpeer =
do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this));
nsPluginByteRangeStreamListener *brrListener =
new nsPluginByteRangeStreamListener(weakpeer);
new nsPluginByteRangeStreamListener(pWeakRefPluginStreamListenerPeer);
if (brrListener)
converter = brrListener;
else
return NS_ERROR_OUT_OF_MEMORY;
}
mPendingRequests += numRequests;
mPluginStreamListenerPeer->mPendingRequests += numRequests;
nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (NS_FAILED(rv))
@ -580,19 +690,68 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::GetStreamOffset(PRInt32* result)
nsPluginStreamInfo::GetStreamOffset(PRInt32 *result)
{
*result = mStreamOffset;
return NS_OK;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::SetStreamOffset(PRInt32 value)
nsPluginStreamInfo::SetStreamOffset(PRInt32 offset)
{
mStreamOffset = value;
mStreamOffset = offset;
return NS_OK;
}
void
nsPluginStreamInfo::SetContentType(const char* contentType)
{
if (mContentType != nsnull)
PL_strfree(mContentType);
mContentType = PL_strdup(contentType);
}
void
nsPluginStreamInfo::SetSeekable(const PRBool seekable)
{
mSeekable = seekable;
}
void
nsPluginStreamInfo::SetLength(const PRUint32 length)
{
mLength = length;
}
void
nsPluginStreamInfo::SetLastModified(const PRUint32 modified)
{
mModified = modified;
}
void
nsPluginStreamInfo::SetURL(const char* url)
{
if (mURL)
PL_strfree(mURL);
mURL = PL_strdup(url);
}
void
nsPluginStreamInfo::SetPluginInstance(nsIPluginInstance * aPluginInstance)
{
NS_IF_ADDREF(mPluginInstance = aPluginInstance);
}
void
nsPluginStreamInfo::SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer)
{
// not addref'd - nsPluginStreamInfo is owned by mPluginStreamListenerPeer
mPluginStreamListenerPeer = aPluginStreamListenerPeer;
}
class nsPluginCacheListener : public nsIStreamListener
{
public:
@ -659,6 +818,10 @@ nsPluginCacheListener::OnStopRequest(nsIRequest *request,
nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
{
mURL = nsnull;
mOwner = nsnull;
mInstance = nsnull;
mPStreamListener = nsnull;
mStreamType = NP_NORMAL;
mStartBinding = PR_FALSE;
mAbort = PR_FALSE;
@ -667,20 +830,24 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
mPendingRequests = 0;
mHaveFiredOnStartRequest = PR_FALSE;
mDataForwardToRequest = nsnull;
mSeekable = PR_FALSE;
mModified = 0;
mStreamOffset = 0;
mStreamComplete = 0;
mLocalCachedFile = nsnull;
}
nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
{
#ifdef PLUGIN_LOGGING
nsCAutoString urlSpec;
if (mURL != nsnull) mURL->GetSpec(urlSpec);
PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
("nsPluginStreamListenerPeer::dtor this=%p, url=%s%c",this, mURLSpec.get(), mLocalCachedFile?',':'\n'));
("nsPluginStreamListenerPeer::dtor this=%p, url=%s%c",this, urlSpec.get(), mLocalCachedFile?',':'\n'));
#endif
NS_IF_RELEASE(mURL);
NS_IF_RELEASE(mOwner);
NS_IF_RELEASE(mInstance);
NS_IF_RELEASE(mPStreamListener);
// close FD of mFileCacheOutputStream if it's still open
// or we won't be able to remove the cache file
if (mFileCacheOutputStream)
@ -702,19 +869,18 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
if (refcnt == 1) {
mLocalCachedFile->Remove(PR_FALSE);
NS_RELEASE(mLocalCachedFile);
}
}
delete mDataForwardToRequest;
}
NS_IMPL_ISUPPORTS6(nsPluginStreamListenerPeer,
NS_IMPL_ISUPPORTS4(nsPluginStreamListenerPeer,
nsIStreamListener,
nsIRequestObserver,
nsIHttpHeaderVisitor,
nsISupportsWeakReference,
nsIPluginStreamInfo,
nsINPAPIPluginStreamInfo)
nsISupportsWeakReference)
// Called as a result of GetURL and PostURL
nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
@ -733,9 +899,20 @@ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
#endif
mURL = aURL;
NS_ADDREF(mURL);
mInstance = aInstance;
NS_ADDREF(mInstance);
mPStreamListener = aListener;
NS_ADDREF(mPStreamListener);
mPluginStreamInfo = new nsPluginStreamInfo();
if (!mPluginStreamInfo)
return NS_ERROR_OUT_OF_MEMORY;
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mPendingRequests = requestCount;
@ -767,14 +944,24 @@ nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL,
#endif
mURL = aURL;
NS_ADDREF(mURL);
if (aInstance) {
NS_ASSERTION(mInstance == nsnull, "nsPluginStreamListenerPeer::InitializeEmbedded mInstance != nsnull");
mInstance = aInstance;
NS_ADDREF(mInstance);
} else {
mOwner = aOwner;
NS_IF_ADDREF(mOwner);
}
mPluginStreamInfo = new nsPluginStreamInfo();
if (!mPluginStreamInfo)
return NS_ERROR_OUT_OF_MEMORY;
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
@ -791,6 +978,14 @@ nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIPluginInstance *aInst
NS_ASSERTION(mInstance == nsnull, "nsPluginStreamListenerPeer::InitializeFullPage mInstance != nsnull");
mInstance = aInstance;
NS_ADDREF(mInstance);
mPluginStreamInfo = new nsPluginStreamInfo();
if (!mPluginStreamInfo)
return NS_ERROR_OUT_OF_MEMORY;
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
@ -824,10 +1019,11 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
while (--cnt >= 0) {
nsPluginStreamListenerPeer *lp =
reinterpret_cast<nsPluginStreamListenerPeer*>(instanceTag->mStreams->ElementAt(cnt));
if (lp && lp->mLocalCachedFile) {
useExistingCacheFile = lp->UseExistingPluginCacheFile(this);
if (lp && lp->mLocalCachedFile && lp->mPluginStreamInfo) {
useExistingCacheFile = lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo);
if (useExistingCacheFile) {
mLocalCachedFile = lp->mLocalCachedFile;
NS_ADDREF(mLocalCachedFile);
break;
}
NS_RELEASE(lp);
@ -877,9 +1073,8 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
return rv;
// save the file.
mLocalCachedFile = pluginTmp;
// Addref to add one extra refcnt, we can use NS_RELEASE2(mLocalCachedFile...) in dtor
CallQueryInterface(pluginTmp, &mLocalCachedFile); // no need to check return value, just addref
// add one extra refcnt, we can use NS_RELEASE2(mLocalCachedFile...) in dtor
// to remove this file when refcnt == 1
NS_ADDREF(mLocalCachedFile);
}
@ -979,13 +1174,13 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
mRequestFailed = PR_TRUE;
return NS_ERROR_FAILURE;
}
mLength = 0;
mPluginStreamInfo->SetLength(PRUint32(0));
}
else {
mLength = length;
mPluginStreamInfo->SetLength(length);
}
mRequest = request;
mPluginStreamInfo->SetRequest(request);
nsCAutoString aContentType; // XXX but we already got the type above!
rv = channel->GetContentType(aContentType);
@ -997,15 +1192,17 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
if (NS_FAILED(rv))
return rv;
aURL->GetSpec(mURLSpec);
nsCAutoString urlSpec;
aURL->GetSpec(urlSpec);
mPluginStreamInfo->SetURL(urlSpec.get());
if (!aContentType.IsEmpty())
mContentType = aContentType;
mPluginStreamInfo->SetContentType(aContentType.get());
#ifdef PLUGIN_LOGGING
PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY,
("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n",
this, request, aContentType.get(), mURLSpec.get()));
this, request, aContentType.get(), urlSpec.get()));
PR_LogFlush();
#endif
@ -1020,8 +1217,7 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
// NOTE: we don't want to try again if we didn't get the MIME type this time
if (!mInstance && mOwner && !aContentType.IsEmpty()) {
mOwner->GetInstance(getter_AddRefs(mInstance));
mOwner->GetInstance(mInstance);
mOwner->GetWindow(window);
if (!mInstance && window) {
nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst());
@ -1035,7 +1231,8 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner);
if (NS_OK == rv) {
mOwner->GetInstance(getter_AddRefs(mInstance));
// GetInstance() adds a ref
mOwner->GetInstance(mInstance);
if (mInstance) {
mInstance->Start();
mOwner->CreateWidget();
@ -1116,13 +1313,13 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
nsresult rv = NS_OK;
if (!mPStreamListener)
if (!mPStreamListener || !mPluginStreamInfo)
return NS_ERROR_FAILURE;
mRequest = request;
mPluginStreamInfo->SetRequest(request);
const char * url = nsnull;
GetURL(&url);
mPluginStreamInfo->GetURL(&url);
PLUGIN_LOG(PLUGIN_LOG_NOISY,
("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, offset=%d, length=%d, url=%s\n",
@ -1155,7 +1352,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
NS_PTR_TO_INT32(mDataForwardToRequest->Get(&key));
mDataForwardToRequest->Put(&key, NS_INT32_TO_PTR(amtForwardToPlugin + aLength));
SetStreamOffset(absoluteOffset + amtForwardToPlugin);
mPluginStreamInfo->SetStreamOffset(absoluteOffset + amtForwardToPlugin);
}
nsCOMPtr<nsIInputStream> stream = aIStream;
@ -1170,7 +1367,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
return rv;
}
rv = mPStreamListener->OnDataAvailable(this,
rv = mPStreamListener->OnDataAvailable(mPluginStreamInfo,
stream,
aLength);
@ -1259,7 +1456,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
return rv;
if (!aContentType.IsEmpty())
mContentType = aContentType;
mPluginStreamInfo->SetContentType(aContentType.get());
// set error status if stream failed so we notify the plugin
if (mRequestFailed)
@ -1268,13 +1465,13 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
if (NS_FAILED(aStatus)) {
// on error status cleanup the stream
// and return w/o OnFileAvailable()
mPStreamListener->OnStopBinding(this, aStatus);
mPStreamListener->OnStopBinding(mPluginStreamInfo, aStatus);
return NS_OK;
}
// call OnFileAvailable if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly
if (mStreamType >= NP_ASFILE) {
nsCOMPtr<nsIFile> localFile = mLocalCachedFile;
nsCOMPtr<nsIFile> localFile = do_QueryInterface(mLocalCachedFile);
if (!localFile) {
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
if (cacheChannel) {
@ -1295,17 +1492,15 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
if (mStartBinding) {
// On start binding has been called
mPStreamListener->OnStopBinding(this, aStatus);
mPStreamListener->OnStopBinding(mPluginStreamInfo, aStatus);
} else {
// OnStartBinding hasn't been called, so complete the action.
mPStreamListener->OnStartBinding(this);
mPStreamListener->OnStopBinding(this, aStatus);
mPStreamListener->OnStartBinding(mPluginStreamInfo);
mPStreamListener->OnStopBinding(mPluginStreamInfo, aStatus);
}
if (NS_SUCCEEDED(aStatus)) {
mStreamComplete = PR_TRUE;
}
mRequest = NULL;
if (NS_SUCCEEDED(aStatus))
mPluginStreamInfo->SetStreamComplete(PR_TRUE);
return NS_OK;
}
@ -1321,7 +1516,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
// with GetURL or PostURL (i.e. it's the initial stream we
// send to the plugin as determined by the SRC or DATA attribute)
if (!mPStreamListener && mInstance)
rv = mInstance->NewStreamToPlugin(getter_AddRefs(mPStreamListener));
rv = mInstance->NewStreamToPlugin(&mPStreamListener);
if (NS_FAILED(rv))
return rv;
@ -1379,7 +1574,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
// Also provide all HTTP response headers to our listener.
httpChannel->VisitResponseHeaders(this);
mSeekable = PR_FALSE;
PRBool bSeekable = PR_FALSE;
// first we look for a content-encoding header. If we find one, we tell the
// plugin that stream is not seekable, because the plugin always sees
// uncompressed data, so it can't make meaningful range requests on a
@ -1395,12 +1590,15 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
// set seekability (seekable if the stream has a known length and if the
// http server accepts byte ranges).
PRUint32 length;
GetLength(&length);
mPluginStreamInfo->GetLength(&length);
if (length) {
nsCAutoString range;
if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("accept-ranges"), range)) &&
range.Equals(NS_LITERAL_CSTRING("bytes"), nsCaseInsensitiveCStringComparator())) {
mSeekable = PR_TRUE;
bSeekable = PR_TRUE;
// nsPluginStreamInfo.mSeekable intitialized by PR_FALSE in ctor of nsPluginStreamInfo
// so we reset it only here.
mPluginStreamInfo->SetSeekable(bSeekable);
}
}
}
@ -1416,11 +1614,11 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
double fpTime;
LL_L2D(fpTime, time64);
mModified = (PRUint32)(fpTime * 1e-6 + 0.5);
mPluginStreamInfo->SetLastModified((PRUint32)(fpTime * 1e-6 + 0.5));
}
}
rv = mPStreamListener->OnStartBinding(this);
rv = mPStreamListener->OnStartBinding(mPluginStreamInfo);
mStartBinding = PR_TRUE;
@ -1464,7 +1662,7 @@ nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile)
return NS_OK;
}
rv = mPStreamListener->OnFileAvailable(this, path.get());
rv = mPStreamListener->OnFileAvailable(mPluginStreamInfo, path.get());
return rv;
}
@ -5173,9 +5371,9 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
}
}
mSeekable = PR_FALSE;
mPStreamListener->OnStartBinding(this);
mStreamOffset = 0;
mPluginStreamInfo->SetSeekable(0);
mPStreamListener->OnStartBinding(mPluginStreamInfo);
mPluginStreamInfo->SetStreamOffset(0);
// force the plugin to use stream as file
mStreamType = NP_ASFILE;
@ -5311,7 +5509,7 @@ nsPluginByteRangeStreamListener::OnDataAvailable(nsIRequest *request, nsISupport
}
PRBool
nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi)
nsPluginStreamInfo::UseExistingPluginCacheFile(nsPluginStreamInfo* psi)
{
NS_ENSURE_ARG_POINTER(psi);
@ -5319,13 +5517,24 @@ nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPee
if ( psi->mLength == mLength &&
psi->mModified == mModified &&
mStreamComplete &&
mURLSpec.Equals(psi->mURLSpec))
!PL_strcmp(psi->mURL, mURL))
{
return PR_TRUE;
}
return PR_FALSE;
}
void
nsPluginStreamInfo::SetStreamComplete(const PRBool complete)
{
mStreamComplete = complete;
if (complete) {
// We're done, release the request.
SetRequest(nsnull);
}
}
// Runnable that does an async destroy of a plugin.
class nsPluginDestroyRunnable : public nsRunnable,

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

@ -1025,6 +1025,9 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf
if (err != NPERR_NO_ERROR) {
instanceData->err << "Error: NPN_DestroyStream returned " << err;
}
if (instanceData->frame.length() > 0) {
sendBufferToFrame(instance);
}
}
}
else {