LCOV - code coverage report
Current view: directory - content/base/src - nsBlobProtocolHandler.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 165 118 71.5 %
Date: 2012-06-02 Functions: 37 25 67.6 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is mozilla.org code.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "nsBlobProtocolHandler.h"
      38                 : #include "nsSimpleURI.h"
      39                 : #include "nsDOMError.h"
      40                 : #include "nsCOMPtr.h"
      41                 : #include "nsClassHashtable.h"
      42                 : #include "nsNetUtil.h"
      43                 : #include "nsIURIWithPrincipal.h"
      44                 : #include "nsIPrincipal.h"
      45                 : #include "nsIDOMFile.h"
      46                 : #include "nsISerializable.h"
      47                 : #include "nsIClassInfo.h"
      48                 : #include "nsIObjectInputStream.h"
      49                 : #include "nsIObjectOutputStream.h"
      50                 : #include "nsIProgrammingLanguage.h"
      51                 : 
      52                 : // -----------------------------------------------------------------------
      53                 : // Hash table
      54                 : struct FileDataInfo
      55               4 : {
      56                 :   nsCOMPtr<nsIDOMBlob> mFile;
      57                 :   nsCOMPtr<nsIPrincipal> mPrincipal;
      58                 : };
      59                 : 
      60                 : static nsClassHashtable<nsCStringHashKey, FileDataInfo>* gFileDataTable;
      61                 : 
      62                 : void
      63               2 : nsBlobProtocolHandler::AddFileDataEntry(nsACString& aUri,
      64                 :                                             nsIDOMBlob* aFile,
      65                 :                                             nsIPrincipal* aPrincipal)
      66                 : {
      67               2 :   if (!gFileDataTable) {
      68               2 :     gFileDataTable = new nsClassHashtable<nsCStringHashKey, FileDataInfo>;
      69               2 :     gFileDataTable->Init();
      70                 :   }
      71                 : 
      72               2 :   FileDataInfo* info = new FileDataInfo;
      73                 : 
      74               2 :   info->mFile = aFile;
      75               2 :   info->mPrincipal = aPrincipal;
      76                 : 
      77               2 :   gFileDataTable->Put(aUri, info);
      78               2 : }
      79                 : 
      80                 : void
      81               2 : nsBlobProtocolHandler::RemoveFileDataEntry(nsACString& aUri)
      82                 : {
      83               2 :   if (gFileDataTable) {
      84               2 :     gFileDataTable->Remove(aUri);
      85               2 :     if (gFileDataTable->Count() == 0) {
      86               2 :       delete gFileDataTable;
      87               2 :       gFileDataTable = nsnull;
      88                 :     }
      89                 :   }
      90               2 : }
      91                 : 
      92                 : nsIPrincipal*
      93               0 : nsBlobProtocolHandler::GetFileDataEntryPrincipal(nsACString& aUri)
      94                 : {
      95               0 :   if (!gFileDataTable) {
      96               0 :     return nsnull;
      97                 :   }
      98                 :   
      99                 :   FileDataInfo* res;
     100               0 :   gFileDataTable->Get(aUri, &res);
     101               0 :   if (!res) {
     102               0 :     return nsnull;
     103                 :   }
     104                 : 
     105               0 :   return res->mPrincipal;
     106                 : }
     107                 : 
     108                 : static FileDataInfo*
     109              17 : GetFileDataInfo(const nsACString& aUri)
     110                 : {
     111              17 :   NS_ASSERTION(StringBeginsWith(aUri,
     112                 :                                 NS_LITERAL_CSTRING(BLOBURI_SCHEME ":")),
     113                 :                "Bad URI");
     114                 :   
     115              17 :   if (!gFileDataTable) {
     116              13 :     return nsnull;
     117                 :   }
     118                 :   
     119                 :   FileDataInfo* res;
     120               4 :   gFileDataTable->Get(aUri, &res);
     121               4 :   return res;
     122                 : }
     123                 : 
     124                 : // -----------------------------------------------------------------------
     125                 : // Uri
     126                 : 
     127                 : #define NS_BLOBURI_CID \
     128                 : { 0xf5475c51, 0x59a7, 0x4757, \
     129                 :   { 0xb3, 0xd9, 0xe2, 0x11, 0xa9, 0x41, 0x08, 0x72 } }
     130                 : 
     131                 : static NS_DEFINE_CID(kBLOBURICID, NS_BLOBURI_CID);
     132                 : 
     133                 : class nsBlobURI : public nsSimpleURI,
     134                 :                       public nsIURIWithPrincipal
     135                 : {
     136                 : public:
     137              15 :   nsBlobURI(nsIPrincipal* aPrincipal) :
     138              15 :       nsSimpleURI(), mPrincipal(aPrincipal)
     139              15 :   {}
     140             108 :   virtual ~nsBlobURI() {}
     141                 : 
     142                 :   // For use only from deserialization
     143              12 :   nsBlobURI() : nsSimpleURI() {}
     144                 : 
     145                 :   NS_DECL_ISUPPORTS_INHERITED
     146                 :   NS_DECL_NSIURIWITHPRINCIPAL
     147                 :   NS_DECL_NSISERIALIZABLE
     148                 :   NS_DECL_NSICLASSINFO
     149                 : 
     150                 :   // Override CloneInternal() and EqualsInternal()
     151                 :   virtual nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
     152                 :                                  nsIURI** aClone);
     153                 :   virtual nsresult EqualsInternal(nsIURI* aOther,
     154                 :                                   RefHandlingEnum aRefHandlingMode,
     155                 :                                   bool* aResult);
     156                 : 
     157                 :   // Override StartClone to hand back a nsBlobURI
     158              12 :   virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
     159              12 :   { return new nsBlobURI(); }
     160                 : 
     161                 :   nsCOMPtr<nsIPrincipal> mPrincipal;
     162                 : };
     163                 : 
     164                 : static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
     165                 :                      NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
     166                 : 
     167             347 : NS_IMPL_ADDREF_INHERITED(nsBlobURI, nsSimpleURI)
     168             347 : NS_IMPL_RELEASE_INHERITED(nsBlobURI, nsSimpleURI)
     169                 : 
     170             447 : NS_INTERFACE_MAP_BEGIN(nsBlobURI)
     171             447 :   NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
     172             445 :   if (aIID.Equals(kBLOBURICID))
     173              78 :     foundInterface = static_cast<nsIURI*>(this);
     174             367 :   else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
     175                 :     // Need to return explicitly here, because if we just set foundInterface
     176                 :     // to null the NS_INTERFACE_MAP_END_INHERITING will end up calling into
     177                 :     // nsSimplURI::QueryInterface and finding something for this CID.
     178               4 :     *aInstancePtr = nsnull;
     179               4 :     return NS_NOINTERFACE;
     180                 :   }
     181                 :   else
     182             363 : NS_INTERFACE_MAP_END_INHERITING(nsSimpleURI)
     183                 : 
     184                 : // nsIURIWithPrincipal methods:
     185                 : 
     186                 : NS_IMETHODIMP
     187               2 : nsBlobURI::GetPrincipal(nsIPrincipal** aPrincipal)
     188                 : {
     189               2 :   NS_IF_ADDREF(*aPrincipal = mPrincipal);
     190                 : 
     191               2 :   return NS_OK;
     192                 : }
     193                 : 
     194                 : NS_IMETHODIMP
     195               0 : nsBlobURI::GetPrincipalUri(nsIURI** aUri)
     196                 : {
     197               0 :   if (mPrincipal) {
     198               0 :     mPrincipal->GetURI(aUri);
     199                 :   }
     200                 :   else {
     201               0 :     *aUri = nsnull;
     202                 :   }
     203                 : 
     204               0 :   return NS_OK;
     205                 : }
     206                 : 
     207                 : // nsISerializable methods:
     208                 : 
     209                 : NS_IMETHODIMP
     210               0 : nsBlobURI::Read(nsIObjectInputStream* aStream)
     211                 : {
     212               0 :   nsresult rv = nsSimpleURI::Read(aStream);
     213               0 :   NS_ENSURE_SUCCESS(rv, rv);
     214                 : 
     215               0 :   return NS_ReadOptionalObject(aStream, true, getter_AddRefs(mPrincipal));
     216                 : }
     217                 : 
     218                 : NS_IMETHODIMP
     219               0 : nsBlobURI::Write(nsIObjectOutputStream* aStream)
     220                 : {
     221               0 :   nsresult rv = nsSimpleURI::Write(aStream);
     222               0 :   NS_ENSURE_SUCCESS(rv, rv);
     223                 : 
     224                 :   return NS_WriteOptionalCompoundObject(aStream, mPrincipal,
     225                 :                                         NS_GET_IID(nsIPrincipal),
     226               0 :                                         true);
     227                 : }
     228                 : 
     229                 : // nsIURI methods:
     230                 : nsresult
     231              12 : nsBlobURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
     232                 :                              nsIURI** aClone)
     233                 : {
     234              24 :   nsCOMPtr<nsIURI> simpleClone;
     235                 :   nsresult rv =
     236              12 :     nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
     237              12 :   NS_ENSURE_SUCCESS(rv, rv);
     238                 : 
     239                 : #ifdef DEBUG
     240              24 :   nsRefPtr<nsBlobURI> uriCheck;
     241              12 :   rv = simpleClone->QueryInterface(kBLOBURICID, getter_AddRefs(uriCheck));
     242              12 :   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
     243                 :                     "Unexpected!");
     244                 : #endif
     245                 : 
     246              12 :   nsBlobURI* blobURI = static_cast<nsBlobURI*>(simpleClone.get());
     247                 : 
     248              12 :   blobURI->mPrincipal = mPrincipal;
     249                 : 
     250              12 :   simpleClone.forget(aClone);
     251              12 :   return NS_OK;
     252                 : }
     253                 : 
     254                 : /* virtual */ nsresult
     255              71 : nsBlobURI::EqualsInternal(nsIURI* aOther,
     256                 :                               nsSimpleURI::RefHandlingEnum aRefHandlingMode,
     257                 :                               bool* aResult)
     258                 : {
     259              71 :   if (!aOther) {
     260               1 :     *aResult = false;
     261               1 :     return NS_OK;
     262                 :   }
     263                 :   
     264             140 :   nsRefPtr<nsBlobURI> otherBlobUri;
     265              70 :   aOther->QueryInterface(kBLOBURICID, getter_AddRefs(otherBlobUri));
     266              70 :   if (!otherBlobUri) {
     267               4 :     *aResult = false;
     268               4 :     return NS_OK;
     269                 :   }
     270                 : 
     271                 :   // Compare the member data that our base class knows about.
     272              66 :   if (!nsSimpleURI::EqualsInternal(otherBlobUri, aRefHandlingMode)) {
     273              10 :     *aResult = false;
     274              10 :     return NS_OK;
     275                 :    }
     276                 : 
     277                 :   // Compare the piece of additional member data that we add to base class.
     278              56 :   if (mPrincipal && otherBlobUri->mPrincipal) {
     279                 :     // Both of us have mPrincipals. Compare them.
     280               0 :     return mPrincipal->Equals(otherBlobUri->mPrincipal, aResult);
     281                 :   }
     282                 :   // else, at least one of us lacks a principal; only equal if *both* lack it.
     283              56 :   *aResult = (!mPrincipal && !otherBlobUri->mPrincipal);
     284              56 :   return NS_OK;
     285                 : }
     286                 : 
     287                 : // nsIClassInfo methods:
     288                 : NS_IMETHODIMP 
     289              25 : nsBlobURI::GetInterfaces(PRUint32 *count, nsIID * **array)
     290                 : {
     291              25 :   *count = 0;
     292              25 :   *array = nsnull;
     293              25 :   return NS_OK;
     294                 : }
     295                 : 
     296                 : NS_IMETHODIMP 
     297              25 : nsBlobURI::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
     298                 : {
     299              25 :   *_retval = nsnull;
     300              25 :   return NS_OK;
     301                 : }
     302                 : 
     303                 : NS_IMETHODIMP 
     304               0 : nsBlobURI::GetContractID(char * *aContractID)
     305                 : {
     306                 :   // Make sure to modify any subclasses as needed if this ever
     307                 :   // changes.
     308               0 :   *aContractID = nsnull;
     309               0 :   return NS_OK;
     310                 : }
     311                 : 
     312                 : NS_IMETHODIMP 
     313               0 : nsBlobURI::GetClassDescription(char * *aClassDescription)
     314                 : {
     315               0 :   *aClassDescription = nsnull;
     316               0 :   return NS_OK;
     317                 : }
     318                 : 
     319                 : NS_IMETHODIMP 
     320               0 : nsBlobURI::GetClassID(nsCID * *aClassID)
     321                 : {
     322                 :   // Make sure to modify any subclasses as needed if this ever
     323                 :   // changes to not call the virtual GetClassIDNoAlloc.
     324               0 :   *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
     325               0 :   NS_ENSURE_TRUE(*aClassID, NS_ERROR_OUT_OF_MEMORY);
     326                 : 
     327               0 :   return GetClassIDNoAlloc(*aClassID);
     328                 : }
     329                 : 
     330                 : NS_IMETHODIMP 
     331               0 : nsBlobURI::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
     332                 : {
     333               0 :   *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
     334               0 :   return NS_OK;
     335                 : }
     336                 : 
     337                 : NS_IMETHODIMP 
     338              25 : nsBlobURI::GetFlags(PRUint32 *aFlags)
     339                 : {
     340              25 :   *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
     341              25 :   return NS_OK;
     342                 : }
     343                 : 
     344                 : NS_IMETHODIMP 
     345               0 : nsBlobURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
     346                 : {
     347               0 :   *aClassIDNoAlloc = kBLOBURICID;
     348               0 :   return NS_OK;
     349                 : }
     350                 : 
     351                 : // -----------------------------------------------------------------------
     352                 : // Protocol handler
     353                 : 
     354             148 : NS_IMPL_ISUPPORTS1(nsBlobProtocolHandler, nsIProtocolHandler)
     355                 : 
     356                 : NS_IMETHODIMP
     357               0 : nsBlobProtocolHandler::GetScheme(nsACString &result)
     358                 : {
     359               0 :   result.AssignLiteral(BLOBURI_SCHEME);
     360               0 :   return NS_OK;
     361                 : }
     362                 : 
     363                 : NS_IMETHODIMP
     364               0 : nsBlobProtocolHandler::GetDefaultPort(PRInt32 *result)
     365                 : {
     366               0 :   *result = -1;
     367               0 :   return NS_OK;
     368                 : }
     369                 : 
     370                 : NS_IMETHODIMP
     371               2 : nsBlobProtocolHandler::GetProtocolFlags(PRUint32 *result)
     372                 : {
     373                 :   *result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_SUBSUMERS |
     374               2 :             URI_IS_LOCAL_RESOURCE | URI_NON_PERSISTABLE;
     375               2 :   return NS_OK;
     376                 : }
     377                 : 
     378                 : NS_IMETHODIMP
     379              15 : nsBlobProtocolHandler::NewURI(const nsACString& aSpec,
     380                 :                                   const char *aCharset,
     381                 :                                   nsIURI *aBaseURI,
     382                 :                                   nsIURI **aResult)
     383                 : {
     384              15 :   *aResult = nsnull;
     385                 :   nsresult rv;
     386                 : 
     387                 :   FileDataInfo* info =
     388              15 :     GetFileDataInfo(aSpec);
     389                 : 
     390                 :   nsRefPtr<nsBlobURI> uri =
     391              45 :     new nsBlobURI(info ? info->mPrincipal.get() : nsnull);
     392                 : 
     393              15 :   rv = uri->SetSpec(aSpec);
     394              15 :   NS_ENSURE_SUCCESS(rv, rv);
     395                 : 
     396              15 :   NS_TryToSetImmutable(uri);
     397              15 :   uri.forget(aResult);
     398                 : 
     399              15 :   return NS_OK;
     400                 : }
     401                 : 
     402                 : NS_IMETHODIMP
     403               2 : nsBlobProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
     404                 : {
     405               2 :   *result = nsnull;
     406                 : 
     407               4 :   nsCString spec;
     408               2 :   uri->GetSpec(spec);
     409                 : 
     410                 :   FileDataInfo* info =
     411               2 :     GetFileDataInfo(spec);
     412                 : 
     413               2 :   if (!info) {
     414               0 :     return NS_ERROR_DOM_BAD_URI;
     415                 :   }
     416                 : 
     417                 : #ifdef DEBUG
     418                 :   {
     419               4 :     nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
     420               4 :     nsCOMPtr<nsIPrincipal> principal;
     421               2 :     uriPrinc->GetPrincipal(getter_AddRefs(principal));
     422               2 :     NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
     423                 :   }
     424                 : #endif
     425                 : 
     426               4 :   nsCOMPtr<nsIInputStream> stream;
     427               2 :   nsresult rv = info->mFile->GetInternalStream(getter_AddRefs(stream));
     428               2 :   NS_ENSURE_SUCCESS(rv, rv);
     429                 : 
     430               4 :   nsCOMPtr<nsIChannel> channel;
     431               2 :   rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
     432                 :                                 uri,
     433               2 :                                 stream);
     434               2 :   NS_ENSURE_SUCCESS(rv, rv);
     435                 : 
     436               4 :   nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
     437                 : 
     438               4 :   nsAutoString type;
     439               2 :   rv = info->mFile->GetType(type);
     440               2 :   NS_ENSURE_SUCCESS(rv, rv);
     441                 : 
     442               2 :   channel->SetOwner(owner);
     443               2 :   channel->SetOriginalURI(uri);
     444               2 :   channel->SetContentType(NS_ConvertUTF16toUTF8(type));
     445               2 :   channel.forget(result);
     446                 :   
     447               2 :   return NS_OK;
     448                 : }
     449                 : 
     450                 : NS_IMETHODIMP 
     451               0 : nsBlobProtocolHandler::AllowPort(PRInt32 port, const char *scheme,
     452                 :                                      bool *_retval)
     453                 : {
     454                 :     // don't override anything.  
     455               0 :     *_retval = false;
     456               0 :     return NS_OK;
     457                 : }

Generated by: LCOV version 1.7