aboutsummaryrefslogtreecommitdiffstats
path: root/embed/xulrunner/src/EmbedStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'embed/xulrunner/src/EmbedStream.cpp')
-rw-r--r--embed/xulrunner/src/EmbedStream.cpp311
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);
+}