tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FontLoaderUtils.cpp (7410B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/FontLoaderUtils.h"
      8 
      9 #include "gfxUserFontSet.h"
     10 #include "mozilla/dom/Document.h"
     11 #include "mozilla/dom/ReferrerInfo.h"
     12 #include "mozilla/dom/WorkerPrivate.h"
     13 #include "nsCOMPtr.h"
     14 #include "nsIChannel.h"
     15 #include "nsIClassOfService.h"
     16 #include "nsIContentPolicy.h"
     17 #include "nsIHttpChannel.h"
     18 #include "nsILoadInfo.h"
     19 #include "nsIReferrerInfo.h"
     20 #include "nsISupportsPriority.h"
     21 #include "nsIURI.h"
     22 #include "nsNetUtil.h"
     23 
     24 namespace mozilla {
     25 
     26 /* static */ void FontLoaderUtils::BuildChannelFlags(
     27    nsIURI* aURI, bool aIsPreload,
     28    nsContentSecurityManager::CORSSecurityMapping& aCorsMapping,
     29    nsSecurityFlags& aSecurityFlags, nsContentPolicyType& aContentPolicyType) {
     30  // aCORSMode is ignored.  We always load as crossorigin=anonymous, but a
     31  // preload started with anything other then "anonymous" will never be found.
     32  aCorsMapping =
     33      aURI->SchemeIs("file") || aURI->SchemeIs("resource") ||
     34              aURI->SchemeIs("chrome")
     35          ? nsContentSecurityManager::CORSSecurityMapping::
     36                CORS_NONE_MAPS_TO_INHERITED_CONTEXT
     37          : nsContentSecurityManager::CORSSecurityMapping::REQUIRE_CORS_CHECKS;
     38 
     39  // Besides the CORS flags, include SEC_ALLOW_CHROME to allow a font to come
     40  // from a resource:// or chrome:// URL (as long as it is marked
     41  // contentaccessible)
     42  aSecurityFlags = nsContentSecurityManager::ComputeSecurityFlags(
     43                       CORSMode::CORS_NONE, aCorsMapping) |
     44                   nsILoadInfo::SEC_ALLOW_CHROME;
     45 
     46  aContentPolicyType = aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD
     47                                  : nsIContentPolicy::TYPE_FONT;
     48 }
     49 
     50 /* static */ nsresult FontLoaderUtils::BuildChannelSetup(
     51    nsIChannel* aChannel, nsIHttpChannel* aHttpChannel,
     52    nsIReferrerInfo* aReferrerInfo, const gfxFontFaceSrc* aFontFaceSrc,
     53    int32_t aSupportsPriorityValue) {
     54  if (aHttpChannel) {
     55    nsresult rv = aHttpChannel->SetRequestHeader(
     56        "Accept"_ns,
     57        "application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"_ns,
     58        false);
     59    NS_ENSURE_SUCCESS(rv, rv);
     60 
     61    if (aReferrerInfo) {
     62      rv = aHttpChannel->SetReferrerInfoWithoutClone(aReferrerInfo);
     63      MOZ_ASSERT(NS_SUCCEEDED(rv));
     64    } else {
     65      MOZ_ASSERT(aFontFaceSrc);
     66 
     67      rv = aHttpChannel->SetReferrerInfo(aFontFaceSrc->mReferrerInfo);
     68      (void)NS_WARN_IF(NS_FAILED(rv));
     69 
     70      // For WOFF and WOFF2, we should tell servers/proxies/etc NOT to try
     71      // and apply additional compression at the content-encoding layer
     72      if (aFontFaceSrc->mFormatHint == StyleFontFaceSourceFormatKeyword::Woff ||
     73          aFontFaceSrc->mFormatHint ==
     74              StyleFontFaceSourceFormatKeyword::Woff2) {
     75        rv = aHttpChannel->SetRequestHeader("Accept-Encoding"_ns, "identity"_ns,
     76                                            false);
     77        NS_ENSURE_SUCCESS(rv, rv);
     78      }
     79    }
     80  }
     81 
     82  nsCOMPtr<nsISupportsPriority> priorityChannel(do_QueryInterface(aChannel));
     83  if (priorityChannel) {
     84    priorityChannel->SetPriority(aSupportsPriorityValue);
     85  }
     86  nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
     87  if (cos) {
     88    cos->AddClassFlags(nsIClassOfService::TailForbidden);
     89  }
     90 
     91  return NS_OK;
     92 }
     93 
     94 // static
     95 nsresult FontLoaderUtils::BuildChannel(
     96    nsIChannel** aChannel, nsIURI* aURI, const CORSMode aCORSMode,
     97    const dom::ReferrerPolicy& aReferrerPolicy,
     98    gfxUserFontEntry* aUserFontEntry, const gfxFontFaceSrc* aFontFaceSrc,
     99    dom::Document* aDocument, nsILoadGroup* aLoadGroup,
    100    nsIInterfaceRequestor* aCallbacks, bool aIsPreload,
    101    int32_t aSupportsPriorityValue) {
    102  nsresult rv;
    103 
    104  nsIPrincipal* principal =
    105      aUserFontEntry ? (aUserFontEntry->GetPrincipal()
    106                            ? aUserFontEntry->GetPrincipal()->NodePrincipal()
    107                            : nullptr)
    108                     : aDocument->NodePrincipal();
    109 
    110  nsContentSecurityManager::CORSSecurityMapping corsMapping;
    111  nsSecurityFlags securityFlags;
    112  nsContentPolicyType contentPolicyType;
    113  BuildChannelFlags(aURI, aIsPreload, corsMapping, securityFlags,
    114                    contentPolicyType);
    115 
    116  nsCOMPtr<nsIChannel> channel;
    117  // Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
    118  // node and a principal.  This is because the document where the font is
    119  // being loaded might have a different origin from the principal of the
    120  // stylesheet that initiated the font load.
    121  rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel), aURI,
    122                                            aDocument, principal, securityFlags,
    123                                            contentPolicyType,
    124                                            nullptr,  // PerformanceStorage
    125                                            aLoadGroup);
    126  NS_ENSURE_SUCCESS(rv, rv);
    127 
    128  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
    129  nsCOMPtr<nsIReferrerInfo> referrerInfo;
    130  if (httpChannel && !aFontFaceSrc) {
    131    referrerInfo = new dom::ReferrerInfo(aDocument->GetDocumentURIAsReferrer(),
    132                                         aReferrerPolicy);
    133    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
    134    MOZ_ASSERT(NS_SUCCEEDED(rv));
    135  }
    136 
    137  rv = BuildChannelSetup(channel, httpChannel, referrerInfo, aFontFaceSrc,
    138                         aSupportsPriorityValue);
    139  NS_ENSURE_SUCCESS(rv, rv);
    140 
    141  channel.forget(aChannel);
    142  return NS_OK;
    143 }
    144 
    145 // static
    146 nsresult FontLoaderUtils::BuildChannel(
    147    nsIChannel** aChannel, nsIURI* aURI, const CORSMode aCORSMode,
    148    const dom::ReferrerPolicy& aReferrerPolicy,
    149    gfxUserFontEntry* aUserFontEntry, const gfxFontFaceSrc* aFontFaceSrc,
    150    dom::WorkerPrivate* aWorkerPrivate, nsILoadGroup* aLoadGroup,
    151    nsIInterfaceRequestor* aCallbacks) {
    152  nsresult rv;
    153 
    154  nsIPrincipal* principal =
    155      aUserFontEntry ? (aUserFontEntry->GetPrincipal()
    156                            ? aUserFontEntry->GetPrincipal()->NodePrincipal()
    157                            : nullptr)
    158                     : aWorkerPrivate->GetPrincipal();
    159 
    160  nsContentSecurityManager::CORSSecurityMapping corsMapping;
    161  nsSecurityFlags securityFlags;
    162  nsContentPolicyType contentPolicyType;
    163  BuildChannelFlags(aURI, /* aIsPreload */ false, corsMapping, securityFlags,
    164                    contentPolicyType);
    165 
    166  nsCOMPtr<nsIChannel> channel;
    167  rv = NS_NewChannelWithTriggeringPrincipal(
    168      getter_AddRefs(channel), aURI, aWorkerPrivate->GetLoadingPrincipal(),
    169      principal, securityFlags, contentPolicyType, nullptr, nullptr,
    170      aLoadGroup);
    171  NS_ENSURE_SUCCESS(rv, rv);
    172 
    173  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
    174 
    175  nsCOMPtr<nsIReferrerInfo> referrerInfo;
    176  if (httpChannel && !aFontFaceSrc) {
    177    referrerInfo =
    178        static_cast<dom::ReferrerInfo*>(aWorkerPrivate->GetReferrerInfo())
    179            ->CloneWithNewPolicy(aReferrerPolicy);
    180  }
    181 
    182  rv = BuildChannelSetup(channel, httpChannel, referrerInfo, aFontFaceSrc,
    183                         nsISupportsPriority::PRIORITY_HIGH);
    184  NS_ENSURE_SUCCESS(rv, rv);
    185 
    186  channel.forget(aChannel);
    187  return NS_OK;
    188 }
    189 
    190 }  // namespace mozilla