LCOV - code coverage report
Current view: directory - caps/src - nsPrincipal.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 583 66 11.3 %
Date: 2012-06-02 Functions: 50 14 28.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2003
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Christopher A. Aillon <christopher@aillon.com>
      25                 :  *   Giorgio Maone <g.maone@informaction.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nscore.h"
      42                 : #include "nsScriptSecurityManager.h"
      43                 : #include "nsString.h"
      44                 : #include "nsReadableUtils.h"
      45                 : #include "plstr.h"
      46                 : #include "nsCRT.h"
      47                 : #include "nsIURI.h"
      48                 : #include "nsIFileURL.h"
      49                 : #include "nsIProtocolHandler.h"
      50                 : #include "nsNetUtil.h"
      51                 : #include "nsJSPrincipals.h"
      52                 : #include "nsVoidArray.h"
      53                 : #include "nsHashtable.h"
      54                 : #include "nsIObjectInputStream.h"
      55                 : #include "nsIObjectOutputStream.h"
      56                 : #include "nsIClassInfoImpl.h"
      57                 : #include "nsDOMError.h"
      58                 : #include "nsIContentSecurityPolicy.h"
      59                 : 
      60                 : #include "nsPrincipal.h"
      61                 : 
      62                 : #include "mozilla/Preferences.h"
      63                 : #include "mozilla/HashFunctions.h"
      64                 : 
      65                 : using namespace mozilla;
      66                 : 
      67                 : static bool gCodeBasePrincipalSupport = false;
      68                 : static bool gIsObservingCodeBasePrincipalSupport = false;
      69                 : 
      70             207 : static bool URIIsImmutable(nsIURI* aURI)
      71                 : {
      72             414 :   nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
      73                 :   bool isMutable;
      74                 :   return
      75                 :     mutableObj &&
      76             414 :     NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
      77             414 :     !isMutable;                               
      78                 : }
      79                 : 
      80                 : // Static member variables
      81                 : PRInt32 nsPrincipal::sCapabilitiesOrdinal = 0;
      82                 : const char nsPrincipal::sInvalid[] = "Invalid";
      83                 : 
      84                 : 
      85                 : NS_IMPL_CLASSINFO(nsPrincipal, NULL, nsIClassInfo::MAIN_THREAD_ONLY,
      86                 :                   NS_PRINCIPAL_CID)
      87            1151 : NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal,
      88                 :                             nsIPrincipal,
      89              42 :                             nsISerializable)
      90              12 : NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
      91                 :                              nsIPrincipal,
      92              12 :                              nsISerializable)
      93                 : 
      94                 : NS_IMETHODIMP_(nsrefcnt)
      95            1833 : nsPrincipal::AddRef()
      96                 : {
      97            1833 :   NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt");
      98                 :   // XXXcaa does this need to be threadsafe?  See bug 143559.
      99            1833 :   nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount);
     100            1833 :   NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this));
     101            1833 :   return count;
     102                 : }
     103                 : 
     104                 : NS_IMETHODIMP_(nsrefcnt)
     105            1833 : nsPrincipal::Release()
     106                 : {
     107            1833 :   NS_PRECONDITION(0 != refcount, "dup release");
     108            1833 :   nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount);
     109            1833 :   NS_LOG_RELEASE(this, count, "nsPrincipal");
     110            1833 :   if (count == 0) {
     111             207 :     delete this;
     112                 :   }
     113                 : 
     114            1833 :   return count;
     115                 : }
     116                 : 
     117             207 : nsPrincipal::nsPrincipal()
     118                 :   : mCapabilities(nsnull),
     119                 :     mSecurityPolicy(nsnull),
     120                 :     mTrusted(false),
     121                 :     mInitialized(false),
     122                 :     mCodebaseImmutable(false),
     123             207 :     mDomainImmutable(false)
     124                 : {
     125             207 :   if (!gIsObservingCodeBasePrincipalSupport) {
     126                 :     nsresult rv =
     127                 :       Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
     128                 :                                    "signed.applets.codebase_principal_support",
     129              51 :                                    false);
     130              51 :     gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv);
     131              51 :     NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport,
     132                 :                      "Installing gCodeBasePrincipalSupport failed!");
     133                 :   }
     134             207 : }
     135                 : 
     136                 : nsresult
     137             207 : nsPrincipal::Init(const nsACString& aCertFingerprint,
     138                 :                   const nsACString& aSubjectName,
     139                 :                   const nsACString& aPrettyName,
     140                 :                   nsISupports* aCert,
     141                 :                   nsIURI *aCodebase)
     142                 : {
     143             207 :   NS_ENSURE_STATE(!mInitialized);
     144             207 :   NS_ENSURE_ARG(!aCertFingerprint.IsEmpty() || aCodebase); // better have one of these.
     145                 : 
     146             207 :   mInitialized = true;
     147                 : 
     148             207 :   mCodebase = NS_TryToMakeImmutable(aCodebase);
     149             207 :   mCodebaseImmutable = URIIsImmutable(mCodebase);
     150                 : 
     151             207 :   if (aCertFingerprint.IsEmpty())
     152             207 :     return NS_OK;
     153                 : 
     154               0 :   return SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert);
     155                 : }
     156                 : 
     157             621 : nsPrincipal::~nsPrincipal(void)
     158                 : {
     159             207 :   SetSecurityPolicy(nsnull); 
     160             207 :   delete mCapabilities;
     161             828 : }
     162                 : 
     163                 : void
     164               0 : nsPrincipal::GetScriptLocation(nsACString &aStr)
     165                 : {
     166               0 :   if (mCert) {
     167               0 :     aStr.Assign(mCert->fingerprint);
     168                 :   } else {
     169               0 :     mCodebase->GetSpec(aStr);
     170                 :   }
     171               0 : }
     172                 : 
     173                 : #ifdef DEBUG
     174               0 : void nsPrincipal::dumpImpl()
     175                 : {
     176               0 :   nsCAutoString str;
     177               0 :   GetScriptLocation(str);
     178               0 :   fprintf(stderr, "nsPrincipal (%p) = %s\n", this, str.get());
     179               0 : }
     180                 : #endif 
     181                 : 
     182                 : NS_IMETHODIMP
     183               0 : nsPrincipal::GetOrigin(char **aOrigin)
     184                 : {
     185               0 :   *aOrigin = nsnull;
     186                 : 
     187               0 :   nsCOMPtr<nsIURI> origin;
     188               0 :   if (mCodebase) {
     189               0 :     origin = NS_GetInnermostURI(mCodebase);
     190                 :   }
     191                 :   
     192               0 :   if (!origin) {
     193               0 :     NS_ASSERTION(mCert, "No Domain or Codebase for a non-cert principal");
     194               0 :     return NS_ERROR_FAILURE;
     195                 :   }
     196                 : 
     197               0 :   nsCAutoString hostPort;
     198                 : 
     199                 :   // chrome: URLs don't have a meaningful origin, so make
     200                 :   // sure we just get the full spec for them.
     201                 :   // XXX this should be removed in favor of the solution in
     202                 :   // bug 160042.
     203                 :   bool isChrome;
     204               0 :   nsresult rv = origin->SchemeIs("chrome", &isChrome);
     205               0 :   if (NS_SUCCEEDED(rv) && !isChrome) {
     206               0 :     rv = origin->GetAsciiHost(hostPort);
     207                 :     // Some implementations return an empty string, treat it as no support
     208                 :     // for asciiHost by that implementation.
     209               0 :     if (hostPort.IsEmpty())
     210               0 :       rv = NS_ERROR_FAILURE;
     211                 :   }
     212                 : 
     213                 :   PRInt32 port;
     214               0 :   if (NS_SUCCEEDED(rv) && !isChrome) {
     215               0 :     rv = origin->GetPort(&port);
     216                 :   }
     217                 : 
     218               0 :   if (NS_SUCCEEDED(rv) && !isChrome) {
     219               0 :     if (port != -1) {
     220               0 :       hostPort.AppendLiteral(":");
     221               0 :       hostPort.AppendInt(port, 10);
     222                 :     }
     223                 : 
     224               0 :     nsCAutoString scheme;
     225               0 :     rv = origin->GetScheme(scheme);
     226               0 :     NS_ENSURE_SUCCESS(rv, rv);
     227               0 :     *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort);
     228                 :   }
     229                 :   else {
     230                 :     // Some URIs (e.g., nsSimpleURI) don't support asciiHost. Just
     231                 :     // get the full spec.
     232               0 :     nsCAutoString spec;
     233                 :     // XXX nsMozIconURI and nsJARURI don't implement this correctly, they
     234                 :     // both fall back to GetSpec.  That needs to be fixed.
     235               0 :     rv = origin->GetAsciiSpec(spec);
     236               0 :     NS_ENSURE_SUCCESS(rv, rv);
     237               0 :     *aOrigin = ToNewCString(spec);
     238                 :   }
     239                 : 
     240               0 :   return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     241                 : }
     242                 : 
     243                 : NS_IMETHODIMP
     244               0 : nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
     245                 : {
     246               0 :   if (mSecurityPolicy && mSecurityPolicy->IsInvalid()) 
     247               0 :     SetSecurityPolicy(nsnull);
     248                 :   
     249               0 :   *aSecurityPolicy = (void *) mSecurityPolicy;
     250               0 :   return NS_OK;
     251                 : }
     252                 : 
     253                 : NS_IMETHODIMP
     254             208 : nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
     255                 : {
     256             208 :   DomainPolicy *newPolicy = reinterpret_cast<DomainPolicy *>(aSecurityPolicy);
     257             208 :   if (newPolicy)
     258               1 :     newPolicy->Hold();
     259                 :  
     260             208 :   if (mSecurityPolicy)
     261               1 :     mSecurityPolicy->Drop();
     262                 :   
     263             208 :   mSecurityPolicy = newPolicy;
     264             208 :   return NS_OK;
     265                 : }
     266                 : 
     267                 : bool
     268               0 : nsPrincipal::CertificateEquals(nsIPrincipal *aOther)
     269                 : {
     270                 :   bool otherHasCert;
     271               0 :   aOther->GetHasCertificate(&otherHasCert);
     272               0 :   if (otherHasCert != (mCert != nsnull)) {
     273                 :     // One has a cert while the other doesn't.  Not equal.
     274               0 :     return false;
     275                 :   }
     276                 : 
     277               0 :   if (!mCert)
     278               0 :     return true;
     279                 : 
     280               0 :   nsCAutoString str;
     281               0 :   aOther->GetFingerprint(str);
     282               0 :   if (!str.Equals(mCert->fingerprint))
     283               0 :     return false;
     284                 : 
     285                 :   // If either subject name is empty, just let the result stand (so that
     286                 :   // nsScriptSecurityManager::SetCanEnableCapability works), but if they're
     287                 :   // both non-empty, only claim equality if they're equal.
     288               0 :   if (!mCert->subjectName.IsEmpty()) {
     289                 :     // Check the other principal's subject name
     290               0 :     aOther->GetSubjectName(str);
     291               0 :     return str.Equals(mCert->subjectName) || str.IsEmpty();
     292                 :   }
     293                 : 
     294               0 :   return true;
     295                 : }
     296                 : 
     297                 : NS_IMETHODIMP
     298               0 : nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
     299                 : {
     300               0 :   if (!aOther) {
     301               0 :     NS_WARNING("Need a principal to compare this to!");
     302               0 :     *aResult = false;
     303               0 :     return NS_OK;
     304                 :   }
     305                 : 
     306               0 :   if (this != aOther) {
     307               0 :     if (!CertificateEquals(aOther)) {
     308               0 :       *aResult = false;
     309               0 :       return NS_OK;
     310                 :     }
     311                 : 
     312               0 :     if (mCert) {
     313                 :       // If either principal has no URI, it's the saved principal from
     314                 :       // preferences; in that case, test true.  Do NOT test true if the two
     315                 :       // principals have URIs with different codebases.
     316               0 :       nsCOMPtr<nsIURI> otherURI;
     317               0 :       nsresult rv = aOther->GetURI(getter_AddRefs(otherURI));
     318               0 :       if (NS_FAILED(rv)) {
     319               0 :         *aResult = false;
     320               0 :         return rv;
     321                 :       }
     322                 : 
     323               0 :       if (!otherURI || !mCodebase) {
     324               0 :         *aResult = true;
     325               0 :         return NS_OK;
     326                 :       }
     327                 : 
     328                 :       // Fall through to the codebase comparison.
     329                 :     }
     330                 : 
     331                 :     // Codebases are equal if they have the same origin.
     332                 :     *aResult =
     333               0 :       NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
     334               0 :                                                                      aOther));
     335               0 :     return NS_OK;
     336                 :   }
     337                 : 
     338               0 :   *aResult = true;
     339               0 :   return NS_OK;
     340                 : }
     341                 : 
     342                 : NS_IMETHODIMP
     343               0 : nsPrincipal::EqualsIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
     344                 : {
     345               0 :   if (this == aOther) {
     346               0 :     *aResult = true;
     347               0 :     return NS_OK;
     348                 :   }
     349                 : 
     350               0 :   *aResult = false;
     351               0 :   if (!CertificateEquals(aOther)) {
     352               0 :     return NS_OK;
     353                 :   }
     354                 : 
     355               0 :   nsCOMPtr<nsIURI> otherURI;
     356               0 :   nsresult rv = aOther->GetURI(getter_AddRefs(otherURI));
     357               0 :   if (NS_FAILED(rv)) {
     358               0 :     return rv;
     359                 :   }
     360                 : 
     361               0 :   NS_ASSERTION(mCodebase,
     362                 :                "shouldn't be calling this on principals from preferences");
     363                 : 
     364                 :   // Compare codebases.
     365                 :   *aResult = nsScriptSecurityManager::SecurityCompareURIs(mCodebase,
     366               0 :                                                           otherURI);
     367               0 :   return NS_OK;
     368                 : }
     369                 : 
     370                 : NS_IMETHODIMP
     371               0 : nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
     372                 : {
     373               0 :   return Equals(aOther, aResult);
     374                 : }
     375                 : 
     376                 : NS_IMETHODIMP
     377               0 : nsPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
     378                 : {
     379               0 :   return EqualsIgnoringDomain(aOther, aResult);
     380                 : }
     381                 : 
     382                 : static bool
     383               1 : URIIsLocalFile(nsIURI *aURI)
     384                 : {
     385                 :   bool isFile;
     386               2 :   nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
     387                 : 
     388               2 :   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
     389                 :                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
     390                 :                                 &isFile)) &&
     391               2 :          isFile;
     392                 : }
     393                 : 
     394                 : NS_IMETHODIMP
     395               2 : nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
     396                 : {
     397               2 :   if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
     398               2 :     if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
     399               1 :         URIIsLocalFile(aURI)) {
     400               0 :       nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(aURI));
     401                 : 
     402               0 :       if (!URIIsLocalFile(mCodebase)) {
     403                 :         // If the codebase is not also a file: uri then forget it
     404                 :         // (don't want resource: principals in a file: doc)
     405                 :         //
     406                 :         // note: we're not de-nesting jar: uris here, we want to
     407                 :         // keep archive content bottled up in its own little island
     408                 : 
     409               0 :         if (aReport) {
     410                 :           nsScriptSecurityManager::ReportError(
     411               0 :             nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
     412                 :         }
     413                 : 
     414               0 :         return NS_ERROR_DOM_BAD_URI;
     415                 :       }
     416                 : 
     417                 :       //
     418                 :       // pull out the internal files
     419                 :       //
     420               0 :       nsCOMPtr<nsIFileURL> codebaseFileURL(do_QueryInterface(mCodebase));
     421               0 :       nsCOMPtr<nsIFile> targetFile;
     422               0 :       nsCOMPtr<nsIFile> codebaseFile;
     423                 :       bool targetIsDir;
     424                 : 
     425                 :       // Make sure targetFile is not a directory (bug 209234)
     426                 :       // and that it exists w/out unescaping (bug 395343)
     427                 : 
     428               0 :       if (!codebaseFileURL || !fileURL ||
     429               0 :           NS_FAILED(fileURL->GetFile(getter_AddRefs(targetFile))) ||
     430               0 :           NS_FAILED(codebaseFileURL->GetFile(getter_AddRefs(codebaseFile))) ||
     431               0 :           !targetFile || !codebaseFile ||
     432               0 :           NS_FAILED(targetFile->Normalize()) ||
     433               0 :           NS_FAILED(codebaseFile->Normalize()) ||
     434               0 :           NS_FAILED(targetFile->IsDirectory(&targetIsDir)) ||
     435                 :           targetIsDir) {
     436               0 :         if (aReport) {
     437                 :           nsScriptSecurityManager::ReportError(
     438               0 :             nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
     439                 :         }
     440                 : 
     441               0 :         return NS_ERROR_DOM_BAD_URI;
     442                 :       }
     443                 : 
     444                 :       //
     445                 :       // If the file to be loaded is in a subdirectory of the codebase
     446                 :       // (or same-dir if codebase is not a directory) then it will
     447                 :       // inherit its codebase principal and be scriptable by that codebase.
     448                 :       //
     449                 :       bool codebaseIsDir;
     450               0 :       bool contained = false;
     451               0 :       nsresult rv = codebaseFile->IsDirectory(&codebaseIsDir);
     452               0 :       if (NS_SUCCEEDED(rv) && codebaseIsDir) {
     453               0 :         rv = codebaseFile->Contains(targetFile, true, &contained);
     454                 :       }
     455                 :       else {
     456               0 :         nsCOMPtr<nsIFile> codebaseParent;
     457               0 :         rv = codebaseFile->GetParent(getter_AddRefs(codebaseParent));
     458               0 :         if (NS_SUCCEEDED(rv) && codebaseParent) {
     459               0 :           rv = codebaseParent->Contains(targetFile, true, &contained);
     460                 :         }
     461                 :       }
     462                 : 
     463               0 :       if (NS_SUCCEEDED(rv) && contained) {
     464               0 :         return NS_OK;
     465                 :       }
     466                 :     }
     467                 : 
     468               1 :     if (aReport) {
     469                 :       nsScriptSecurityManager::ReportError(
     470               0 :         nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
     471                 :     }
     472                 :     
     473               1 :     return NS_ERROR_DOM_BAD_URI;
     474                 :   }
     475                 : 
     476               1 :   return NS_OK;
     477                 : }
     478                 : 
     479                 : NS_IMETHODIMP
     480               0 : nsPrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
     481                 : {
     482                 :   // If this principal is marked invalid, can't enable any capabilities
     483               0 :   if (mCapabilities) {
     484               0 :     nsCStringKey invalidKey(sInvalid);
     485               0 :     if (mCapabilities->Exists(&invalidKey)) {
     486               0 :       *result = nsIPrincipal::ENABLE_DENIED;
     487                 : 
     488               0 :       return NS_OK;
     489                 :     }
     490                 :   }
     491                 : 
     492               0 :   if (!mCert && !mTrusted) {
     493               0 :     NS_ASSERTION(mInitialized, "Trying to enable a capability on an "
     494                 :                                "uninitialized principal");
     495                 : 
     496                 :     // If we are a non-trusted codebase principal, capabilities can not
     497                 :     // be enabled if the user has not set the pref allowing scripts to
     498                 :     // request enhanced capabilities; however, the file: and resource:
     499                 :     // schemes are special and may be able to get extra capabilities
     500                 :     // even with the pref disabled.
     501                 : 
     502               0 :     if (!gCodeBasePrincipalSupport) {
     503               0 :       bool mightEnable = false;
     504               0 :       nsresult rv = mCodebase->SchemeIs("file", &mightEnable);
     505               0 :       if (NS_FAILED(rv) || !mightEnable) {
     506               0 :         rv = mCodebase->SchemeIs("resource", &mightEnable);
     507               0 :         if (NS_FAILED(rv) || !mightEnable) {
     508               0 :           *result = nsIPrincipal::ENABLE_DENIED;
     509                 : 
     510               0 :           return NS_OK;
     511                 :         }
     512                 :       }
     513                 :     }
     514                 :   }
     515                 : 
     516               0 :   const char *start = capability;
     517               0 :   *result = nsIPrincipal::ENABLE_GRANTED;
     518               0 :   for(;;) {
     519               0 :     const char *space = PL_strchr(start, ' ');
     520               0 :     PRInt32 len = space ? space - start : strlen(start);
     521               0 :     nsCAutoString capString(start, len);
     522               0 :     nsCStringKey key(capString);
     523                 :     PRInt16 value =
     524               0 :       mCapabilities ? (PRInt16)NS_PTR_TO_INT32(mCapabilities->Get(&key)) : 0;
     525               0 :     if (value == 0 || value == nsIPrincipal::ENABLE_UNKNOWN) {
     526                 :       // We don't know whether we can enable this capability,
     527                 :       // so we should ask the user.
     528               0 :       value = nsIPrincipal::ENABLE_WITH_USER_PERMISSION;
     529                 :     }
     530                 : 
     531               0 :     if (value < *result) {
     532               0 :       *result = value;
     533                 :     }
     534                 : 
     535               0 :     if (!space) {
     536                 :       break;
     537                 :     }
     538                 : 
     539               0 :     start = space + 1;
     540                 :   }
     541                 : 
     542               0 :   return NS_OK;
     543                 : }
     544                 : 
     545                 : NS_IMETHODIMP
     546               0 : nsPrincipal::SetCanEnableCapability(const char *capability,
     547                 :                                     PRInt16 canEnable)
     548                 : {
     549                 :   // If this principal is marked invalid, can't enable any capabilities
     550               0 :   if (!mCapabilities) {
     551               0 :     mCapabilities = new nsHashtable(7);  // XXXbz gets bumped up to 16 anyway
     552               0 :     NS_ENSURE_TRUE(mCapabilities, NS_ERROR_OUT_OF_MEMORY);
     553                 :   }
     554                 : 
     555               0 :   nsCStringKey invalidKey(sInvalid);
     556               0 :   if (mCapabilities->Exists(&invalidKey)) {
     557               0 :     return NS_OK;
     558                 :   }
     559                 : 
     560               0 :   if (PL_strcmp(capability, sInvalid) == 0) {
     561               0 :     mCapabilities->Reset();
     562                 :   }
     563                 : 
     564               0 :   const char *start = capability;
     565               0 :   for(;;) {
     566               0 :     const char *space = PL_strchr(start, ' ');
     567               0 :     int len = space ? space - start : strlen(start);
     568               0 :     nsCAutoString capString(start, len);
     569               0 :     nsCStringKey key(capString);
     570               0 :     mCapabilities->Put(&key, NS_INT32_TO_PTR(canEnable));
     571               0 :     if (!space) {
     572                 :       break;
     573                 :     }
     574                 : 
     575               0 :     start = space + 1;
     576                 :   }
     577                 : 
     578               0 :   return NS_OK;
     579                 : }
     580                 : 
     581                 : NS_IMETHODIMP
     582               0 : nsPrincipal::IsCapabilityEnabled(const char *capability, void *annotation,
     583                 :                                  bool *result)
     584                 : {
     585               0 :   *result = false;
     586               0 :   nsHashtable *ht = (nsHashtable *) annotation;
     587               0 :   if (!ht) {
     588               0 :     return NS_OK;
     589                 :   }
     590               0 :   const char *start = capability;
     591               0 :   for(;;) {
     592               0 :     const char *space = PL_strchr(start, ' ');
     593               0 :     int len = space ? space - start : strlen(start);
     594               0 :     nsCAutoString capString(start, len);
     595               0 :     nsCStringKey key(capString);
     596               0 :     *result = (ht->Get(&key) == (void *) AnnotationEnabled);
     597               0 :     if (!*result) {
     598                 :       // If any single capability is not enabled, then return false.
     599               0 :       return NS_OK;
     600                 :     }
     601                 : 
     602               0 :     if (!space) {
     603               0 :       return NS_OK;
     604                 :     }
     605                 : 
     606               0 :     start = space + 1;
     607                 :   }
     608                 : 
     609                 :   return NS_OK;
     610                 : }
     611                 : 
     612                 : NS_IMETHODIMP
     613               0 : nsPrincipal::EnableCapability(const char *capability, void **annotation)
     614                 : {
     615               0 :   return SetCapability(capability, annotation, AnnotationEnabled);
     616                 : }
     617                 : 
     618                 : NS_IMETHODIMP
     619               0 : nsPrincipal::DisableCapability(const char *capability, void **annotation)
     620                 : {
     621               0 :   return SetCapability(capability, annotation, AnnotationDisabled);
     622                 : }
     623                 : 
     624                 : NS_IMETHODIMP
     625               0 : nsPrincipal::RevertCapability(const char *capability, void **annotation)
     626                 : {
     627               0 :   if (*annotation) {
     628               0 :     nsHashtable *ht = (nsHashtable *) *annotation;
     629               0 :     const char *start = capability;
     630               0 :     for(;;) {
     631               0 :       const char *space = PL_strchr(start, ' ');
     632               0 :       int len = space ? space - start : strlen(start);
     633               0 :       nsCAutoString capString(start, len);
     634               0 :       nsCStringKey key(capString);
     635               0 :       ht->Remove(&key);
     636               0 :       if (!space) {
     637               0 :         return NS_OK;
     638                 :       }
     639                 : 
     640               0 :       start = space + 1;
     641                 :     }
     642                 :   }
     643               0 :   return NS_OK;
     644                 : }
     645                 : 
     646                 : nsresult
     647               0 : nsPrincipal::SetCapability(const char *capability, void **annotation,
     648                 :                            AnnotationValue value)
     649                 : {
     650               0 :   if (*annotation == nsnull) {
     651               0 :     nsHashtable* ht = new nsHashtable(5);
     652                 : 
     653               0 :     if (!ht) {
     654               0 :        return NS_ERROR_OUT_OF_MEMORY;
     655                 :      }
     656                 : 
     657                 :     // This object owns its annotations. Save them so we can release
     658                 :     // them when we destroy this object.
     659               0 :     if (!mAnnotations.AppendElement(ht)) {
     660               0 :       delete ht;
     661               0 :       return NS_ERROR_OUT_OF_MEMORY;
     662                 :     }
     663                 : 
     664               0 :     *annotation = ht;
     665                 :   }
     666                 : 
     667               0 :   const char *start = capability;
     668               0 :   for(;;) {
     669               0 :     const char *space = PL_strchr(start, ' ');
     670               0 :     int len = space ? space - start : strlen(start);
     671               0 :     nsCAutoString capString(start, len);
     672               0 :     nsCStringKey key(capString);
     673               0 :     nsHashtable *ht = static_cast<nsHashtable *>(*annotation);
     674               0 :     ht->Put(&key, (void *) value);
     675               0 :     if (!space) {
     676                 :       break;
     677                 :     }
     678                 : 
     679               0 :     start = space + 1;
     680                 :   }
     681                 : 
     682               0 :   return NS_OK;
     683                 : }
     684                 : 
     685                 : NS_IMETHODIMP
     686               0 : nsPrincipal::GetHasCertificate(bool* aResult)
     687                 : {
     688               0 :   *aResult = (mCert != nsnull);
     689                 : 
     690               0 :   return NS_OK;
     691                 : }
     692                 : 
     693                 : NS_IMETHODIMP
     694             226 : nsPrincipal::GetURI(nsIURI** aURI)
     695                 : {
     696             226 :   if (mCodebaseImmutable) {
     697             226 :     NS_ADDREF(*aURI = mCodebase);
     698             226 :     return NS_OK;
     699                 :   }
     700                 : 
     701               0 :   if (!mCodebase) {
     702               0 :     *aURI = nsnull;
     703               0 :     return NS_OK;
     704                 :   }
     705                 : 
     706               0 :   return NS_EnsureSafeToReturn(mCodebase, aURI);
     707                 : }
     708                 : 
     709                 : void
     710               0 : nsPrincipal::SetURI(nsIURI* aURI)
     711                 : {
     712               0 :   mCodebase = NS_TryToMakeImmutable(aURI);
     713               0 :   mCodebaseImmutable = URIIsImmutable(mCodebase);
     714               0 : }
     715                 : 
     716                 : 
     717                 : nsresult
     718               0 : nsPrincipal::SetCertificate(const nsACString& aFingerprint,
     719                 :                             const nsACString& aSubjectName,
     720                 :                             const nsACString& aPrettyName,
     721                 :                             nsISupports* aCert)
     722                 : {
     723               0 :   NS_ENSURE_STATE(!mCert);
     724                 : 
     725               0 :   if (aFingerprint.IsEmpty()) {
     726               0 :     return NS_ERROR_INVALID_ARG;
     727                 :   }
     728                 : 
     729               0 :   mCert = new Certificate(aFingerprint, aSubjectName, aPrettyName, aCert);
     730               0 :   if (!mCert) {
     731               0 :     return NS_ERROR_OUT_OF_MEMORY;
     732                 :   }
     733                 : 
     734               0 :   return NS_OK;
     735                 : }
     736                 : 
     737                 : NS_IMETHODIMP
     738               0 : nsPrincipal::GetFingerprint(nsACString& aFingerprint)
     739                 : {
     740               0 :   NS_ENSURE_STATE(mCert);
     741                 : 
     742               0 :   aFingerprint = mCert->fingerprint;
     743                 : 
     744               0 :   return NS_OK;
     745                 : }
     746                 : 
     747                 : NS_IMETHODIMP
     748               0 : nsPrincipal::GetPrettyName(nsACString& aName)
     749                 : {
     750               0 :   NS_ENSURE_STATE(mCert);
     751                 : 
     752               0 :   aName = mCert->prettyName;
     753                 : 
     754               0 :   return NS_OK;
     755                 : }
     756                 : 
     757                 : NS_IMETHODIMP
     758               0 : nsPrincipal::GetSubjectName(nsACString& aName)
     759                 : {
     760               0 :   NS_ENSURE_STATE(mCert);
     761                 : 
     762               0 :   aName = mCert->subjectName;
     763                 : 
     764               0 :   return NS_OK;
     765                 : }
     766                 : 
     767                 : NS_IMETHODIMP
     768               0 : nsPrincipal::GetCertificate(nsISupports** aCertificate)
     769                 : {
     770               0 :   if (mCert) {
     771               0 :     NS_IF_ADDREF(*aCertificate = mCert->cert);
     772                 :   }
     773                 :   else {
     774               0 :     *aCertificate = nsnull;
     775                 :   }
     776               0 :   return NS_OK;
     777                 : }
     778                 : 
     779                 : NS_IMETHODIMP
     780               0 : nsPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
     781                 : {
     782               0 :   NS_IF_ADDREF(*aCsp = mCSP);
     783               0 :   return NS_OK;
     784                 : }
     785                 : 
     786                 : NS_IMETHODIMP
     787               0 : nsPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
     788                 : {
     789                 :   // If CSP was already set, it should not be destroyed!  Instead, it should
     790                 :   // get set anew when a new principal is created.
     791               0 :   if (mCSP)
     792               0 :     return NS_ERROR_ALREADY_INITIALIZED;
     793                 : 
     794               0 :   mCSP = aCsp;
     795               0 :   return NS_OK;
     796                 : }
     797                 : 
     798                 : NS_IMETHODIMP
     799               0 : nsPrincipal::GetHashValue(PRUint32* aValue)
     800                 : {
     801               0 :   NS_PRECONDITION(mCert || mCodebase, "Need a cert or codebase");
     802                 : 
     803                 :   // If there is a certificate, it takes precendence over the codebase.
     804               0 :   if (mCert) {
     805               0 :     *aValue = HashString(mCert->fingerprint);
     806                 :   }
     807                 :   else {
     808               0 :     *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);
     809                 :   }
     810                 : 
     811               0 :   return NS_OK;
     812                 : }
     813                 : 
     814                 : NS_IMETHODIMP
     815               1 : nsPrincipal::GetDomain(nsIURI** aDomain)
     816                 : {
     817               1 :   if (!mDomain) {
     818               1 :     *aDomain = nsnull;
     819               1 :     return NS_OK;
     820                 :   }
     821                 : 
     822               0 :   if (mDomainImmutable) {
     823               0 :     NS_ADDREF(*aDomain = mDomain);
     824               0 :     return NS_OK;
     825                 :   }
     826                 : 
     827               0 :   return NS_EnsureSafeToReturn(mDomain, aDomain);
     828                 : }
     829                 : 
     830                 : NS_IMETHODIMP
     831               0 : nsPrincipal::SetDomain(nsIURI* aDomain)
     832                 : {
     833               0 :   mDomain = NS_TryToMakeImmutable(aDomain);
     834               0 :   mDomainImmutable = URIIsImmutable(mDomain);
     835                 :   
     836                 :   // Domain has changed, forget cached security policy
     837               0 :   SetSecurityPolicy(nsnull);
     838                 : 
     839               0 :   return NS_OK;
     840                 : }
     841                 : 
     842                 : nsresult
     843               0 : nsPrincipal::InitFromPersistent(const char* aPrefName,
     844                 :                                 const nsCString& aToken,
     845                 :                                 const nsCString& aSubjectName,
     846                 :                                 const nsACString& aPrettyName,
     847                 :                                 const char* aGrantedList,
     848                 :                                 const char* aDeniedList,
     849                 :                                 nsISupports* aCert,
     850                 :                                 bool aIsCert,
     851                 :                                 bool aTrusted)
     852                 : {
     853               0 :   NS_PRECONDITION(!mCapabilities || mCapabilities->Count() == 0,
     854                 :                   "mCapabilities was already initialized?");
     855               0 :   NS_PRECONDITION(mAnnotations.Length() == 0,
     856                 :                   "mAnnotations was already initialized?");
     857               0 :   NS_PRECONDITION(!mInitialized, "We were already initialized?");
     858                 : 
     859               0 :   mInitialized = true;
     860                 : 
     861                 :   nsresult rv;
     862               0 :   if (aIsCert) {
     863               0 :     rv = SetCertificate(aToken, aSubjectName, aPrettyName, aCert);
     864                 :     
     865               0 :     if (NS_FAILED(rv)) {
     866               0 :       return rv;
     867                 :     }
     868                 :   }
     869                 :   else {
     870               0 :     rv = NS_NewURI(getter_AddRefs(mCodebase), aToken, nsnull);
     871               0 :     if (NS_FAILED(rv)) {
     872               0 :       NS_ERROR("Malformed URI in capability.principal preference.");
     873               0 :       return rv;
     874                 :     }
     875                 : 
     876               0 :     NS_TryToSetImmutable(mCodebase);
     877               0 :     mCodebaseImmutable = URIIsImmutable(mCodebase);
     878                 : 
     879               0 :     mTrusted = aTrusted;
     880                 :   }
     881                 : 
     882                 :   //-- Save the preference name
     883               0 :   mPrefName = aPrefName;
     884                 : 
     885               0 :   const char* ordinalBegin = PL_strpbrk(aPrefName, "1234567890");
     886               0 :   if (ordinalBegin) {
     887               0 :     PRIntn n = atoi(ordinalBegin);
     888               0 :     if (sCapabilitiesOrdinal <= n) {
     889               0 :       sCapabilitiesOrdinal = n + 1;
     890                 :     }
     891                 :   }
     892                 : 
     893                 :   //-- Store the capabilities
     894               0 :   rv = NS_OK;
     895               0 :   if (aGrantedList) {
     896               0 :     rv = SetCanEnableCapability(aGrantedList, nsIPrincipal::ENABLE_GRANTED);
     897                 :   }
     898                 : 
     899               0 :   if (NS_SUCCEEDED(rv) && aDeniedList) {
     900               0 :     rv = SetCanEnableCapability(aDeniedList, nsIPrincipal::ENABLE_DENIED);
     901                 :   }
     902                 : 
     903               0 :   return rv;
     904                 : }
     905                 : 
     906                 : nsresult
     907               0 : nsPrincipal::EnsureCertData(const nsACString& aSubjectName,
     908                 :                             const nsACString& aPrettyName,
     909                 :                             nsISupports* aCert)
     910                 : {
     911               0 :   NS_ENSURE_STATE(mCert);
     912                 : 
     913               0 :   if (!mCert->subjectName.IsEmpty() &&
     914               0 :       !mCert->subjectName.Equals(aSubjectName)) {
     915               0 :     return NS_ERROR_INVALID_ARG;
     916                 :   }
     917                 : 
     918               0 :   mCert->subjectName = aSubjectName;
     919               0 :   mCert->prettyName = aPrettyName;
     920               0 :   mCert->cert = aCert;
     921               0 :   return NS_OK;
     922                 : }
     923                 : 
     924                 : struct CapabilityList
     925                 : {
     926                 :   nsCString* granted;
     927                 :   nsCString* denied;
     928                 : };
     929                 : 
     930                 : static bool
     931               0 : AppendCapability(nsHashKey *aKey, void *aData, void *capListPtr)
     932                 : {
     933               0 :   CapabilityList* capList = (CapabilityList*)capListPtr;
     934               0 :   PRInt16 value = (PRInt16)NS_PTR_TO_INT32(aData);
     935               0 :   nsCStringKey* key = (nsCStringKey *)aKey;
     936               0 :   if (value == nsIPrincipal::ENABLE_GRANTED) {
     937               0 :     capList->granted->Append(key->GetString(), key->GetStringLength());
     938               0 :     capList->granted->Append(' ');
     939                 :   }
     940               0 :   else if (value == nsIPrincipal::ENABLE_DENIED) {
     941               0 :     capList->denied->Append(key->GetString(), key->GetStringLength());
     942               0 :     capList->denied->Append(' ');
     943                 :   }
     944                 : 
     945               0 :   return true;
     946                 : }
     947                 : 
     948                 : NS_IMETHODIMP
     949               0 : nsPrincipal::GetPreferences(char** aPrefName, char** aID,
     950                 :                             char** aSubjectName,
     951                 :                             char** aGrantedList, char** aDeniedList,
     952                 :                             bool* aIsTrusted)
     953                 : {
     954               0 :   if (mPrefName.IsEmpty()) {
     955               0 :     if (mCert) {
     956               0 :       mPrefName.Assign("capability.principal.certificate.p");
     957                 :     }
     958                 :     else {
     959               0 :       mPrefName.Assign("capability.principal.codebase.p");
     960                 :     }
     961                 : 
     962               0 :     mPrefName.AppendInt(sCapabilitiesOrdinal++);
     963               0 :     mPrefName.Append(".id");
     964                 :   }
     965                 : 
     966               0 :   *aPrefName = nsnull;
     967               0 :   *aID = nsnull;
     968               0 :   *aSubjectName = nsnull;
     969               0 :   *aGrantedList = nsnull;
     970               0 :   *aDeniedList = nsnull;
     971               0 :   *aIsTrusted = mTrusted;
     972                 : 
     973               0 :   char *prefName = nsnull;
     974               0 :   char *id = nsnull;
     975               0 :   char *subjectName = nsnull;
     976               0 :   char *granted = nsnull;
     977               0 :   char *denied = nsnull;
     978                 : 
     979                 :   //-- Preference name
     980               0 :   prefName = ToNewCString(mPrefName);
     981               0 :   if (!prefName) {
     982               0 :     return NS_ERROR_OUT_OF_MEMORY;
     983                 :   }
     984                 : 
     985                 :   //-- ID
     986               0 :   nsresult rv = NS_OK;
     987               0 :   if (mCert) {
     988               0 :     id = ToNewCString(mCert->fingerprint);
     989               0 :     if (!id) {
     990               0 :       rv = NS_ERROR_OUT_OF_MEMORY;
     991                 :     }
     992                 :   }
     993                 :   else {
     994               0 :     rv = GetOrigin(&id);
     995                 :   }
     996                 : 
     997               0 :   if (NS_FAILED(rv)) {
     998               0 :     nsMemory::Free(prefName);
     999               0 :     return rv;
    1000                 :   }
    1001                 : 
    1002               0 :   if (mCert) {
    1003               0 :     subjectName = ToNewCString(mCert->subjectName);
    1004                 :   } else {
    1005               0 :     subjectName = ToNewCString(EmptyCString());
    1006                 :   }
    1007                 : 
    1008               0 :   if (!subjectName) {
    1009               0 :     nsMemory::Free(prefName);
    1010               0 :     nsMemory::Free(id);
    1011               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1012                 :   }
    1013                 : 
    1014                 :   //-- Capabilities
    1015               0 :   nsCAutoString grantedListStr, deniedListStr;
    1016               0 :   if (mCapabilities) {
    1017               0 :     CapabilityList capList = CapabilityList();
    1018               0 :     capList.granted = &grantedListStr;
    1019               0 :     capList.denied = &deniedListStr;
    1020               0 :     mCapabilities->Enumerate(AppendCapability, (void*)&capList);
    1021                 :   }
    1022                 : 
    1023               0 :   if (!grantedListStr.IsEmpty()) {
    1024               0 :     grantedListStr.Truncate(grantedListStr.Length() - 1);
    1025               0 :     granted = ToNewCString(grantedListStr);
    1026               0 :     if (!granted) {
    1027               0 :       nsMemory::Free(prefName);
    1028               0 :       nsMemory::Free(id);
    1029               0 :       nsMemory::Free(subjectName);
    1030               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1031                 :     }
    1032                 :   }
    1033                 : 
    1034               0 :   if (!deniedListStr.IsEmpty()) {
    1035               0 :     deniedListStr.Truncate(deniedListStr.Length() - 1);
    1036               0 :     denied = ToNewCString(deniedListStr);
    1037               0 :     if (!denied) {
    1038               0 :       nsMemory::Free(prefName);
    1039               0 :       nsMemory::Free(id);
    1040               0 :       nsMemory::Free(subjectName);
    1041               0 :       if (granted) {
    1042               0 :         nsMemory::Free(granted);
    1043                 :       }
    1044               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1045                 :     }
    1046                 :   }
    1047                 : 
    1048               0 :   *aPrefName = prefName;
    1049               0 :   *aID = id;
    1050               0 :   *aSubjectName = subjectName;
    1051               0 :   *aGrantedList = granted;
    1052               0 :   *aDeniedList = denied;
    1053                 : 
    1054               0 :   return NS_OK;
    1055                 : }
    1056                 : 
    1057                 : static nsresult
    1058               0 : ReadAnnotationEntry(nsIObjectInputStream* aStream, nsHashKey** aKey,
    1059                 :                     void** aData)
    1060                 : {
    1061                 :   nsresult rv;
    1062               0 :   nsCStringKey* key = new nsCStringKey(aStream, &rv);
    1063               0 :   if (!key)
    1064               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1065                 : 
    1066               0 :   if (NS_FAILED(rv)) {
    1067               0 :     delete key;
    1068               0 :     return rv;
    1069                 :   }
    1070                 : 
    1071                 :   PRUint32 value;
    1072               0 :   rv = aStream->Read32(&value);
    1073               0 :   if (NS_FAILED(rv)) {
    1074               0 :     delete key;
    1075               0 :     return rv;
    1076                 :   }
    1077                 : 
    1078               0 :   *aKey = key;
    1079               0 :   *aData = (void*) value;
    1080               0 :   return NS_OK;
    1081                 : }
    1082                 : 
    1083                 : static void
    1084               0 : FreeAnnotationEntry(nsIObjectInputStream* aStream, nsHashKey* aKey,
    1085                 :                     void* aData)
    1086                 : {
    1087               0 :   delete aKey;
    1088               0 : }
    1089                 : 
    1090                 : NS_IMETHODIMP
    1091               0 : nsPrincipal::Read(nsIObjectInputStream* aStream)
    1092                 : {
    1093                 :   bool hasCapabilities;
    1094               0 :   nsresult rv = aStream->ReadBoolean(&hasCapabilities);
    1095               0 :   if (NS_SUCCEEDED(rv) && hasCapabilities) {
    1096                 :     mCapabilities = new nsHashtable(aStream, ReadAnnotationEntry,
    1097               0 :                                     FreeAnnotationEntry, &rv);
    1098               0 :     NS_ENSURE_TRUE(mCapabilities, NS_ERROR_OUT_OF_MEMORY);
    1099                 :   }
    1100                 : 
    1101               0 :   if (NS_FAILED(rv)) {
    1102               0 :     return rv;
    1103                 :   }
    1104                 : 
    1105               0 :   rv = NS_ReadOptionalCString(aStream, mPrefName);
    1106               0 :   if (NS_FAILED(rv)) {
    1107               0 :     return rv;
    1108                 :   }
    1109                 : 
    1110               0 :   const char* ordinalBegin = PL_strpbrk(mPrefName.get(), "1234567890");
    1111               0 :   if (ordinalBegin) {
    1112               0 :     PRIntn n = atoi(ordinalBegin);
    1113               0 :     if (sCapabilitiesOrdinal <= n) {
    1114               0 :       sCapabilitiesOrdinal = n + 1;
    1115                 :     }
    1116                 :   }
    1117                 : 
    1118                 :   bool haveCert;
    1119               0 :   rv = aStream->ReadBoolean(&haveCert);
    1120               0 :   if (NS_FAILED(rv)) {
    1121               0 :     return rv;
    1122                 :   }
    1123                 : 
    1124               0 :   nsCString fingerprint;
    1125               0 :   nsCString subjectName;
    1126               0 :   nsCString prettyName;
    1127               0 :   nsCOMPtr<nsISupports> cert;
    1128               0 :   if (haveCert) {
    1129               0 :     rv = NS_ReadOptionalCString(aStream, fingerprint);
    1130               0 :     if (NS_FAILED(rv)) {
    1131               0 :       return rv;
    1132                 :     }
    1133                 : 
    1134               0 :     rv = NS_ReadOptionalCString(aStream, subjectName);
    1135               0 :     if (NS_FAILED(rv)) {
    1136               0 :       return rv;
    1137                 :     }
    1138                 : 
    1139               0 :     rv = NS_ReadOptionalCString(aStream, prettyName);
    1140               0 :     if (NS_FAILED(rv)) {
    1141               0 :       return rv;
    1142                 :     }
    1143                 : 
    1144               0 :     rv = aStream->ReadObject(true, getter_AddRefs(cert));
    1145               0 :     if (NS_FAILED(rv)) {
    1146               0 :       return rv;
    1147                 :     }
    1148                 :   }
    1149                 : 
    1150               0 :   nsCOMPtr<nsIURI> codebase;
    1151               0 :   rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(codebase));
    1152               0 :   if (NS_FAILED(rv)) {
    1153               0 :     return rv;
    1154                 :   }
    1155                 : 
    1156               0 :   rv = Init(fingerprint, subjectName, prettyName, cert, codebase);
    1157               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1158                 : 
    1159               0 :   nsCOMPtr<nsIURI> domain;
    1160               0 :   rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(domain));
    1161               0 :   if (NS_FAILED(rv)) {
    1162               0 :     return rv;
    1163                 :   }
    1164                 : 
    1165               0 :   SetDomain(domain);
    1166                 : 
    1167               0 :   rv = aStream->ReadBoolean(&mTrusted);
    1168               0 :   if (NS_FAILED(rv)) {
    1169               0 :     return rv;
    1170                 :   }
    1171                 : 
    1172               0 :   return NS_OK;
    1173                 : }
    1174                 : 
    1175                 : static nsresult
    1176               0 : WriteScalarValue(nsIObjectOutputStream* aStream, void* aData)
    1177                 : {
    1178               0 :   PRUint32 value = NS_PTR_TO_INT32(aData);
    1179                 : 
    1180               0 :   return aStream->Write32(value);
    1181                 : }
    1182                 : 
    1183                 : NS_IMETHODIMP
    1184               0 : nsPrincipal::Write(nsIObjectOutputStream* aStream)
    1185                 : {
    1186               0 :   NS_ENSURE_STATE(mCert || mCodebase);
    1187                 :   
    1188                 :   // mAnnotations is transient data associated to specific JS stack frames.  We
    1189                 :   // don't want to serialize that.
    1190                 :   
    1191               0 :   bool hasCapabilities = (mCapabilities && mCapabilities->Count() > 0);
    1192               0 :   nsresult rv = aStream->WriteBoolean(hasCapabilities);
    1193               0 :   if (NS_SUCCEEDED(rv) && hasCapabilities) {
    1194               0 :     rv = mCapabilities->Write(aStream, WriteScalarValue);
    1195                 :   }
    1196                 : 
    1197               0 :   if (NS_FAILED(rv)) {
    1198               0 :     return rv;
    1199                 :   }
    1200                 : 
    1201               0 :   rv = NS_WriteOptionalStringZ(aStream, mPrefName.get());
    1202               0 :   if (NS_FAILED(rv)) {
    1203               0 :     return rv;
    1204                 :   }
    1205                 : 
    1206               0 :   rv = aStream->WriteBoolean(mCert != nsnull);
    1207               0 :   if (NS_FAILED(rv)) {
    1208               0 :     return rv;
    1209                 :   }
    1210                 : 
    1211               0 :   if (mCert) {
    1212               0 :     NS_ENSURE_STATE(mCert->cert);
    1213                 :     
    1214               0 :     rv = NS_WriteOptionalStringZ(aStream, mCert->fingerprint.get());
    1215               0 :     if (NS_FAILED(rv)) {
    1216               0 :       return rv;
    1217                 :     }
    1218                 :     
    1219               0 :     rv = NS_WriteOptionalStringZ(aStream, mCert->subjectName.get());
    1220               0 :     if (NS_FAILED(rv)) {
    1221               0 :       return rv;
    1222                 :     }
    1223                 :     
    1224               0 :     rv = NS_WriteOptionalStringZ(aStream, mCert->prettyName.get());
    1225               0 :     if (NS_FAILED(rv)) {
    1226               0 :       return rv;
    1227                 :     }
    1228                 : 
    1229               0 :     rv = aStream->WriteCompoundObject(mCert->cert, NS_GET_IID(nsISupports),
    1230               0 :                                       true);
    1231               0 :     if (NS_FAILED(rv)) {
    1232               0 :       return rv;
    1233                 :     }    
    1234                 :   }
    1235                 :   
    1236                 :   // mSecurityPolicy is an optimization; it'll get looked up again as needed.
    1237                 :   // Don't bother saving and restoring it, esp. since it might change if
    1238                 :   // preferences change.
    1239                 : 
    1240                 :   rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI),
    1241               0 :                                       true);
    1242               0 :   if (NS_FAILED(rv)) {
    1243               0 :     return rv;
    1244                 :   }
    1245                 : 
    1246                 :   rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI),
    1247               0 :                                       true);
    1248               0 :   if (NS_FAILED(rv)) {
    1249               0 :     return rv;
    1250                 :   }
    1251                 : 
    1252               0 :   rv = aStream->Write8(mTrusted);
    1253               0 :   if (NS_FAILED(rv)) {
    1254               0 :     return rv;
    1255                 :   }
    1256                 : 
    1257                 :   // mCodebaseImmutable and mDomainImmutable will be recomputed based
    1258                 :   // on the deserialized URIs in Read().
    1259                 : 
    1260               0 :   return NS_OK;
    1261                 : }

Generated by: LCOV version 1.7