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

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set sw=2 ts=8 et tw=80 : */
       3                 : 
       4                 : /* ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is mozilla.org code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  *  The Mozilla Foundation
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Jason Duell <jduell.mcbugs@gmail.com>
      26                 :  *   Daniel Witte <dwitte@mozilla.com>
      27                 :  *   Honza Bambas <honzab@firemni.cz>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      31                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : #include "nsHttp.h"
      44                 : #include "mozilla/dom/TabChild.h"
      45                 : #include "mozilla/net/NeckoChild.h"
      46                 : #include "mozilla/net/HttpChannelChild.h"
      47                 : 
      48                 : #include "nsStringStream.h"
      49                 : #include "nsHttpHandler.h"
      50                 : #include "nsMimeTypes.h"
      51                 : #include "nsNetUtil.h"
      52                 : #include "nsSerializationHelper.h"
      53                 : 
      54                 : namespace mozilla {
      55                 : namespace net {
      56                 : 
      57                 : //-----------------------------------------------------------------------------
      58                 : // HttpChannelChild
      59                 : //-----------------------------------------------------------------------------
      60                 : 
      61               0 : HttpChannelChild::HttpChannelChild()
      62                 :   : HttpAsyncAborter<HttpChannelChild>(this)
      63                 :   , mIsFromCache(false)
      64                 :   , mCacheEntryAvailable(false)
      65                 :   , mCacheExpirationTime(nsICache::NO_EXPIRATION_TIME)
      66                 :   , mSendResumeAt(false)
      67                 :   , mIPCOpen(false)
      68                 :   , mKeptAlive(false)
      69               0 :   , mEventQ(static_cast<nsIHttpChannel*>(this))
      70                 : {
      71               0 :   LOG(("Creating HttpChannelChild @%x\n", this));
      72               0 : }
      73                 : 
      74               0 : HttpChannelChild::~HttpChannelChild()
      75                 : {
      76               0 :   LOG(("Destroying HttpChannelChild @%x\n", this));
      77               0 : }
      78                 : 
      79                 : //-----------------------------------------------------------------------------
      80                 : // HttpChannelChild::nsISupports
      81                 : //-----------------------------------------------------------------------------
      82                 : 
      83                 : // Override nsHashPropertyBag's AddRef: we don't need thread-safe refcnt
      84               0 : NS_IMPL_ADDREF(HttpChannelChild)
      85                 : 
      86               0 : NS_IMETHODIMP_(nsrefcnt) HttpChannelChild::Release()
      87                 : {
      88               0 :   NS_PRECONDITION(0 != mRefCnt, "dup release");
      89               0 :   NS_ASSERT_OWNINGTHREAD(HttpChannelChild);
      90               0 :   --mRefCnt;
      91               0 :   NS_LOG_RELEASE(this, mRefCnt, "HttpChannelChild");
      92                 : 
      93                 :   // Normally we Send_delete in OnStopRequest, but when we need to retain the
      94                 :   // remote channel for security info IPDL itself holds 1 reference, so we
      95                 :   // Send_delete when refCnt==1.  But if !mIPCOpen, then there's nobody to send
      96                 :   // to, so we fall through.
      97               0 :   if (mKeptAlive && mRefCnt == 1 && mIPCOpen) {
      98               0 :     mKeptAlive = false;
      99                 :     // Send_delete calls NeckoChild::DeallocPHttpChannel, which will release
     100                 :     // again to refcount==0
     101               0 :     PHttpChannelChild::Send__delete__(this);
     102               0 :     return 0;
     103                 :   }
     104                 : 
     105               0 :   if (mRefCnt == 0) {
     106               0 :     mRefCnt = 1; /* stabilize */
     107               0 :     delete this;
     108               0 :     return 0;
     109                 :   }
     110               0 :   return mRefCnt;
     111                 : }
     112                 : 
     113               0 : NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
     114               0 :   NS_INTERFACE_MAP_ENTRY(nsIRequest)
     115               0 :   NS_INTERFACE_MAP_ENTRY(nsIChannel)
     116               0 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
     117               0 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
     118               0 :   NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
     119               0 :   NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
     120               0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
     121               0 :   NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
     122               0 :   NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
     123               0 :   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
     124               0 :   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
     125               0 :   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
     126               0 :   NS_INTERFACE_MAP_ENTRY(nsIChildChannel)
     127               0 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelChild)
     128               0 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAssociatedContentSecurity, GetAssociatedContentSecurity())
     129               0 : NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
     130                 : 
     131                 : //-----------------------------------------------------------------------------
     132                 : // HttpChannelChild::PHttpChannelChild
     133                 : //-----------------------------------------------------------------------------
     134                 : 
     135                 : void
     136               0 : HttpChannelChild::AddIPDLReference()
     137                 : {
     138               0 :   NS_ABORT_IF_FALSE(!mIPCOpen, "Attempt to retain more than one IPDL reference");
     139               0 :   mIPCOpen = true;
     140               0 :   AddRef();
     141               0 : }
     142                 : 
     143                 : void
     144               0 : HttpChannelChild::ReleaseIPDLReference()
     145                 : {
     146               0 :   NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
     147               0 :   mIPCOpen = false;
     148               0 :   Release();
     149               0 : }
     150                 : 
     151                 : class AssociateApplicationCacheEvent : public ChannelEvent
     152               0 : {
     153                 :   public:
     154               0 :     AssociateApplicationCacheEvent(HttpChannelChild* child,
     155                 :                                    const nsCString &groupID,
     156                 :                                    const nsCString &clientID)
     157                 :     : mChild(child)
     158                 :     , groupID(groupID)
     159               0 :     , clientID(clientID) {}
     160                 : 
     161               0 :     void Run() { mChild->AssociateApplicationCache(groupID, clientID); }
     162                 :   private:
     163                 :     HttpChannelChild* mChild;
     164                 :     nsCString groupID;
     165                 :     nsCString clientID;
     166                 : };
     167                 : 
     168                 : bool
     169               0 : HttpChannelChild::RecvAssociateApplicationCache(const nsCString &groupID,
     170                 :                                                 const nsCString &clientID)
     171                 : {
     172               0 :   if (mEventQ.ShouldEnqueue()) {
     173               0 :     mEventQ.Enqueue(new AssociateApplicationCacheEvent(this, groupID, clientID));
     174                 :   } else {
     175               0 :     AssociateApplicationCache(groupID, clientID);
     176                 :   }
     177               0 :   return true;
     178                 : }
     179                 : 
     180                 : void
     181               0 : HttpChannelChild::AssociateApplicationCache(const nsCString &groupID,
     182                 :                                             const nsCString &clientID)
     183                 : {
     184                 :   nsresult rv;
     185               0 :   mApplicationCache = do_CreateInstance(NS_APPLICATIONCACHE_CONTRACTID, &rv);
     186               0 :   if (NS_FAILED(rv))
     187               0 :     return;
     188                 : 
     189               0 :   mLoadedFromApplicationCache = true;
     190               0 :   mApplicationCache->InitAsHandle(groupID, clientID);
     191                 : }
     192                 : 
     193                 : class StartRequestEvent : public ChannelEvent
     194               0 : {
     195                 :  public:
     196               0 :   StartRequestEvent(HttpChannelChild* child,
     197                 :                     const nsHttpResponseHead& responseHead,
     198                 :                     const bool& useResponseHead,
     199                 :                     const nsHttpHeaderArray& requestHeaders,
     200                 :                     const bool& isFromCache,
     201                 :                     const bool& cacheEntryAvailable,
     202                 :                     const PRUint32& cacheExpirationTime,
     203                 :                     const nsCString& cachedCharset,
     204                 :                     const nsCString& securityInfoSerialization,
     205                 :                     const PRNetAddr& selfAddr,
     206                 :                     const PRNetAddr& peerAddr)
     207                 :   : mChild(child)
     208                 :   , mResponseHead(responseHead)
     209                 :   , mRequestHeaders(requestHeaders)
     210                 :   , mUseResponseHead(useResponseHead)
     211                 :   , mIsFromCache(isFromCache)
     212                 :   , mCacheEntryAvailable(cacheEntryAvailable)
     213                 :   , mCacheExpirationTime(cacheExpirationTime)
     214                 :   , mCachedCharset(cachedCharset)
     215                 :   , mSecurityInfoSerialization(securityInfoSerialization)
     216                 :   , mSelfAddr(selfAddr)
     217               0 :   , mPeerAddr(peerAddr)
     218               0 :   {}
     219                 : 
     220               0 :   void Run() 
     221                 :   { 
     222                 :     mChild->OnStartRequest(mResponseHead, mUseResponseHead, mRequestHeaders,
     223                 :                            mIsFromCache, mCacheEntryAvailable,
     224                 :                            mCacheExpirationTime, mCachedCharset,
     225               0 :                            mSecurityInfoSerialization, mSelfAddr, mPeerAddr);
     226               0 :   }
     227                 :  private:
     228                 :   HttpChannelChild* mChild;
     229                 :   nsHttpResponseHead mResponseHead;
     230                 :   nsHttpHeaderArray mRequestHeaders;
     231                 :   bool mUseResponseHead;
     232                 :   bool mIsFromCache;
     233                 :   bool mCacheEntryAvailable;
     234                 :   PRUint32 mCacheExpirationTime;
     235                 :   nsCString mCachedCharset;
     236                 :   nsCString mSecurityInfoSerialization;
     237                 :   PRNetAddr mSelfAddr;
     238                 :   PRNetAddr mPeerAddr;
     239                 : };
     240                 : 
     241                 : bool 
     242               0 : HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
     243                 :                                      const bool& useResponseHead,
     244                 :                                      const nsHttpHeaderArray& requestHeaders,
     245                 :                                      const bool& isFromCache,
     246                 :                                      const bool& cacheEntryAvailable,
     247                 :                                      const PRUint32& cacheExpirationTime,
     248                 :                                      const nsCString& cachedCharset,
     249                 :                                      const nsCString& securityInfoSerialization,
     250                 :                                      const PRNetAddr& selfAddr,
     251                 :                                      const PRNetAddr& peerAddr)
     252                 : {
     253               0 :   if (mEventQ.ShouldEnqueue()) {
     254                 :     mEventQ.Enqueue(new StartRequestEvent(this, responseHead, useResponseHead,
     255                 :                                           requestHeaders, isFromCache,
     256                 :                                           cacheEntryAvailable,
     257                 :                                           cacheExpirationTime, cachedCharset,
     258                 :                                           securityInfoSerialization, selfAddr,
     259               0 :                                           peerAddr));
     260                 :   } else {
     261                 :     OnStartRequest(responseHead, useResponseHead, requestHeaders, isFromCache,
     262                 :                    cacheEntryAvailable, cacheExpirationTime, cachedCharset,
     263               0 :                    securityInfoSerialization, selfAddr, peerAddr);
     264                 :   }
     265               0 :   return true;
     266                 : }
     267                 : 
     268                 : void 
     269               0 : HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead,
     270                 :                                  const bool& useResponseHead,
     271                 :                                  const nsHttpHeaderArray& requestHeaders,
     272                 :                                  const bool& isFromCache,
     273                 :                                  const bool& cacheEntryAvailable,
     274                 :                                  const PRUint32& cacheExpirationTime,
     275                 :                                  const nsCString& cachedCharset,
     276                 :                                  const nsCString& securityInfoSerialization,
     277                 :                                  const PRNetAddr& selfAddr,
     278                 :                                  const PRNetAddr& peerAddr)
     279                 : {
     280               0 :   LOG(("HttpChannelChild::RecvOnStartRequest [this=%x]\n", this));
     281                 : 
     282               0 :   if (useResponseHead && !mCanceled)
     283               0 :     mResponseHead = new nsHttpResponseHead(responseHead);
     284                 : 
     285               0 :   if (!securityInfoSerialization.IsEmpty()) {
     286                 :     NS_DeserializeObject(securityInfoSerialization, 
     287               0 :                          getter_AddRefs(mSecurityInfo));
     288                 :   }
     289                 : 
     290               0 :   mIsFromCache = isFromCache;
     291               0 :   mCacheEntryAvailable = cacheEntryAvailable;
     292               0 :   mCacheExpirationTime = cacheExpirationTime;
     293               0 :   mCachedCharset = cachedCharset;
     294                 : 
     295               0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     296                 : 
     297                 :   // replace our request headers with what actually got sent in the parent
     298               0 :   mRequestHead.Headers() = requestHeaders;
     299                 : 
     300                 :   // notify "http-on-examine-response" observers
     301               0 :   gHttpHandler->OnExamineResponse(this);
     302               0 :   mTracingEnabled = false;
     303                 : 
     304               0 :   nsresult rv = mListener->OnStartRequest(this, mListenerContext);
     305               0 :   if (NS_FAILED(rv)) {
     306               0 :     Cancel(rv);
     307                 :     return;
     308                 :   }
     309                 : 
     310               0 :   if (mResponseHead)
     311               0 :     SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
     312                 : 
     313               0 :   rv = ApplyContentConversions();
     314               0 :   if (NS_FAILED(rv))
     315               0 :     Cancel(rv);
     316                 : 
     317               0 :   mSelfAddr = selfAddr;
     318               0 :   mPeerAddr = peerAddr;
     319                 : }
     320                 : 
     321                 : class TransportAndDataEvent : public ChannelEvent
     322               0 : {
     323                 :  public:
     324               0 :   TransportAndDataEvent(HttpChannelChild* child,
     325                 :                         const nsresult& status,
     326                 :                         const PRUint64& progress,
     327                 :                         const PRUint64& progressMax,
     328                 :                         const nsCString& data,
     329                 :                         const PRUint32& offset,
     330                 :                         const PRUint32& count)
     331                 :   : mChild(child)
     332                 :   , mStatus(status)
     333                 :   , mProgress(progress)
     334                 :   , mProgressMax(progressMax)
     335                 :   , mData(data)
     336                 :   , mOffset(offset)
     337               0 :   , mCount(count) {}
     338                 : 
     339               0 :   void Run() { mChild->OnTransportAndData(mStatus, mProgress, mProgressMax,
     340               0 :                                           mData, mOffset, mCount); }
     341                 :  private:
     342                 :   HttpChannelChild* mChild;
     343                 :   nsresult mStatus;
     344                 :   PRUint64 mProgress;
     345                 :   PRUint64 mProgressMax;
     346                 :   nsCString mData;
     347                 :   PRUint32 mOffset;
     348                 :   PRUint32 mCount;
     349                 : };
     350                 : 
     351                 : bool
     352               0 : HttpChannelChild::RecvOnTransportAndData(const nsresult& status,
     353                 :                                          const PRUint64& progress,
     354                 :                                          const PRUint64& progressMax,
     355                 :                                          const nsCString& data,
     356                 :                                          const PRUint32& offset,
     357                 :                                          const PRUint32& count)
     358                 : {
     359               0 :   if (mEventQ.ShouldEnqueue()) {
     360                 :     mEventQ.Enqueue(new TransportAndDataEvent(this, status, progress,
     361                 :                                               progressMax, data, offset, 
     362               0 :                                               count));
     363                 :   } else {
     364               0 :     OnTransportAndData(status, progress, progressMax, data, offset, count);
     365                 :   }
     366               0 :   return true;
     367                 : }
     368                 : 
     369                 : void
     370               0 : HttpChannelChild::OnTransportAndData(const nsresult& status,
     371                 :                                      const PRUint64 progress,
     372                 :                                      const PRUint64& progressMax,
     373                 :                                      const nsCString& data,
     374                 :                                      const PRUint32& offset,
     375                 :                                      const PRUint32& count)
     376                 : {
     377               0 :   LOG(("HttpChannelChild::OnTransportAndData [this=%x]\n", this));
     378                 : 
     379               0 :   if (mCanceled)
     380               0 :     return;
     381                 : 
     382                 :   // cache the progress sink so we don't have to query for it each time.
     383               0 :   if (!mProgressSink)
     384               0 :     GetCallback(mProgressSink);
     385                 : 
     386                 :   // Hold queue lock throughout all three calls, else we might process a later
     387                 :   // necko msg in between them.
     388               0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     389                 : 
     390                 :   // block status/progress after Cancel or OnStopRequest has been called,
     391                 :   // or if channel has LOAD_BACKGROUND set.
     392                 :   // - JDUELL: may not need mStatus/mIsPending checks, given this is always called
     393                 :   //   during OnDataAvailable, and we've already checked mCanceled.  Code
     394                 :   //   dupe'd from nsHttpChannel
     395               0 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
     396               0 :       !(mLoadFlags & LOAD_BACKGROUND))
     397                 :   {
     398                 :     // OnStatus
     399                 :     //
     400               0 :     NS_ASSERTION(status == nsISocketTransport::STATUS_RECEIVING_FROM ||
     401                 :                  status == nsITransport::STATUS_READING,
     402                 :                  "unexpected status code");
     403                 : 
     404               0 :     nsCAutoString host;
     405               0 :     mURI->GetHost(host);
     406               0 :     mProgressSink->OnStatus(this, nsnull, status,
     407               0 :                             NS_ConvertUTF8toUTF16(host).get());
     408                 :     // OnProgress
     409                 :     //
     410               0 :     if (progress > 0) {
     411               0 :       NS_ASSERTION(progress <= progressMax, "unexpected progress values");
     412               0 :       mProgressSink->OnProgress(this, nsnull, progress, progressMax);
     413                 :     }
     414                 :   }
     415                 : 
     416                 :   // OnDataAvailable
     417                 :   //
     418                 :   // NOTE: the OnDataAvailable contract requires the client to read all the data
     419                 :   // in the inputstream.  This code relies on that ('data' will go away after
     420                 :   // this function).  Apparently the previous, non-e10s behavior was to actually
     421                 :   // support only reading part of the data, allowing later calls to read the
     422                 :   // rest.
     423               0 :   nsCOMPtr<nsIInputStream> stringStream;
     424               0 :   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
     425               0 :                                       count, NS_ASSIGNMENT_DEPEND);
     426               0 :   if (NS_FAILED(rv)) {
     427               0 :     Cancel(rv);
     428                 :     return;
     429                 :   }
     430                 : 
     431               0 :   rv = mListener->OnDataAvailable(this, mListenerContext,
     432               0 :                                   stringStream, offset, count);
     433               0 :   stringStream->Close();
     434               0 :   if (NS_FAILED(rv)) {
     435               0 :     Cancel(rv);
     436                 :   }
     437                 : }
     438                 : 
     439                 : class StopRequestEvent : public ChannelEvent
     440               0 : {
     441                 :  public:
     442               0 :   StopRequestEvent(HttpChannelChild* child,
     443                 :                    const nsresult& statusCode)
     444                 :   : mChild(child)
     445               0 :   , mStatusCode(statusCode) {}
     446                 : 
     447               0 :   void Run() { mChild->OnStopRequest(mStatusCode); }
     448                 :  private:
     449                 :   HttpChannelChild* mChild;
     450                 :   nsresult mStatusCode;
     451                 : };
     452                 : 
     453                 : bool 
     454               0 : HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode)
     455                 : {
     456               0 :   if (mEventQ.ShouldEnqueue()) {
     457               0 :     mEventQ.Enqueue(new StopRequestEvent(this, statusCode));
     458                 :   } else {
     459               0 :     OnStopRequest(statusCode);
     460                 :   }
     461               0 :   return true;
     462                 : }
     463                 : 
     464                 : void 
     465               0 : HttpChannelChild::OnStopRequest(const nsresult& statusCode)
     466                 : {
     467               0 :   LOG(("HttpChannelChild::OnStopRequest [this=%x status=%u]\n", 
     468                 :            this, statusCode));
     469                 : 
     470               0 :   mIsPending = false;
     471                 : 
     472               0 :   if (!mCanceled && NS_SUCCEEDED(mStatus))
     473               0 :     mStatus = statusCode;
     474                 : 
     475                 :   { // We must flush the queue before we Send__delete__
     476                 :     // (although we really shouldn't receive any msgs after OnStop),
     477                 :     // so make sure this goes out of scope before then.
     478               0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     479                 : 
     480               0 :     mListener->OnStopRequest(this, mListenerContext, mStatus);
     481                 : 
     482               0 :     mListener = 0;
     483               0 :     mListenerContext = 0;
     484               0 :     mCacheEntryAvailable = false;
     485               0 :     if (mLoadGroup)
     486               0 :       mLoadGroup->RemoveRequest(this, nsnull, mStatus);
     487                 :   }
     488                 : 
     489               0 :   if (mLoadFlags & LOAD_DOCUMENT_URI) {
     490                 :     // Keep IPDL channel open, but only for updating security info.
     491               0 :     mKeptAlive = true;
     492               0 :     SendDocumentChannelCleanup();
     493                 :   } else {
     494                 :     // This calls NeckoChild::DeallocPHttpChannel(), which deletes |this| if IPDL
     495                 :     // holds the last reference.  Don't rely on |this| existing after here.
     496               0 :     PHttpChannelChild::Send__delete__(this);
     497                 :   }
     498               0 : }
     499                 : 
     500                 : class ProgressEvent : public ChannelEvent
     501               0 : {
     502                 :  public:
     503               0 :   ProgressEvent(HttpChannelChild* child,
     504                 :                 const PRUint64& progress,
     505                 :                 const PRUint64& progressMax)
     506                 :   : mChild(child)
     507                 :   , mProgress(progress)
     508               0 :   , mProgressMax(progressMax) {}
     509                 : 
     510               0 :   void Run() { mChild->OnProgress(mProgress, mProgressMax); }
     511                 :  private:
     512                 :   HttpChannelChild* mChild;
     513                 :   PRUint64 mProgress, mProgressMax;
     514                 : };
     515                 : 
     516                 : bool
     517               0 : HttpChannelChild::RecvOnProgress(const PRUint64& progress,
     518                 :                                  const PRUint64& progressMax)
     519                 : {
     520               0 :   if (mEventQ.ShouldEnqueue())  {
     521               0 :     mEventQ.Enqueue(new ProgressEvent(this, progress, progressMax));
     522                 :   } else {
     523               0 :     OnProgress(progress, progressMax);
     524                 :   }
     525               0 :   return true;
     526                 : }
     527                 : 
     528                 : void
     529               0 : HttpChannelChild::OnProgress(const PRUint64& progress,
     530                 :                              const PRUint64& progressMax)
     531                 : {
     532               0 :   LOG(("HttpChannelChild::OnProgress [this=%p progress=%llu/%llu]\n",
     533                 :        this, progress, progressMax));
     534                 : 
     535               0 :   if (mCanceled)
     536               0 :     return;
     537                 : 
     538                 :   // cache the progress sink so we don't have to query for it each time.
     539               0 :   if (!mProgressSink)
     540               0 :     GetCallback(mProgressSink);
     541                 : 
     542               0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     543                 : 
     544                 :   // block socket status event after Cancel or OnStopRequest has been called,
     545                 :   // or if channel has LOAD_BACKGROUND set
     546               0 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending && 
     547               0 :       !(mLoadFlags & LOAD_BACKGROUND)) 
     548                 :   {
     549               0 :     if (progress > 0) {
     550               0 :       NS_ASSERTION(progress <= progressMax, "unexpected progress values");
     551               0 :       mProgressSink->OnProgress(this, nsnull, progress, progressMax);
     552                 :     }
     553                 :   }
     554                 : }
     555                 : 
     556                 : class StatusEvent : public ChannelEvent
     557               0 : {
     558                 :  public:
     559               0 :   StatusEvent(HttpChannelChild* child,
     560                 :               const nsresult& status)
     561                 :   : mChild(child)
     562               0 :   , mStatus(status) {}
     563                 : 
     564               0 :   void Run() { mChild->OnStatus(mStatus); }
     565                 :  private:
     566                 :   HttpChannelChild* mChild;
     567                 :   nsresult mStatus;
     568                 : };
     569                 : 
     570                 : bool
     571               0 : HttpChannelChild::RecvOnStatus(const nsresult& status)
     572                 : {
     573               0 :   if (mEventQ.ShouldEnqueue()) {
     574               0 :     mEventQ.Enqueue(new StatusEvent(this, status));
     575                 :   } else {
     576               0 :     OnStatus(status);
     577                 :   }
     578               0 :   return true;
     579                 : }
     580                 : 
     581                 : void
     582               0 : HttpChannelChild::OnStatus(const nsresult& status)
     583                 : {
     584               0 :   LOG(("HttpChannelChild::OnStatus [this=%p status=%x]\n", this, status));
     585                 : 
     586               0 :   if (mCanceled)
     587               0 :     return;
     588                 : 
     589                 :   // cache the progress sink so we don't have to query for it each time.
     590               0 :   if (!mProgressSink)
     591               0 :     GetCallback(mProgressSink);
     592                 : 
     593               0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     594                 : 
     595                 :   // block socket status event after Cancel or OnStopRequest has been called,
     596                 :   // or if channel has LOAD_BACKGROUND set
     597               0 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending && 
     598               0 :       !(mLoadFlags & LOAD_BACKGROUND)) 
     599                 :   {
     600               0 :     nsCAutoString host;
     601               0 :     mURI->GetHost(host);
     602               0 :     mProgressSink->OnStatus(this, nsnull, status,
     603               0 :                             NS_ConvertUTF8toUTF16(host).get());
     604                 :   }
     605                 : }
     606                 : 
     607                 : class FailedAsyncOpenEvent : public ChannelEvent
     608               0 : {
     609                 :  public:
     610               0 :   FailedAsyncOpenEvent(HttpChannelChild* child, const nsresult& status)
     611                 :   : mChild(child)
     612               0 :   , mStatus(status) {}
     613                 : 
     614               0 :   void Run() { mChild->FailedAsyncOpen(mStatus); }
     615                 :  private:
     616                 :   HttpChannelChild* mChild;
     617                 :   nsresult mStatus;
     618                 : };
     619                 : 
     620                 : bool
     621               0 : HttpChannelChild::RecvFailedAsyncOpen(const nsresult& status)
     622                 : {
     623               0 :   if (mEventQ.ShouldEnqueue()) {
     624               0 :     mEventQ.Enqueue(new FailedAsyncOpenEvent(this, status));
     625                 :   } else {
     626               0 :     FailedAsyncOpen(status);
     627                 :   }
     628               0 :   return true;
     629                 : }
     630                 : 
     631                 : // We need to have an implementation of this function just so that we can keep
     632                 : // all references to mCallOnResume of type HttpChannelChild:  it's not OK in C++
     633                 : // to set a member function ptr to a base class function.
     634                 : void
     635               0 : HttpChannelChild::HandleAsyncAbort()
     636                 : {
     637               0 :   HttpAsyncAborter<HttpChannelChild>::HandleAsyncAbort();
     638               0 : }
     639                 : 
     640                 : void
     641               0 : HttpChannelChild::FailedAsyncOpen(const nsresult& status)
     642                 : {
     643               0 :   LOG(("HttpChannelChild::FailedAsyncOpen [this=%p status=%x]\n", this, status));
     644                 : 
     645               0 :   mStatus = status;
     646               0 :   mIsPending = false;
     647                 :   // We're already being called from IPDL, therefore already "async"
     648               0 :   HandleAsyncAbort();
     649               0 : }
     650                 : 
     651                 : void
     652               0 : HttpChannelChild::DoNotifyListenerCleanup()
     653                 : {
     654               0 :   if (mIPCOpen)
     655               0 :     PHttpChannelChild::Send__delete__(this);
     656               0 : }
     657                 : 
     658                 : class DeleteSelfEvent : public ChannelEvent
     659               0 : {
     660                 :  public:
     661               0 :   DeleteSelfEvent(HttpChannelChild* child) : mChild(child) {}
     662               0 :   void Run() { mChild->DeleteSelf(); }
     663                 :  private:
     664                 :   HttpChannelChild* mChild;
     665                 : };
     666                 : 
     667                 : bool
     668               0 : HttpChannelChild::RecvDeleteSelf()
     669                 : {
     670               0 :   if (mEventQ.ShouldEnqueue()) {
     671               0 :     mEventQ.Enqueue(new DeleteSelfEvent(this));
     672                 :   } else {
     673               0 :     DeleteSelf();
     674                 :   }
     675               0 :   return true;
     676                 : }
     677                 : 
     678                 : void
     679               0 : HttpChannelChild::DeleteSelf()
     680                 : {
     681               0 :   Send__delete__(this);
     682               0 : }
     683                 : 
     684                 : class Redirect1Event : public ChannelEvent
     685               0 : {
     686                 :  public:
     687               0 :   Redirect1Event(HttpChannelChild* child,
     688                 :                  const PRUint32& newChannelId,
     689                 :                  const IPC::URI& newURI,
     690                 :                  const PRUint32& redirectFlags,
     691                 :                  const nsHttpResponseHead& responseHead)
     692                 :   : mChild(child)
     693                 :   , mNewChannelId(newChannelId)
     694                 :   , mNewURI(newURI)
     695                 :   , mRedirectFlags(redirectFlags)
     696               0 :   , mResponseHead(responseHead) {}
     697                 : 
     698               0 :   void Run() 
     699                 :   { 
     700                 :     mChild->Redirect1Begin(mNewChannelId, mNewURI, mRedirectFlags,
     701               0 :                            mResponseHead); 
     702               0 :   }
     703                 :  private:
     704                 :   HttpChannelChild*   mChild;
     705                 :   PRUint32            mNewChannelId;
     706                 :   IPC::URI            mNewURI;
     707                 :   PRUint32            mRedirectFlags;
     708                 :   nsHttpResponseHead  mResponseHead;
     709                 : };
     710                 : 
     711                 : bool
     712               0 : HttpChannelChild::RecvRedirect1Begin(const PRUint32& newChannelId,
     713                 :                                      const URI& newUri,
     714                 :                                      const PRUint32& redirectFlags,
     715                 :                                      const nsHttpResponseHead& responseHead)
     716                 : {
     717               0 :   if (mEventQ.ShouldEnqueue()) {
     718                 :     mEventQ.Enqueue(new Redirect1Event(this, newChannelId, newUri,
     719               0 :                                        redirectFlags, responseHead));
     720                 :   } else {
     721               0 :     Redirect1Begin(newChannelId, newUri, redirectFlags, responseHead);
     722                 :   }
     723               0 :   return true;
     724                 : }
     725                 : 
     726                 : void
     727               0 : HttpChannelChild::Redirect1Begin(const PRUint32& newChannelId,
     728                 :                                  const IPC::URI& newURI,
     729                 :                                  const PRUint32& redirectFlags,
     730                 :                                  const nsHttpResponseHead& responseHead)
     731                 : {
     732                 :   nsresult rv;
     733                 : 
     734               0 :   nsCOMPtr<nsIIOService> ioService;
     735               0 :   rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
     736               0 :   if (NS_FAILED(rv)) {
     737                 :     // Veto redirect.  nsHttpChannel decides to cancel or continue.
     738               0 :     OnRedirectVerifyCallback(rv);
     739                 :     return;
     740                 :   }
     741                 : 
     742               0 :   nsCOMPtr<nsIURI> uri(newURI);
     743                 : 
     744               0 :   nsCOMPtr<nsIChannel> newChannel;
     745               0 :   rv = ioService->NewChannelFromURI(uri, getter_AddRefs(newChannel));
     746               0 :   if (NS_FAILED(rv)) {
     747                 :     // Veto redirect.  nsHttpChannel decides to cancel or continue.
     748               0 :     OnRedirectVerifyCallback(rv);
     749                 :     return;
     750                 :   }
     751                 : 
     752                 :   // We won't get OnStartRequest, set cookies here.
     753               0 :   mResponseHead = new nsHttpResponseHead(responseHead);
     754               0 :   SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
     755                 : 
     756               0 :   bool rewriteToGET = ShouldRewriteRedirectToGET(mResponseHead->Status(), 
     757               0 :                                                  mRequestHead.Method());
     758                 :   
     759               0 :   rv = SetupReplacementChannel(uri, newChannel, !rewriteToGET, false);
     760               0 :   if (NS_FAILED(rv)) {
     761                 :     // Veto redirect.  nsHttpChannel decides to cancel or continue.
     762               0 :     OnRedirectVerifyCallback(rv);
     763                 :     return;
     764                 :   }
     765                 : 
     766               0 :   mRedirectChannelChild = do_QueryInterface(newChannel);
     767               0 :   if (mRedirectChannelChild) {
     768               0 :     mRedirectChannelChild->ConnectParent(newChannelId);
     769                 :   } else {
     770               0 :     NS_ERROR("Redirecting to a protocol that doesn't support universal protocol redirect");
     771                 :   }
     772                 : 
     773                 :   rv = gHttpHandler->AsyncOnChannelRedirect(this, 
     774                 :                                             newChannel,
     775               0 :                                             redirectFlags);
     776               0 :   if (NS_FAILED(rv))
     777               0 :     OnRedirectVerifyCallback(rv);
     778                 : }
     779                 : 
     780                 : class Redirect3Event : public ChannelEvent
     781               0 : {
     782                 :  public:
     783               0 :   Redirect3Event(HttpChannelChild* child) : mChild(child) {}
     784               0 :   void Run() { mChild->Redirect3Complete(); }
     785                 :  private:
     786                 :   HttpChannelChild* mChild;
     787                 : };
     788                 : 
     789                 : bool
     790               0 : HttpChannelChild::RecvRedirect3Complete()
     791                 : {
     792               0 :   if (mEventQ.ShouldEnqueue()) {
     793               0 :     mEventQ.Enqueue(new Redirect3Event(this));
     794                 :   } else {
     795               0 :     Redirect3Complete();
     796                 :   }
     797               0 :   return true;
     798                 : }
     799                 : 
     800                 : void
     801               0 : HttpChannelChild::Redirect3Complete()
     802                 : {
     803               0 :   nsresult rv = NS_OK;
     804                 : 
     805                 :   // Chrome channel has been AsyncOpen'd.  Reflect this in child.
     806               0 :   if (mRedirectChannelChild)
     807               0 :     rv = mRedirectChannelChild->CompleteRedirectSetup(mListener,
     808               0 :                                                       mListenerContext);
     809                 : 
     810                 :   // Redirecting to new channel: shut this down and init new channel
     811               0 :   if (mLoadGroup)
     812               0 :     mLoadGroup->RemoveRequest(this, nsnull, NS_BINDING_ABORTED);
     813                 : 
     814               0 :   if (NS_FAILED(rv))
     815               0 :     NS_WARNING("CompleteRedirectSetup failed, HttpChannelChild already open?");
     816                 : 
     817                 :   // Release ref to new channel.
     818               0 :   mRedirectChannelChild = nsnull;
     819               0 : }
     820                 : 
     821                 : //-----------------------------------------------------------------------------
     822                 : // HttpChannelChild::nsIChildChannel
     823                 : //-----------------------------------------------------------------------------
     824                 : 
     825                 : NS_IMETHODIMP
     826               0 : HttpChannelChild::ConnectParent(PRUint32 id)
     827                 : {
     828               0 :   mozilla::dom::TabChild* tabChild = nsnull;
     829               0 :   nsCOMPtr<nsITabChild> iTabChild;
     830               0 :   GetCallback(iTabChild);
     831               0 :   if (iTabChild) {
     832               0 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
     833                 :   }
     834                 : 
     835                 :   // The socket transport in the chrome process now holds a logical ref to us
     836                 :   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
     837               0 :   AddIPDLReference();
     838                 : 
     839               0 :   if (!gNeckoChild->SendPHttpChannelConstructor(this, tabChild))
     840               0 :     return NS_ERROR_FAILURE;
     841                 : 
     842               0 :   if (!SendConnectChannel(id))
     843               0 :     return NS_ERROR_FAILURE;
     844                 : 
     845               0 :   return NS_OK;
     846                 : }
     847                 : 
     848                 : NS_IMETHODIMP
     849               0 : HttpChannelChild::CompleteRedirectSetup(nsIStreamListener *listener, 
     850                 :                                         nsISupports *aContext)
     851                 : {
     852               0 :   LOG(("HttpChannelChild::FinishRedirectSetup [this=%x]\n", this));
     853                 : 
     854               0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     855               0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
     856                 : 
     857                 :   /*
     858                 :    * No need to check for cancel: we don't get here if nsHttpChannel canceled
     859                 :    * before AsyncOpen(); if it's canceled after that, OnStart/Stop will just
     860                 :    * get called with error code as usual.  So just setup mListener and make the
     861                 :    * channel reflect AsyncOpen'ed state.
     862                 :    */
     863                 : 
     864               0 :   mIsPending = true;
     865               0 :   mWasOpened = true;
     866               0 :   mListener = listener;
     867               0 :   mListenerContext = aContext;
     868                 : 
     869                 :   // add ourselves to the load group. 
     870               0 :   if (mLoadGroup)
     871               0 :     mLoadGroup->AddRequest(this, nsnull);
     872                 : 
     873                 :   // We already have an open IPDL connection to the parent. If on-modify-request
     874                 :   // listeners or load group observers canceled us, let the parent handle it
     875                 :   // and send it back to us naturally.
     876               0 :   return NS_OK;
     877                 : }
     878                 : 
     879                 : //-----------------------------------------------------------------------------
     880                 : // HttpChannelChild::nsIAsyncVerifyRedirectCallback
     881                 : //-----------------------------------------------------------------------------
     882                 : 
     883                 : NS_IMETHODIMP
     884               0 : HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
     885                 : {
     886                 :   nsCOMPtr<nsIHttpChannel> newHttpChannel =
     887               0 :       do_QueryInterface(mRedirectChannelChild);
     888                 : 
     889               0 :   if (newHttpChannel) {
     890                 :     // Must not be called until after redirect observers called.
     891               0 :     newHttpChannel->SetOriginalURI(mOriginalURI);
     892                 :   }
     893                 : 
     894               0 :   RequestHeaderTuples emptyHeaders;
     895               0 :   RequestHeaderTuples* headerTuples = &emptyHeaders;
     896                 : 
     897                 :   nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild =
     898               0 :       do_QueryInterface(mRedirectChannelChild);
     899               0 :   if (newHttpChannelChild && NS_SUCCEEDED(result)) {
     900               0 :     newHttpChannelChild->AddCookiesToRequest();
     901               0 :     newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
     902                 :   }
     903                 : 
     904                 :   // After we verify redirect, nsHttpChannel may hit the network: must give
     905                 :   // "http-on-modify-request" observers the chance to cancel before that.
     906               0 :   if (NS_SUCCEEDED(result))
     907               0 :     gHttpHandler->OnModifyRequest(newHttpChannel);
     908                 : 
     909               0 :   if (mIPCOpen)
     910               0 :     SendRedirect2Verify(result, *headerTuples);
     911                 : 
     912               0 :   return NS_OK;
     913                 : }
     914                 : 
     915                 : //-----------------------------------------------------------------------------
     916                 : // HttpChannelChild::nsIRequest
     917                 : //-----------------------------------------------------------------------------
     918                 : 
     919                 : NS_IMETHODIMP
     920               0 : HttpChannelChild::Cancel(nsresult status)
     921                 : {
     922               0 :   if (!mCanceled) {
     923                 :     // If this cancel occurs before nsHttpChannel has been set up, AsyncOpen
     924                 :     // is responsible for cleaning up.
     925               0 :     mCanceled = true;
     926               0 :     mStatus = status;
     927               0 :     if (RemoteChannelExists())
     928               0 :       SendCancel(status);
     929                 :   }
     930               0 :   return NS_OK;
     931                 : }
     932                 : 
     933                 : NS_IMETHODIMP
     934               0 : HttpChannelChild::Suspend()
     935                 : {
     936               0 :   NS_ENSURE_TRUE(RemoteChannelExists(), NS_ERROR_NOT_AVAILABLE);
     937               0 :   if (!mSuspendCount++) {
     938               0 :     SendSuspend();
     939               0 :     mEventQ.Suspend();
     940                 :   }
     941               0 :   return NS_OK;
     942                 : }
     943                 : 
     944                 : void
     945               0 : HttpChannelChild::CompleteResume()
     946                 : {
     947               0 :   if (mCallOnResume) {
     948               0 :     (this->*mCallOnResume)();
     949               0 :     mCallOnResume = 0;
     950                 :   }
     951                 : 
     952                 :   // Don't resume event queue until now, else queued events could get
     953                 :   // flushed/called before mCallOnResume, which needs to run first.
     954               0 :   mEventQ.Resume();
     955               0 : }
     956                 : 
     957                 : NS_IMETHODIMP
     958               0 : HttpChannelChild::Resume()
     959                 : {
     960               0 :   NS_ENSURE_TRUE(RemoteChannelExists(), NS_ERROR_NOT_AVAILABLE);
     961               0 :   NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
     962                 : 
     963               0 :   nsresult rv = NS_OK;
     964                 : 
     965               0 :   if (!--mSuspendCount) {
     966               0 :     SendResume();
     967               0 :     rv = AsyncCall(&HttpChannelChild::CompleteResume);
     968                 :   }
     969               0 :   return rv;
     970                 : }
     971                 : 
     972                 : //-----------------------------------------------------------------------------
     973                 : // HttpChannelChild::nsIChannel
     974                 : //-----------------------------------------------------------------------------
     975                 : 
     976                 : NS_IMETHODIMP
     977               0 : HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
     978                 : {
     979               0 :   NS_ENSURE_ARG_POINTER(aSecurityInfo);
     980               0 :   NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
     981               0 :   return NS_OK;
     982                 : }
     983                 : 
     984                 : NS_IMETHODIMP
     985               0 : HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
     986                 : {
     987               0 :   LOG(("HttpChannelChild::AsyncOpen [this=%x uri=%s]\n", this, mSpec.get()));
     988                 : 
     989               0 :   if (mCanceled)
     990               0 :     return mStatus;
     991                 : 
     992               0 :   NS_ENSURE_TRUE(gNeckoChild != nsnull, NS_ERROR_FAILURE);
     993               0 :   NS_ENSURE_ARG_POINTER(listener);
     994               0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     995               0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
     996                 : 
     997                 :   // Port checked in parent, but duplicate here so we can return with error
     998                 :   // immediately
     999                 :   nsresult rv;
    1000               0 :   rv = NS_CheckPortSafety(mURI);
    1001               0 :   if (NS_FAILED(rv))
    1002               0 :     return rv;
    1003                 : 
    1004               0 :   const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie);
    1005               0 :   if (cookieHeader) {
    1006               0 :     mUserSetCookieHeader = cookieHeader;
    1007                 :   }
    1008                 : 
    1009               0 :   AddCookiesToRequest();
    1010                 : 
    1011                 :   //
    1012                 :   // NOTE: From now on we must return NS_OK; all errors must be handled via
    1013                 :   // OnStart/OnStopRequest
    1014                 :   //
    1015                 : 
    1016                 :   // notify "http-on-modify-request" observers
    1017               0 :   gHttpHandler->OnModifyRequest(this);
    1018                 : 
    1019               0 :   mIsPending = true;
    1020               0 :   mWasOpened = true;
    1021               0 :   mListener = listener;
    1022               0 :   mListenerContext = aContext;
    1023                 : 
    1024                 :   // add ourselves to the load group. 
    1025               0 :   if (mLoadGroup)
    1026               0 :     mLoadGroup->AddRequest(this, nsnull);
    1027                 : 
    1028               0 :   if (mCanceled) {
    1029                 :     // We may have been canceled already, either by on-modify-request
    1030                 :     // listeners or by load group observers; in that case, don't create IPDL
    1031                 :     // connection. See nsHttpChannel::AsyncOpen().
    1032               0 :     AsyncAbort(mStatus);
    1033               0 :     return NS_OK;
    1034                 :   }
    1035                 : 
    1036               0 :   nsCString appCacheClientId;
    1037               0 :   if (mInheritApplicationCache) {
    1038                 :     // Pick up an application cache from the notification
    1039                 :     // callbacks if available
    1040               0 :     nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
    1041               0 :     GetCallback(appCacheContainer);
    1042                 : 
    1043               0 :     if (appCacheContainer) {
    1044               0 :       nsCOMPtr<nsIApplicationCache> appCache;
    1045               0 :       rv = appCacheContainer->GetApplicationCache(getter_AddRefs(appCache));
    1046               0 :       if (NS_SUCCEEDED(rv) && appCache) {
    1047               0 :         appCache->GetClientID(appCacheClientId);
    1048                 :       }
    1049                 :     }
    1050                 :   }
    1051                 : 
    1052                 :   //
    1053                 :   // Send request to the chrome process...
    1054                 :   //
    1055                 : 
    1056                 :   // FIXME: bug 558623: Combine constructor and SendAsyncOpen into one IPC msg
    1057                 : 
    1058               0 :   mozilla::dom::TabChild* tabChild = nsnull;
    1059               0 :   nsCOMPtr<nsITabChild> iTabChild;
    1060               0 :   GetCallback(iTabChild);
    1061               0 :   if (iTabChild) {
    1062               0 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
    1063                 :   }
    1064                 : 
    1065                 :   // The socket transport in the chrome process now holds a logical ref to us
    1066                 :   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
    1067               0 :   AddIPDLReference();
    1068                 : 
    1069               0 :   gNeckoChild->SendPHttpChannelConstructor(this, tabChild);
    1070                 : 
    1071               0 :   SendAsyncOpen(IPC::URI(mURI), IPC::URI(mOriginalURI),
    1072               0 :                 IPC::URI(mDocumentURI), IPC::URI(mReferrer), mLoadFlags,
    1073               0 :                 mClientSetRequestHeaders, mRequestHead.Method(),
    1074               0 :                 IPC::InputStream(mUploadStream), mUploadStreamHasHeaders,
    1075                 :                 mPriority, mRedirectionLimit, mAllowPipelining,
    1076                 :                 mForceAllowThirdPartyCookie, mSendResumeAt,
    1077                 :                 mStartPos, mEntityID, mChooseApplicationCache, 
    1078               0 :                 appCacheClientId, mAllowSpdy);
    1079                 : 
    1080               0 :   return NS_OK;
    1081                 : }
    1082                 : 
    1083                 : //-----------------------------------------------------------------------------
    1084                 : // HttpChannelChild::nsIHttpChannel
    1085                 : //-----------------------------------------------------------------------------
    1086                 : 
    1087                 : NS_IMETHODIMP
    1088               0 : HttpChannelChild::SetRequestHeader(const nsACString& aHeader, 
    1089                 :                                    const nsACString& aValue, 
    1090                 :                                    bool aMerge)
    1091                 : {
    1092               0 :   nsresult rv = HttpBaseChannel::SetRequestHeader(aHeader, aValue, aMerge);
    1093               0 :   if (NS_FAILED(rv))
    1094               0 :     return rv;
    1095                 : 
    1096               0 :   RequestHeaderTuple* tuple = mClientSetRequestHeaders.AppendElement();
    1097               0 :   if (!tuple)
    1098               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1099                 : 
    1100               0 :   tuple->mHeader = aHeader;
    1101               0 :   tuple->mValue = aValue;
    1102               0 :   tuple->mMerge = aMerge;
    1103               0 :   return NS_OK;
    1104                 : }
    1105                 : 
    1106                 : //-----------------------------------------------------------------------------
    1107                 : // HttpChannelChild::nsIHttpChannelInternal
    1108                 : //-----------------------------------------------------------------------------
    1109                 : 
    1110                 : NS_IMETHODIMP
    1111               0 : HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey)
    1112                 : {
    1113               0 :   DROP_DEAD();
    1114                 : }
    1115                 : 
    1116                 : // The next four _should_ be implemented, but we need to figure out how
    1117                 : // to transfer the data from the chrome process first.
    1118                 : 
    1119                 : NS_IMETHODIMP
    1120               0 : HttpChannelChild::GetRemoteAddress(nsACString & _result)
    1121                 : {
    1122               0 :   return NS_ERROR_NOT_AVAILABLE;
    1123                 : }
    1124                 : 
    1125                 : NS_IMETHODIMP
    1126               0 : HttpChannelChild::GetRemotePort(PRInt32 * _result)
    1127                 : {
    1128               0 :   NS_ENSURE_ARG_POINTER(_result);
    1129               0 :   return NS_ERROR_NOT_AVAILABLE;
    1130                 : }
    1131                 : 
    1132                 : NS_IMETHODIMP
    1133               0 : HttpChannelChild::GetLocalAddress(nsACString & _result)
    1134                 : {
    1135               0 :   return NS_ERROR_NOT_AVAILABLE;
    1136                 : }
    1137                 : 
    1138                 : NS_IMETHODIMP
    1139               0 : HttpChannelChild::GetLocalPort(PRInt32 * _result)
    1140                 : {
    1141               0 :   NS_ENSURE_ARG_POINTER(_result);
    1142               0 :   return NS_ERROR_NOT_AVAILABLE;
    1143                 : }
    1144                 : 
    1145                 : 
    1146                 : //-----------------------------------------------------------------------------
    1147                 : // HttpChannelChild::nsICacheInfoChannel
    1148                 : //-----------------------------------------------------------------------------
    1149                 : 
    1150                 : NS_IMETHODIMP
    1151               0 : HttpChannelChild::GetCacheTokenExpirationTime(PRUint32 *_retval)
    1152                 : {
    1153               0 :   NS_ENSURE_ARG_POINTER(_retval);
    1154               0 :   if (!mCacheEntryAvailable)
    1155               0 :     return NS_ERROR_NOT_AVAILABLE;
    1156                 : 
    1157               0 :   *_retval = mCacheExpirationTime;
    1158               0 :   return NS_OK;
    1159                 : }
    1160                 : 
    1161                 : NS_IMETHODIMP
    1162               0 : HttpChannelChild::GetCacheTokenCachedCharset(nsACString &_retval)
    1163                 : {
    1164               0 :   if (!mCacheEntryAvailable)
    1165               0 :     return NS_ERROR_NOT_AVAILABLE;
    1166                 : 
    1167               0 :   _retval = mCachedCharset;
    1168               0 :   return NS_OK;
    1169                 : }
    1170                 : NS_IMETHODIMP
    1171               0 : HttpChannelChild::SetCacheTokenCachedCharset(const nsACString &aCharset)
    1172                 : {
    1173               0 :   if (!mCacheEntryAvailable || !RemoteChannelExists())
    1174               0 :     return NS_ERROR_NOT_AVAILABLE;
    1175                 : 
    1176               0 :   mCachedCharset = aCharset;
    1177               0 :   if (!SendSetCacheTokenCachedCharset(PromiseFlatCString(aCharset))) {
    1178               0 :     return NS_ERROR_FAILURE;
    1179                 :   }
    1180               0 :   return NS_OK;
    1181                 : }
    1182                 : 
    1183                 : NS_IMETHODIMP
    1184               0 : HttpChannelChild::IsFromCache(bool *value)
    1185                 : {
    1186               0 :   if (!mIsPending)
    1187               0 :     return NS_ERROR_NOT_AVAILABLE;
    1188                 : 
    1189               0 :   *value = mIsFromCache;
    1190               0 :   return NS_OK;
    1191                 : }
    1192                 : 
    1193                 : //-----------------------------------------------------------------------------
    1194                 : // HttpChannelChild::nsIResumableChannel
    1195                 : //-----------------------------------------------------------------------------
    1196                 : 
    1197                 : NS_IMETHODIMP
    1198               0 : HttpChannelChild::ResumeAt(PRUint64 startPos, const nsACString& entityID)
    1199                 : {
    1200               0 :   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
    1201               0 :   mStartPos = startPos;
    1202               0 :   mEntityID = entityID;
    1203               0 :   mSendResumeAt = true;
    1204               0 :   return NS_OK;
    1205                 : }
    1206                 : 
    1207                 : // GetEntityID is shared in HttpBaseChannel
    1208                 : 
    1209                 : //-----------------------------------------------------------------------------
    1210                 : // HttpChannelChild::nsISupportsPriority
    1211                 : //-----------------------------------------------------------------------------
    1212                 : 
    1213                 : NS_IMETHODIMP
    1214               0 : HttpChannelChild::SetPriority(PRInt32 aPriority)
    1215                 : {
    1216               0 :   PRInt16 newValue = clamped(aPriority, PR_INT16_MIN, PR_INT16_MAX);
    1217               0 :   if (mPriority == newValue)
    1218               0 :     return NS_OK;
    1219               0 :   mPriority = newValue;
    1220               0 :   if (RemoteChannelExists())
    1221               0 :     SendSetPriority(mPriority);
    1222               0 :   return NS_OK;
    1223                 : }
    1224                 : 
    1225                 : //-----------------------------------------------------------------------------
    1226                 : // HttpChannelChild::nsIProxiedChannel
    1227                 : //-----------------------------------------------------------------------------
    1228                 : 
    1229                 : NS_IMETHODIMP
    1230               0 : HttpChannelChild::GetProxyInfo(nsIProxyInfo **aProxyInfo)
    1231                 : {
    1232               0 :   DROP_DEAD();
    1233                 : }
    1234                 : 
    1235                 : //-----------------------------------------------------------------------------
    1236                 : // HttpChannelChild::nsIApplicationCacheContainer
    1237                 : //-----------------------------------------------------------------------------
    1238                 : 
    1239                 : NS_IMETHODIMP
    1240               0 : HttpChannelChild::GetApplicationCache(nsIApplicationCache **aApplicationCache)
    1241                 : {
    1242               0 :   NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
    1243               0 :   return NS_OK;
    1244                 : }
    1245                 : NS_IMETHODIMP
    1246               0 : HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
    1247                 : {
    1248               0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
    1249                 : 
    1250               0 :   mApplicationCache = aApplicationCache;
    1251               0 :   return NS_OK;
    1252                 : }
    1253                 : 
    1254                 : //-----------------------------------------------------------------------------
    1255                 : // HttpChannelChild::nsIApplicationCacheChannel
    1256                 : //-----------------------------------------------------------------------------
    1257                 : 
    1258                 : NS_IMETHODIMP
    1259               0 : HttpChannelChild::GetLoadedFromApplicationCache(bool *aLoadedFromApplicationCache)
    1260                 : {
    1261               0 :   *aLoadedFromApplicationCache = mLoadedFromApplicationCache;
    1262               0 :   return NS_OK;
    1263                 : }
    1264                 : 
    1265                 : NS_IMETHODIMP
    1266               0 : HttpChannelChild::GetInheritApplicationCache(bool *aInherit)
    1267                 : {
    1268               0 :   *aInherit = mInheritApplicationCache;
    1269               0 :   return NS_OK;
    1270                 : }
    1271                 : NS_IMETHODIMP
    1272               0 : HttpChannelChild::SetInheritApplicationCache(bool aInherit)
    1273                 : {
    1274               0 :   mInheritApplicationCache = aInherit;
    1275               0 :   return NS_OK;
    1276                 : }
    1277                 : 
    1278                 : NS_IMETHODIMP
    1279               0 : HttpChannelChild::GetChooseApplicationCache(bool *aChoose)
    1280                 : {
    1281               0 :   *aChoose = mChooseApplicationCache;
    1282               0 :   return NS_OK;
    1283                 : }
    1284                 : 
    1285                 : NS_IMETHODIMP
    1286               0 : HttpChannelChild::SetChooseApplicationCache(bool aChoose)
    1287                 : {
    1288               0 :   mChooseApplicationCache = aChoose;
    1289               0 :   return NS_OK;
    1290                 : }
    1291                 : 
    1292                 : NS_IMETHODIMP
    1293               0 : HttpChannelChild::MarkOfflineCacheEntryAsForeign()
    1294                 : {
    1295               0 :   SendMarkOfflineCacheEntryAsForeign();
    1296               0 :   return NS_OK;
    1297                 : }
    1298                 : 
    1299                 : //-----------------------------------------------------------------------------
    1300                 : // HttpChannelChild::nsIAssociatedContentSecurity
    1301                 : //-----------------------------------------------------------------------------
    1302                 : 
    1303                 : bool
    1304               0 : HttpChannelChild::GetAssociatedContentSecurity(
    1305                 :                     nsIAssociatedContentSecurity** _result)
    1306                 : {
    1307               0 :   if (!mSecurityInfo)
    1308               0 :     return false;
    1309                 : 
    1310                 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc =
    1311               0 :       do_QueryInterface(mSecurityInfo);
    1312               0 :   if (!assoc)
    1313               0 :     return false;
    1314                 : 
    1315               0 :   if (_result)
    1316               0 :     assoc.forget(_result);
    1317               0 :   return true;
    1318                 : }
    1319                 : 
    1320                 : /* attribute unsigned long countSubRequestsHighSecurity; */
    1321                 : NS_IMETHODIMP
    1322               0 : HttpChannelChild::GetCountSubRequestsHighSecurity(
    1323                 :                     PRInt32 *aSubRequestsHighSecurity)
    1324                 : {
    1325               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1326               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1327               0 :     return NS_OK;
    1328                 : 
    1329               0 :   return assoc->GetCountSubRequestsHighSecurity(aSubRequestsHighSecurity);
    1330                 : }
    1331                 : NS_IMETHODIMP
    1332               0 : HttpChannelChild::SetCountSubRequestsHighSecurity(
    1333                 :                     PRInt32 aSubRequestsHighSecurity)
    1334                 : {
    1335               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1336               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1337               0 :     return NS_OK;
    1338                 : 
    1339               0 :   return assoc->SetCountSubRequestsHighSecurity(aSubRequestsHighSecurity);
    1340                 : }
    1341                 : 
    1342                 : /* attribute unsigned long countSubRequestsLowSecurity; */
    1343                 : NS_IMETHODIMP
    1344               0 : HttpChannelChild::GetCountSubRequestsLowSecurity(
    1345                 :                     PRInt32 *aSubRequestsLowSecurity)
    1346                 : {
    1347               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1348               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1349               0 :     return NS_OK;
    1350                 : 
    1351               0 :   return assoc->GetCountSubRequestsLowSecurity(aSubRequestsLowSecurity);
    1352                 : }
    1353                 : NS_IMETHODIMP
    1354               0 : HttpChannelChild::SetCountSubRequestsLowSecurity(
    1355                 :                     PRInt32 aSubRequestsLowSecurity)
    1356                 : {
    1357               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1358               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1359               0 :     return NS_OK;
    1360                 : 
    1361               0 :   return assoc->SetCountSubRequestsLowSecurity(aSubRequestsLowSecurity);
    1362                 : }
    1363                 : 
    1364                 : /* attribute unsigned long countSubRequestsBrokenSecurity; */
    1365                 : NS_IMETHODIMP 
    1366               0 : HttpChannelChild::GetCountSubRequestsBrokenSecurity(
    1367                 :                     PRInt32 *aSubRequestsBrokenSecurity)
    1368                 : {
    1369               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1370               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1371               0 :     return NS_OK;
    1372                 : 
    1373               0 :   return assoc->GetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
    1374                 : }
    1375                 : NS_IMETHODIMP 
    1376               0 : HttpChannelChild::SetCountSubRequestsBrokenSecurity(
    1377                 :                     PRInt32 aSubRequestsBrokenSecurity)
    1378                 : {
    1379               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1380               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1381               0 :     return NS_OK;
    1382                 : 
    1383               0 :   return assoc->SetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
    1384                 : }
    1385                 : 
    1386                 : /* attribute unsigned long countSubRequestsNoSecurity; */
    1387                 : NS_IMETHODIMP
    1388               0 : HttpChannelChild::GetCountSubRequestsNoSecurity(PRInt32 *aSubRequestsNoSecurity)
    1389                 : {
    1390               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1391               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1392               0 :     return NS_OK;
    1393                 : 
    1394               0 :   return assoc->GetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
    1395                 : }
    1396                 : NS_IMETHODIMP
    1397               0 : HttpChannelChild::SetCountSubRequestsNoSecurity(PRInt32 aSubRequestsNoSecurity)
    1398                 : {
    1399               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1400               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1401               0 :     return NS_OK;
    1402                 : 
    1403               0 :   return assoc->SetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
    1404                 : }
    1405                 : 
    1406                 : NS_IMETHODIMP
    1407               0 : HttpChannelChild::Flush()
    1408                 : {
    1409               0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    1410               0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    1411               0 :     return NS_OK;
    1412                 : 
    1413                 :   nsresult rv;
    1414                 :   PRInt32 hi, low, broken, no;
    1415                 : 
    1416               0 :   rv = assoc->GetCountSubRequestsHighSecurity(&hi);
    1417               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1418               0 :   rv = assoc->GetCountSubRequestsLowSecurity(&low);
    1419               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1420               0 :   rv = assoc->GetCountSubRequestsBrokenSecurity(&broken);
    1421               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1422               0 :   rv = assoc->GetCountSubRequestsNoSecurity(&no);
    1423               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1424                 : 
    1425               0 :   if (mIPCOpen)
    1426               0 :     SendUpdateAssociatedContentSecurity(hi, low, broken, no);
    1427                 : 
    1428               0 :   return NS_OK;
    1429                 : }
    1430                 : 
    1431                 : //-----------------------------------------------------------------------------
    1432                 : // HttpChannelChild::nsIHttpChannelChild
    1433                 : //-----------------------------------------------------------------------------
    1434                 : 
    1435               0 : NS_IMETHODIMP HttpChannelChild::AddCookiesToRequest()
    1436                 : {
    1437               0 :   HttpBaseChannel::AddCookiesToRequest();
    1438               0 :   return NS_OK;
    1439                 : }
    1440                 : 
    1441               0 : NS_IMETHODIMP HttpChannelChild::GetClientSetRequestHeaders(RequestHeaderTuples **aRequestHeaders)
    1442                 : {
    1443               0 :   *aRequestHeaders = &mClientSetRequestHeaders;
    1444               0 :   return NS_OK;
    1445                 : }
    1446                 : 
    1447                 : //------------------------------------------------------------------------------
    1448                 : 
    1449                 : }} // mozilla::net

Generated by: LCOV version 1.7