LCOV - code coverage report
Current view: top level - caps - nsJSPrincipals.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 60 134 44.8 %
Date: 2017-07-14 16:53:18 Functions: 8 12 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "xpcpublic.h"
       7             : #include "nsString.h"
       8             : #include "nsIObjectOutputStream.h"
       9             : #include "nsIObjectInputStream.h"
      10             : #include "nsJSPrincipals.h"
      11             : #include "plstr.h"
      12             : #include "nsXPIDLString.h"
      13             : #include "nsCOMPtr.h"
      14             : #include "nsIServiceManager.h"
      15             : #include "nsMemory.h"
      16             : #include "nsStringBuffer.h"
      17             : 
      18             : #include "mozilla/dom/StructuredCloneTags.h"
      19             : // for mozilla::dom::workers::kJSPrincipalsDebugToken
      20             : #include "mozilla/dom/workers/Workers.h"
      21             : #include "mozilla/ipc/BackgroundUtils.h"
      22             : 
      23             : using namespace mozilla;
      24             : using namespace mozilla::ipc;
      25             : 
      26             : NS_IMETHODIMP_(MozExternalRefCountType)
      27       15122 : nsJSPrincipals::AddRef()
      28             : {
      29       15122 :   MOZ_ASSERT(NS_IsMainThread());
      30       15122 :   NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt");
      31       15122 :   nsrefcnt count = ++refcount;
      32       15122 :   NS_LOG_ADDREF(this, count, "nsJSPrincipals", sizeof(*this));
      33       15122 :   return count;
      34             : }
      35             : 
      36             : NS_IMETHODIMP_(MozExternalRefCountType)
      37       13145 : nsJSPrincipals::Release()
      38             : {
      39       13145 :   MOZ_ASSERT(NS_IsMainThread());
      40       13145 :   NS_PRECONDITION(0 != refcount, "dup release");
      41       13145 :   nsrefcnt count = --refcount;
      42       13145 :   NS_LOG_RELEASE(this, count, "nsJSPrincipals");
      43       13145 :   if (count == 0) {
      44         177 :     delete this;
      45             :   }
      46             : 
      47       13145 :   return count;
      48             : }
      49             : 
      50             : /* static */ bool
      51           0 : nsJSPrincipals::Subsume(JSPrincipals *jsprin, JSPrincipals *other)
      52             : {
      53             :     bool result;
      54           0 :     nsresult rv = nsJSPrincipals::get(jsprin)->Subsumes(nsJSPrincipals::get(other), &result);
      55           0 :     return NS_SUCCEEDED(rv) && result;
      56             : }
      57             : 
      58             : /* static */ void
      59           0 : nsJSPrincipals::Destroy(JSPrincipals *jsprin)
      60             : {
      61             :     // The JS runtime can call this method during the last GC when
      62             :     // nsScriptSecurityManager is destroyed. So we must not assume here that
      63             :     // the security manager still exists.
      64             : 
      65           0 :     nsJSPrincipals *nsjsprin = nsJSPrincipals::get(jsprin);
      66             : 
      67             :     // We need to destroy the nsIPrincipal. We'll do this by adding
      68             :     // to the refcount and calling release
      69             : 
      70             : #ifdef NS_BUILD_REFCNT_LOGGING
      71             :     // The refcount logging considers AddRef-to-1 to indicate creation,
      72             :     // so trick it into thinking it's otherwise, but balance the
      73             :     // Release() we do below.
      74           0 :     nsjsprin->refcount++;
      75           0 :     nsjsprin->AddRef();
      76           0 :     nsjsprin->refcount--;
      77             : #else
      78             :     nsjsprin->refcount++;
      79             : #endif
      80           0 :     nsjsprin->Release();
      81           0 : }
      82             : 
      83             : #ifdef DEBUG
      84             : 
      85             : // Defined here so one can do principals->dump() in the debugger
      86             : JS_PUBLIC_API(void)
      87           0 : JSPrincipals::dump()
      88             : {
      89           0 :     if (debugToken == nsJSPrincipals::DEBUG_TOKEN) {
      90           0 :       nsAutoCString str;
      91           0 :       nsresult rv = static_cast<nsJSPrincipals *>(this)->GetScriptLocation(str);
      92           0 :       fprintf(stderr, "nsIPrincipal (%p) = %s\n", static_cast<void*>(this),
      93           0 :               NS_SUCCEEDED(rv) ? str.get() : "(unknown)");
      94           0 :     } else if (debugToken == dom::workers::kJSPrincipalsDebugToken) {
      95           0 :         fprintf(stderr, "Web Worker principal singleton (%p)\n", this);
      96             :     } else {
      97             :         fprintf(stderr,
      98             :                 "!!! JSPrincipals (%p) is not nsJSPrincipals instance - bad token: "
      99             :                 "actual=0x%x expected=0x%x\n",
     100           0 :                 this, unsigned(debugToken), unsigned(nsJSPrincipals::DEBUG_TOKEN));
     101             :     }
     102           0 : }
     103             : 
     104             : #endif
     105             : 
     106             : /* static */ bool
     107           0 : nsJSPrincipals::ReadPrincipals(JSContext* aCx, JSStructuredCloneReader* aReader,
     108             :                                JSPrincipals** aOutPrincipals)
     109             : {
     110             :     uint32_t tag;
     111             :     uint32_t unused;
     112           0 :     if (!JS_ReadUint32Pair(aReader, &tag, &unused)) {
     113           0 :         return false;
     114             :     }
     115             : 
     116           0 :     if (!(tag == SCTAG_DOM_NULL_PRINCIPAL ||
     117           0 :           tag == SCTAG_DOM_SYSTEM_PRINCIPAL ||
     118           0 :           tag == SCTAG_DOM_CONTENT_PRINCIPAL ||
     119           0 :           tag == SCTAG_DOM_EXPANDED_PRINCIPAL)) {
     120           0 :         xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
     121           0 :         return false;
     122             :     }
     123             : 
     124           0 :     return ReadKnownPrincipalType(aCx, aReader, tag, aOutPrincipals);
     125             : }
     126             : 
     127             : static bool
     128           1 : ReadSuffixAndSpec(JSStructuredCloneReader* aReader,
     129             :                   OriginAttributes& aAttrs,
     130             :                   nsACString& aSpec)
     131             : {
     132             :     uint32_t suffixLength, specLength;
     133           1 :     if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) {
     134           0 :         return false;
     135             :     }
     136             : 
     137           2 :     nsAutoCString suffix;
     138           1 :     if (!suffix.SetLength(suffixLength, fallible)) {
     139           0 :         return false;
     140             :     }
     141             : 
     142           1 :     if (!JS_ReadBytes(aReader, suffix.BeginWriting(), suffixLength)) {
     143           0 :         return false;
     144             :     }
     145             : 
     146           1 :     if (!aAttrs.PopulateFromSuffix(suffix)) {
     147           0 :         return false;
     148             :     }
     149             : 
     150           1 :     if (!aSpec.SetLength(specLength, fallible)) {
     151           0 :         return false;
     152             :     }
     153             : 
     154           1 :     if (!JS_ReadBytes(aReader, aSpec.BeginWriting(), specLength)) {
     155           0 :         return false;
     156             :     }
     157             : 
     158           1 :     return true;
     159             : }
     160             : 
     161             : static bool
     162           1 : ReadPrincipalInfo(JSStructuredCloneReader* aReader,
     163             :                   uint32_t aTag,
     164             :                   PrincipalInfo& aInfo)
     165             : {
     166           1 :     if (aTag == SCTAG_DOM_SYSTEM_PRINCIPAL) {
     167           0 :         aInfo = SystemPrincipalInfo();
     168           1 :     } else if (aTag == SCTAG_DOM_NULL_PRINCIPAL) {
     169           0 :         OriginAttributes attrs;
     170           0 :         nsAutoCString spec;
     171           0 :         if (!ReadSuffixAndSpec(aReader, attrs, spec)) {
     172           0 :             return false;
     173             :         }
     174           0 :         aInfo = NullPrincipalInfo(attrs, spec);
     175           1 :     } else if (aTag == SCTAG_DOM_EXPANDED_PRINCIPAL) {
     176             :         uint32_t length, unused;
     177           0 :         if (!JS_ReadUint32Pair(aReader, &length, &unused)) {
     178           0 :             return false;
     179             :         }
     180             : 
     181           0 :         ExpandedPrincipalInfo expanded;
     182             : 
     183           0 :         for (uint32_t i = 0; i < length; i++) {
     184             :             uint32_t tag;
     185           0 :             if (!JS_ReadUint32Pair(aReader, &tag, &unused)) {
     186           0 :                 return false;
     187             :             }
     188             : 
     189           0 :             PrincipalInfo sub;
     190           0 :             if (!ReadPrincipalInfo(aReader, tag, sub)) {
     191           0 :                 return false;
     192             :             }
     193           0 :             expanded.whitelist().AppendElement(sub);
     194             :         }
     195             : 
     196           0 :         aInfo = expanded;
     197           1 :     } else if (aTag == SCTAG_DOM_CONTENT_PRINCIPAL) {
     198           2 :         OriginAttributes attrs;
     199           2 :         nsAutoCString spec;
     200           1 :         if (!ReadSuffixAndSpec(aReader, attrs, spec)) {
     201           0 :             return false;
     202             :         }
     203             : 
     204           1 :         aInfo = ContentPrincipalInfo(attrs, void_t(), spec);
     205             :     } else {
     206           0 :         MOZ_CRASH("unexpected principal structured clone tag");
     207             :     }
     208             : 
     209           1 :     return true;
     210             : }
     211             : 
     212             : /* static */ bool
     213           1 : nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
     214             :                                        JSStructuredCloneReader* aReader,
     215             :                                        uint32_t aTag,
     216             :                                        JSPrincipals** aOutPrincipals)
     217             : {
     218           1 :     MOZ_ASSERT(aTag == SCTAG_DOM_NULL_PRINCIPAL ||
     219             :                aTag == SCTAG_DOM_SYSTEM_PRINCIPAL ||
     220             :                aTag == SCTAG_DOM_CONTENT_PRINCIPAL ||
     221             :                aTag == SCTAG_DOM_EXPANDED_PRINCIPAL);
     222             : 
     223           1 :     if (NS_WARN_IF(!NS_IsMainThread())) {
     224           0 :         xpc::Throw(aCx, NS_ERROR_UNCATCHABLE_EXCEPTION);
     225           0 :         return false;
     226             :     }
     227             : 
     228           2 :     PrincipalInfo info;
     229           1 :     if (!ReadPrincipalInfo(aReader, aTag, info)) {
     230           0 :         return false;
     231             :     }
     232             : 
     233             :     nsresult rv;
     234           2 :     nsCOMPtr<nsIPrincipal> prin = PrincipalInfoToPrincipal(info, &rv);
     235           1 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     236           0 :         xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
     237           0 :         return false;
     238             :     }
     239             : 
     240           1 :     *aOutPrincipals = get(prin.forget().take());
     241           1 :     return true;
     242             : }
     243             : 
     244             : static bool
     245           1 : WriteSuffixAndSpec(JSStructuredCloneWriter* aWriter,
     246             :                    const OriginAttributes& aAttrs,
     247             :                    const nsCString& aSpec)
     248             : {
     249           2 :   nsAutoCString suffix;
     250           1 :   aAttrs.CreateSuffix(suffix);
     251             : 
     252           2 :   return JS_WriteUint32Pair(aWriter, suffix.Length(), aSpec.Length()) &&
     253           2 :          JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) &&
     254           3 :          JS_WriteBytes(aWriter, aSpec.get(), aSpec.Length());
     255             : }
     256             : 
     257             : static bool
     258           1 : WritePrincipalInfo(JSStructuredCloneWriter* aWriter, const PrincipalInfo& aInfo)
     259             : {
     260           1 :     if (aInfo.type() == PrincipalInfo::TNullPrincipalInfo) {
     261           0 :         const NullPrincipalInfo& nullInfo = aInfo;
     262           0 :         return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0) &&
     263           0 :                WriteSuffixAndSpec(aWriter, nullInfo.attrs(), nullInfo.spec());
     264             :     }
     265           1 :     if (aInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
     266           0 :         return JS_WriteUint32Pair(aWriter, SCTAG_DOM_SYSTEM_PRINCIPAL, 0);
     267             :     }
     268           1 :     if (aInfo.type() == PrincipalInfo::TExpandedPrincipalInfo) {
     269           0 :         const ExpandedPrincipalInfo& expanded = aInfo;
     270           0 :         if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_EXPANDED_PRINCIPAL, 0) ||
     271           0 :             !JS_WriteUint32Pair(aWriter, expanded.whitelist().Length(), 0)) {
     272           0 :             return false;
     273             :         }
     274             : 
     275           0 :         for (uint32_t i = 0; i < expanded.whitelist().Length(); i++) {
     276           0 :             if (!WritePrincipalInfo(aWriter, expanded.whitelist()[i])) {
     277           0 :                 return false;
     278             :             }
     279             :         }
     280           0 :         return true;
     281             :     }
     282             : 
     283           1 :     MOZ_ASSERT(aInfo.type() == PrincipalInfo::TContentPrincipalInfo);
     284           1 :     const ContentPrincipalInfo& cInfo = aInfo;
     285           2 :     return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) &&
     286           2 :            WriteSuffixAndSpec(aWriter, cInfo.attrs(), cInfo.spec());
     287             : }
     288             : 
     289             : bool
     290           1 : nsJSPrincipals::write(JSContext* aCx, JSStructuredCloneWriter* aWriter)
     291             : {
     292           2 :     PrincipalInfo info;
     293           1 :     if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(this, &info)))) {
     294           0 :         xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
     295           0 :         return false;
     296             :     }
     297             : 
     298           1 :     return WritePrincipalInfo(aWriter, info);
     299             : }

Generated by: LCOV version 1.13