LCOV - code coverage report
Current view: top level - dom/security - nsCSPUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 678 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 114 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsAttrValue.h"
       8             : #include "nsCharSeparatedTokenizer.h"
       9             : #include "nsContentUtils.h"
      10             : #include "nsCSPUtils.h"
      11             : #include "nsDebug.h"
      12             : #include "nsIConsoleService.h"
      13             : #include "nsICryptoHash.h"
      14             : #include "nsIScriptError.h"
      15             : #include "nsIServiceManager.h"
      16             : #include "nsIStringBundle.h"
      17             : #include "nsIURL.h"
      18             : #include "nsReadableUtils.h"
      19             : #include "nsSandboxFlags.h"
      20             : 
      21             : #define DEFAULT_PORT -1
      22             : 
      23             : static mozilla::LogModule*
      24           0 : GetCspUtilsLog()
      25             : {
      26             :   static mozilla::LazyLogModule gCspUtilsPRLog("CSPUtils");
      27           0 :   return gCspUtilsPRLog;
      28             : }
      29             : 
      30             : #define CSPUTILSLOG(args) MOZ_LOG(GetCspUtilsLog(), mozilla::LogLevel::Debug, args)
      31             : #define CSPUTILSLOGENABLED() MOZ_LOG_TEST(GetCspUtilsLog(), mozilla::LogLevel::Debug)
      32             : 
      33             : void
      34           0 : CSP_PercentDecodeStr(const nsAString& aEncStr, nsAString& outDecStr)
      35             : {
      36           0 :   outDecStr.Truncate();
      37             : 
      38             :   // helper function that should not be visible outside this methods scope
      39             :   struct local {
      40           0 :     static inline char16_t convertHexDig(char16_t aHexDig) {
      41           0 :       if (isNumberToken(aHexDig)) {
      42           0 :         return aHexDig - '0';
      43             :       }
      44           0 :       if (aHexDig >= 'A' && aHexDig <= 'F') {
      45           0 :         return aHexDig - 'A' + 10;
      46             :       }
      47             :       // must be a lower case character
      48             :       // (aHexDig >= 'a' && aHexDig <= 'f')
      49           0 :       return aHexDig - 'a' + 10;
      50             :     }
      51             :   };
      52             : 
      53             :   const char16_t *cur, *end, *hexDig1, *hexDig2;
      54           0 :   cur = aEncStr.BeginReading();
      55           0 :   end = aEncStr.EndReading();
      56             : 
      57           0 :   while (cur != end) {
      58             :     // if it's not a percent sign then there is
      59             :     // nothing to do for that character
      60           0 :     if (*cur != PERCENT_SIGN) {
      61           0 :       outDecStr.Append(*cur);
      62           0 :       cur++;
      63           0 :       continue;
      64             :     }
      65             : 
      66             :     // get the two hexDigs following the '%'-sign
      67           0 :     hexDig1 = cur + 1;
      68           0 :     hexDig2 = cur + 2;
      69             : 
      70             :     // if there are no hexdigs after the '%' then
      71             :     // there is nothing to do for us.
      72           0 :     if (hexDig1 == end || hexDig2 == end ||
      73           0 :         !isValidHexDig(*hexDig1) ||
      74           0 :         !isValidHexDig(*hexDig2)) {
      75           0 :       outDecStr.Append(PERCENT_SIGN);
      76           0 :       cur++;
      77           0 :       continue;
      78             :     }
      79             : 
      80             :     // decode "% hexDig1 hexDig2" into a character.
      81           0 :     char16_t decChar = (local::convertHexDig(*hexDig1) << 4) +
      82           0 :                        local::convertHexDig(*hexDig2);
      83           0 :     outDecStr.Append(decChar);
      84             : 
      85             :     // increment 'cur' to after the second hexDig
      86           0 :     cur = ++hexDig2;
      87             :   }
      88           0 : }
      89             : 
      90             : void
      91           0 : CSP_GetLocalizedStr(const char16_t* aName,
      92             :                     const char16_t** aParams,
      93             :                     uint32_t aLength,
      94             :                     char16_t** outResult)
      95             : {
      96           0 :   nsCOMPtr<nsIStringBundle> keyStringBundle;
      97             :   nsCOMPtr<nsIStringBundleService> stringBundleService =
      98           0 :     mozilla::services::GetStringBundleService();
      99             : 
     100           0 :   NS_ASSERTION(stringBundleService, "String bundle service must be present!");
     101           0 :   stringBundleService->CreateBundle("chrome://global/locale/security/csp.properties",
     102           0 :                                       getter_AddRefs(keyStringBundle));
     103             : 
     104           0 :   NS_ASSERTION(keyStringBundle, "Key string bundle must be available!");
     105             : 
     106           0 :   if (!keyStringBundle) {
     107           0 :     return;
     108             :   }
     109           0 :   keyStringBundle->FormatStringFromName(aName, aParams, aLength, outResult);
     110             : }
     111             : 
     112             : void
     113           0 : CSP_LogStrMessage(const nsAString& aMsg)
     114             : {
     115           0 :   nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1"));
     116             : 
     117           0 :   if (!console) {
     118           0 :     return;
     119             :   }
     120           0 :   nsString msg = PromiseFlatString(aMsg);
     121           0 :   console->LogStringMessage(msg.get());
     122             : }
     123             : 
     124             : void
     125           0 : CSP_LogMessage(const nsAString& aMessage,
     126             :                const nsAString& aSourceName,
     127             :                const nsAString& aSourceLine,
     128             :                uint32_t aLineNumber,
     129             :                uint32_t aColumnNumber,
     130             :                uint32_t aFlags,
     131             :                const char *aCategory,
     132             :                uint64_t aInnerWindowID)
     133             : {
     134           0 :   nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
     135             : 
     136           0 :   nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
     137             : 
     138           0 :   if (!console || !error) {
     139           0 :     return;
     140             :   }
     141             : 
     142             :   // Prepending CSP to the outgoing console message
     143           0 :   nsString cspMsg;
     144           0 :   cspMsg.Append(NS_LITERAL_STRING("Content Security Policy: "));
     145           0 :   cspMsg.Append(aMessage);
     146             : 
     147             :   // Currently 'aSourceLine' is not logged to the console, because similar
     148             :   // information is already included within the source link of the message.
     149             :   // For inline violations however, the line and column number are 0 and
     150             :   // information contained within 'aSourceLine' can be really useful for devs.
     151             :   // E.g. 'aSourceLine' might be: 'onclick attribute on DIV element'.
     152             :   // In such cases we append 'aSourceLine' directly to the error message.
     153           0 :   if (!aSourceLine.IsEmpty()) {
     154           0 :     cspMsg.Append(NS_LITERAL_STRING(" Source: "));
     155           0 :     cspMsg.Append(aSourceLine);
     156           0 :     cspMsg.Append(NS_LITERAL_STRING("."));
     157             :   }
     158             : 
     159             :   nsresult rv;
     160           0 :   if (aInnerWindowID > 0) {
     161           0 :     nsCString catStr;
     162           0 :     catStr.AssignASCII(aCategory);
     163           0 :     rv = error->InitWithWindowID(cspMsg, aSourceName,
     164             :                                  aSourceLine, aLineNumber,
     165             :                                  aColumnNumber, aFlags,
     166           0 :                                  catStr, aInnerWindowID);
     167             :   }
     168             :   else {
     169           0 :     rv = error->Init(cspMsg, aSourceName,
     170             :                      aSourceLine, aLineNumber,
     171             :                      aColumnNumber, aFlags,
     172           0 :                      aCategory);
     173             :   }
     174           0 :   if (NS_FAILED(rv)) {
     175           0 :     return;
     176             :   }
     177           0 :   console->LogMessage(error);
     178             : }
     179             : 
     180             : /**
     181             :  * Combines CSP_LogMessage and CSP_GetLocalizedStr into one call.
     182             :  */
     183             : void
     184           0 : CSP_LogLocalizedStr(const char16_t* aName,
     185             :                     const char16_t** aParams,
     186             :                     uint32_t aLength,
     187             :                     const nsAString& aSourceName,
     188             :                     const nsAString& aSourceLine,
     189             :                     uint32_t aLineNumber,
     190             :                     uint32_t aColumnNumber,
     191             :                     uint32_t aFlags,
     192             :                     const char* aCategory,
     193             :                     uint64_t aInnerWindowID)
     194             : {
     195           0 :   nsXPIDLString logMsg;
     196           0 :   CSP_GetLocalizedStr(aName, aParams, aLength, getter_Copies(logMsg));
     197             :   CSP_LogMessage(logMsg, aSourceName, aSourceLine,
     198             :                  aLineNumber, aColumnNumber, aFlags,
     199           0 :                  aCategory, aInnerWindowID);
     200           0 : }
     201             : 
     202             : /* ===== Helpers ============================ */
     203             : CSPDirective
     204           0 : CSP_ContentTypeToDirective(nsContentPolicyType aType)
     205             : {
     206           0 :   switch (aType) {
     207             :     case nsIContentPolicy::TYPE_IMAGE:
     208             :     case nsIContentPolicy::TYPE_IMAGESET:
     209           0 :       return nsIContentSecurityPolicy::IMG_SRC_DIRECTIVE;
     210             : 
     211             :     // BLock XSLT as script, see bug 910139
     212             :     case nsIContentPolicy::TYPE_XSLT:
     213             :     case nsIContentPolicy::TYPE_SCRIPT:
     214             :     case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
     215             :     case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
     216             :     case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
     217           0 :       return nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE;
     218             : 
     219             :     case nsIContentPolicy::TYPE_STYLESHEET:
     220           0 :       return nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE;
     221             : 
     222             :     case nsIContentPolicy::TYPE_FONT:
     223           0 :       return nsIContentSecurityPolicy::FONT_SRC_DIRECTIVE;
     224             : 
     225             :     case nsIContentPolicy::TYPE_MEDIA:
     226           0 :       return nsIContentSecurityPolicy::MEDIA_SRC_DIRECTIVE;
     227             : 
     228             :     case nsIContentPolicy::TYPE_WEB_MANIFEST:
     229           0 :       return nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE;
     230             : 
     231             :     case nsIContentPolicy::TYPE_INTERNAL_WORKER:
     232             :     case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
     233             :     case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
     234           0 :       return nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE;
     235             : 
     236             :     case nsIContentPolicy::TYPE_SUBDOCUMENT:
     237           0 :       return nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE;
     238             : 
     239             :     case nsIContentPolicy::TYPE_WEBSOCKET:
     240             :     case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
     241             :     case nsIContentPolicy::TYPE_BEACON:
     242             :     case nsIContentPolicy::TYPE_PING:
     243             :     case nsIContentPolicy::TYPE_FETCH:
     244           0 :       return nsIContentSecurityPolicy::CONNECT_SRC_DIRECTIVE;
     245             : 
     246             :     case nsIContentPolicy::TYPE_OBJECT:
     247             :     case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
     248           0 :       return nsIContentSecurityPolicy::OBJECT_SRC_DIRECTIVE;
     249             : 
     250             :     case nsIContentPolicy::TYPE_XBL:
     251             :     case nsIContentPolicy::TYPE_DTD:
     252             :     case nsIContentPolicy::TYPE_OTHER:
     253           0 :       return nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
     254             : 
     255             :     // csp shold not block top level loads, e.g. in case
     256             :     // of a redirect.
     257             :     case nsIContentPolicy::TYPE_DOCUMENT:
     258             :     // CSP can not block csp reports
     259             :     case nsIContentPolicy::TYPE_CSP_REPORT:
     260           0 :       return nsIContentSecurityPolicy::NO_DIRECTIVE;
     261             : 
     262             :     // Fall through to error for all other directives
     263             :     default:
     264           0 :       MOZ_ASSERT(false, "Can not map nsContentPolicyType to CSPDirective");
     265             :   }
     266             :   return nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
     267             : }
     268             : 
     269             : nsCSPHostSrc*
     270           0 : CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI)
     271             : {
     272             :   // Create the host first
     273           0 :   nsCString host;
     274           0 :   aSelfURI->GetAsciiHost(host);
     275           0 :   nsCSPHostSrc *hostsrc = new nsCSPHostSrc(NS_ConvertUTF8toUTF16(host));
     276           0 :   hostsrc->setGeneratedFromSelfKeyword();
     277             : 
     278             :   // Add the scheme.
     279           0 :   nsCString scheme;
     280           0 :   aSelfURI->GetScheme(scheme);
     281           0 :   hostsrc->setScheme(NS_ConvertUTF8toUTF16(scheme));
     282             : 
     283             :   int32_t port;
     284           0 :   aSelfURI->GetPort(&port);
     285             :   // Only add port if it's not default port.
     286           0 :   if (port > 0) {
     287           0 :     nsAutoString portStr;
     288           0 :     portStr.AppendInt(port);
     289           0 :     hostsrc->setPort(portStr);
     290             :   }
     291           0 :   return hostsrc;
     292             : }
     293             : 
     294             : bool
     295           0 : CSP_IsValidDirective(const nsAString& aDir)
     296             : {
     297           0 :   uint32_t numDirs = (sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]));
     298             : 
     299           0 :   for (uint32_t i = 0; i < numDirs; i++) {
     300           0 :     if (aDir.LowerCaseEqualsASCII(CSPStrDirectives[i])) {
     301           0 :       return true;
     302             :     }
     303             :   }
     304           0 :   return false;
     305             : }
     306             : bool
     307           0 : CSP_IsDirective(const nsAString& aValue, CSPDirective aDir)
     308             : {
     309           0 :   return aValue.LowerCaseEqualsASCII(CSP_CSPDirectiveToString(aDir));
     310             : }
     311             : 
     312             : bool
     313           0 : CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey)
     314             : {
     315           0 :   return aValue.LowerCaseEqualsASCII(CSP_EnumToKeyword(aKey));
     316             : }
     317             : 
     318             : bool
     319           0 : CSP_IsQuotelessKeyword(const nsAString& aKey)
     320             : {
     321           0 :   nsString lowerKey = PromiseFlatString(aKey);
     322           0 :   ToLowerCase(lowerKey);
     323             : 
     324             :   static_assert(CSP_LAST_KEYWORD_VALUE ==
     325             :                 (sizeof(CSPStrKeywords) / sizeof(CSPStrKeywords[0])),
     326             :                 "CSP_LAST_KEYWORD_VALUE does not match length of CSPStrKeywords");
     327             : 
     328           0 :   nsAutoString keyword;
     329           0 :   for (uint32_t i = 0; i < CSP_LAST_KEYWORD_VALUE; i++) {
     330             :     // skipping the leading ' and trimming the trailing '
     331           0 :     keyword.AssignASCII(CSPStrKeywords[i] + 1);
     332           0 :     keyword.Trim("'", false, true);
     333           0 :     if (lowerKey.Equals(keyword)) {
     334           0 :       return true;
     335             :     }
     336             :   }
     337           0 :   return false;
     338             : }
     339             : 
     340             : /*
     341             :  * Checks whether the current directive permits a specific
     342             :  * scheme. This function is called from nsCSPSchemeSrc() and
     343             :  * also nsCSPHostSrc.
     344             :  * @param aEnforcementScheme
     345             :  *        The scheme that this directive allows
     346             :  * @param aUri
     347             :  *        The uri of the subresource load.
     348             :  * @param aReportOnly
     349             :  *        Whether the enforced policy is report only or not.
     350             :  * @param aUpgradeInsecure
     351             :  *        Whether the policy makes use of the directive
     352             :  *        'upgrade-insecure-requests'.
     353             :  * @param aFromSelfURI
     354             :  *        Whether a scheme was generated from the keyword 'self'
     355             :  *        which then allows schemeless sources to match ws and wss.
     356             :  */
     357             : 
     358             : bool
     359           0 : permitsScheme(const nsAString& aEnforcementScheme,
     360             :               nsIURI* aUri,
     361             :               bool aReportOnly,
     362             :               bool aUpgradeInsecure,
     363             :               bool aFromSelfURI)
     364             : {
     365           0 :   nsAutoCString scheme;
     366           0 :   nsresult rv = aUri->GetScheme(scheme);
     367           0 :   NS_ENSURE_SUCCESS(rv, false);
     368             : 
     369             :   // no scheme to enforce, let's allow the load (e.g. script-src *)
     370           0 :   if (aEnforcementScheme.IsEmpty()) {
     371           0 :     return true;
     372             :   }
     373             : 
     374             :   // if the scheme matches, all good - allow the load
     375           0 :   if (aEnforcementScheme.EqualsASCII(scheme.get())) {
     376           0 :     return true;
     377             :   }
     378             : 
     379             :   // allow scheme-less sources where the protected resource is http
     380             :   // and the load is https, see:
     381             :   // http://www.w3.org/TR/CSP2/#match-source-expression
     382           0 :   if (aEnforcementScheme.EqualsASCII("http")) {
     383           0 :     if (scheme.EqualsASCII("https")) {
     384           0 :       return true;
     385             :     }
     386           0 :     if ((scheme.EqualsASCII("ws") || scheme.EqualsASCII("wss")) && aFromSelfURI) {
     387           0 :       return true;
     388             :     }
     389             :   }
     390           0 :   if (aEnforcementScheme.EqualsASCII("https")) {
     391           0 :     if (scheme.EqualsLiteral("wss") && aFromSelfURI) {
     392           0 :       return true;
     393             :     }
     394             :   }
     395           0 :   if (aEnforcementScheme.EqualsASCII("ws") && scheme.EqualsASCII("wss")) {
     396           0 :     return true;
     397             :   }
     398             : 
     399             :   // Allow the load when enforcing upgrade-insecure-requests with the
     400             :   // promise the request gets upgraded from http to https and ws to wss.
     401             :   // See nsHttpChannel::Connect() and also WebSocket.cpp. Please note,
     402             :   // the report only policies should not allow the load and report
     403             :   // the error back to the page.
     404           0 :   return ((aUpgradeInsecure && !aReportOnly) &&
     405           0 :           ((scheme.EqualsASCII("http") && aEnforcementScheme.EqualsASCII("https")) ||
     406           0 :            (scheme.EqualsASCII("ws") && aEnforcementScheme.EqualsASCII("wss"))));
     407             : }
     408             : 
     409             : /*
     410             :  * A helper function for appending a CSP header to an existing CSP
     411             :  * policy.
     412             :  *
     413             :  * @param aCsp           the CSP policy
     414             :  * @param aHeaderValue   the header
     415             :  * @param aReportOnly    is this a report-only header?
     416             :  */
     417             : 
     418             : nsresult
     419           0 : CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp,
     420             :                         const nsAString& aHeaderValue,
     421             :                         bool aReportOnly)
     422             : {
     423           0 :   NS_ENSURE_ARG(aCsp);
     424             : 
     425             :   // Need to tokenize the header value since multiple headers could be
     426             :   // concatenated into one comma-separated list of policies.
     427             :   // See RFC2616 section 4.2 (last paragraph)
     428           0 :   nsresult rv = NS_OK;
     429           0 :   nsCharSeparatedTokenizer tokenizer(aHeaderValue, ',');
     430           0 :   while (tokenizer.hasMoreTokens()) {
     431           0 :     const nsAString& policy = tokenizer.nextToken();
     432           0 :     rv = aCsp->AppendPolicy(policy, aReportOnly, false);
     433           0 :     NS_ENSURE_SUCCESS(rv, rv);
     434             :     {
     435           0 :       CSPUTILSLOG(("CSP refined with policy: \"%s\"",
     436             :                    NS_ConvertUTF16toUTF8(policy).get()));
     437             :     }
     438             :   }
     439           0 :   return NS_OK;
     440             : }
     441             : 
     442             : /* ===== nsCSPSrc ============================ */
     443             : 
     444           0 : nsCSPBaseSrc::nsCSPBaseSrc()
     445           0 :   : mInvalidated(false)
     446             : {
     447           0 : }
     448             : 
     449           0 : nsCSPBaseSrc::~nsCSPBaseSrc()
     450             : {
     451           0 : }
     452             : 
     453             : // ::permits is only called for external load requests, therefore:
     454             : // nsCSPKeywordSrc and nsCSPHashSource fall back to this base class
     455             : // implementation which will never allow the load.
     456             : bool
     457           0 : nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
     458             :                       bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const
     459             : {
     460           0 :   if (CSPUTILSLOGENABLED()) {
     461           0 :     CSPUTILSLOG(("nsCSPBaseSrc::permits, aUri: %s",
     462             :                  aUri->GetSpecOrDefault().get()));
     463             :   }
     464           0 :   return false;
     465             : }
     466             : 
     467             : // ::allows is only called for inlined loads, therefore:
     468             : // nsCSPSchemeSrc, nsCSPHostSrc fall back
     469             : // to this base class implementation which will never allow the load.
     470             : bool
     471           0 : nsCSPBaseSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
     472             :                      bool aParserCreated) const
     473             : {
     474           0 :   CSPUTILSLOG(("nsCSPBaseSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
     475             :               aKeyword == CSP_HASH ? "hash" : CSP_EnumToKeyword(aKeyword),
     476             :               NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
     477           0 :   return false;
     478             : }
     479             : 
     480             : /* ====== nsCSPSchemeSrc ===================== */
     481             : 
     482           0 : nsCSPSchemeSrc::nsCSPSchemeSrc(const nsAString& aScheme)
     483           0 :   : mScheme(aScheme)
     484             : {
     485           0 :   ToLowerCase(mScheme);
     486           0 : }
     487             : 
     488           0 : nsCSPSchemeSrc::~nsCSPSchemeSrc()
     489             : {
     490           0 : }
     491             : 
     492             : bool
     493           0 : nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
     494             :                         bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const
     495             : {
     496           0 :   if (CSPUTILSLOGENABLED()) {
     497           0 :     CSPUTILSLOG(("nsCSPSchemeSrc::permits, aUri: %s",
     498             :                  aUri->GetSpecOrDefault().get()));
     499             :   }
     500           0 :   MOZ_ASSERT((!mScheme.EqualsASCII("")), "scheme can not be the empty string");
     501           0 :   if (mInvalidated) {
     502           0 :     return false;
     503             :   }
     504           0 :   return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure, false);
     505             : }
     506             : 
     507             : bool
     508           0 : nsCSPSchemeSrc::visit(nsCSPSrcVisitor* aVisitor) const
     509             : {
     510           0 :   return aVisitor->visitSchemeSrc(*this);
     511             : }
     512             : 
     513             : void
     514           0 : nsCSPSchemeSrc::toString(nsAString& outStr) const
     515             : {
     516           0 :   outStr.Append(mScheme);
     517           0 :   outStr.AppendASCII(":");
     518           0 : }
     519             : 
     520             : /* ===== nsCSPHostSrc ======================== */
     521             : 
     522           0 : nsCSPHostSrc::nsCSPHostSrc(const nsAString& aHost)
     523             :   : mHost(aHost)
     524             :   , mGeneratedFromSelfKeyword(false)
     525           0 :   , mWithinFrameAncstorsDir(false)
     526             : {
     527           0 :   ToLowerCase(mHost);
     528           0 : }
     529             : 
     530           0 : nsCSPHostSrc::~nsCSPHostSrc()
     531             : {
     532           0 : }
     533             : 
     534             : /*
     535             :  * Checks whether the current directive permits a specific port.
     536             :  * @param aEnforcementScheme
     537             :  *        The scheme that this directive allows
     538             :  *        (used to query the default port for that scheme)
     539             :  * @param aEnforcementPort
     540             :  *        The port that this directive allows
     541             :  * @param aResourceURI
     542             :  *        The uri of the subresource load
     543             :  */
     544             : bool
     545           0 : permitsPort(const nsAString& aEnforcementScheme,
     546             :             const nsAString& aEnforcementPort,
     547             :             nsIURI* aResourceURI)
     548             : {
     549             :   // If enforcement port is the wildcard, don't block the load.
     550           0 :   if (aEnforcementPort.EqualsASCII("*")) {
     551           0 :     return true;
     552             :   }
     553             : 
     554             :   int32_t resourcePort;
     555           0 :   nsresult rv = aResourceURI->GetPort(&resourcePort);
     556           0 :   NS_ENSURE_SUCCESS(rv, false);
     557             : 
     558             :   // Avoid unnecessary string creation/manipulation and don't block the
     559             :   // load if the resource to be loaded uses the default port for that
     560             :   // scheme and there is no port to be enforced.
     561             :   // Note, this optimization relies on scheme checks within permitsScheme().
     562           0 :   if (resourcePort == DEFAULT_PORT && aEnforcementPort.IsEmpty()) {
     563           0 :     return true;
     564             :   }
     565             : 
     566             :   // By now we know at that either the resourcePort does not use the default
     567             :   // port or there is a port restriction to be enforced. A port value of -1
     568             :   // corresponds to the protocol's default port (eg. -1 implies port 80 for
     569             :   // http URIs), in such a case we have to query the default port of the
     570             :   // resource to be loaded.
     571           0 :   if (resourcePort == DEFAULT_PORT) {
     572           0 :     nsAutoCString resourceScheme;
     573           0 :     rv = aResourceURI->GetScheme(resourceScheme);
     574           0 :     NS_ENSURE_SUCCESS(rv, false);
     575           0 :     resourcePort = NS_GetDefaultPort(resourceScheme.get());
     576             :   }
     577             : 
     578             :   // If there is a port to be enforced and the ports match, then
     579             :   // don't block the load.
     580           0 :   nsString resourcePortStr;
     581           0 :   resourcePortStr.AppendInt(resourcePort);
     582           0 :   if (aEnforcementPort.Equals(resourcePortStr)) {
     583           0 :     return true;
     584             :   }
     585             : 
     586             :   // If there is no port to be enforced, query the default port for the load.
     587           0 :   nsString enforcementPort(aEnforcementPort);
     588           0 :   if (enforcementPort.IsEmpty()) {
     589             :     // For scheme less sources, our parser always generates a scheme
     590             :     // which is the scheme of the protected resource.
     591           0 :     MOZ_ASSERT(!aEnforcementScheme.IsEmpty(),
     592             :                "need a scheme to query default port");
     593             :     int32_t defaultEnforcementPort =
     594           0 :       NS_GetDefaultPort(NS_ConvertUTF16toUTF8(aEnforcementScheme).get());
     595           0 :     enforcementPort.Truncate();
     596           0 :     enforcementPort.AppendInt(defaultEnforcementPort);
     597             :   }
     598             : 
     599             :   // If default ports match, don't block the load
     600           0 :   if (enforcementPort.Equals(resourcePortStr)) {
     601           0 :     return true;
     602             :   }
     603             : 
     604             :   // Additional port matching where the regular URL matching algorithm
     605             :   // treats insecure ports as matching their secure variants.
     606             :   // default port for http is  :80
     607             :   // default port for https is :443
     608           0 :   if (enforcementPort.EqualsLiteral("80") &&
     609           0 :       resourcePortStr.EqualsLiteral("443")) {
     610           0 :     return true;
     611             :   }
     612             : 
     613             :   // ports do not match, block the load.
     614           0 :   return false;
     615             : }
     616             : 
     617             : bool
     618           0 : nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
     619             :                       bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const
     620             : {
     621           0 :   if (CSPUTILSLOGENABLED()) {
     622           0 :     CSPUTILSLOG(("nsCSPHostSrc::permits, aUri: %s",
     623             :                  aUri->GetSpecOrDefault().get()));
     624             :   }
     625             : 
     626           0 :   if (mInvalidated) {
     627           0 :     return false;
     628             :   }
     629             : 
     630             :   // we are following the enforcement rules from the spec, see:
     631             :   // http://www.w3.org/TR/CSP11/#match-source-expression
     632             : 
     633             :   // 4.3) scheme matching: Check if the scheme matches.
     634           0 :   if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure, mGeneratedFromSelfKeyword)) {
     635           0 :     return false;
     636             :   }
     637             : 
     638             :   // The host in nsCSpHostSrc should never be empty. In case we are enforcing
     639             :   // just a specific scheme, the parser should generate a nsCSPSchemeSource.
     640           0 :   NS_ASSERTION((!mHost.IsEmpty()), "host can not be the empty string");
     641             : 
     642             :   // 2) host matching: Enforce a single *
     643           0 :   if (mHost.EqualsASCII("*")) {
     644             :     // The single ASTERISK character (*) does not match a URI's scheme of a type
     645             :     // designating a globally unique identifier (such as blob:, data:, or filesystem:)
     646             :     // At the moment firefox does not support filesystem; but for future compatibility
     647             :     // we support it in CSP according to the spec, see: 4.2.2 Matching Source Expressions
     648             :     // Note, that whitelisting any of these schemes would call nsCSPSchemeSrc::permits().
     649             :     bool isBlobScheme =
     650           0 :       (NS_SUCCEEDED(aUri->SchemeIs("blob", &isBlobScheme)) && isBlobScheme);
     651             :     bool isDataScheme =
     652           0 :       (NS_SUCCEEDED(aUri->SchemeIs("data", &isDataScheme)) && isDataScheme);
     653             :     bool isFileScheme =
     654           0 :       (NS_SUCCEEDED(aUri->SchemeIs("filesystem", &isFileScheme)) && isFileScheme);
     655             : 
     656           0 :     if (isBlobScheme || isDataScheme || isFileScheme) {
     657           0 :       return false;
     658             :     }
     659           0 :     return true;
     660             :   }
     661             : 
     662             :   // Before we can check if the host matches, we have to
     663             :   // extract the host part from aUri.
     664           0 :   nsAutoCString uriHost;
     665           0 :   nsresult rv = aUri->GetAsciiHost(uriHost);
     666           0 :   NS_ENSURE_SUCCESS(rv, false);
     667             : 
     668           0 :   nsString decodedUriHost;
     669           0 :   CSP_PercentDecodeStr(NS_ConvertUTF8toUTF16(uriHost), decodedUriHost);
     670             : 
     671             :   // 4.5) host matching: Check if the allowed host starts with a wilcard.
     672           0 :   if (mHost.First() == '*') {
     673           0 :     NS_ASSERTION(mHost[1] == '.', "Second character needs to be '.' whenever host starts with '*'");
     674             : 
     675             :     // Eliminate leading "*", but keeping the FULL STOP (.) thereafter before checking
     676             :     // if the remaining characters match
     677           0 :     nsString wildCardHost = mHost;
     678           0 :     wildCardHost = Substring(wildCardHost, 1, wildCardHost.Length() - 1);
     679           0 :     if (!StringEndsWith(decodedUriHost, wildCardHost)) {
     680           0 :       return false;
     681             :     }
     682             :   }
     683             :   // 4.6) host matching: Check if hosts match.
     684           0 :   else if (!mHost.Equals(decodedUriHost)) {
     685           0 :     return false;
     686             :   }
     687             : 
     688             :   // Port matching: Check if the ports match.
     689           0 :   if (!permitsPort(mScheme, mPort, aUri)) {
     690           0 :     return false;
     691             :   }
     692             : 
     693             :   // 4.9) Path matching: If there is a path, we have to enforce
     694             :   // path-level matching, unless the channel got redirected, see:
     695             :   // http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects
     696           0 :   if (!aWasRedirected && !mPath.IsEmpty()) {
     697             :     // converting aUri into nsIURL so we can strip query and ref
     698             :     // example.com/test#foo     -> example.com/test
     699             :     // example.com/test?val=foo -> example.com/test
     700           0 :     nsCOMPtr<nsIURL> url = do_QueryInterface(aUri);
     701           0 :     if (!url) {
     702           0 :       NS_ASSERTION(false, "can't QI into nsIURI");
     703           0 :       return false;
     704             :     }
     705           0 :     nsAutoCString uriPath;
     706           0 :     rv = url->GetFilePath(uriPath);
     707           0 :     NS_ENSURE_SUCCESS(rv, false);
     708             : 
     709           0 :     if (mWithinFrameAncstorsDir) {
     710             :       // no path matching for frame-ancestors to not leak any path information.
     711           0 :       return true;
     712             :     }
     713             : 
     714           0 :     nsString decodedUriPath;
     715           0 :     CSP_PercentDecodeStr(NS_ConvertUTF8toUTF16(uriPath), decodedUriPath);
     716             : 
     717             :     // check if the last character of mPath is '/'; if so
     718             :     // we just have to check loading resource is within
     719             :     // the allowed path.
     720           0 :     if (mPath.Last() == '/') {
     721           0 :       if (!StringBeginsWith(decodedUriPath, mPath)) {
     722           0 :         return false;
     723             :       }
     724             :     }
     725             :     // otherwise mPath whitelists a specific file, and we have to
     726             :     // check if the loading resource matches that whitelisted file.
     727             :     else {
     728           0 :       if (!mPath.Equals(decodedUriPath)) {
     729           0 :         return false;
     730             :       }
     731             :     }
     732             :   }
     733             : 
     734             :   // At the end: scheme, host, port and path match -> allow the load.
     735           0 :   return true;
     736             : }
     737             : 
     738             : bool
     739           0 : nsCSPHostSrc::visit(nsCSPSrcVisitor* aVisitor) const
     740             : {
     741           0 :   return aVisitor->visitHostSrc(*this);
     742             : }
     743             : 
     744             : void
     745           0 : nsCSPHostSrc::toString(nsAString& outStr) const
     746             : {
     747             :   // If mHost is a single "*", we append the wildcard and return.
     748           0 :   if (mHost.EqualsASCII("*") &&
     749           0 :       mScheme.IsEmpty() &&
     750           0 :       mPort.IsEmpty()) {
     751           0 :     outStr.Append(mHost);
     752           0 :     return;
     753             :   }
     754             : 
     755             :   // append scheme
     756           0 :   outStr.Append(mScheme);
     757             : 
     758             :   // append host
     759           0 :   outStr.AppendASCII("://");
     760           0 :   outStr.Append(mHost);
     761             : 
     762             :   // append port
     763           0 :   if (!mPort.IsEmpty()) {
     764           0 :     outStr.AppendASCII(":");
     765           0 :     outStr.Append(mPort);
     766             :   }
     767             : 
     768             :   // append path
     769           0 :   outStr.Append(mPath);
     770             : }
     771             : 
     772             : void
     773           0 : nsCSPHostSrc::setScheme(const nsAString& aScheme)
     774             : {
     775           0 :   mScheme = aScheme;
     776           0 :   ToLowerCase(mScheme);
     777           0 : }
     778             : 
     779             : void
     780           0 : nsCSPHostSrc::setPort(const nsAString& aPort)
     781             : {
     782           0 :   mPort = aPort;
     783           0 : }
     784             : 
     785             : void
     786           0 : nsCSPHostSrc::appendPath(const nsAString& aPath)
     787             : {
     788           0 :   mPath.Append(aPath);
     789           0 : }
     790             : 
     791             : /* ===== nsCSPKeywordSrc ===================== */
     792             : 
     793           0 : nsCSPKeywordSrc::nsCSPKeywordSrc(enum CSPKeyword aKeyword)
     794           0 :  : mKeyword(aKeyword)
     795             : {
     796           0 :   NS_ASSERTION((aKeyword != CSP_SELF),
     797             :                "'self' should have been replaced in the parser");
     798           0 : }
     799             : 
     800           0 : nsCSPKeywordSrc::~nsCSPKeywordSrc()
     801             : {
     802           0 : }
     803             : 
     804             : bool
     805           0 : nsCSPKeywordSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
     806             :                          bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const
     807             : {
     808             :   // no need to check for invalidated, this will always return false unless
     809             :   // it is an nsCSPKeywordSrc for 'strict-dynamic', which should allow non
     810             :   // parser created scripts.
     811           0 :   return ((mKeyword == CSP_STRICT_DYNAMIC) && !aParserCreated);
     812             : }
     813             : 
     814             : bool
     815           0 : nsCSPKeywordSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
     816             :                         bool aParserCreated) const
     817             : {
     818           0 :   CSPUTILSLOG(("nsCSPKeywordSrc::allows, aKeyWord: %s, aHashOrNonce: %s, mInvalidated: %s",
     819             :               CSP_EnumToKeyword(aKeyword),
     820             :               NS_ConvertUTF16toUTF8(aHashOrNonce).get(),
     821             :               mInvalidated ? "yes" : "false"));
     822             : 
     823           0 :   if (mInvalidated) {
     824             :     // only 'self' and 'unsafe-inline' are keywords that can be ignored. Please note that
     825             :     // the parser already translates 'self' into a uri (see assertion in constructor).
     826           0 :     MOZ_ASSERT(mKeyword == CSP_UNSAFE_INLINE,
     827             :                "should only invalidate unsafe-inline");
     828           0 :     return false;
     829             :   }
     830             :   // either the keyword allows the load or the policy contains 'strict-dynamic', in which
     831             :   // case we have to make sure the script is not parser created before allowing the load.
     832           0 :   return ((mKeyword == aKeyword) ||
     833           0 :           ((mKeyword == CSP_STRICT_DYNAMIC) && !aParserCreated));
     834             : }
     835             : 
     836             : bool
     837           0 : nsCSPKeywordSrc::visit(nsCSPSrcVisitor* aVisitor) const
     838             : {
     839           0 :   return aVisitor->visitKeywordSrc(*this);
     840             : }
     841             : 
     842             : void
     843           0 : nsCSPKeywordSrc::toString(nsAString& outStr) const
     844             : {
     845           0 :   outStr.AppendASCII(CSP_EnumToKeyword(mKeyword));
     846           0 : }
     847             : 
     848             : /* ===== nsCSPNonceSrc ==================== */
     849             : 
     850           0 : nsCSPNonceSrc::nsCSPNonceSrc(const nsAString& aNonce)
     851           0 :   : mNonce(aNonce)
     852             : {
     853           0 : }
     854             : 
     855           0 : nsCSPNonceSrc::~nsCSPNonceSrc()
     856             : {
     857           0 : }
     858             : 
     859             : bool
     860           0 : nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
     861             :                        bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const
     862             : {
     863           0 :   if (CSPUTILSLOGENABLED()) {
     864           0 :     CSPUTILSLOG(("nsCSPNonceSrc::permits, aUri: %s, aNonce: %s",
     865             :                  aUri->GetSpecOrDefault().get(),
     866             :                  NS_ConvertUTF16toUTF8(aNonce).get()));
     867             :   }
     868             : 
     869             :   // nonces can not be invalidated by strict-dynamic
     870           0 :   return mNonce.Equals(aNonce);
     871             : }
     872             : 
     873             : bool
     874           0 : nsCSPNonceSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
     875             :                       bool aParserCreated) const
     876             : {
     877           0 :   CSPUTILSLOG(("nsCSPNonceSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
     878             :               CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
     879             : 
     880           0 :   if (aKeyword != CSP_NONCE) {
     881           0 :     return false;
     882             :   }
     883             :   // nonces can not be invalidated by strict-dynamic
     884           0 :   return mNonce.Equals(aHashOrNonce);
     885             : }
     886             : 
     887             : bool
     888           0 : nsCSPNonceSrc::visit(nsCSPSrcVisitor* aVisitor) const
     889             : {
     890           0 :   return aVisitor->visitNonceSrc(*this);
     891             : }
     892             : 
     893             : void
     894           0 : nsCSPNonceSrc::toString(nsAString& outStr) const
     895             : {
     896           0 :   outStr.AppendASCII(CSP_EnumToKeyword(CSP_NONCE));
     897           0 :   outStr.Append(mNonce);
     898           0 :   outStr.AppendASCII("'");
     899           0 : }
     900             : 
     901             : /* ===== nsCSPHashSrc ===================== */
     902             : 
     903           0 : nsCSPHashSrc::nsCSPHashSrc(const nsAString& aAlgo, const nsAString& aHash)
     904             :  : mAlgorithm(aAlgo)
     905           0 :  , mHash(aHash)
     906             : {
     907             :   // Only the algo should be rewritten to lowercase, the hash must remain the same.
     908           0 :   ToLowerCase(mAlgorithm);
     909           0 : }
     910             : 
     911           0 : nsCSPHashSrc::~nsCSPHashSrc()
     912             : {
     913           0 : }
     914             : 
     915             : bool
     916           0 : nsCSPHashSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
     917             :                      bool aParserCreated) const
     918             : {
     919           0 :   CSPUTILSLOG(("nsCSPHashSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
     920             :               CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
     921             : 
     922           0 :   if (aKeyword != CSP_HASH) {
     923           0 :     return false;
     924             :   }
     925             : 
     926             :   // hashes can not be invalidated by strict-dynamic
     927             : 
     928             :   // Convert aHashOrNonce to UTF-8
     929           0 :   NS_ConvertUTF16toUTF8 utf8_hash(aHashOrNonce);
     930             : 
     931             :   nsresult rv;
     932           0 :   nsCOMPtr<nsICryptoHash> hasher;
     933           0 :   hasher = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
     934           0 :   NS_ENSURE_SUCCESS(rv, false);
     935             : 
     936           0 :   rv = hasher->InitWithString(NS_ConvertUTF16toUTF8(mAlgorithm));
     937           0 :   NS_ENSURE_SUCCESS(rv, false);
     938             : 
     939           0 :   rv = hasher->Update((uint8_t *)utf8_hash.get(), utf8_hash.Length());
     940           0 :   NS_ENSURE_SUCCESS(rv, false);
     941             : 
     942           0 :   nsAutoCString hash;
     943           0 :   rv = hasher->Finish(true, hash);
     944           0 :   NS_ENSURE_SUCCESS(rv, false);
     945             : 
     946           0 :   return NS_ConvertUTF16toUTF8(mHash).Equals(hash);
     947             : }
     948             : 
     949             : bool
     950           0 : nsCSPHashSrc::visit(nsCSPSrcVisitor* aVisitor) const
     951             : {
     952           0 :   return aVisitor->visitHashSrc(*this);
     953             : }
     954             : 
     955             : void
     956           0 : nsCSPHashSrc::toString(nsAString& outStr) const
     957             : {
     958           0 :   outStr.AppendASCII("'");
     959           0 :   outStr.Append(mAlgorithm);
     960           0 :   outStr.AppendASCII("-");
     961           0 :   outStr.Append(mHash);
     962           0 :   outStr.AppendASCII("'");
     963           0 : }
     964             : 
     965             : /* ===== nsCSPReportURI ===================== */
     966             : 
     967           0 : nsCSPReportURI::nsCSPReportURI(nsIURI *aURI)
     968           0 :   :mReportURI(aURI)
     969             : {
     970           0 : }
     971             : 
     972           0 : nsCSPReportURI::~nsCSPReportURI()
     973             : {
     974           0 : }
     975             : 
     976             : bool
     977           0 : nsCSPReportURI::visit(nsCSPSrcVisitor* aVisitor) const
     978             : {
     979           0 :   return false;
     980             : }
     981             : 
     982             : void
     983           0 : nsCSPReportURI::toString(nsAString& outStr) const
     984             : {
     985           0 :   nsAutoCString spec;
     986           0 :   nsresult rv = mReportURI->GetSpec(spec);
     987           0 :   if (NS_FAILED(rv)) {
     988           0 :     return;
     989             :   }
     990           0 :   outStr.AppendASCII(spec.get());
     991             : }
     992             : 
     993             : /* ===== nsCSPSandboxFlags ===================== */
     994             : 
     995           0 : nsCSPSandboxFlags::nsCSPSandboxFlags(const nsAString& aFlags)
     996           0 :   : mFlags(aFlags)
     997             : {
     998           0 :   ToLowerCase(mFlags);
     999           0 : }
    1000             : 
    1001           0 : nsCSPSandboxFlags::~nsCSPSandboxFlags()
    1002             : {
    1003           0 : }
    1004             : 
    1005             : bool
    1006           0 : nsCSPSandboxFlags::visit(nsCSPSrcVisitor* aVisitor) const
    1007             : {
    1008           0 :   return false;
    1009             : }
    1010             : 
    1011             : void
    1012           0 : nsCSPSandboxFlags::toString(nsAString& outStr) const
    1013             : {
    1014           0 :   outStr.Append(mFlags);
    1015           0 : }
    1016             : 
    1017             : /* ===== nsCSPDirective ====================== */
    1018             : 
    1019           0 : nsCSPDirective::nsCSPDirective(CSPDirective aDirective)
    1020             : {
    1021           0 :   mDirective = aDirective;
    1022           0 : }
    1023             : 
    1024           0 : nsCSPDirective::~nsCSPDirective()
    1025             : {
    1026           0 :   for (uint32_t i = 0; i < mSrcs.Length(); i++) {
    1027           0 :     delete mSrcs[i];
    1028             :   }
    1029           0 : }
    1030             : 
    1031             : bool
    1032           0 : nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
    1033             :                         bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const
    1034             : {
    1035           0 :   if (CSPUTILSLOGENABLED()) {
    1036           0 :     CSPUTILSLOG(("nsCSPDirective::permits, aUri: %s",
    1037             :                  aUri->GetSpecOrDefault().get()));
    1038             :   }
    1039             : 
    1040           0 :   for (uint32_t i = 0; i < mSrcs.Length(); i++) {
    1041           0 :     if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected, aReportOnly, aUpgradeInsecure, aParserCreated)) {
    1042           0 :       return true;
    1043             :     }
    1044             :   }
    1045           0 :   return false;
    1046             : }
    1047             : 
    1048             : bool
    1049           0 : nsCSPDirective::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
    1050             :                        bool aParserCreated) const
    1051             : {
    1052           0 :   CSPUTILSLOG(("nsCSPDirective::allows, aKeyWord: %s, a HashOrNonce: %s",
    1053             :               CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
    1054             : 
    1055           0 :   for (uint32_t i = 0; i < mSrcs.Length(); i++) {
    1056           0 :     if (mSrcs[i]->allows(aKeyword, aHashOrNonce, aParserCreated)) {
    1057           0 :       return true;
    1058             :     }
    1059             :   }
    1060           0 :   return false;
    1061             : }
    1062             : 
    1063             : void
    1064           0 : nsCSPDirective::toString(nsAString& outStr) const
    1065             : {
    1066             :   // Append directive name
    1067           0 :   outStr.AppendASCII(CSP_CSPDirectiveToString(mDirective));
    1068           0 :   outStr.AppendASCII(" ");
    1069             : 
    1070             :   // Append srcs
    1071           0 :   uint32_t length = mSrcs.Length();
    1072           0 :   for (uint32_t i = 0; i < length; i++) {
    1073           0 :     mSrcs[i]->toString(outStr);
    1074           0 :     if (i != (length - 1)) {
    1075           0 :       outStr.AppendASCII(" ");
    1076             :     }
    1077             :   }
    1078           0 : }
    1079             : 
    1080             : void
    1081           0 : nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
    1082             : {
    1083           0 :   mozilla::dom::Sequence<nsString> srcs;
    1084           0 :   nsString src;
    1085           0 :   for (uint32_t i = 0; i < mSrcs.Length(); i++) {
    1086           0 :     src.Truncate();
    1087           0 :     mSrcs[i]->toString(src);
    1088           0 :     srcs.AppendElement(src, mozilla::fallible);
    1089             :   }
    1090             : 
    1091           0 :   switch(mDirective) {
    1092             :     case nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE:
    1093           0 :       outCSP.mDefault_src.Construct();
    1094           0 :       outCSP.mDefault_src.Value() = mozilla::Move(srcs);
    1095           0 :       return;
    1096             : 
    1097             :     case nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE:
    1098           0 :       outCSP.mScript_src.Construct();
    1099           0 :       outCSP.mScript_src.Value() = mozilla::Move(srcs);
    1100           0 :       return;
    1101             : 
    1102             :     case nsIContentSecurityPolicy::OBJECT_SRC_DIRECTIVE:
    1103           0 :       outCSP.mObject_src.Construct();
    1104           0 :       outCSP.mObject_src.Value() = mozilla::Move(srcs);
    1105           0 :       return;
    1106             : 
    1107             :     case nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE:
    1108           0 :       outCSP.mStyle_src.Construct();
    1109           0 :       outCSP.mStyle_src.Value() = mozilla::Move(srcs);
    1110           0 :       return;
    1111             : 
    1112             :     case nsIContentSecurityPolicy::IMG_SRC_DIRECTIVE:
    1113           0 :       outCSP.mImg_src.Construct();
    1114           0 :       outCSP.mImg_src.Value() = mozilla::Move(srcs);
    1115           0 :       return;
    1116             : 
    1117             :     case nsIContentSecurityPolicy::MEDIA_SRC_DIRECTIVE:
    1118           0 :       outCSP.mMedia_src.Construct();
    1119           0 :       outCSP.mMedia_src.Value() = mozilla::Move(srcs);
    1120           0 :       return;
    1121             : 
    1122             :     case nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE:
    1123           0 :       outCSP.mFrame_src.Construct();
    1124           0 :       outCSP.mFrame_src.Value() = mozilla::Move(srcs);
    1125           0 :       return;
    1126             : 
    1127             :     case nsIContentSecurityPolicy::FONT_SRC_DIRECTIVE:
    1128           0 :       outCSP.mFont_src.Construct();
    1129           0 :       outCSP.mFont_src.Value() = mozilla::Move(srcs);
    1130           0 :       return;
    1131             : 
    1132             :     case nsIContentSecurityPolicy::CONNECT_SRC_DIRECTIVE:
    1133           0 :       outCSP.mConnect_src.Construct();
    1134           0 :       outCSP.mConnect_src.Value() = mozilla::Move(srcs);
    1135           0 :       return;
    1136             : 
    1137             :     case nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE:
    1138           0 :       outCSP.mReport_uri.Construct();
    1139           0 :       outCSP.mReport_uri.Value() = mozilla::Move(srcs);
    1140           0 :       return;
    1141             : 
    1142             :     case nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE:
    1143           0 :       outCSP.mFrame_ancestors.Construct();
    1144           0 :       outCSP.mFrame_ancestors.Value() = mozilla::Move(srcs);
    1145           0 :       return;
    1146             : 
    1147             :     case nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE:
    1148           0 :       outCSP.mManifest_src.Construct();
    1149           0 :       outCSP.mManifest_src.Value() = mozilla::Move(srcs);
    1150           0 :       return;
    1151             :     // not supporting REFLECTED_XSS_DIRECTIVE
    1152             : 
    1153             :     case nsIContentSecurityPolicy::BASE_URI_DIRECTIVE:
    1154           0 :       outCSP.mBase_uri.Construct();
    1155           0 :       outCSP.mBase_uri.Value() = mozilla::Move(srcs);
    1156           0 :       return;
    1157             : 
    1158             :     case nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE:
    1159           0 :       outCSP.mForm_action.Construct();
    1160           0 :       outCSP.mForm_action.Value() = mozilla::Move(srcs);
    1161           0 :       return;
    1162             : 
    1163             :     case nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT:
    1164           0 :       outCSP.mBlock_all_mixed_content.Construct();
    1165             :       // does not have any srcs
    1166           0 :       return;
    1167             : 
    1168             :     case nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE:
    1169           0 :       outCSP.mUpgrade_insecure_requests.Construct();
    1170             :       // does not have any srcs
    1171           0 :       return;
    1172             : 
    1173             :     case nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE:
    1174           0 :       outCSP.mChild_src.Construct();
    1175           0 :       outCSP.mChild_src.Value() = mozilla::Move(srcs);
    1176           0 :       return;
    1177             : 
    1178             :     case nsIContentSecurityPolicy::SANDBOX_DIRECTIVE:
    1179           0 :       outCSP.mSandbox.Construct();
    1180           0 :       outCSP.mSandbox.Value() = mozilla::Move(srcs);
    1181           0 :       return;
    1182             : 
    1183             :     // REFERRER_DIRECTIVE and REQUIRE_SRI_FOR are handled in nsCSPPolicy::toDomCSPStruct()
    1184             : 
    1185             :     default:
    1186           0 :       NS_ASSERTION(false, "cannot find directive to convert CSP to JSON");
    1187             :   }
    1188             : }
    1189             : 
    1190             : 
    1191             : bool
    1192           0 : nsCSPDirective::restrictsContentType(nsContentPolicyType aContentType) const
    1193             : {
    1194             :   // make sure we do not check for the default src before any other sources
    1195           0 :   if (isDefaultDirective()) {
    1196           0 :     return false;
    1197             :   }
    1198           0 :   return mDirective == CSP_ContentTypeToDirective(aContentType);
    1199             : }
    1200             : 
    1201             : void
    1202           0 : nsCSPDirective::getReportURIs(nsTArray<nsString> &outReportURIs) const
    1203             : {
    1204           0 :   NS_ASSERTION((mDirective == nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE), "not a report-uri directive");
    1205             : 
    1206             :   // append uris
    1207           0 :   nsString tmpReportURI;
    1208           0 :   for (uint32_t i = 0; i < mSrcs.Length(); i++) {
    1209           0 :     tmpReportURI.Truncate();
    1210           0 :     mSrcs[i]->toString(tmpReportURI);
    1211           0 :     outReportURIs.AppendElement(tmpReportURI);
    1212             :   }
    1213           0 : }
    1214             : 
    1215             : bool
    1216           0 : nsCSPDirective::visitSrcs(nsCSPSrcVisitor* aVisitor) const
    1217             : {
    1218           0 :   for (uint32_t i = 0; i < mSrcs.Length(); i++) {
    1219           0 :     if (!mSrcs[i]->visit(aVisitor)) {
    1220           0 :       return false;
    1221             :     }
    1222             :   }
    1223           0 :   return true;
    1224             : }
    1225             : 
    1226           0 : bool nsCSPDirective::equals(CSPDirective aDirective) const
    1227             : {
    1228           0 :   return (mDirective == aDirective);
    1229             : }
    1230             : 
    1231             : /* =============== nsCSPChildSrcDirective ============= */
    1232             : 
    1233           0 : nsCSPChildSrcDirective::nsCSPChildSrcDirective(CSPDirective aDirective)
    1234             :   : nsCSPDirective(aDirective)
    1235           0 :   , mHandleFrameSrc(false)
    1236             : {
    1237           0 : }
    1238             : 
    1239           0 : nsCSPChildSrcDirective::~nsCSPChildSrcDirective()
    1240             : {
    1241           0 : }
    1242             : 
    1243           0 : void nsCSPChildSrcDirective::setHandleFrameSrc()
    1244             : {
    1245           0 :   mHandleFrameSrc = true;
    1246           0 : }
    1247             : 
    1248           0 : bool nsCSPChildSrcDirective::restrictsContentType(nsContentPolicyType aContentType) const
    1249             : {
    1250           0 :   if (aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
    1251           0 :     return mHandleFrameSrc;
    1252             :   }
    1253             : 
    1254             :   return (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER
    1255           0 :       || aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
    1256           0 :       || aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER
    1257           0 :       );
    1258             : }
    1259             : 
    1260           0 : bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const
    1261             : {
    1262           0 :   if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) {
    1263           0 :     return mHandleFrameSrc;
    1264             :   }
    1265             : 
    1266           0 :   return (aDirective == nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE);
    1267             : }
    1268             : 
    1269             : /* =============== nsBlockAllMixedContentDirective ============= */
    1270             : 
    1271           0 : nsBlockAllMixedContentDirective::nsBlockAllMixedContentDirective(CSPDirective aDirective)
    1272           0 : : nsCSPDirective(aDirective)
    1273             : {
    1274           0 : }
    1275             : 
    1276           0 : nsBlockAllMixedContentDirective::~nsBlockAllMixedContentDirective()
    1277             : {
    1278           0 : }
    1279             : 
    1280             : void
    1281           0 : nsBlockAllMixedContentDirective::toString(nsAString& outStr) const
    1282             : {
    1283           0 :   outStr.AppendASCII(CSP_CSPDirectiveToString(
    1284           0 :     nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT));
    1285           0 : }
    1286             : 
    1287             : /* =============== nsUpgradeInsecureDirective ============= */
    1288             : 
    1289           0 : nsUpgradeInsecureDirective::nsUpgradeInsecureDirective(CSPDirective aDirective)
    1290           0 : : nsCSPDirective(aDirective)
    1291             : {
    1292           0 : }
    1293             : 
    1294           0 : nsUpgradeInsecureDirective::~nsUpgradeInsecureDirective()
    1295             : {
    1296           0 : }
    1297             : 
    1298             : void
    1299           0 : nsUpgradeInsecureDirective::toString(nsAString& outStr) const
    1300             : {
    1301           0 :   outStr.AppendASCII(CSP_CSPDirectiveToString(
    1302           0 :     nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE));
    1303           0 : }
    1304             : 
    1305             : /* ===== nsRequireSRIForDirective ========================= */
    1306             : 
    1307           0 : nsRequireSRIForDirective::nsRequireSRIForDirective(CSPDirective aDirective)
    1308           0 : : nsCSPDirective(aDirective)
    1309             : {
    1310           0 : }
    1311             : 
    1312           0 : nsRequireSRIForDirective::~nsRequireSRIForDirective()
    1313             : {
    1314           0 : }
    1315             : 
    1316             : void
    1317           0 : nsRequireSRIForDirective::toString(nsAString &outStr) const
    1318             : {
    1319           0 :   outStr.AppendASCII(CSP_CSPDirectiveToString(
    1320           0 :     nsIContentSecurityPolicy::REQUIRE_SRI_FOR));
    1321           0 :   for (uint32_t i = 0; i < mTypes.Length(); i++) {
    1322           0 :     if (mTypes[i] == nsIContentPolicy::TYPE_SCRIPT) {
    1323           0 :       outStr.AppendASCII(" script");
    1324             :     }
    1325           0 :     else if (mTypes[i] == nsIContentPolicy::TYPE_STYLESHEET) {
    1326           0 :       outStr.AppendASCII(" style");
    1327             :     }
    1328             :   }
    1329           0 : }
    1330             : 
    1331             : bool
    1332           0 : nsRequireSRIForDirective::hasType(nsContentPolicyType aType) const
    1333             : {
    1334           0 :   for (uint32_t i = 0; i < mTypes.Length(); i++) {
    1335           0 :     if (mTypes[i] == aType) {
    1336           0 :       return true;
    1337             :     }
    1338             :   }
    1339           0 :   return false;
    1340             : }
    1341             : 
    1342             : bool
    1343           0 : nsRequireSRIForDirective::restrictsContentType(const nsContentPolicyType aType) const
    1344             : {
    1345           0 :   return this->hasType(aType);
    1346             : }
    1347             : 
    1348             : bool
    1349           0 : nsRequireSRIForDirective::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
    1350             :                                  bool aParserCreated) const
    1351             : {
    1352             :   // can only disallow CSP_REQUIRE_SRI_FOR.
    1353           0 :   return (aKeyword != CSP_REQUIRE_SRI_FOR);
    1354             : }
    1355             : 
    1356             : /* ===== nsCSPPolicy ========================= */
    1357             : 
    1358           0 : nsCSPPolicy::nsCSPPolicy()
    1359             :   : mUpgradeInsecDir(nullptr)
    1360           0 :   , mReportOnly(false)
    1361             : {
    1362           0 :   CSPUTILSLOG(("nsCSPPolicy::nsCSPPolicy"));
    1363           0 : }
    1364             : 
    1365           0 : nsCSPPolicy::~nsCSPPolicy()
    1366             : {
    1367           0 :   CSPUTILSLOG(("nsCSPPolicy::~nsCSPPolicy"));
    1368             : 
    1369           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1370           0 :     delete mDirectives[i];
    1371             :   }
    1372           0 : }
    1373             : 
    1374             : bool
    1375           0 : nsCSPPolicy::permits(CSPDirective aDir,
    1376             :                      nsIURI* aUri,
    1377             :                      bool aSpecific) const
    1378             : {
    1379           0 :   nsString outp;
    1380           0 :   return this->permits(aDir, aUri, EmptyString(), false, aSpecific, false, outp);
    1381             : }
    1382             : 
    1383             : bool
    1384           0 : nsCSPPolicy::permits(CSPDirective aDir,
    1385             :                      nsIURI* aUri,
    1386             :                      const nsAString& aNonce,
    1387             :                      bool aWasRedirected,
    1388             :                      bool aSpecific,
    1389             :                      bool aParserCreated,
    1390             :                      nsAString& outViolatedDirective) const
    1391             : {
    1392           0 :   if (CSPUTILSLOGENABLED()) {
    1393           0 :     CSPUTILSLOG(("nsCSPPolicy::permits, aUri: %s, aDir: %d, aSpecific: %s",
    1394             :                  aUri->GetSpecOrDefault().get(), aDir,
    1395             :                  aSpecific ? "true" : "false"));
    1396             :   }
    1397             : 
    1398           0 :   NS_ASSERTION(aUri, "permits needs an uri to perform the check!");
    1399           0 :   outViolatedDirective.Truncate();
    1400             : 
    1401           0 :   nsCSPDirective* defaultDir = nullptr;
    1402             : 
    1403             :   // Try to find a relevant directive
    1404             :   // These directive arrays are short (1-5 elements), not worth using a hashtable.
    1405           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1406           0 :     if (mDirectives[i]->equals(aDir)) {
    1407           0 :       if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected, mReportOnly,
    1408           0 :                                    mUpgradeInsecDir, aParserCreated)) {
    1409           0 :         mDirectives[i]->toString(outViolatedDirective);
    1410           0 :         return false;
    1411             :       }
    1412           0 :       return true;
    1413             :     }
    1414           0 :     if (mDirectives[i]->isDefaultDirective()) {
    1415           0 :       defaultDir = mDirectives[i];
    1416             :     }
    1417             :   }
    1418             : 
    1419             :   // If the above loop runs through, we haven't found a matching directive.
    1420             :   // Avoid relooping, just store the result of default-src while looping.
    1421           0 :   if (!aSpecific && defaultDir) {
    1422           0 :     if (!defaultDir->permits(aUri, aNonce, aWasRedirected, mReportOnly,
    1423           0 :                              mUpgradeInsecDir, aParserCreated)) {
    1424           0 :       defaultDir->toString(outViolatedDirective);
    1425           0 :       return false;
    1426             :     }
    1427           0 :     return true;
    1428             :   }
    1429             : 
    1430             :   // Nothing restricts this, so we're allowing the load
    1431             :   // See bug 764937
    1432           0 :   return true;
    1433             : }
    1434             : 
    1435             : bool
    1436           0 : nsCSPPolicy::allows(nsContentPolicyType aContentType,
    1437             :                     enum CSPKeyword aKeyword,
    1438             :                     const nsAString& aHashOrNonce,
    1439             :                     bool aParserCreated) const
    1440             : {
    1441           0 :   CSPUTILSLOG(("nsCSPPolicy::allows, aKeyWord: %s, a HashOrNonce: %s",
    1442             :               CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
    1443             : 
    1444           0 :   nsCSPDirective* defaultDir = nullptr;
    1445             : 
    1446             :   // Try to find a matching directive
    1447           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1448           0 :     if (mDirectives[i]->restrictsContentType(aContentType)) {
    1449           0 :       if (mDirectives[i]->allows(aKeyword, aHashOrNonce, aParserCreated)) {
    1450           0 :         return true;
    1451             :       }
    1452           0 :       return false;
    1453             :     }
    1454           0 :     if (mDirectives[i]->isDefaultDirective()) {
    1455           0 :       defaultDir = mDirectives[i];
    1456             :     }
    1457             :   }
    1458             : 
    1459             :   // {nonce,hash}-source should not consult default-src:
    1460             :   //   * return false if default-src is specified
    1461             :   //   * but allow the load if default-src is *not* specified (Bug 1198422)
    1462           0 :   if (aKeyword == CSP_NONCE || aKeyword == CSP_HASH) {
    1463           0 :      if (!defaultDir) {
    1464           0 :        return true;
    1465             :      }
    1466           0 :     return false;
    1467             :   }
    1468             : 
    1469             :   // If the above loop runs through, we haven't found a matching directive.
    1470             :   // Avoid relooping, just store the result of default-src while looping.
    1471           0 :   if (defaultDir) {
    1472           0 :     return defaultDir->allows(aKeyword, aHashOrNonce, aParserCreated);
    1473             :   }
    1474             : 
    1475             :   // Allowing the load; see Bug 885433
    1476             :   // a) inline scripts (also unsafe eval) should only be blocked
    1477             :   //    if there is a [script-src] or [default-src]
    1478             :   // b) inline styles should only be blocked
    1479             :   //    if there is a [style-src] or [default-src]
    1480           0 :   return true;
    1481             : }
    1482             : 
    1483             : bool
    1484           0 : nsCSPPolicy::allows(nsContentPolicyType aContentType,
    1485             :                     enum CSPKeyword aKeyword) const
    1486             : {
    1487           0 :   return allows(aContentType, aKeyword, NS_LITERAL_STRING(""), false);
    1488             : }
    1489             : 
    1490             : void
    1491           0 : nsCSPPolicy::toString(nsAString& outStr) const
    1492             : {
    1493           0 :   uint32_t length = mDirectives.Length();
    1494           0 :   for (uint32_t i = 0; i < length; ++i) {
    1495             : 
    1496           0 :     if (mDirectives[i]->equals(nsIContentSecurityPolicy::REFERRER_DIRECTIVE)) {
    1497           0 :       outStr.AppendASCII(CSP_CSPDirectiveToString(nsIContentSecurityPolicy::REFERRER_DIRECTIVE));
    1498           0 :       outStr.AppendASCII(" ");
    1499           0 :       outStr.Append(mReferrerPolicy);
    1500             :     } else {
    1501           0 :       mDirectives[i]->toString(outStr);
    1502             :     }
    1503           0 :     if (i != (length - 1)) {
    1504           0 :       outStr.AppendASCII("; ");
    1505             :     }
    1506             :   }
    1507           0 : }
    1508             : 
    1509             : void
    1510           0 : nsCSPPolicy::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
    1511             : {
    1512           0 :   outCSP.mReport_only = mReportOnly;
    1513             : 
    1514           0 :   for (uint32_t i = 0; i < mDirectives.Length(); ++i) {
    1515           0 :     if (mDirectives[i]->equals(nsIContentSecurityPolicy::REFERRER_DIRECTIVE)) {
    1516           0 :       mozilla::dom::Sequence<nsString> srcs;
    1517           0 :       srcs.AppendElement(mReferrerPolicy, mozilla::fallible);
    1518           0 :       outCSP.mReferrer.Construct();
    1519           0 :       outCSP.mReferrer.Value() = srcs;
    1520             :     } else {
    1521           0 :       mDirectives[i]->toDomCSPStruct(outCSP);
    1522             :     }
    1523             :   }
    1524           0 : }
    1525             : 
    1526             : bool
    1527           0 : nsCSPPolicy::hasDirective(CSPDirective aDir) const
    1528             : {
    1529           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1530           0 :     if (mDirectives[i]->equals(aDir)) {
    1531           0 :       return true;
    1532             :     }
    1533             :   }
    1534           0 :   return false;
    1535             : }
    1536             : 
    1537             : /*
    1538             :  * Use this function only after ::allows() returned 'false'. Most and
    1539             :  * foremost it's used to get the violated directive before sending reports.
    1540             :  * The parameter outDirective is the equivalent of 'outViolatedDirective'
    1541             :  * for the ::permits() function family.
    1542             :  */
    1543             : void
    1544           0 : nsCSPPolicy::getDirectiveStringForContentType(nsContentPolicyType aContentType,
    1545             :                                               nsAString& outDirective) const
    1546             : {
    1547           0 :   nsCSPDirective* defaultDir = nullptr;
    1548           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1549           0 :     if (mDirectives[i]->restrictsContentType(aContentType)) {
    1550           0 :       mDirectives[i]->toString(outDirective);
    1551           0 :       return;
    1552             :     }
    1553           0 :     if (mDirectives[i]->isDefaultDirective()) {
    1554           0 :       defaultDir = mDirectives[i];
    1555             :     }
    1556             :   }
    1557             :   // if we haven't found a matching directive yet,
    1558             :   // the contentType must be restricted by the default directive
    1559           0 :   if (defaultDir) {
    1560           0 :     defaultDir->toString(outDirective);
    1561           0 :     return;
    1562             :   }
    1563           0 :   NS_ASSERTION(false, "Can not query directive string for contentType!");
    1564           0 :   outDirective.AppendASCII("couldNotQueryViolatedDirective");
    1565             : }
    1566             : 
    1567             : void
    1568           0 : nsCSPPolicy::getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const
    1569             : {
    1570           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1571           0 :     if (mDirectives[i]->equals(aDir)) {
    1572           0 :       mDirectives[i]->toString(outDirective);
    1573           0 :       return;
    1574             :     }
    1575             :   }
    1576             : }
    1577             : 
    1578             : /*
    1579             :  * Helper function that returns the underlying bit representation of sandbox
    1580             :  * flags. The function returns SANDBOXED_NONE if there are no sandbox
    1581             :  * directives.
    1582             :  */
    1583             : uint32_t
    1584           0 : nsCSPPolicy::getSandboxFlags() const
    1585             : {
    1586           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1587           0 :     if (mDirectives[i]->equals(nsIContentSecurityPolicy::SANDBOX_DIRECTIVE)) {
    1588           0 :       nsAutoString flags;
    1589           0 :       mDirectives[i]->toString(flags);
    1590             : 
    1591           0 :       if (flags.IsEmpty()) {
    1592           0 :         return SANDBOX_ALL_FLAGS;
    1593             :       }
    1594             : 
    1595           0 :       nsAttrValue attr;
    1596           0 :       attr.ParseAtomArray(flags);
    1597             : 
    1598           0 :       return nsContentUtils::ParseSandboxAttributeToFlags(&attr);
    1599             :     }
    1600             :   }
    1601             : 
    1602           0 :   return SANDBOXED_NONE;
    1603             : }
    1604             : 
    1605             : void
    1606           0 : nsCSPPolicy::getReportURIs(nsTArray<nsString>& outReportURIs) const
    1607             : {
    1608           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1609           0 :     if (mDirectives[i]->equals(nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE)) {
    1610           0 :       mDirectives[i]->getReportURIs(outReportURIs);
    1611           0 :       return;
    1612             :     }
    1613             :   }
    1614             : }
    1615             : 
    1616             : bool
    1617           0 : nsCSPPolicy::visitDirectiveSrcs(CSPDirective aDir, nsCSPSrcVisitor* aVisitor) const
    1618             : {
    1619           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1620           0 :     if (mDirectives[i]->equals(aDir)) {
    1621           0 :       return mDirectives[i]->visitSrcs(aVisitor);
    1622             :     }
    1623             :   }
    1624           0 :   return false;
    1625             : }
    1626             : 
    1627             : bool
    1628           0 : nsCSPPolicy::requireSRIForType(nsContentPolicyType aContentType)
    1629             : {
    1630           0 :   for (uint32_t i = 0; i < mDirectives.Length(); i++) {
    1631           0 :     if (mDirectives[i]->equals(nsIContentSecurityPolicy::REQUIRE_SRI_FOR)) {
    1632           0 :       return static_cast<nsRequireSRIForDirective*>(mDirectives[i])->hasType(aContentType);
    1633             :     }
    1634             :   }
    1635           0 :   return false;
    1636             : }

Generated by: LCOV version 1.13