diff options
Diffstat (limited to 'embed/xulrunner/src/EmbedStream.cpp')
-rw-r--r-- | embed/xulrunner/src/EmbedStream.cpp | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/embed/xulrunner/src/EmbedStream.cpp b/embed/xulrunner/src/EmbedStream.cpp new file mode 100644 index 000000000..6cd08d400 --- /dev/null +++ b/embed/xulrunner/src/EmbedStream.cpp @@ -0,0 +1,311 @@ +/* + * Copyright © Christopher Blizzard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * --------------------------------------------------------------------------- + * Derived from Mozilla.org code, which had the following attributions: + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved. + * Portions created by the Initial Developer are Copyright © 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Christopher Blizzard <blizzard@mozilla.org> + * --------------------------------------------------------------------------- + * + * $Id$ + */ + +#include <mozilla-config.h> +#include <config.h> + +#include <nsIPipe.h> +#include <nsIInputStream.h> +#include <nsIOutputStream.h> +#include <nsIContentViewerContainer.h> +#include <nsIDocumentLoaderFactory.h> +#include <nsNetUtil.h> +#include <prmem.h> + +#include "nsXPCOMCID.h" +#include "nsICategoryManager.h" + +#include "nsIContentViewer.h" + +#include "EmbedStream.h" +#include "EmbedPrivate.h" +#include "EmbedWindow.h" +#include "nsReadableUtils.h" + +// nsIInputStream interface + +NS_IMPL_ISUPPORTS1(EmbedStream, nsIInputStream) + +EmbedStream::EmbedStream() +{ + mOwner = nsnull; + mOffset = 0; + mDoingStream = PR_FALSE; +} + +EmbedStream::~EmbedStream() +{ +} + +void +EmbedStream::InitOwner(EmbedPrivate *aOwner) +{ + mOwner = aOwner; +} + +NS_METHOD +EmbedStream::Init(void) +{ + nsresult rv = NS_OK; + + nsCOMPtr<nsIInputStream> bufInStream; + nsCOMPtr<nsIOutputStream> bufOutStream; + + rv = NS_NewPipe(getter_AddRefs(bufInStream), + getter_AddRefs(bufOutStream)); + + if (NS_FAILED(rv)) return rv; + + mInputStream = bufInStream; + mOutputStream = bufOutStream; + return NS_OK; +} + +NS_METHOD +EmbedStream::OpenStream(const char *aBaseURI, const char *aContentType) +{ + NS_ENSURE_ARG_POINTER(aBaseURI); + NS_ENSURE_ARG_POINTER(aContentType); + + nsresult rv = NS_OK; + + // if we're already doing a stream then close the current one + if (mDoingStream) + CloseStream(); + + // set our state + mDoingStream = PR_TRUE; + + // initialize our streams + rv = Init(); + if (NS_FAILED(rv)) + return rv; + + // get the content area of our web browser + nsCOMPtr<nsIWebBrowser> browser; + mOwner->mWindow->GetWebBrowser(getter_AddRefs(browser)); + + // get the viewer container + nsCOMPtr<nsIContentViewerContainer> viewerContainer; + viewerContainer = do_GetInterface(browser); + + // create a new uri object + nsCOMPtr<nsIURI> uri; + nsCAutoString spec(aBaseURI); + rv = NS_NewURI(getter_AddRefs(uri), spec.get()); + + if (NS_FAILED(rv)) + return rv; + + // create a new load group + rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), nsnull); + if (NS_FAILED(rv)) + return rv; + + // create a new input stream channel + rv = NS_NewInputStreamChannel(getter_AddRefs(mChannel), uri, + static_cast<nsIInputStream *>(this), + nsDependentCString(aContentType), + EmptyCString()); + if (NS_FAILED(rv)) + return rv; + + // set the channel's load group + rv = mChannel->SetLoadGroup(mLoadGroup); + if (NS_FAILED(rv)) + return rv; + + // find a document loader for this content type + + nsXPIDLCString docLoaderContractID; + nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); + if (NS_FAILED(rv)) + return rv; + rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aContentType, + getter_Copies(docLoaderContractID)); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory; + docLoaderFactory = do_GetService(docLoaderContractID.get(), &rv); + if (NS_FAILED(rv)) + return rv; + + // ok, create an instance of the content viewer for that command and + // mime type + nsCOMPtr<nsIContentViewer> contentViewer; + rv = docLoaderFactory->CreateInstance("view", mChannel, mLoadGroup, + aContentType, viewerContainer, + nsnull, + getter_AddRefs(mStreamListener), + getter_AddRefs(contentViewer)); + if (NS_FAILED(rv)) + return rv; + + // set the container viewer container for this content view + rv = contentViewer->SetContainer(viewerContainer); + if (NS_FAILED(rv)) + return rv; + + // embed this sucker + rv = viewerContainer->Embed(contentViewer, "view", nsnull); + if (NS_FAILED(rv)) + return rv; + + // start our request + nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel); + rv = mStreamListener->OnStartRequest(request, NULL); + if (NS_FAILED(rv)) + return rv; + + return NS_OK; +} + +NS_METHOD +EmbedStream::AppendToStream(const char *aData, gint32 aLen) +{ + nsresult rv; + + // append the data + rv = Append(aData, aLen); + if (NS_FAILED(rv)) + return rv; + + // notify our listeners + nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel); + rv = mStreamListener->OnDataAvailable(request, + NULL, + static_cast<nsIInputStream *>(this), + mOffset, /* offset */ + aLen); /* len */ + // move our counter + mOffset += aLen; + if (NS_FAILED(rv)) + return rv; + + return NS_OK; +} + +NS_METHOD +EmbedStream::CloseStream(void) +{ + nsresult rv = NS_OK; + + NS_ENSURE_STATE(mDoingStream); + mDoingStream = PR_FALSE; + + nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel, &rv); + if (NS_FAILED(rv)) + goto loser; + + rv = mStreamListener->OnStopRequest(request, NULL, NS_OK); + if (NS_FAILED(rv)) + return rv; + + loser: + mLoadGroup = nsnull; + mChannel = nsnull; + mStreamListener = nsnull; + mOffset = 0; + + return rv; +} + +NS_METHOD +EmbedStream::Append(const char *aData, PRUint32 aLen) +{ + nsresult rv = NS_OK; + PRUint32 bytesWritten = 0; + rv = mOutputStream->Write(aData, aLen, &bytesWritten); + if (NS_FAILED(rv)) + return rv; + + NS_ASSERTION(bytesWritten == aLen, + "underlying byffer couldn't handle the write"); + return rv; +} + +NS_IMETHODIMP +EmbedStream::Available(PRUint32 *_retval) +{ + return mInputStream->Available(_retval); +} + +NS_IMETHODIMP +EmbedStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval) +{ + return mInputStream->Read(aBuf, aCount, _retval); +} + +NS_IMETHODIMP EmbedStream::Close(void) +{ + return mInputStream->Close(); +} + +NS_IMETHODIMP +EmbedStream::ReadSegments(nsWriteSegmentFun aWriter, void * aClosure, + PRUint32 aCount, PRUint32 *_retval) +{ + char *readBuf = (char *)nsMemory::Alloc(aCount); + PRUint32 nBytes; + + if (!readBuf) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = mInputStream->Read(readBuf, aCount, &nBytes); + + *_retval = 0; + + if (NS_SUCCEEDED(rv)) { + PRUint32 writeCount = 0; + rv = aWriter(this, aClosure, readBuf, 0, nBytes, &writeCount); + + // XXX writeCount may be less than nBytes!! This is the wrong + // way to synthesize ReadSegments. + NS_ASSERTION(writeCount == nBytes, "data loss"); + + // errors returned from the writer end here! + rv = NS_OK; + } + + nsMemory::Free(readBuf); + + return rv; +} + +NS_IMETHODIMP +EmbedStream::IsNonBlocking(PRBool *aNonBlocking) +{ + return mInputStream->IsNonBlocking(aNonBlocking); +} |