Bug 758227: NPAPI plugin stream decomtamination: nsIPluginStreamInfo. r=bsmedberg

This commit is contained in:
Josh Aas 2012-06-05 09:58:39 -04:00
parent 70c756f599
commit 5db7c076c3
8 changed files with 104 additions and 168 deletions

View File

@ -26,7 +26,6 @@ XPIDLSRCS = \
nsIPluginHost.idl \
nsIPluginInputStream.idl \
nsIPluginInstanceOwner.idl \
nsIPluginStreamInfo.idl \
nsIPluginTag.idl \
nsIPluginTagInfo.idl \
nspluginroot.idl \

View File

@ -1,39 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* nsIPluginStreamInfo
*
* @status DEPRECATED
*
* Originally published XPCOM Plugin API is now deprecated
* Developers are welcome to use NPAPI, please refer to:
* http://mozilla.org/projects/plugins/
*/
#include "nsISupports.idl"
#include "nspluginroot.idl"
%{C++
#include "npapi.h"
%}
[uuid(A700845F-0E26-44EA-84F5-3BE5381F98D5)]
interface nsIPluginStreamInfo : nsISupports
{
readonly attribute string contentType;
void isSeekable(out boolean aSeekable);
readonly attribute unsigned long length;
readonly attribute unsigned long lastModified;
void getURL(out constCharPtr aURL);
void requestRead(in NPByteRangePtr aRangeList);
attribute long streamOffset;
};

View File

@ -19,6 +19,7 @@
#include "nsNPAPIPlugin.h"
#include "nsNPAPIPluginInstance.h"
#include "nsNPAPIPluginStreamListener.h"
#include "nsPluginStreamListenerPeer.h"
#include "nsIServiceManager.h"
#include "nsThreadUtils.h"
#include "mozilla/Preferences.h"
@ -533,11 +534,12 @@ nsNPAPIPlugin::RetainStream(NPStream *pstream, nsISupports **aRetainedPeer)
return NPERR_GENERIC_ERROR;
}
nsPluginStreamListenerPeer* peer = listener->GetStreamListenerPeer();
if (!peer)
nsIStreamListener* streamListener = listener->GetStreamListenerPeer();
if (!streamListener) {
return NPERR_GENERIC_ERROR;
}
*aRetainedPeer = (nsISupports*) peer;
*aRetainedPeer = streamListener;
NS_ADDREF(*aRetainedPeer);
return NS_OK;
}
@ -2510,10 +2512,10 @@ _requestread(NPStream *pstream, NPByteRange *rangeList)
if (streamtype != NP_SEEK)
return NPERR_STREAM_NOT_SEEKABLE;
if (!streamlistener->mStreamInfo)
if (!streamlistener->mStreamListenerPeer)
return NPERR_GENERIC_ERROR;
nsresult rv = streamlistener->mStreamInfo->RequestRead((NPByteRange *)rangeList);
nsresult rv = streamlistener->mStreamListenerPeer->RequestRead((NPByteRange *)rangeList);
if (NS_FAILED(rv))
return NPERR_GENERIC_ERROR;

View File

