LCOV - app.info - content/base/src/nsSyncLoadService.cpp

LCOV - code coverage report
| Current view: | directory - content/base/src - nsSyncLoadService.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 147 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 25 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Peter Van der Beken <peterv@netscape.com>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : /*
          40                 :  * A service that provides methods for synchronously loading a DOM in various ways.
          41                 :  */
          42                 :
          43                 : #include "nsSyncLoadService.h"
          44                 : #include "nsCOMPtr.h"
          45                 : #include "nsIChannel.h"
          46                 : #include "nsIChannelEventSink.h"
          47                 : #include "nsIAsyncVerifyRedirectCallback.h"
          48                 : #include "nsIInterfaceRequestor.h"
          49                 : #include "nsString.h"
          50                 : #include "nsWeakReference.h"
          51                 : #include "nsIDocument.h"
          52                 : #include "nsIDOMDocument.h"
          53                 : #include "nsIScriptSecurityManager.h"
          54                 : #include "nsContentUtils.h"
          55                 : #include "nsThreadUtils.h"
          56                 : #include "nsNetUtil.h"
          57                 : #include "nsAutoPtr.h"
          58                 : #include "nsStreamUtils.h"
          59                 : #include "nsCrossSiteListenerProxy.h"
          60                 :
          61                 : /**
          62                 :  * This class manages loading a single XML document
          63                 :  */
          64                 :
          65                 : class nsSyncLoader : public nsIStreamListener,
          66                 :                      public nsIChannelEventSink,
          67                 :                      public nsIInterfaceRequestor,
          68                 :                      public nsSupportsWeakReference
          69                 : {
          70                 : public:
          71               0 :     nsSyncLoader() : mLoading(false) {}
          72                 :     virtual ~nsSyncLoader();
          73                 :
          74                 :     NS_DECL_ISUPPORTS
          75                 :
          76                 :     nsresult LoadDocument(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
          77                 :                           bool aChannelIsSync, bool aForceToXML,
          78                 :                           nsIDOMDocument** aResult);
          79                 :
          80               0 :     NS_FORWARD_NSISTREAMLISTENER(mListener->)
          81                 :     NS_DECL_NSIREQUESTOBSERVER
          82                 :
          83                 :     NS_DECL_NSICHANNELEVENTSINK
          84                 :
          85                 :     NS_DECL_NSIINTERFACEREQUESTOR
          86                 :
          87                 : private:
          88                 :     nsresult PushAsyncStream(nsIStreamListener* aListener);
          89                 :     nsresult PushSyncStream(nsIStreamListener* aListener);
          90                 :
          91                 :     nsCOMPtr<nsIChannel> mChannel;
          92                 :     nsCOMPtr<nsIStreamListener> mListener;
          93                 :     bool mLoading;
          94                 :     nsresult mAsyncLoadStatus;
          95                 : };
          96                 :
          97                 : class nsForceXMLListener : public nsIStreamListener
          98                 : {
          99                 : public:
         100                 :     nsForceXMLListener(nsIStreamListener* aListener);
         101                 :     virtual ~nsForceXMLListener();
         102                 :
         103                 :     NS_DECL_ISUPPORTS
         104               0 :     NS_FORWARD_NSISTREAMLISTENER(mListener->)
         105                 :     NS_DECL_NSIREQUESTOBSERVER
         106                 :
         107                 : private:
         108                 :     nsCOMPtr<nsIStreamListener> mListener;
         109                 : };
         110                 :
         111               0 : nsForceXMLListener::nsForceXMLListener(nsIStreamListener* aListener)
         112               0 :     : mListener(aListener)
         113                 : {
         114               0 : }
         115                 :
         116               0 : nsForceXMLListener::~nsForceXMLListener()
         117                 : {
         118               0 : }
         119                 :
         120               0 : NS_IMPL_ISUPPORTS2(nsForceXMLListener,
         121                 :                    nsIStreamListener,
         122                 :                    nsIRequestObserver)
         123                 :
         124                 : NS_IMETHODIMP
         125               0 : nsForceXMLListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
         126                 : {
         127                 :     nsresult status;
         128               0 :     aRequest->GetStatus(&status);
         129               0 :     nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
         130               0 :     if (channel && NS_SUCCEEDED(status)) {
         131               0 :       channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));
         132                 :     }
         133                 :
         134               0 :     return mListener->OnStartRequest(aRequest, aContext);
         135                 : }
         136                 :
         137                 : NS_IMETHODIMP
         138               0 : nsForceXMLListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
         139                 :                                   nsresult aStatusCode)
         140                 : {
         141               0 :     return mListener->OnStopRequest(aRequest, aContext, aStatusCode);
         142                 : }
         143                 :
         144               0 : nsSyncLoader::~nsSyncLoader()
         145                 : {
         146               0 :     if (mLoading && mChannel) {
         147               0 :         mChannel->Cancel(NS_BINDING_ABORTED);
         148                 :     }
         149               0 : }
         150                 :
         151               0 : NS_IMPL_ISUPPORTS5(nsSyncLoader,
         152                 :                    nsIStreamListener,
         153                 :                    nsIRequestObserver,
         154                 :                    nsIChannelEventSink,
         155                 :                    nsIInterfaceRequestor,
         156                 :                    nsISupportsWeakReference)
         157                 :
         158                 : nsresult
         159               0 : nsSyncLoader::LoadDocument(nsIChannel* aChannel,
         160                 :                            nsIPrincipal *aLoaderPrincipal,
         161                 :                            bool aChannelIsSync,
         162                 :                            bool aForceToXML,
         163                 :                            nsIDOMDocument **aResult)
         164                 : {
         165               0 :     NS_ENSURE_ARG_POINTER(aResult);
         166               0 :     *aResult = nsnull;
         167               0 :     nsresult rv = NS_OK;
         168                 :
         169               0 :     nsCOMPtr<nsIURI> loaderUri;
         170               0 :     if (aLoaderPrincipal) {
         171               0 :         aLoaderPrincipal->GetURI(getter_AddRefs(loaderUri));
         172                 :     }
         173                 :
         174               0 :     mChannel = aChannel;
         175               0 :     nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
         176               0 :     if (http) {
         177               0 :         http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
         178               0 :                                NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
         179               0 :                                false);
         180               0 :         if (loaderUri) {
         181               0 :             http->SetReferrer(loaderUri);
         182                 :         }
         183                 :     }
         184                 :
         185                 :     // Hook us up to listen to redirects and the like.
         186                 :     // Do this before setting up the cross-site proxy since
         187                 :     // that installs its own proxies.
         188               0 :     mChannel->SetNotificationCallbacks(this);
         189                 :
         190                 :     // Get the loadgroup of the channel
         191               0 :     nsCOMPtr<nsILoadGroup> loadGroup;
         192               0 :     rv = aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
         193               0 :     NS_ENSURE_SUCCESS(rv, rv);
         194                 :
         195                 :     // Create document
         196               0 :     nsCOMPtr<nsIDocument> document;
         197               0 :     rv = NS_NewXMLDocument(getter_AddRefs(document));
         198               0 :     NS_ENSURE_SUCCESS(rv, rv);
         199                 :
         200                 :     // Start the document load. Do this before we attach the load listener
         201                 :     // since we reset the document which drops all observers.
         202               0 :     nsCOMPtr<nsIStreamListener> listener;
         203               0 :     rv = document->StartDocumentLoad(kLoadAsData, mChannel,
         204                 :                                      loadGroup, nsnull,
         205               0 :                                      getter_AddRefs(listener),
         206               0 :                                      true);
         207               0 :     NS_ENSURE_SUCCESS(rv, rv);
         208                 :
         209               0 :     if (aForceToXML) {
         210                 :         nsCOMPtr<nsIStreamListener> forceListener =
         211               0 :             new nsForceXMLListener(listener);
         212               0 :         listener.swap(forceListener);
         213                 :     }
         214                 :
         215               0 :     if (aLoaderPrincipal) {
         216                 :         listener = new nsCORSListenerProxy(listener, aLoaderPrincipal,
         217               0 :                                            mChannel, false, &rv);
         218               0 :         NS_ENSURE_SUCCESS(rv, rv);
         219                 :     }
         220                 :
         221               0 :     if (aChannelIsSync) {
         222               0 :         rv = PushSyncStream(listener);
         223                 :     }
         224                 :     else {
         225               0 :         rv = PushAsyncStream(listener);
         226                 :     }
         227                 :
         228               0 :     http = do_QueryInterface(mChannel);
         229               0 :     if (NS_SUCCEEDED(rv) && http) {
         230                 :         bool succeeded;
         231               0 :         if (NS_FAILED(http->GetRequestSucceeded(&succeeded)) || !succeeded) {
         232               0 :             rv = NS_ERROR_FAILURE;
         233                 :         }
         234                 :     }
         235               0 :     mChannel = nsnull;
         236                 :
         237                 :     // check that the load succeeded
         238               0 :     NS_ENSURE_SUCCESS(rv, rv);
         239                 :
         240               0 :     NS_ENSURE_TRUE(document->GetRootElement(), NS_ERROR_FAILURE);
         241                 :
         242               0 :     return CallQueryInterface(document, aResult);
         243                 : }
         244                 :
         245                 : nsresult
         246               0 : nsSyncLoader::PushAsyncStream(nsIStreamListener* aListener)
         247                 : {
         248               0 :     mListener = aListener;
         249                 :
         250               0 :     mAsyncLoadStatus = NS_OK;
         251                 :
         252                 :     // Start reading from the channel
         253               0 :     nsresult rv = mChannel->AsyncOpen(this, nsnull);
         254                 :
         255               0 :     if (NS_SUCCEEDED(rv)) {
         256                 :         // process events until we're finished.
         257               0 :         mLoading = true;
         258               0 :         nsIThread *thread = NS_GetCurrentThread();
         259               0 :         while (mLoading && NS_SUCCEEDED(rv)) {
         260                 :             bool processedEvent;
         261               0 :             rv = thread->ProcessNextEvent(true, &processedEvent);
         262               0 :             if (NS_SUCCEEDED(rv) && !processedEvent)
         263               0 :                 rv = NS_ERROR_UNEXPECTED;
         264                 :         }
         265                 :     }
         266                 :
         267               0 :     mListener = nsnull;
         268                 :
         269               0 :     NS_ENSURE_SUCCESS(rv, rv);
         270                 :
         271                 :     // Note that if AsyncOpen failed that's ok -- the only caller of
         272                 :     // this method nulls out mChannel immediately after we return.
         273                 :
         274               0 :     return mAsyncLoadStatus;
         275                 : }
         276                 :
         277                 : nsresult
         278               0 : nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
         279                 : {
         280               0 :     nsCOMPtr<nsIInputStream> in;
         281               0 :     nsresult rv = mChannel->Open(getter_AddRefs(in));
         282               0 :     NS_ENSURE_SUCCESS(rv, rv);
         283                 :
         284               0 :     mLoading = true;
         285               0 :     rv = nsSyncLoadService::PushSyncStreamToListener(in, aListener, mChannel);
         286               0 :     mLoading = false;
         287                 :
         288               0 :     return rv;
         289                 : }
         290                 :
         291                 : NS_IMETHODIMP
         292               0 : nsSyncLoader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
         293                 : {
         294               0 :     return mListener->OnStartRequest(aRequest, aContext);
         295                 : }
         296                 :
         297                 : NS_IMETHODIMP
         298               0 : nsSyncLoader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
         299                 :                             nsresult aStatusCode)
         300                 : {
         301               0 :     if (NS_SUCCEEDED(mAsyncLoadStatus) && NS_FAILED(aStatusCode)) {
         302               0 :         mAsyncLoadStatus = aStatusCode;
         303                 :     }
         304               0 :     nsresult rv = mListener->OnStopRequest(aRequest, aContext, aStatusCode);
         305               0 :     if (NS_SUCCEEDED(mAsyncLoadStatus) && NS_FAILED(rv)) {
         306               0 :         mAsyncLoadStatus = rv;
         307                 :     }
         308               0 :     mLoading = false;
         309                 :
         310               0 :     return rv;
         311                 : }
         312                 :
         313                 : NS_IMETHODIMP
         314               0 : nsSyncLoader::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
         315                 :                                      nsIChannel *aNewChannel,
         316                 :                                      PRUint32 aFlags,
         317                 :                                      nsIAsyncVerifyRedirectCallback *callback)
         318                 : {
         319               0 :     NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
         320                 :
         321               0 :     mChannel = aNewChannel;
         322                 :
         323               0 :     callback->OnRedirectVerifyCallback(NS_OK);
         324               0 :     return NS_OK;
         325                 : }
         326                 :
         327                 : NS_IMETHODIMP
         328               0 : nsSyncLoader::GetInterface(const nsIID & aIID,
         329                 :                            void **aResult)
         330                 : {
         331               0 :     return QueryInterface(aIID, aResult);
         332                 : }
         333                 :
         334                 : /* static */
         335                 : nsresult
         336               0 : nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
         337                 :                                 nsILoadGroup *aLoadGroup, bool aForceToXML,
         338                 :                                 nsIDOMDocument** aResult)
         339                 : {
         340               0 :     nsCOMPtr<nsIChannel> channel;
         341               0 :     nsresult rv = NS_NewChannel(getter_AddRefs(channel), aURI, nsnull,
         342               0 :                                 aLoadGroup);
         343               0 :     NS_ENSURE_SUCCESS(rv, rv);
         344                 :
         345               0 :     if (!aForceToXML) {
         346               0 :         channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));
         347                 :     }
         348                 :
         349               0 :     bool isChrome = false, isResource = false;
         350               0 :     bool isSync = (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) &&
         351                 :                      isChrome) ||
         352               0 :                     (NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) &&
         353               0 :                      isResource);
         354                 :
         355               0 :     nsRefPtr<nsSyncLoader> loader = new nsSyncLoader();
         356                 :     return loader->LoadDocument(channel, aLoaderPrincipal, isSync,
         357               0 :                                 aForceToXML, aResult);
         358                 :
         359                 : }
         360                 :
         361                 : /* static */
         362                 : nsresult
         363               0 : nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
         364                 :                                             nsIStreamListener* aListener,
         365                 :                                             nsIChannel* aChannel)
         366                 : {
         367                 :     // Set up buffering stream
         368                 :     nsresult rv;
         369               0 :     nsCOMPtr<nsIInputStream> bufferedStream;
         370               0 :     if (!NS_InputStreamIsBuffered(aIn)) {
         371                 :         PRInt32 chunkSize;
         372               0 :         rv = aChannel->GetContentLength(&chunkSize);
         373               0 :         if (NS_FAILED(rv)) {
         374               0 :             chunkSize = 4096;
         375                 :         }
         376               0 :         chunkSize = NS_MIN(PRInt32(PR_UINT16_MAX), chunkSize);
         377                 :
         378               0 :         rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
         379               0 :                                        chunkSize);
         380               0 :         NS_ENSURE_SUCCESS(rv, rv);
         381                 :
         382               0 :         aIn = bufferedStream;
         383                 :     }
         384                 :
         385                 :     // Load
         386               0 :     rv = aListener->OnStartRequest(aChannel, nsnull);
         387               0 :     if (NS_SUCCEEDED(rv)) {
         388               0 :         PRUint32 sourceOffset = 0;
         389               0 :         while (1) {
         390               0 :             PRUint32 readCount = 0;
         391               0 :             rv = aIn->Available(&readCount);
         392               0 :             if (NS_FAILED(rv) || !readCount) {
         393               0 :                 if (rv == NS_BASE_STREAM_CLOSED) {
         394                 :                     // End of file, but not an error
         395               0 :                     rv = NS_OK;
         396                 :                 }
         397               0 :                 break;
         398                 :             }
         399                 :
         400                 :             rv = aListener->OnDataAvailable(aChannel, nsnull, aIn,
         401               0 :                                             sourceOffset, readCount);
         402               0 :             if (NS_FAILED(rv)) {
         403               0 :                 break;
         404                 :             }
         405               0 :             sourceOffset += readCount;
         406                 :         }
         407                 :     }
         408               0 :     if (NS_FAILED(rv)) {
         409               0 :         aChannel->Cancel(rv);
         410                 :     }
         411               0 :     aListener->OnStopRequest(aChannel, nsnull, rv);
         412                 :
         413               0 :     return rv;
         414                 : }

Generated by: LCOV version 1.7