Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / layout / style / FontPreloader.cpp
bloba0eaab07a6632cd26125835ad8e90f728bcca4e6
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/. */
7 #include "FontPreloader.h"
9 #include "gfxUserFontSet.h"
10 #include "mozilla/dom/Document.h"
11 #include "mozilla/dom/WorkerPrivate.h"
12 #include "mozilla/dom/ReferrerInfo.h"
13 #include "nsContentSecurityManager.h"
14 #include "nsIClassOfService.h"
15 #include "nsIHttpChannel.h"
16 #include "nsISupportsPriority.h"
17 #include "nsNetUtil.h"
19 namespace mozilla {
21 FontPreloader::FontPreloader()
22 : FetchPreloader(nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD) {}
24 nsresult FontPreloader::CreateChannel(
25 nsIChannel** aChannel, nsIURI* aURI, const CORSMode aCORSMode,
26 const dom::ReferrerPolicy& aReferrerPolicy, dom::Document* aDocument,
27 nsILoadGroup* aLoadGroup, nsIInterfaceRequestor* aCallbacks,
28 uint64_t aEarlyHintPreloaderId) {
29 // Don't preload fonts if they've been preffed-off.
30 if (!gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
31 return NS_ERROR_NOT_AVAILABLE;
34 return BuildChannel(aChannel, aURI, aCORSMode, aReferrerPolicy, nullptr,
35 nullptr, aDocument, aLoadGroup, aCallbacks, true);
38 // static
39 void FontPreloader::PrioritizeAsPreload(nsIChannel* aChannel) {
40 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
41 if (cos) {
42 cos->AddClassFlags(nsIClassOfService::Unblocked);
46 /* static */ void FontPreloader::BuildChannelFlags(
47 nsIURI* aURI, bool aIsPreload,
48 nsContentSecurityManager::CORSSecurityMapping& aCorsMapping,
49 nsSecurityFlags& aSecurityFlags, nsContentPolicyType& aContentPolicyType) {
50 // aCORSMode is ignored. We always load as crossorigin=anonymous, but a
51 // preload started with anything other then "anonymous" will never be found.
52 aCorsMapping =
53 aURI->SchemeIs("file")
54 ? nsContentSecurityManager::CORSSecurityMapping::
55 CORS_NONE_MAPS_TO_INHERITED_CONTEXT
56 : nsContentSecurityManager::CORSSecurityMapping::REQUIRE_CORS_CHECKS;
58 aSecurityFlags = nsContentSecurityManager::ComputeSecurityFlags(
59 CORSMode::CORS_NONE, aCorsMapping);
61 aContentPolicyType = aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD
62 : nsIContentPolicy::TYPE_FONT;
65 /* static */ nsresult FontPreloader::BuildChannelSetup(
66 nsIChannel* aChannel, nsIHttpChannel* aHttpChannel,
67 nsIReferrerInfo* aReferrerInfo, const gfxFontFaceSrc* aFontFaceSrc) {
68 if (aHttpChannel) {
69 nsresult rv = aHttpChannel->SetRequestHeader(
70 "Accept"_ns,
71 "application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"_ns,
72 false);
73 NS_ENSURE_SUCCESS(rv, rv);
75 if (aReferrerInfo) {
76 rv = aHttpChannel->SetReferrerInfoWithoutClone(aReferrerInfo);
77 MOZ_ASSERT(NS_SUCCEEDED(rv));
78 } else {
79 MOZ_ASSERT(aFontFaceSrc);
81 rv = aHttpChannel->SetReferrerInfo(aFontFaceSrc->mReferrerInfo);
82 Unused << NS_WARN_IF(NS_FAILED(rv));
84 // For WOFF and WOFF2, we should tell servers/proxies/etc NOT to try
85 // and apply additional compression at the content-encoding layer
86 if (aFontFaceSrc->mFormatHint == StyleFontFaceSourceFormatKeyword::Woff ||
87 aFontFaceSrc->mFormatHint ==
88 StyleFontFaceSourceFormatKeyword::Woff2) {
89 rv = aHttpChannel->SetRequestHeader("Accept-Encoding"_ns, "identity"_ns,
90 false);
91 NS_ENSURE_SUCCESS(rv, rv);
96 nsCOMPtr<nsISupportsPriority> priorityChannel(do_QueryInterface(aChannel));
97 if (priorityChannel) {
98 priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGH);
100 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
101 if (cos) {
102 cos->AddClassFlags(nsIClassOfService::TailForbidden);
105 return NS_OK;
108 // static
109 nsresult FontPreloader::BuildChannel(
110 nsIChannel** aChannel, nsIURI* aURI, const CORSMode aCORSMode,
111 const dom::ReferrerPolicy& aReferrerPolicy,
112 gfxUserFontEntry* aUserFontEntry, const gfxFontFaceSrc* aFontFaceSrc,
113 dom::Document* aDocument, nsILoadGroup* aLoadGroup,
114 nsIInterfaceRequestor* aCallbacks, bool aIsPreload) {
115 nsresult rv;
117 nsIPrincipal* principal =
118 aUserFontEntry ? (aUserFontEntry->GetPrincipal()
119 ? aUserFontEntry->GetPrincipal()->NodePrincipal()
120 : nullptr)
121 : aDocument->NodePrincipal();
123 nsContentSecurityManager::CORSSecurityMapping corsMapping;
124 nsSecurityFlags securityFlags;
125 nsContentPolicyType contentPolicyType;
126 BuildChannelFlags(aURI, aIsPreload, corsMapping, securityFlags,
127 contentPolicyType);
129 nsCOMPtr<nsIChannel> channel;
130 // Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
131 // node and a principal. This is because the document where the font is
132 // being loaded might have a different origin from the principal of the
133 // stylesheet that initiated the font load.
134 rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel), aURI,
135 aDocument, principal, securityFlags,
136 contentPolicyType,
137 nullptr, // PerformanceStorage
138 aLoadGroup);
139 NS_ENSURE_SUCCESS(rv, rv);
141 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
142 nsCOMPtr<nsIReferrerInfo> referrerInfo;
143 if (httpChannel && !aFontFaceSrc) {
144 referrerInfo = new dom::ReferrerInfo(aDocument->GetDocumentURIAsReferrer(),
145 aReferrerPolicy);
146 rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
147 MOZ_ASSERT(NS_SUCCEEDED(rv));
150 rv = BuildChannelSetup(channel, httpChannel, referrerInfo, aFontFaceSrc);
151 NS_ENSURE_SUCCESS(rv, rv);
153 channel.forget(aChannel);
154 return NS_OK;
157 // static
158 nsresult FontPreloader::BuildChannel(
159 nsIChannel** aChannel, nsIURI* aURI, const CORSMode aCORSMode,
160 const dom::ReferrerPolicy& aReferrerPolicy,
161 gfxUserFontEntry* aUserFontEntry, const gfxFontFaceSrc* aFontFaceSrc,
162 dom::WorkerPrivate* aWorkerPrivate, nsILoadGroup* aLoadGroup,
163 nsIInterfaceRequestor* aCallbacks, bool aIsPreload) {
164 nsresult rv;
166 nsIPrincipal* principal =
167 aUserFontEntry ? (aUserFontEntry->GetPrincipal()
168 ? aUserFontEntry->GetPrincipal()->NodePrincipal()
169 : nullptr)
170 : aWorkerPrivate->GetPrincipal();
172 nsContentSecurityManager::CORSSecurityMapping corsMapping;
173 nsSecurityFlags securityFlags;
174 nsContentPolicyType contentPolicyType;
175 BuildChannelFlags(aURI, aIsPreload, corsMapping, securityFlags,
176 contentPolicyType);
178 nsCOMPtr<nsIChannel> channel;
179 rv = NS_NewChannelWithTriggeringPrincipal(
180 getter_AddRefs(channel), aURI, aWorkerPrivate->GetLoadingPrincipal(),
181 principal, securityFlags, contentPolicyType, nullptr, nullptr,
182 aLoadGroup);
183 NS_ENSURE_SUCCESS(rv, rv);
185 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
187 nsCOMPtr<nsIReferrerInfo> referrerInfo;
188 if (httpChannel && !aFontFaceSrc) {
189 referrerInfo =
190 static_cast<dom::ReferrerInfo*>(aWorkerPrivate->GetReferrerInfo())
191 ->CloneWithNewPolicy(aReferrerPolicy);
194 rv = BuildChannelSetup(channel, httpChannel, referrerInfo, aFontFaceSrc);
195 NS_ENSURE_SUCCESS(rv, rv);
197 channel.forget(aChannel);
198 return NS_OK;
201 } // namespace mozilla