@ -137,7 +137,6 @@ nsNPAPIPluginStreamListener::nsNPAPIPluginStreamListener(nsNPAPIPluginInstance*
: mStreamBuffer(nsnull),
mNotifyURL(aURL ? PL_strdup(aURL) : nsnull),
mInst(inst),
mStreamListenerPeer(nsnull),
mStreamBufferSize(0),
mStreamBufferByteCount(0),
mStreamType(NP_NORMAL),
@ -215,7 +214,7 @@ nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason)
if (!mInst || !mInst->CanFireNotifications())
return rv;
mStreamInfo = NULL;
mStreamListenerPeer = nsnull;
PluginDestructionGuard guard(mInst);
@ -279,7 +278,7 @@ nsNPAPIPluginStreamListener::CallURLNotify(NPReason reason)
}
nsresult
nsNPAPIPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
nsNPAPIPluginStreamListener::OnStartBinding(nsPluginStreamListenerPeer* streamPeer)
{
if (!mInst || !mInst->CanFireNotifications())
return NS_ERROR_FAILURE;
@ -303,18 +302,18 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
PRUint16 streamType = NP_NORMAL;
NPError error;
pluginInfo->GetURL(&mNPStreamWrapper->mNPStream.url);
pluginInfo->GetLength((PRUint32*)&(mNPStreamWrapper->mNPStream.end));
pluginInfo->GetLastModified((PRUint32*)&(mNPStreamWrapper->mNPStream.lastmodified));
pluginInfo->IsSeekable(&seekable);
pluginInfo->GetContentType(&contentType);
streamPeer->GetURL(&mNPStreamWrapper->mNPStream.url);
streamPeer->GetLength((PRUint32*)&(mNPStreamWrapper->mNPStream.end));
streamPeer->GetLastModified((PRUint32*)&(mNPStreamWrapper->mNPStream.lastmodified));
streamPeer->IsSeekable(&seekable);
streamPeer->GetContentType(&contentType);
if (!mResponseHeaders.IsEmpty()) {
mResponseHeaderBuf = PL_strdup(mResponseHeaders.get());
mNPStreamWrapper->mNPStream.headers = mResponseHeaderBuf;
}
mStreamInfo = pluginInfo;
mStreamListenerPeer = streamPeer;
NPPAutoPusher nppPusher(npp);
@ -360,31 +359,22 @@ nsNPAPIPluginStreamListener::SuspendRequest()
{
NS_ASSERTION(!mIsSuspended,
"Suspending a request that's already suspended!");
nsCOMPtr<nsINPAPIPluginStreamInfo> pluginInfoNPAPI =
do_QueryInterface(mStreamInfo);
if (!pluginInfoNPAPI) {
return;
}
nsresult rv = StartDataPump();
if (NS_FAILED(rv))
return;
mIsSuspended = true;
pluginInfoNPAPI->SuspendRequests();
if (mStreamListenerPeer) {
mStreamListenerPeer->SuspendRequests();
}
}
void
nsNPAPIPluginStreamListener::ResumeRequest()
{
nsCOMPtr<nsINPAPIPluginStreamInfo> pluginInfoNPAPI =
do_QueryInterface(mStreamInfo);
pluginInfoNPAPI->ResumeRequests();
mStreamListenerPeer->ResumeRequests();
mIsSuspended = false;
}
@ -436,7 +426,7 @@ nsNPAPIPluginStreamListener::PluginInitJSLoadInProgress()
// and the length will be the number of bytes available in our
// internal buffer.
nsresult
nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
nsNPAPIPluginStreamListener::OnDataAvailable(nsPluginStreamListenerPeer* streamPeer,
nsIInputStream* input,
PRUint32 length)
{
@ -446,7 +436,7 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
PluginDestructionGuard guard(mInst);
// Just in case the caller switches plugin info on us.
mStreamInfo = pluginInfo;
mStreamListenerPeer = streamPeer;
nsNPAPIPlugin* plugin = mInst->GetPlugin();
if (!plugin || !plugin->GetLibrary())
@ -466,7 +456,7 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
// consecutive Read() calls form input stream into our buff.
PRUint32 contentLength;
pluginInfo->GetLength(&contentLength);
streamPeer->GetLength(&contentLength);
mStreamBufferSize = NS_MAX(length, contentLength);
@ -486,7 +476,7 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
mInst->GetNPP(&npp);
PRInt32 streamPosition;
pluginInfo->GetStreamOffset(&streamPosition);
streamPeer->GetStreamOffset(&streamPosition);
PRInt32 streamOffset = streamPosition;
if (input) {
@ -501,7 +491,7 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
//
// Note: there is a special case when data flow should be
// temporarily stopped if NPP_WriteReady returns 0 (bug #89270)
pluginInfo->SetStreamOffset(streamOffset);
streamPeer->SetStreamOffset(streamOffset);
// set new end in case the content is compressed
// initial end is less than end of decompressed stream
@ -695,10 +685,10 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
// NPN_RequestRead() call.
PRInt32 postWriteStreamPosition;
pluginInfo->GetStreamOffset(&postWriteStreamPosition);
streamPeer->GetStreamOffset(&postWriteStreamPosition);
if (postWriteStreamPosition == streamOffset) {
pluginInfo->SetStreamOffset(streamPosition);
streamPeer->SetStreamOffset(streamPosition);
}
}
@ -706,7 +696,7 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
}
nsresult
nsNPAPIPluginStreamListener::OnFileAvailable(nsIPluginStreamInfo* pluginInfo,
nsNPAPIPluginStreamListener::OnFileAvailable(nsPluginStreamListenerPeer* streamPeer,
const char* fileName)
{
if (!mInst || !mInst->CanFireNotifications())
@ -736,7 +726,7 @@ nsNPAPIPluginStreamListener::OnFileAvailable(nsIPluginStreamInfo* pluginInfo,
}
nsresult
nsNPAPIPluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo,
nsNPAPIPluginStreamListener::OnStopBinding(nsPluginStreamListenerPeer* streamPeer,
nsresult status)
{
StopDataPump();
@ -744,9 +734,8 @@ nsNPAPIPluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo,
if (NS_FAILED(status)) {
// The stream was destroyed, or died for some reason. Make sure we
// cancel the underlying request.
nsCOMPtr<nsINPAPIPluginStreamInfo> pluginInfoNPAPI = do_QueryInterface(mStreamInfo);
if (pluginInfoNPAPI) {
pluginInfoNPAPI->CancelRequests(status);
if (mStreamListenerPeer) {
mStreamListenerPeer->CancelRequests(status);
}
}
@ -788,7 +777,7 @@ nsNPAPIPluginStreamListener::Notify(nsITimer *aTimer)
PRInt32 oldStreamBufferByteCount = mStreamBufferByteCount;
nsresult rv = OnDataAvailable(mStreamInfo, nsnull, mStreamBufferByteCount);
nsresult rv = OnDataAvailable(mStreamListenerPeer, nsnull, mStreamBufferByteCount);
if (NS_FAILED(rv)) {
// We ran into an error, no need to keep firing this timer then.

View File

@ -7,7 +7,6 @@
#define nsNPAPIPluginStreamListener_h_
#include "nscore.h"
#include "nsIPluginStreamInfo.h"
#include "nsIHTTPHeaderListener.h"
#include "nsIRequest.h"
#include "nsITimer.h"
@ -22,7 +21,6 @@
#define MAX_PLUGIN_NECKO_BUFFER 16384
class nsINPAPIPluginStreamInfo;
class nsPluginStreamListenerPeer;
class nsNPAPIPluginStreamListener;
@ -42,64 +40,6 @@ protected:
nsNPAPIPluginStreamListener* mStreamListener; // only valid if browser initiated
};
// nsINPAPIPluginStreamInfo is an internal helper interface that exposes
// the underlying necko request to consumers of nsIPluginStreamInfo's.
#define NS_INPAPIPLUGINSTREAMINFO_IID \
{ 0x097fdaaa, 0xa2a3, 0x49c2, \
{0x91, 0xee, 0xeb, 0xc5, 0x7d, 0x6c, 0x9c, 0x97} }
class nsINPAPIPluginStreamInfo : public nsIPluginStreamInfo
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INPAPIPLUGINSTREAMINFO_IID)
void TrackRequest(nsIRequest* request)
{
mRequests.AppendObject(request);
}
void ReplaceRequest(nsIRequest* oldRequest, nsIRequest* newRequest)
{
PRInt32 i = mRequests.IndexOfObject(oldRequest);
if (i == -1) {
NS_ASSERTION(mRequests.Count() == 0,
"Only our initial stream should be unknown!");
mRequests.AppendObject(oldRequest);
}
else {
mRequests.ReplaceObjectAt(newRequest, i);
}
}
void CancelRequests(nsresult status)
{
// Copy the array to avoid modification during the loop.
nsCOMArray<nsIRequest> requestsCopy(mRequests);
for (PRInt32 i = 0; i < requestsCopy.Count(); ++i)
requestsCopy[i]->Cancel(status);
}
void SuspendRequests() {
nsCOMArray<nsIRequest> requestsCopy(mRequests);
for (PRInt32 i = 0; i < requestsCopy.Count(); ++i)
requestsCopy[i]->Suspend();
}
void ResumeRequests() {
nsCOMArray<nsIRequest> requestsCopy(mRequests);
for (PRInt32 i = 0; i < requestsCopy.Count(); ++i)
requestsCopy[i]->Resume();
}
protected:
friend class nsPluginByteRangeStreamListener;
nsCOMArray<nsIRequest> mRequests;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsINPAPIPluginStreamInfo,
NS_INPAPIPLUGINSTREAMINFO_IID)
// Used to handle NPN_NewStream() - writes the stream as received by the plugin
// to a file and at completion (NPN_DestroyStream), tells the browser to load it into
// a plugin-specified target
@ -134,13 +74,13 @@ public:
const char* aURL);
virtual ~nsNPAPIPluginStreamListener();
nsresult OnStartBinding(nsIPluginStreamInfo* pluginInfo);
nsresult OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
nsresult OnStartBinding(nsPluginStreamListenerPeer* streamPeer);
nsresult OnDataAvailable(nsPluginStreamListenerPeer* streamPeer,
nsIInputStream* input,
PRUint32 length);
nsresult OnFileAvailable(nsIPluginStreamInfo* pluginInfo,
nsresult OnFileAvailable(nsPluginStreamListenerPeer* streamPeer,
const char* fileName);
nsresult OnStopBinding(nsIPluginStreamInfo* pluginInfo,
nsresult OnStopBinding(nsPluginStreamListenerPeer* streamPeer,
nsresult status);
nsresult GetStreamType(PRInt32 *result);
@ -167,7 +107,6 @@ protected:
char* mStreamBuffer;
char* mNotifyURL;
nsRefPtr<nsNPAPIPluginInstance> mInst;
nsPluginStreamListenerPeer* mStreamListenerPeer;
nsNPAPIStreamWrapper *mNPStreamWrapper;
PRUint32 mStreamBufferSize;
PRInt32 mStreamBufferByteCount;
@ -184,7 +123,7 @@ protected:
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mHTTPRedirectCallback;
public:
nsCOMPtr<nsIPluginStreamInfo> mStreamInfo;
nsRefPtr<nsPluginStreamListenerPeer> mStreamListenerPeer;
};
#endif // nsNPAPIPluginStreamListener_h_

View File

@ -15,6 +15,8 @@
#include "nsNPAPIPlugin.h"
#include "nsNPAPIPluginStreamListener.h"
#include "nsNPAPIPluginInstance.h"
#include "nsPluginInstanceOwner.h"
#include "nsObjectLoadingContent.h"
#include "nsIHTTPHeaderListener.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsIObserverService.h"

View File

@ -27,6 +27,7 @@
#include "nsNetUtil.h"
#include "nsPluginNativeWindow.h"
#include "sampler.h"
#include "nsObjectLoadingContent.h"
#define MAGIC_REQUEST_CONTEXT 0x01020304
@ -264,13 +265,11 @@ public:
// nsPluginStreamListenerPeer
NS_IMPL_ISUPPORTS8(nsPluginStreamListenerPeer,
NS_IMPL_ISUPPORTS6(nsPluginStreamListenerPeer,
nsIStreamListener,
nsIRequestObserver,
nsIHttpHeaderVisitor,
nsISupportsWeakReference,
nsIPluginStreamInfo,
nsINPAPIPluginStreamInfo,
nsIInterfaceRequestor,
nsIChannelEventSink)
@ -635,7 +634,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStatus(nsIRequest *request,
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::GetContentType(char** result)
{
*result = const_cast<char*>(mContentType.get());
@ -643,28 +642,28 @@ nsPluginStreamListenerPeer::GetContentType(char** result)
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::IsSeekable(bool* result)
{
*result = mSeekable;
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::GetLength(PRUint32* result)
{
*result = mLength;
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::GetLastModified(PRUint32* result)
{
*result = mModified;
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::GetURL(const char** result)
{
*result = mURLSpec.get();
@ -707,7 +706,7 @@ nsPluginStreamListenerPeer::MakeByteRangeString(NPByteRange* aRangeList, nsACStr
return;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
{
nsCAutoString rangeString;
@ -770,14 +769,14 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
return rv;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::GetStreamOffset(PRInt32* result)
{
*result = mStreamOffset;
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsPluginStreamListenerPeer::SetStreamOffset(PRInt32 value)
{
mStreamOffset = value;
@ -1289,11 +1288,11 @@ nsPluginStreamListenerPeer::GetInterface(const nsIID& aIID, void** result)
class ChannelRedirectProxyCallback : public nsIAsyncVerifyRedirectCallback
{
public:
ChannelRedirectProxyCallback(nsINPAPIPluginStreamInfo* listener,
ChannelRedirectProxyCallback(nsPluginStreamListenerPeer* listener,
nsIAsyncVerifyRedirectCallback* parent,
nsIChannel* oldChannel,
nsIChannel* newChannel)
: mWeakListener(do_GetWeakReference(listener))
: mWeakListener(do_GetWeakReference(static_cast<nsIStreamListener*>(listener)))
, mParent(parent)
, mOldChannel(oldChannel)
, mNewChannel(newChannel)
@ -1308,9 +1307,9 @@ public:
NS_IMETHODIMP OnRedirectVerifyCallback(nsresult result)
{
if (NS_SUCCEEDED(result)) {
nsCOMPtr<nsINPAPIPluginStreamInfo> listener = do_QueryReferent(mWeakListener);
nsCOMPtr<nsIStreamListener> listener = do_QueryReferent(mWeakListener);
if (listener)
listener->ReplaceRequest(mOldChannel, mNewChannel);
static_cast<nsPluginStreamListenerPeer*>(listener.get())->ReplaceRequest(mOldChannel, mNewChannel);
}
return mParent->OnRedirectVerifyCallback(result);
}

View File

@ -17,9 +17,10 @@
#include "nsNPAPIPluginInstance.h"
#include "nsIInterfaceRequestor.h"
#include "nsIChannelEventSink.h"
#include "nsObjectLoadingContent.h"
#include "nsIObjectLoadingContent.h"
class nsIChannel;
class nsObjectLoadingContent;
/**
* When a plugin requests opens multiple requests to the same URL and
@ -47,7 +48,6 @@ class nsPluginStreamListenerPeer : public nsIStreamListener,
public nsIProgressEventSink,
public nsIHttpHeaderVisitor,
public nsSupportsWeakReference,
public nsINPAPIPluginStreamInfo,
public nsIInterfaceRequestor,
public nsIChannelEventSink
{
@ -63,9 +63,6 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
// nsINPAPIPluginStreamInfo interface
NS_DECL_NSIPLUGINSTREAMINFO
// Called by RequestRead
void
MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, PRInt32 *numRequests);
@ -89,6 +86,53 @@ public:
nsNPAPIPluginInstance *GetPluginInstance() { return mPluginInstance; }
nsresult RequestRead(NPByteRange* rangeList);
nsresult GetLength(PRUint32* result);
nsresult GetURL(const char** result);
nsresult GetLastModified(PRUint32* result);
nsresult IsSeekable(bool* result);
nsresult GetContentType(char** result);
nsresult GetStreamOffset(PRInt32* result);
nsresult SetStreamOffset(PRInt32 value);
void TrackRequest(nsIRequest* request)
{
mRequests.AppendObject(request);
}
void ReplaceRequest(nsIRequest* oldRequest, nsIRequest* newRequest)
{
PRInt32 i = mRequests.IndexOfObject(oldRequest);
if (i == -1) {
NS_ASSERTION(mRequests.Count() == 0,
"Only our initial stream should be unknown!");
mRequests.AppendObject(oldRequest);
}
else {
mRequests.ReplaceObjectAt(newRequest, i);
}
}
void CancelRequests(nsresult status)
{
// Copy the array to avoid modification during the loop.
nsCOMArray<nsIRequest> requestsCopy(mRequests);
for (PRInt32 i = 0; i < requestsCopy.Count(); ++i)
requestsCopy[i]->Cancel(status);
}
void SuspendRequests() {
nsCOMArray<nsIRequest> requestsCopy(mRequests);
for (PRInt32 i = 0; i < requestsCopy.Count(); ++i)
requestsCopy[i]->Suspend();
}
void ResumeRequests() {
nsCOMArray<nsIRequest> requestsCopy(mRequests);
for (PRInt32 i = 0; i < requestsCopy.Count(); ++i)
requestsCopy[i]->Resume();
}
private:
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
nsresult SetupPluginCacheFile(nsIChannel* channel);
@ -132,6 +176,7 @@ public:
PRInt32 mPendingRequests;
nsWeakPtr mWeakPtrChannelCallbacks;
nsWeakPtr mWeakPtrChannelLoadGroup;
nsCOMArray<nsIRequest> mRequests;
};
#endif // nsPluginStreamListenerPeer_h_