LCOV - code coverage report
Current view: directory - netwerk/protocol/wyciwyg - nsWyciwygChannel.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 324 0 0.0 %
Date: 2012-06-02 Functions: 68 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Radha Kulkarni(radha@netscape.com)
      25                 :  *   Michal Novotny <michal.novotny@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsWyciwyg.h"
      42                 : #include "nsWyciwygChannel.h"
      43                 : #include "nsIServiceManager.h"
      44                 : #include "nsILoadGroup.h"
      45                 : #include "nsIScriptSecurityManager.h"
      46                 : #include "nsNetUtil.h"
      47                 : #include "nsContentUtils.h"
      48                 : #include "nsICacheService.h"
      49                 : #include "nsICacheSession.h"
      50                 : #include "nsIParser.h"
      51                 : #include "nsThreadUtils.h"
      52                 : #include "nsProxyRelease.h"
      53                 : 
      54                 : // Must release mChannel on the main thread
      55                 : class nsWyciwygAsyncEvent : public nsRunnable {
      56                 : public:
      57               0 :   nsWyciwygAsyncEvent(nsWyciwygChannel *aChannel) : mChannel(aChannel) {}
      58                 : 
      59               0 :   ~nsWyciwygAsyncEvent()
      60               0 :   {
      61               0 :     nsCOMPtr<nsIThread> thread = do_GetMainThread();
      62               0 :     NS_WARN_IF_FALSE(thread, "Couldn't get the main thread!");
      63               0 :     if (thread) {
      64               0 :       nsIWyciwygChannel *chan = static_cast<nsIWyciwygChannel *>(mChannel);
      65               0 :       mChannel.forget();
      66               0 :       NS_ProxyRelease(thread, chan);
      67                 :     }
      68               0 :   }
      69                 : protected:
      70                 :   nsRefPtr<nsWyciwygChannel> mChannel;
      71                 : };
      72                 : 
      73               0 : class nsWyciwygSetCharsetandSourceEvent : public nsWyciwygAsyncEvent {
      74                 : public:
      75               0 :   nsWyciwygSetCharsetandSourceEvent(nsWyciwygChannel *aChannel)
      76               0 :     : nsWyciwygAsyncEvent(aChannel) {}
      77                 : 
      78               0 :   NS_IMETHOD Run()
      79                 :   {
      80               0 :     mChannel->SetCharsetAndSourceInternal();
      81               0 :     return NS_OK;
      82                 :   }
      83                 : };
      84                 : 
      85               0 : class nsWyciwygWriteEvent : public nsWyciwygAsyncEvent {
      86                 : public:
      87               0 :   nsWyciwygWriteEvent(nsWyciwygChannel *aChannel, const nsAString &aData, 
      88                 :                       const nsACString &spec)
      89               0 :     : nsWyciwygAsyncEvent(aChannel), mData(aData), mSpec(spec) {}
      90                 : 
      91               0 :   NS_IMETHOD Run()
      92                 :   {
      93               0 :     mChannel->WriteToCacheEntryInternal(mData, mSpec);
      94               0 :     return NS_OK;
      95                 :   }
      96                 : private:
      97                 :   nsString mData;
      98                 :   nsCString mSpec;
      99                 : };
     100                 : 
     101               0 : class nsWyciwygCloseEvent : public nsWyciwygAsyncEvent {
     102                 : public:
     103               0 :   nsWyciwygCloseEvent(nsWyciwygChannel *aChannel, nsresult aReason)
     104               0 :     : nsWyciwygAsyncEvent(aChannel), mReason(aReason) {}
     105                 : 
     106               0 :   NS_IMETHOD Run()
     107                 :   {
     108               0 :     mChannel->CloseCacheEntryInternal(mReason);
     109               0 :     return NS_OK;
     110                 :   }
     111                 : private:
     112                 :   nsresult mReason;
     113                 : };
     114                 : 
     115                 : 
     116                 : // nsWyciwygChannel methods 
     117               0 : nsWyciwygChannel::nsWyciwygChannel()
     118                 :   : mStatus(NS_OK),
     119                 :     mIsPending(false),
     120                 :     mCharsetAndSourceSet(false),
     121                 :     mNeedToWriteCharset(false),
     122                 :     mCharsetSource(kCharsetUninitialized),
     123                 :     mContentLength(-1),
     124               0 :     mLoadFlags(LOAD_NORMAL)
     125                 : {
     126               0 : }
     127                 : 
     128               0 : nsWyciwygChannel::~nsWyciwygChannel() 
     129                 : {
     130               0 : }
     131                 : 
     132               0 : NS_IMPL_THREADSAFE_ISUPPORTS6(nsWyciwygChannel,
     133                 :                               nsIChannel,
     134                 :                               nsIRequest,
     135                 :                               nsIStreamListener,
     136                 :                               nsIRequestObserver,
     137                 :                               nsICacheListener, 
     138                 :                               nsIWyciwygChannel)
     139                 : 
     140                 : nsresult
     141               0 : nsWyciwygChannel::Init(nsIURI* uri)
     142                 : {
     143               0 :   NS_ENSURE_ARG_POINTER(uri);
     144                 : 
     145                 :   nsresult rv;
     146                 : 
     147               0 :   mURI = uri;
     148               0 :   mOriginalURI = uri;
     149                 : 
     150                 :   nsCOMPtr<nsICacheService> serv =
     151               0 :     do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
     152               0 :   NS_ENSURE_SUCCESS(rv, rv);
     153                 : 
     154               0 :   rv = serv->GetCacheIOTarget(getter_AddRefs(mCacheIOTarget));
     155               0 :   NS_ENSURE_SUCCESS(rv, rv);
     156                 : 
     157               0 :   return NS_OK;
     158                 : }
     159                 : 
     160                 : ///////////////////////////////////////////////////////////////////////////////
     161                 : // nsIRequest methods:
     162                 : ///////////////////////////////////////////////////////////////////////////////
     163                 : 
     164                 : NS_IMETHODIMP
     165               0 : nsWyciwygChannel::GetName(nsACString &aName)
     166                 : {
     167               0 :   return mURI->GetSpec(aName);
     168                 : }
     169                 :  
     170                 : NS_IMETHODIMP
     171               0 : nsWyciwygChannel::IsPending(bool *aIsPending)
     172                 : {
     173               0 :   *aIsPending = mIsPending;
     174               0 :   return NS_OK;
     175                 : }
     176                 : 
     177                 : NS_IMETHODIMP
     178               0 : nsWyciwygChannel::GetStatus(nsresult *aStatus)
     179                 : {
     180               0 :   if (NS_SUCCEEDED(mStatus) && mPump)
     181               0 :     mPump->GetStatus(aStatus);
     182                 :   else
     183               0 :     *aStatus = mStatus;
     184               0 :   return NS_OK;
     185                 : }
     186                 : 
     187                 : NS_IMETHODIMP
     188               0 : nsWyciwygChannel::Cancel(nsresult status)
     189                 : {
     190               0 :   mStatus = status;
     191               0 :   if (mPump)
     192               0 :     mPump->Cancel(status);
     193                 :   // else we're waiting for OnCacheEntryAvailable
     194               0 :   return NS_OK;
     195                 : }
     196                 :  
     197                 : NS_IMETHODIMP
     198               0 : nsWyciwygChannel::Suspend()
     199                 : {
     200               0 :   if (mPump)
     201               0 :     mPump->Suspend();
     202                 :   // XXX else, we'll ignore this ... and that's probably bad!
     203               0 :   return NS_OK;
     204                 : }
     205                 :  
     206                 : NS_IMETHODIMP
     207               0 : nsWyciwygChannel::Resume()
     208                 : {
     209               0 :   if (mPump)
     210               0 :     mPump->Resume();
     211                 :   // XXX else, we'll ignore this ... and that's probably bad!
     212               0 :   return NS_OK;
     213                 : }
     214                 : 
     215                 : NS_IMETHODIMP
     216               0 : nsWyciwygChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
     217                 : {
     218               0 :   *aLoadGroup = mLoadGroup;
     219               0 :   NS_IF_ADDREF(*aLoadGroup);
     220               0 :   return NS_OK;
     221                 : }
     222                 : 
     223                 : NS_IMETHODIMP
     224               0 : nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
     225                 : {
     226               0 :   mLoadGroup = aLoadGroup;
     227                 :   NS_QueryNotificationCallbacks(mCallbacks,
     228                 :                                 mLoadGroup,
     229                 :                                 NS_GET_IID(nsIProgressEventSink),
     230               0 :                                 getter_AddRefs(mProgressSink));
     231               0 :   return NS_OK;
     232                 : }
     233                 : 
     234                 : NS_IMETHODIMP
     235               0 : nsWyciwygChannel::SetLoadFlags(PRUint32 aLoadFlags)
     236                 : {
     237               0 :   mLoadFlags = aLoadFlags;
     238               0 :   return NS_OK;
     239                 : }
     240                 : 
     241                 : NS_IMETHODIMP
     242               0 : nsWyciwygChannel::GetLoadFlags(PRUint32 * aLoadFlags)
     243                 : {
     244               0 :   *aLoadFlags = mLoadFlags;
     245               0 :   return NS_OK;
     246                 : }
     247                 : 
     248                 : ////////////////////////////////////////////////////////////////////////////////
     249                 : // nsIChannel methods:
     250                 : ///////////////////////////////////////////////////////////////////////////////
     251                 : 
     252                 : NS_IMETHODIMP
     253               0 : nsWyciwygChannel::GetOriginalURI(nsIURI* *aURI)
     254                 : {
     255               0 :   *aURI = mOriginalURI;
     256               0 :   NS_ADDREF(*aURI);
     257               0 :   return NS_OK;
     258                 : }
     259                 : 
     260                 : NS_IMETHODIMP
     261               0 : nsWyciwygChannel::SetOriginalURI(nsIURI* aURI)
     262                 : {
     263               0 :   NS_ENSURE_ARG_POINTER(aURI);
     264               0 :   mOriginalURI = aURI;
     265               0 :   return NS_OK;
     266                 : }
     267                 : 
     268                 : NS_IMETHODIMP
     269               0 : nsWyciwygChannel::GetURI(nsIURI* *aURI)
     270                 : {
     271               0 :   *aURI = mURI;
     272               0 :   NS_IF_ADDREF(*aURI);
     273               0 :   return NS_OK;
     274                 : }
     275                 : 
     276                 : NS_IMETHODIMP
     277               0 : nsWyciwygChannel::GetOwner(nsISupports **aOwner)
     278                 : {
     279               0 :   NS_PRECONDITION(mOwner, "Must have a principal!");
     280               0 :   NS_ENSURE_STATE(mOwner);
     281                 : 
     282               0 :   NS_ADDREF(*aOwner = mOwner);
     283               0 :   return NS_OK;
     284                 : }
     285                 : 
     286                 : NS_IMETHODIMP
     287               0 : nsWyciwygChannel::SetOwner(nsISupports* aOwner)
     288                 : {
     289               0 :   mOwner = aOwner;
     290               0 :   return NS_OK;
     291                 : }
     292                 : 
     293                 : NS_IMETHODIMP
     294               0 : nsWyciwygChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
     295                 : {
     296               0 :   *aCallbacks = mCallbacks.get();
     297               0 :   NS_IF_ADDREF(*aCallbacks);
     298               0 :   return NS_OK;
     299                 : }
     300                 : 
     301                 : NS_IMETHODIMP
     302               0 : nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
     303                 : {
     304               0 :   mCallbacks = aNotificationCallbacks;
     305                 :   NS_QueryNotificationCallbacks(mCallbacks,
     306                 :                                 mLoadGroup,
     307                 :                                 NS_GET_IID(nsIProgressEventSink),
     308               0 :                                 getter_AddRefs(mProgressSink));
     309               0 :   return NS_OK;
     310                 : }
     311                 : 
     312                 : NS_IMETHODIMP 
     313               0 : nsWyciwygChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
     314                 : {
     315               0 :   NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
     316                 : 
     317               0 :   return NS_OK;
     318                 : }
     319                 : 
     320                 : NS_IMETHODIMP
     321               0 : nsWyciwygChannel::GetContentType(nsACString &aContentType)
     322                 : {
     323               0 :   aContentType.AssignLiteral(WYCIWYG_TYPE);
     324               0 :   return NS_OK;
     325                 : }
     326                 : 
     327                 : NS_IMETHODIMP
     328               0 : nsWyciwygChannel::SetContentType(const nsACString &aContentType)
     329                 : {
     330               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     331                 : }
     332                 : 
     333                 : NS_IMETHODIMP
     334               0 : nsWyciwygChannel::GetContentCharset(nsACString &aContentCharset)
     335                 : {
     336               0 :   aContentCharset.Assign("UTF-16");
     337               0 :   return NS_OK;
     338                 : }
     339                 : 
     340                 : NS_IMETHODIMP
     341               0 : nsWyciwygChannel::SetContentCharset(const nsACString &aContentCharset)
     342                 : {
     343               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     344                 : }
     345                 : 
     346                 : NS_IMETHODIMP
     347               0 : nsWyciwygChannel::GetContentDisposition(PRUint32 *aContentDisposition)
     348                 : {
     349               0 :   return NS_ERROR_NOT_AVAILABLE;
     350                 : }
     351                 : 
     352                 : NS_IMETHODIMP
     353               0 : nsWyciwygChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
     354                 : {
     355               0 :   return NS_ERROR_NOT_AVAILABLE;
     356                 : }
     357                 : 
     358                 : NS_IMETHODIMP
     359               0 : nsWyciwygChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
     360                 : {
     361               0 :   return NS_ERROR_NOT_AVAILABLE;
     362                 : }
     363                 : 
     364                 : NS_IMETHODIMP
     365               0 : nsWyciwygChannel::GetContentLength(PRInt32 *aContentLength)
     366                 : {
     367               0 :   *aContentLength = mContentLength;
     368               0 :   return NS_OK;
     369                 : }
     370                 : 
     371                 : NS_IMETHODIMP
     372               0 : nsWyciwygChannel::SetContentLength(PRInt32 aContentLength)
     373                 : {
     374               0 :   mContentLength = aContentLength;
     375                 : 
     376               0 :   return NS_OK;
     377                 : }
     378                 : 
     379                 : NS_IMETHODIMP
     380               0 : nsWyciwygChannel::Open(nsIInputStream ** aReturn)
     381                 : {
     382               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     383                 : }
     384                 : 
     385                 : NS_IMETHODIMP
     386               0 : nsWyciwygChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
     387                 : {
     388               0 :   LOG(("nsWyciwygChannel::AsyncOpen [this=%x]\n", this));
     389                 : 
     390               0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     391               0 :   NS_ENSURE_ARG_POINTER(listener);
     392                 : 
     393               0 :   nsCAutoString spec;
     394               0 :   mURI->GetSpec(spec);
     395                 : 
     396                 :   // open a cache entry for this channel...
     397               0 :   nsresult rv = OpenCacheEntry(spec, nsICache::ACCESS_READ);
     398               0 :   if (rv == NS_ERROR_CACHE_KEY_NOT_FOUND) {
     399                 :     // Overwrite rv on purpose; if event dispatch fails we'll bail, and
     400                 :     // otherwise we'll wait until the event fires before calling back.
     401                 :     rv = NS_DispatchToCurrentThread(
     402               0 :             NS_NewRunnableMethod(this, &nsWyciwygChannel::NotifyListener));
     403                 :   }
     404                 : 
     405               0 :   if (NS_FAILED(rv)) {
     406               0 :     LOG(("nsWyciwygChannel::OpenCacheEntry failed [rv=%x]\n", rv));
     407               0 :     return rv;
     408                 :   }
     409                 : 
     410               0 :   mIsPending = true;
     411               0 :   mListener = listener;
     412               0 :   mListenerContext = ctx;
     413                 : 
     414               0 :   if (mLoadGroup)
     415               0 :     mLoadGroup->AddRequest(this, nsnull);
     416                 : 
     417               0 :   return NS_OK;
     418                 : }
     419                 : 
     420                 : //////////////////////////////////////////////////////////////////////////////
     421                 : // nsIWyciwygChannel
     422                 : //////////////////////////////////////////////////////////////////////////////
     423                 : 
     424                 : NS_IMETHODIMP
     425               0 : nsWyciwygChannel::WriteToCacheEntry(const nsAString &aData)
     426                 : {
     427                 :   // URIs not thread-safe, so get spec now in case we need it
     428               0 :   nsCAutoString spec;
     429               0 :   nsresult rv = mURI->GetAsciiSpec(spec);
     430               0 :   if (NS_FAILED(rv)) 
     431               0 :     return rv;
     432                 : 
     433               0 :   return mCacheIOTarget->Dispatch(new nsWyciwygWriteEvent(this, aData, spec),
     434               0 :                                   NS_DISPATCH_NORMAL);
     435                 : }
     436                 : 
     437                 : nsresult
     438               0 : nsWyciwygChannel::WriteToCacheEntryInternal(const nsAString &aData, const nsACString& spec)
     439                 : {
     440               0 :   NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
     441                 : 
     442                 :   nsresult rv;
     443                 : 
     444               0 :   if (!mCacheEntry) {
     445               0 :     rv = OpenCacheEntry(spec, nsICache::ACCESS_WRITE);
     446               0 :     if (NS_FAILED(rv)) return rv;
     447                 :   }
     448                 : 
     449               0 :   if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
     450               0 :     rv = mCacheEntry->SetMetaDataElement("inhibit-persistent-caching", "1");
     451               0 :     if (NS_FAILED(rv)) return rv;
     452                 :   }
     453                 : 
     454               0 :   if (mSecurityInfo) {
     455               0 :     mCacheEntry->SetSecurityInfo(mSecurityInfo);
     456                 :   }
     457                 : 
     458               0 :   if (mNeedToWriteCharset) {
     459               0 :     WriteCharsetAndSourceToCache(mCharsetSource, mCharset);
     460               0 :     mNeedToWriteCharset = false;
     461                 :   }
     462                 :   
     463                 :   PRUint32 out;
     464               0 :   if (!mCacheOutputStream) {
     465                 :     // Get the outputstream from the cache entry.
     466               0 :     rv = mCacheEntry->OpenOutputStream(0, getter_AddRefs(mCacheOutputStream));    
     467               0 :     if (NS_FAILED(rv)) return rv;
     468                 : 
     469                 :     // Write out a Byte Order Mark, so that we'll know if the data is
     470                 :     // BE or LE when we go to read it.
     471               0 :     PRUnichar bom = 0xFEFF;
     472               0 :     rv = mCacheOutputStream->Write((char *)&bom, sizeof(bom), &out);
     473               0 :     if (NS_FAILED(rv)) return rv;
     474                 :   }
     475                 : 
     476               0 :   return mCacheOutputStream->Write((char *)PromiseFlatString(aData).get(),
     477               0 :                                    aData.Length() * sizeof(PRUnichar), &out);
     478                 : }
     479                 : 
     480                 : 
     481                 : NS_IMETHODIMP
     482               0 : nsWyciwygChannel::CloseCacheEntry(nsresult reason)
     483                 : {
     484               0 :   return mCacheIOTarget->Dispatch(new nsWyciwygCloseEvent(this, reason),
     485               0 :                                   NS_DISPATCH_NORMAL);
     486                 : }
     487                 : 
     488                 : nsresult
     489               0 : nsWyciwygChannel::CloseCacheEntryInternal(nsresult reason)
     490                 : {
     491               0 :   NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
     492                 : 
     493               0 :   if (mCacheEntry) {
     494               0 :     LOG(("nsWyciwygChannel::CloseCacheEntryInternal [this=%x ]", this));
     495               0 :     mCacheOutputStream = 0;
     496               0 :     mCacheInputStream = 0;
     497                 : 
     498               0 :     if (NS_FAILED(reason))
     499               0 :       mCacheEntry->Doom();
     500                 : 
     501               0 :     mCacheEntry = 0;
     502                 :   }
     503               0 :   return NS_OK;
     504                 : }
     505                 : 
     506                 : NS_IMETHODIMP
     507               0 : nsWyciwygChannel::SetSecurityInfo(nsISupports *aSecurityInfo)
     508                 : {
     509               0 :   mSecurityInfo = aSecurityInfo;
     510                 : 
     511               0 :   return NS_OK;
     512                 : }
     513                 : 
     514                 : NS_IMETHODIMP
     515               0 : nsWyciwygChannel::SetCharsetAndSource(PRInt32 aSource,
     516                 :                                       const nsACString& aCharset)
     517                 : {
     518               0 :   NS_ENSURE_ARG(!aCharset.IsEmpty());
     519                 : 
     520               0 :   mCharsetAndSourceSet = true;
     521               0 :   mCharset = aCharset;
     522               0 :   mCharsetSource = aSource;
     523                 : 
     524               0 :   return mCacheIOTarget->Dispatch(new nsWyciwygSetCharsetandSourceEvent(this),
     525               0 :                                   NS_DISPATCH_NORMAL);
     526                 : }
     527                 : 
     528                 : void
     529               0 : nsWyciwygChannel::SetCharsetAndSourceInternal()
     530                 : {
     531               0 :   NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
     532                 : 
     533               0 :   if (mCacheEntry) {
     534               0 :     WriteCharsetAndSourceToCache(mCharsetSource, mCharset);
     535                 :   } else {
     536               0 :     mNeedToWriteCharset = true;
     537                 :   }
     538               0 : }
     539                 : 
     540                 : NS_IMETHODIMP
     541               0 : nsWyciwygChannel::GetCharsetAndSource(PRInt32* aSource, nsACString& aCharset)
     542                 : {
     543               0 :   if (mCharsetAndSourceSet) {
     544               0 :     *aSource = mCharsetSource;
     545               0 :     aCharset = mCharset;
     546               0 :     return NS_OK;
     547                 :   }
     548                 : 
     549               0 :   if (!mCacheEntry) {
     550               0 :     return NS_ERROR_NOT_AVAILABLE;
     551                 :   }
     552                 : 
     553               0 :   nsXPIDLCString data;
     554               0 :   mCacheEntry->GetMetaDataElement("charset", getter_Copies(data));
     555                 : 
     556               0 :   if (data.IsEmpty()) {
     557               0 :     return NS_ERROR_NOT_AVAILABLE;
     558                 :   }
     559                 : 
     560               0 :   nsXPIDLCString sourceStr;
     561               0 :   mCacheEntry->GetMetaDataElement("charset-source", getter_Copies(sourceStr));
     562                 : 
     563                 :   PRInt32 source;
     564                 :   // XXXbz ToInteger takes an PRInt32* but outputs an nsresult in it... :(
     565                 :   PRInt32 err;
     566               0 :   source = sourceStr.ToInteger(&err);
     567               0 :   if (NS_FAILED(err) || source == 0) {
     568               0 :     return NS_ERROR_NOT_AVAILABLE;
     569                 :   }
     570                 : 
     571               0 :   *aSource = source;
     572               0 :   aCharset = data;
     573               0 :   return NS_OK;
     574                 : }
     575                 : 
     576                 : //////////////////////////////////////////////////////////////////////////////
     577                 : // nsICachelistener
     578                 : //////////////////////////////////////////////////////////////////////////////
     579                 : NS_IMETHODIMP
     580               0 : nsWyciwygChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor * aCacheEntry, nsCacheAccessMode aMode, nsresult aStatus)
     581                 : {
     582               0 :   LOG(("nsWyciwygChannel::OnCacheEntryAvailable [this=%x entry=%x "
     583                 :        "access=%x status=%x]\n", this, aCacheEntry, aMode, aStatus));
     584                 : 
     585                 :   // if the channel's already fired onStopRequest, 
     586                 :   // then we should ignore this event.
     587               0 :   if (!mIsPending)
     588               0 :     return NS_OK;
     589                 : 
     590                 :   // otherwise, we have to handle this event.
     591               0 :   if (NS_SUCCEEDED(aStatus))
     592               0 :     mCacheEntry = aCacheEntry;
     593               0 :   else if (NS_SUCCEEDED(mStatus))
     594               0 :     mStatus = aStatus;
     595                 : 
     596                 :   nsresult rv;
     597               0 :   if (NS_FAILED(mStatus)) {
     598               0 :     LOG(("channel was canceled [this=%x status=%x]\n", this, mStatus));
     599               0 :     rv = mStatus;
     600                 :   }
     601                 :   else { // advance to the next state...
     602               0 :     rv = ReadFromCache();
     603                 :   }
     604                 : 
     605                 :   // a failure from Connect means that we have to abort the channel.
     606               0 :   if (NS_FAILED(rv)) {
     607               0 :     CloseCacheEntry(rv);
     608                 : 
     609               0 :     NotifyListener();
     610                 :   }
     611                 : 
     612               0 :   return NS_OK;
     613                 : }
     614                 : 
     615                 : //-----------------------------------------------------------------------------
     616                 : // nsWyciwygChannel::nsIStreamListener
     617                 : //-----------------------------------------------------------------------------
     618                 : 
     619                 : NS_IMETHODIMP
     620               0 : nsWyciwygChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctx,
     621                 :                                   nsIInputStream *input,
     622                 :                                   PRUint32 offset, PRUint32 count)
     623                 : {
     624               0 :   LOG(("nsWyciwygChannel::OnDataAvailable [this=%x request=%x offset=%u count=%u]\n",
     625                 :       this, request, offset, count));
     626                 : 
     627                 :   nsresult rv;
     628                 :   
     629               0 :   rv = mListener->OnDataAvailable(this, mListenerContext, input, offset, count);
     630                 : 
     631                 :   // XXX handle 64-bit stuff for real
     632               0 :   if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND))
     633               0 :     mProgressSink->OnProgress(this, nsnull, PRUint64(offset + count),
     634               0 :                               PRUint64(mContentLength));
     635                 : 
     636               0 :   return rv; // let the pump cancel on failure
     637                 : }
     638                 : 
     639                 : //////////////////////////////////////////////////////////////////////////////
     640                 : // nsIRequestObserver
     641                 : //////////////////////////////////////////////////////////////////////////////
     642                 : 
     643                 : NS_IMETHODIMP
     644               0 : nsWyciwygChannel::OnStartRequest(nsIRequest *request, nsISupports *ctx)
     645                 : {
     646               0 :   LOG(("nsWyciwygChannel::OnStartRequest [this=%x request=%x\n",
     647                 :       this, request));
     648                 : 
     649               0 :   return mListener->OnStartRequest(this, mListenerContext);
     650                 : }
     651                 : 
     652                 : 
     653                 : NS_IMETHODIMP
     654               0 : nsWyciwygChannel::OnStopRequest(nsIRequest *request, nsISupports *ctx, nsresult status)
     655                 : {
     656               0 :   LOG(("nsWyciwygChannel::OnStopRequest [this=%x request=%x status=%d\n",
     657                 :       this, request, status));
     658                 : 
     659               0 :   if (NS_SUCCEEDED(mStatus))
     660               0 :     mStatus = status;
     661                 : 
     662               0 :   mListener->OnStopRequest(this, mListenerContext, mStatus);
     663               0 :   mListener = 0;
     664               0 :   mListenerContext = 0;
     665                 : 
     666               0 :   if (mLoadGroup)
     667               0 :     mLoadGroup->RemoveRequest(this, nsnull, mStatus);
     668                 : 
     669               0 :   CloseCacheEntry(mStatus);
     670               0 :   mPump = 0;
     671               0 :   mIsPending = false;
     672                 : 
     673                 :   // Drop notification callbacks to prevent cycles.
     674               0 :   mCallbacks = 0;
     675               0 :   mProgressSink = 0;
     676                 : 
     677               0 :   return NS_OK;
     678                 : }
     679                 : 
     680                 : //////////////////////////////////////////////////////////////////////////////
     681                 : // Helper functions
     682                 : //////////////////////////////////////////////////////////////////////////////
     683                 : 
     684                 : nsresult
     685               0 : nsWyciwygChannel::OpenCacheEntry(const nsACString & aCacheKey,
     686                 :                                  nsCacheAccessMode aAccessMode)
     687                 : {
     688               0 :   nsresult rv = NS_ERROR_FAILURE;
     689                 :   // Get cache service
     690                 :   nsCOMPtr<nsICacheService> cacheService =
     691               0 :     do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
     692               0 :   NS_ENSURE_SUCCESS(rv, rv);
     693                 : 
     694                 :   // honor security settings
     695                 :   nsCacheStoragePolicy storagePolicy;
     696               0 :   if (mLoadFlags & INHIBIT_PERSISTENT_CACHING)
     697               0 :     storagePolicy = nsICache::STORE_IN_MEMORY;
     698                 :   else
     699               0 :     storagePolicy = nsICache::STORE_ANYWHERE;
     700                 : 
     701               0 :   nsCOMPtr<nsICacheSession> cacheSession;
     702                 :   // Open a stream based cache session.
     703               0 :   rv = cacheService->CreateSession("wyciwyg", storagePolicy, true,
     704               0 :                                    getter_AddRefs(cacheSession));
     705               0 :   if (!cacheSession) 
     706               0 :     return NS_ERROR_FAILURE;
     707                 : 
     708               0 :   if (aAccessMode == nsICache::ACCESS_WRITE)
     709               0 :     rv = cacheSession->OpenCacheEntry(aCacheKey, aAccessMode, false,
     710               0 :                                       getter_AddRefs(mCacheEntry));
     711                 :   else
     712               0 :     rv = cacheSession->AsyncOpenCacheEntry(aCacheKey, aAccessMode, this);
     713                 : 
     714               0 :   return rv;
     715                 : }
     716                 : 
     717                 : nsresult
     718               0 : nsWyciwygChannel::ReadFromCache()
     719                 : {
     720               0 :   LOG(("nsWyciwygChannel::ReadFromCache [this=%x] ", this));
     721                 : 
     722               0 :   NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE);
     723                 :   nsresult rv;
     724                 : 
     725                 :   // Get the stored security info
     726               0 :   mCacheEntry->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
     727                 : 
     728               0 :   nsCAutoString tmpStr;
     729               0 :   rv = mCacheEntry->GetMetaDataElement("inhibit-persistent-caching",
     730               0 :                                        getter_Copies(tmpStr));
     731               0 :   if (NS_SUCCEEDED(rv) && tmpStr == NS_LITERAL_CSTRING("1"))
     732               0 :     mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
     733                 : 
     734                 :   // Get a transport to the cached data...
     735               0 :   rv = mCacheEntry->OpenInputStream(0, getter_AddRefs(mCacheInputStream));
     736               0 :   if (NS_FAILED(rv))
     737               0 :     return rv;
     738               0 :   NS_ENSURE_TRUE(mCacheInputStream, NS_ERROR_UNEXPECTED);
     739                 : 
     740               0 :   rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mCacheInputStream);
     741               0 :   if (NS_FAILED(rv)) return rv;
     742                 : 
     743                 :   // Pump the cache data downstream
     744               0 :   return mPump->AsyncRead(this, nsnull);
     745                 : }
     746                 : 
     747                 : void
     748               0 : nsWyciwygChannel::WriteCharsetAndSourceToCache(PRInt32 aSource,
     749                 :                                                const nsCString& aCharset)
     750                 : {
     751               0 :   NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
     752               0 :   NS_PRECONDITION(mCacheEntry, "Better have cache entry!");
     753                 :   
     754               0 :   mCacheEntry->SetMetaDataElement("charset", aCharset.get());
     755                 : 
     756               0 :   nsCAutoString source;
     757               0 :   source.AppendInt(aSource);
     758               0 :   mCacheEntry->SetMetaDataElement("charset-source", source.get());
     759               0 : }
     760                 : 
     761                 : void
     762               0 : nsWyciwygChannel::NotifyListener()
     763                 : {    
     764               0 :   if (mListener) {
     765               0 :     mListener->OnStartRequest(this, mListenerContext);
     766               0 :     mListener->OnStopRequest(this, mListenerContext, mStatus);
     767               0 :     mListener = 0;
     768               0 :     mListenerContext = 0;
     769                 :   }
     770                 : 
     771               0 :   mIsPending = false;
     772                 : 
     773                 :   // Remove ourselves from the load group.
     774               0 :   if (mLoadGroup) {
     775               0 :     mLoadGroup->RemoveRequest(this, nsnull, mStatus);
     776                 :   }
     777               0 : }
     778                 : 
     779                 : bool
     780               0 : nsWyciwygChannel::IsOnCacheIOThread()
     781                 : {
     782                 :   bool correctThread;
     783               0 :   mCacheIOTarget->IsOnCurrentThread(&correctThread);
     784               0 :   return correctThread;
     785                 : }
     786                 : 
     787                 : // vim: ts=2 sw=2

Generated by: LCOV version 1.7