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 "mozilla/FontLoaderUtils.h"
9 #include "mozilla/dom/Document.h"
10 #include "mozilla/dom/ReferrerInfo.h"
11 #include "mozilla/dom/WorkerPrivate.h"
12 #include "gfxUserFontSet.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"
22 #include "nsNetUtil.h"
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.
33 aURI
->SchemeIs("file")
34 ? nsContentSecurityManager::CORSSecurityMapping::
35 CORS_NONE_MAPS_TO_INHERITED_CONTEXT
36 : nsContentSecurityManager::CORSSecurityMapping::REQUIRE_CORS_CHECKS
;
38 aSecurityFlags
= nsContentSecurityManager::ComputeSecurityFlags(
39 CORSMode::CORS_NONE
, aCorsMapping
);
41 aContentPolicyType
= aIsPreload
? nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD
42 : nsIContentPolicy::TYPE_FONT
;
45 /* static */ nsresult
FontLoaderUtils::BuildChannelSetup(
46 nsIChannel
* aChannel
, nsIHttpChannel
* aHttpChannel
,
47 nsIReferrerInfo
* aReferrerInfo
, const gfxFontFaceSrc
* aFontFaceSrc
,
48 int32_t aSupportsPriorityValue
) {
50 nsresult rv
= aHttpChannel
->SetRequestHeader(
52 "application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"_ns
,
54 NS_ENSURE_SUCCESS(rv
, rv
);
57 rv
= aHttpChannel
->SetReferrerInfoWithoutClone(aReferrerInfo
);
58 MOZ_ASSERT(NS_SUCCEEDED(rv
));
60 MOZ_ASSERT(aFontFaceSrc
);
62 rv
= aHttpChannel
->SetReferrerInfo(aFontFaceSrc
->mReferrerInfo
);
63 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
65 // For WOFF and WOFF2, we should tell servers/proxies/etc NOT to try
66 // and apply additional compression at the content-encoding layer
67 if (aFontFaceSrc
->mFormatHint
== StyleFontFaceSourceFormatKeyword::Woff
||
68 aFontFaceSrc
->mFormatHint
==
69 StyleFontFaceSourceFormatKeyword::Woff2
) {
70 rv
= aHttpChannel
->SetRequestHeader("Accept-Encoding"_ns
, "identity"_ns
,
72 NS_ENSURE_SUCCESS(rv
, rv
);
77 nsCOMPtr
<nsISupportsPriority
> priorityChannel(do_QueryInterface(aChannel
));
78 if (priorityChannel
) {
79 priorityChannel
->SetPriority(aSupportsPriorityValue
);
81 nsCOMPtr
<nsIClassOfService
> cos(do_QueryInterface(aChannel
));
83 cos
->AddClassFlags(nsIClassOfService::TailForbidden
);
90 nsresult
FontLoaderUtils::BuildChannel(
91 nsIChannel
** aChannel
, nsIURI
* aURI
, const CORSMode aCORSMode
,
92 const dom::ReferrerPolicy
& aReferrerPolicy
,
93 gfxUserFontEntry
* aUserFontEntry
, const gfxFontFaceSrc
* aFontFaceSrc
,
94 dom::Document
* aDocument
, nsILoadGroup
* aLoadGroup
,
95 nsIInterfaceRequestor
* aCallbacks
, bool aIsPreload
,
96 int32_t aSupportsPriorityValue
) {
99 nsIPrincipal
* principal
=
100 aUserFontEntry
? (aUserFontEntry
->GetPrincipal()
101 ? aUserFontEntry
->GetPrincipal()->NodePrincipal()
103 : aDocument
->NodePrincipal();
105 nsContentSecurityManager::CORSSecurityMapping corsMapping
;
106 nsSecurityFlags securityFlags
;
107 nsContentPolicyType contentPolicyType
;
108 BuildChannelFlags(aURI
, aIsPreload
, corsMapping
, securityFlags
,
111 nsCOMPtr
<nsIChannel
> channel
;
112 // Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
113 // node and a principal. This is because the document where the font is
114 // being loaded might have a different origin from the principal of the
115 // stylesheet that initiated the font load.
116 rv
= NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel
), aURI
,
117 aDocument
, principal
, securityFlags
,
119 nullptr, // PerformanceStorage
121 NS_ENSURE_SUCCESS(rv
, rv
);
123 nsCOMPtr
<nsIHttpChannel
> httpChannel(do_QueryInterface(channel
));
124 nsCOMPtr
<nsIReferrerInfo
> referrerInfo
;
125 if (httpChannel
&& !aFontFaceSrc
) {
126 referrerInfo
= new dom::ReferrerInfo(aDocument
->GetDocumentURIAsReferrer(),
128 rv
= httpChannel
->SetReferrerInfoWithoutClone(referrerInfo
);
129 MOZ_ASSERT(NS_SUCCEEDED(rv
));
132 rv
= BuildChannelSetup(channel
, httpChannel
, referrerInfo
, aFontFaceSrc
,
133 aSupportsPriorityValue
);
134 NS_ENSURE_SUCCESS(rv
, rv
);
136 channel
.forget(aChannel
);
141 nsresult
FontLoaderUtils::BuildChannel(
142 nsIChannel
** aChannel
, nsIURI
* aURI
, const CORSMode aCORSMode
,
143 const dom::ReferrerPolicy
& aReferrerPolicy
,
144 gfxUserFontEntry
* aUserFontEntry
, const gfxFontFaceSrc
* aFontFaceSrc
,
145 dom::WorkerPrivate
* aWorkerPrivate
, nsILoadGroup
* aLoadGroup
,
146 nsIInterfaceRequestor
* aCallbacks
) {
149 nsIPrincipal
* principal
=
150 aUserFontEntry
? (aUserFontEntry
->GetPrincipal()
151 ? aUserFontEntry
->GetPrincipal()->NodePrincipal()
153 : aWorkerPrivate
->GetPrincipal();
155 nsContentSecurityManager::CORSSecurityMapping corsMapping
;
156 nsSecurityFlags securityFlags
;
157 nsContentPolicyType contentPolicyType
;
158 BuildChannelFlags(aURI
, /* aIsPreload */ false, corsMapping
, securityFlags
,
161 nsCOMPtr
<nsIChannel
> channel
;
162 rv
= NS_NewChannelWithTriggeringPrincipal(
163 getter_AddRefs(channel
), aURI
, aWorkerPrivate
->GetLoadingPrincipal(),
164 principal
, securityFlags
, contentPolicyType
, nullptr, nullptr,
166 NS_ENSURE_SUCCESS(rv
, rv
);
168 nsCOMPtr
<nsIHttpChannel
> httpChannel(do_QueryInterface(channel
));
170 nsCOMPtr
<nsIReferrerInfo
> referrerInfo
;
171 if (httpChannel
&& !aFontFaceSrc
) {
173 static_cast<dom::ReferrerInfo
*>(aWorkerPrivate
->GetReferrerInfo())
174 ->CloneWithNewPolicy(aReferrerPolicy
);
177 rv
= BuildChannelSetup(channel
, httpChannel
, referrerInfo
, aFontFaceSrc
,
178 nsISupportsPriority::PRIORITY_HIGH
);
179 NS_ENSURE_SUCCESS(rv
, rv
);
181 channel
.forget(aChannel
);
185 } // namespace mozilla