michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsPluginStreamListenerPeer_h_ michael@0: #define nsPluginStreamListenerPeer_h_ michael@0: michael@0: #include "nscore.h" michael@0: #include "nsIFile.h" michael@0: #include "nsIStreamListener.h" michael@0: #include "nsIProgressEventSink.h" michael@0: #include "nsIHttpHeaderVisitor.h" michael@0: #include "nsWeakReference.h" michael@0: #include "nsNPAPIPluginStreamListener.h" michael@0: #include "nsDataHashtable.h" michael@0: #include "nsHashKeys.h" michael@0: #include "nsNPAPIPluginInstance.h" michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIChannelEventSink.h" michael@0: michael@0: class nsIChannel; michael@0: michael@0: /** michael@0: * When a plugin requests opens multiple requests to the same URL and michael@0: * the request must be satified by saving a file to disk, each stream michael@0: * listener holds a reference to the backing file: the file is only removed michael@0: * when all the listeners are done. michael@0: */ michael@0: class CachedFileHolder michael@0: { michael@0: public: michael@0: CachedFileHolder(nsIFile* cacheFile); michael@0: ~CachedFileHolder(); michael@0: michael@0: void AddRef(); michael@0: void Release(); michael@0: michael@0: nsIFile* file() const { return mFile; } michael@0: michael@0: private: michael@0: nsAutoRefCnt mRefCnt; michael@0: nsCOMPtr mFile; michael@0: }; michael@0: michael@0: class nsPluginStreamListenerPeer : public nsIStreamListener, michael@0: public nsIProgressEventSink, michael@0: public nsIHttpHeaderVisitor, michael@0: public nsSupportsWeakReference, michael@0: public nsIInterfaceRequestor, michael@0: public nsIChannelEventSink michael@0: { michael@0: public: michael@0: nsPluginStreamListenerPeer(); michael@0: virtual ~nsPluginStreamListenerPeer(); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIPROGRESSEVENTSINK michael@0: NS_DECL_NSIREQUESTOBSERVER michael@0: NS_DECL_NSISTREAMLISTENER michael@0: NS_DECL_NSIHTTPHEADERVISITOR michael@0: NS_DECL_NSIINTERFACEREQUESTOR michael@0: NS_DECL_NSICHANNELEVENTSINK michael@0: michael@0: // Called by RequestRead michael@0: void michael@0: MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, int32_t *numRequests); michael@0: michael@0: bool UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi); michael@0: michael@0: // Called by GetURL and PostURL (via NewStream) or by the host in the case of michael@0: // the initial plugin stream. michael@0: nsresult Initialize(nsIURI *aURL, michael@0: nsNPAPIPluginInstance *aInstance, michael@0: nsNPAPIPluginStreamListener *aListener); michael@0: michael@0: nsresult OnFileAvailable(nsIFile* aFile); michael@0: michael@0: nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt); michael@0: michael@0: nsNPAPIPluginInstance *GetPluginInstance() { return mPluginInstance; } michael@0: michael@0: nsresult RequestRead(NPByteRange* rangeList); michael@0: nsresult GetLength(uint32_t* result); michael@0: nsresult GetURL(const char** result); michael@0: nsresult GetLastModified(uint32_t* result); michael@0: nsresult IsSeekable(bool* result); michael@0: nsresult GetContentType(char** result); michael@0: nsresult GetStreamOffset(int32_t* result); michael@0: nsresult SetStreamOffset(int32_t value); michael@0: michael@0: void TrackRequest(nsIRequest* request) michael@0: { michael@0: mRequests.AppendObject(request); michael@0: } michael@0: michael@0: void ReplaceRequest(nsIRequest* oldRequest, nsIRequest* newRequest) michael@0: { michael@0: int32_t i = mRequests.IndexOfObject(oldRequest); michael@0: if (i == -1) { michael@0: NS_ASSERTION(mRequests.Count() == 0, michael@0: "Only our initial stream should be unknown!"); michael@0: mRequests.AppendObject(oldRequest); michael@0: } michael@0: else { michael@0: mRequests.ReplaceObjectAt(newRequest, i); michael@0: } michael@0: } michael@0: michael@0: void CancelRequests(nsresult status) michael@0: { michael@0: // Copy the array to avoid modification during the loop. michael@0: nsCOMArray requestsCopy(mRequests); michael@0: for (int32_t i = 0; i < requestsCopy.Count(); ++i) michael@0: requestsCopy[i]->Cancel(status); michael@0: } michael@0: michael@0: void SuspendRequests() { michael@0: nsCOMArray requestsCopy(mRequests); michael@0: for (int32_t i = 0; i < requestsCopy.Count(); ++i) michael@0: requestsCopy[i]->Suspend(); michael@0: } michael@0: michael@0: void ResumeRequests() { michael@0: nsCOMArray requestsCopy(mRequests); michael@0: for (int32_t i = 0; i < requestsCopy.Count(); ++i) michael@0: requestsCopy[i]->Resume(); michael@0: } michael@0: michael@0: private: michael@0: nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL); michael@0: nsresult SetupPluginCacheFile(nsIChannel* channel); michael@0: nsresult GetInterfaceGlobal(const nsIID& aIID, void** result); michael@0: michael@0: nsCOMPtr mURL; michael@0: nsCString mURLSpec; // Have to keep this member because GetURL hands out char* michael@0: nsRefPtr mPStreamListener; michael@0: michael@0: // Set to true if we request failed (like with a HTTP response of 404) michael@0: bool mRequestFailed; michael@0: michael@0: /* michael@0: * Set to true after nsNPAPIPluginStreamListener::OnStartBinding() has michael@0: * been called. Checked in ::OnStopRequest so we can call the michael@0: * plugin's OnStartBinding if, for some reason, it has not already michael@0: * been called. michael@0: */ michael@0: bool mStartBinding; michael@0: bool mHaveFiredOnStartRequest; michael@0: // these get passed to the plugin stream listener michael@0: uint32_t mLength; michael@0: int32_t mStreamType; michael@0: michael@0: // local cached file, we save the content into local cache if browser cache is not available, michael@0: // or plugin asks stream as file and it expects file extension until bug 90558 got fixed michael@0: nsRefPtr mLocalCachedFileHolder; michael@0: nsCOMPtr mFileCacheOutputStream; michael@0: nsDataHashtable* mDataForwardToRequest; michael@0: michael@0: nsCString mContentType; michael@0: bool mSeekable; michael@0: uint32_t mModified; michael@0: nsRefPtr mPluginInstance; michael@0: int32_t mStreamOffset; michael@0: bool mStreamComplete; michael@0: michael@0: public: michael@0: bool mAbort; michael@0: int32_t mPendingRequests; michael@0: nsWeakPtr mWeakPtrChannelCallbacks; michael@0: nsWeakPtr mWeakPtrChannelLoadGroup; michael@0: nsCOMArray mRequests; michael@0: }; michael@0: michael@0: #endif // nsPluginStreamListenerPeer_h_