Back to index

lightning-sunbird  0.9+nobinonly
EmbedStream.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard.  All Rights Reserved.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Christopher Blizzard <blizzard@mozilla.org>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <nsIPipe.h>
00039 #include <nsIInputStream.h>
00040 #include <nsIOutputStream.h>
00041 #include <nsIContentViewerContainer.h>
00042 #include <nsIDocumentLoaderFactory.h>
00043 #include <nsNetUtil.h>
00044 #include <prmem.h>
00045 
00046 #include "nsIContentViewer.h"
00047 #include "nsXPCOMCID.h"
00048 #include "nsICategoryManager.h"
00049 
00050 #include "EmbedStream.h"
00051 #include "EmbedPrivate.h"
00052 #include "EmbedWindow.h"
00053 
00054 // nsIInputStream interface
00055 
00056 NS_IMPL_ISUPPORTS1(EmbedStream, nsIInputStream)
00057 
00058 EmbedStream::EmbedStream()
00059 {
00060        NS_INIT_ISUPPORTS();
00061   mOwner       = nsnull;
00062   mOffset      = 0;
00063   mDoingStream = PR_FALSE;
00064 }
00065 
00066 EmbedStream::~EmbedStream()
00067 {
00068 }
00069 
00070 void
00071 EmbedStream::InitOwner(EmbedPrivate *aOwner)
00072 {
00073   mOwner = aOwner;
00074 }
00075 
00076 NS_METHOD
00077 EmbedStream::Init(void)
00078 {
00079   nsresult rv = NS_OK;
00080 
00081   nsCOMPtr<nsIInputStream> bufInStream;
00082   nsCOMPtr<nsIOutputStream> bufOutStream;
00083   
00084   rv = NS_NewPipe(getter_AddRefs(bufInStream),
00085                 getter_AddRefs(bufOutStream));
00086 
00087   if (NS_FAILED(rv)) return rv;
00088   
00089   mInputStream  = bufInStream;
00090   mOutputStream = bufOutStream;
00091   return NS_OK;
00092 }
00093 
00094 NS_METHOD
00095 EmbedStream::OpenStream(const char *aBaseURI, const char *aContentType)
00096 {
00097   NS_ENSURE_ARG_POINTER(aBaseURI);
00098   NS_ENSURE_ARG_POINTER(aContentType);
00099 
00100   nsresult rv = NS_OK;
00101 
00102   // if we're already doing a stream then close the current one
00103   if (mDoingStream)
00104     CloseStream();
00105 
00106   // set our state
00107   mDoingStream = PR_TRUE;
00108 
00109   // initialize our streams
00110   rv = Init();
00111   if (NS_FAILED(rv))
00112     return rv;
00113 
00114   // get the content area of our web browser
00115   nsCOMPtr<nsIWebBrowser> browser;
00116   mOwner->mWindow->GetWebBrowser(getter_AddRefs(browser));
00117 
00118   // get the viewer container
00119   nsCOMPtr<nsIContentViewerContainer> viewerContainer;
00120   viewerContainer = do_GetInterface(browser);
00121 
00122   // create a new uri object
00123   nsCOMPtr<nsIURI> uri;
00124   nsCAutoString spec(aBaseURI);
00125   rv = NS_NewURI(getter_AddRefs(uri), spec.get());
00126   
00127   if (NS_FAILED(rv))
00128     return rv;
00129 
00130   // create a new load group
00131   rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), nsnull);
00132   if (NS_FAILED(rv))
00133     return rv;
00134 
00135   // create a new input stream channel
00136   rv = NS_NewInputStreamChannel(getter_AddRefs(mChannel), uri,
00137                             NS_STATIC_CAST(nsIInputStream *, this),
00138                             nsDependentCString(aContentType));
00139   if (NS_FAILED(rv))
00140     return rv;
00141 
00142   // set the channel's load group
00143   rv = mChannel->SetLoadGroup(mLoadGroup);
00144   if (NS_FAILED(rv))
00145     return rv;
00146 
00147   // find a document loader for this content type
00148   nsXPIDLCString docLoaderContractID;
00149   nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
00150   if (NS_FAILED(rv))
00151     return rv;
00152   rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aContentType,
00153                                 getter_Copies(docLoaderContractID));
00154   if (NS_FAILED(rv))
00155     return rv;
00156 
00157   nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory;  
00158   docLoaderFactory = do_GetService(docLoaderContractID.get(), &rv);
00159   if (NS_FAILED(rv))
00160     return rv;
00161 
00162   // ok, create an instance of the content viewer for that command and
00163   // mime type
00164   nsCOMPtr<nsIContentViewer> contentViewer;
00165   rv = docLoaderFactory->CreateInstance("view", mChannel, mLoadGroup,
00166                                    aContentType, viewerContainer,
00167                                    nsnull,
00168                                    getter_AddRefs(mStreamListener),
00169                                    getter_AddRefs(contentViewer));
00170   if (NS_FAILED(rv))
00171     return rv;
00172 
00173   // set the container viewer container for this content view
00174   rv = contentViewer->SetContainer(viewerContainer);
00175   if (NS_FAILED(rv))
00176     return rv;
00177 
00178   // embed this sucker
00179   rv = viewerContainer->Embed(contentViewer, "view", nsnull);
00180   if (NS_FAILED(rv))
00181     return rv;
00182 
00183   // start our request
00184   nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel); 
00185   rv = mStreamListener->OnStartRequest(request, NULL);
00186   if (NS_FAILED(rv))
00187     return rv;
00188   
00189   return NS_OK;
00190 }
00191 
00192 NS_METHOD
00193 EmbedStream::AppendToStream(const char *aData, int aLen)
00194 {
00195   nsresult rv;
00196 
00197   // append the data
00198   rv = Append(aData, aLen);
00199   if (NS_FAILED(rv))
00200     return rv;
00201 
00202   // notify our listeners
00203   nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel); 
00204   rv = mStreamListener->OnDataAvailable(request,
00205                                    NULL,
00206                                    NS_STATIC_CAST(nsIInputStream *, this),
00207                                    mOffset, /* offset */
00208                                    aLen); /* len */
00209   // move our counter
00210   mOffset += aLen;
00211   if (NS_FAILED(rv))
00212     return rv;
00213 
00214   return NS_OK;
00215 }
00216 
00217 NS_METHOD
00218 EmbedStream::CloseStream(void)
00219 {
00220   nsresult rv = NS_OK;
00221 
00222   NS_ENSURE_STATE(mDoingStream);
00223   mDoingStream = PR_FALSE;
00224 
00225   nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel, &rv); 
00226   if (NS_FAILED(rv))
00227     goto loser;
00228   
00229   rv = mStreamListener->OnStopRequest(request, NULL, NS_OK);
00230   if (NS_FAILED(rv))
00231     return rv;
00232 
00233  loser:
00234   mLoadGroup = nsnull;
00235   mChannel = nsnull;
00236   mStreamListener = nsnull;
00237   mOffset = 0;
00238 
00239   return rv;
00240 }
00241 
00242 NS_METHOD
00243 EmbedStream::Append(const char *aData, PRUint32 aLen)
00244 {
00245   nsresult rv = NS_OK;
00246   PRUint32 bytesWritten = 0;
00247   rv = mOutputStream->Write(aData, aLen, &bytesWritten);
00248   if (NS_FAILED(rv))
00249     return rv;
00250   
00251   NS_ASSERTION(bytesWritten == aLen,
00252               "underlying byffer couldn't handle the write");
00253   return rv;
00254 }
00255 
00256 NS_IMETHODIMP
00257 EmbedStream::Available(PRUint32 *_retval)
00258 {
00259   return mInputStream->Available(_retval);
00260 }
00261 
00262 NS_IMETHODIMP
00263 EmbedStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
00264 {
00265   return mInputStream->Read(aBuf, aCount, _retval);
00266 }
00267 
00268 NS_IMETHODIMP EmbedStream::Close(void)
00269 {
00270   return mInputStream->Close();
00271 }
00272 
00273 NS_IMETHODIMP
00274 EmbedStream::ReadSegments(nsWriteSegmentFun aWriter, void * aClosure,
00275                        PRUint32 aCount, PRUint32 *_retval)
00276 {
00277   char *readBuf = (char *)nsMemory::Alloc(aCount);
00278   PRUint32 nBytes;
00279 
00280   if (!readBuf)
00281     return NS_ERROR_OUT_OF_MEMORY;
00282   
00283   nsresult rv = mInputStream->Read(readBuf, aCount, &nBytes);
00284 
00285   *_retval = 0;
00286 
00287   if (NS_SUCCEEDED(rv)) {
00288     PRUint32 writeCount = 0;
00289     rv = aWriter(this, aClosure, readBuf, 0, nBytes, &writeCount);
00290 
00291     // XXX writeCount may be less than nBytes!!  This is the wrong
00292     // way to synthesize ReadSegments.
00293     NS_ASSERTION(writeCount == nBytes, "data loss");
00294   }
00295 
00296   nsMemory::Free(readBuf);
00297 
00298   return rv;
00299 }
00300 
00301 NS_IMETHODIMP
00302 EmbedStream::IsNonBlocking(PRBool *aNonBlocking)
00303 {
00304     return mInputStream->IsNonBlocking(aNonBlocking);
00305 }