Back to index

lightning-sunbird  0.9+nobinonly
nsEmbedStream.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 "nsXPCOMCID.h"
00047 #include "nsICategoryManager.h"
00048 
00049 #include "nsIContentViewer.h"
00050 
00051 #include "nsEmbedStream.h"
00052 #include "nsReadableUtils.h"
00053 
00054 // nsIInputStream interface
00055 
00056 NS_IMPL_ISUPPORTS1(nsEmbedStream, nsIInputStream)
00057 
00058 nsEmbedStream::nsEmbedStream()
00059 {
00060   mOwner       = nsnull;
00061   mOffset      = 0;
00062   mDoingStream = PR_FALSE;
00063 }
00064 
00065 nsEmbedStream::~nsEmbedStream()
00066 {
00067 }
00068 
00069 void
00070 nsEmbedStream::InitOwner(nsIWebBrowser *aOwner)
00071 {
00072   mOwner = aOwner;
00073 }
00074 
00075 NS_METHOD
00076 nsEmbedStream::Init(void)
00077 {
00078   nsresult rv = NS_OK;
00079 
00080   nsCOMPtr<nsIInputStream> bufInStream;
00081   nsCOMPtr<nsIOutputStream> bufOutStream;
00082 
00083   rv = NS_NewPipe(getter_AddRefs(bufInStream),
00084                   getter_AddRefs(bufOutStream));
00085 
00086   if (NS_FAILED(rv)) return rv;
00087  
00088   mInputStream  = bufInStream;
00089   mOutputStream = bufOutStream;
00090 
00091   return NS_OK;
00092 }
00093 
00094 NS_METHOD
00095 nsEmbedStream::OpenStream(nsIURI *aBaseURI, const nsACString& aContentType)
00096 {
00097   NS_ENSURE_ARG_POINTER(aBaseURI);
00098   NS_ENSURE_TRUE(IsASCII(aContentType), NS_ERROR_INVALID_ARG);
00099 
00100   // if we're already doing a stream, return an error
00101   if (mDoingStream)
00102     return NS_ERROR_IN_PROGRESS;
00103 
00104   // set our state
00105   mDoingStream = PR_TRUE;
00106 
00107   // initialize our streams
00108   nsresult rv = Init();
00109   if (NS_FAILED(rv))
00110     return rv;
00111 
00112   // get the viewer container
00113   nsCOMPtr<nsIContentViewerContainer> viewerContainer;
00114   viewerContainer = do_GetInterface(mOwner);
00115 
00116   // create a new load group
00117   rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), nsnull);
00118   if (NS_FAILED(rv))
00119     return rv;
00120 
00121   // create a new input stream channel
00122   rv = NS_NewInputStreamChannel(getter_AddRefs(mChannel), aBaseURI,
00123                             NS_STATIC_CAST(nsIInputStream *, this),
00124                             aContentType);
00125   if (NS_FAILED(rv))
00126     return rv;
00127 
00128   // set the channel's load group
00129   rv = mChannel->SetLoadGroup(mLoadGroup);
00130   if (NS_FAILED(rv))
00131     return rv;
00132 
00133   // find a document loader for this content type
00134 
00135   const nsCString& flatContentType = PromiseFlatCString(aContentType);
00136 
00137   nsXPIDLCString docLoaderContractID;
00138   nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
00139   if (NS_FAILED(rv))
00140     return rv;
00141   rv = catMan->GetCategoryEntry("Gecko-Content-Viewers",
00142                                 flatContentType.get(),
00143                                 getter_Copies(docLoaderContractID));
00144   // Note: When the category manager does not find an entry for the requested
00145   // contract ID, it will return NS_ERROR_NOT_AVAILABLE. This conveniently
00146   // matches what this method wants to return in that case.
00147   if (NS_FAILED(rv))
00148     return rv;
00149 
00150   nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory;  
00151   docLoaderFactory = do_GetService(docLoaderContractID.get(), &rv);
00152   if (NS_FAILED(rv))
00153     return rv;
00154 
00155   // ok, create an instance of the content viewer for that command and
00156   // mime type
00157   nsCOMPtr<nsIContentViewer> contentViewer;
00158   rv = docLoaderFactory->CreateInstance("view", mChannel, mLoadGroup,
00159                                    flatContentType.get(), viewerContainer,
00160                                    nsnull,
00161                                    getter_AddRefs(mStreamListener),
00162                                    getter_AddRefs(contentViewer));
00163   if (NS_FAILED(rv))
00164     return rv;
00165 
00166   // set the container viewer container for this content view
00167   rv = contentViewer->SetContainer(viewerContainer);
00168   if (NS_FAILED(rv))
00169     return rv;
00170 
00171   // embed this sucker
00172   rv = viewerContainer->Embed(contentViewer, "view", nsnull);
00173   if (NS_FAILED(rv))
00174     return rv;
00175 
00176   // start our request
00177   rv = mStreamListener->OnStartRequest(mChannel, NULL);
00178   if (NS_FAILED(rv))
00179     return rv;
00180   
00181   return NS_OK;
00182 }
00183 
00184 NS_METHOD
00185 nsEmbedStream::AppendToStream(const PRUint8 *aData, PRUint32 aLen)
00186 {
00187   nsresult rv;
00188 
00189   // append the data
00190   rv = Append(aData, aLen);
00191   if (NS_FAILED(rv))
00192     return rv;
00193 
00194   // notify our listeners
00195   rv = mStreamListener->OnDataAvailable(mChannel,
00196                                    NULL,
00197                                    NS_STATIC_CAST(nsIInputStream *, this),
00198                                    mOffset, /* offset */
00199                                    aLen); /* len */
00200   // move our counter
00201   mOffset += aLen;
00202   if (NS_FAILED(rv))
00203     return rv;
00204 
00205   return NS_OK;
00206 }
00207 
00208 NS_METHOD
00209 nsEmbedStream::CloseStream(void)
00210 {
00211   nsresult rv = NS_OK;
00212 
00213   // NS_ENSURE_STATE returns NS_ERROR_UNEXPECTED if the condition isn't
00214   // satisfied; this is exactly what we want to return.
00215   NS_ENSURE_STATE(mDoingStream);
00216   mDoingStream = PR_FALSE;
00217 
00218   rv = mStreamListener->OnStopRequest(mChannel, NULL, NS_OK);
00219   if (NS_FAILED(rv))
00220     return rv;
00221 
00222   mLoadGroup = nsnull;
00223   mChannel = nsnull;
00224   mStreamListener = nsnull;
00225   mOffset = 0;
00226 
00227   return rv;
00228 }
00229 
00230 NS_METHOD
00231 nsEmbedStream::Append(const PRUint8 *aData, PRUint32 aLen)
00232 {
00233   PRUint32 bytesWritten = 0;
00234   nsresult rv = mOutputStream->Write(NS_REINTERPRET_CAST(const char*, aData),
00235                                      aLen, &bytesWritten);
00236   if (NS_FAILED(rv))
00237     return rv;
00238   
00239   NS_ASSERTION(bytesWritten == aLen,
00240               "underlying byffer couldn't handle the write");
00241   return rv;
00242 }
00243 
00244 NS_IMETHODIMP
00245 nsEmbedStream::Available(PRUint32 *_retval)
00246 {
00247   return mInputStream->Available(_retval);
00248 }
00249 
00250 NS_IMETHODIMP
00251 nsEmbedStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
00252 {
00253   return mInputStream->Read(aBuf, aCount, _retval);
00254 }
00255 
00256 NS_IMETHODIMP nsEmbedStream::Close(void)
00257 {
00258   return mInputStream->Close();
00259 }
00260 
00261 NS_IMETHODIMP
00262 nsEmbedStream::ReadSegments(nsWriteSegmentFun aWriter, void * aClosure,
00263                          PRUint32 aCount, PRUint32 *_retval)
00264 {
00265   return mInputStream->ReadSegments(aWriter, aClosure, aCount, _retval);
00266 }
00267 
00268 NS_IMETHODIMP
00269 nsEmbedStream::IsNonBlocking(PRBool *aNonBlocking)
00270 {
00271     return mInputStream->IsNonBlocking(aNonBlocking);
00272 }