Bug 1854550 - pt 10. Allow LOG() with zero extra arguments r=glandium
[gecko.git] / dom / base / nsContentPolicyUtils.h
blob9fc96eb1ac3d92762630a9c1822a5084d9bdc77b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * Utility routines for checking content load/process policy settings,
8 * and routines helpful for content policy implementors.
10 * XXXbz it would be nice if some of this stuff could be out-of-lined in
11 * nsContentUtils. That would work for almost all the callers...
14 #ifndef __nsContentPolicyUtils_h__
15 #define __nsContentPolicyUtils_h__
17 #include "mozilla/BasePrincipal.h"
19 #include "nsContentUtils.h"
20 #include "nsIContentPolicy.h"
21 #include "nsIContent.h"
22 #include "nsIURI.h"
23 #include "nsServiceManagerUtils.h"
24 #include "nsStringFwd.h"
25 #include "mozilla/dom/nsCSPService.h"
27 // XXXtw sadly, this makes consumers of nsContentPolicyUtils depend on widget
28 #include "mozilla/dom/Document.h"
29 #include "nsPIDOMWindow.h"
31 #define NS_CONTENTPOLICY_CONTRACTID "@mozilla.org/layout/content-policy;1"
32 #define NS_CONTENTPOLICY_CATEGORY "content-policy"
33 #define NS_CONTENTPOLICY_CID \
34 { \
35 0x0e3afd3d, 0xeb60, 0x4c2b, { \
36 0x96, 0x3b, 0x56, 0xd7, 0xc4, 0x39, 0xf1, 0x24 \
37 } \
40 /**
41 * Evaluates to true if val is ACCEPT.
43 * @param val the status returned from shouldProcess/shouldLoad
45 #define NS_CP_ACCEPTED(val) ((val) == nsIContentPolicy::ACCEPT)
47 /**
48 * Evaluates to true if val is a REJECT_* status
50 * @param val the status returned from shouldProcess/shouldLoad
52 #define NS_CP_REJECTED(val) ((val) != nsIContentPolicy::ACCEPT)
54 // Offer convenient translations of constants -> const char*
56 // convenience macro to reduce some repetative typing...
57 // name is the name of a constant from this interface
58 #define CASE_RETURN(name) \
59 case nsIContentPolicy::name: \
60 return #name
62 /**
63 * Returns a string corresponding to the name of the response constant, or
64 * "<Unknown Response>" if an unknown response value is given.
66 * The return value is static and must not be freed.
68 * @param response the response code
69 * @return the name of the given response code
71 inline const char* NS_CP_ResponseName(int16_t response) {
72 switch (response) {
73 CASE_RETURN(REJECT_REQUEST);
74 CASE_RETURN(REJECT_TYPE);
75 CASE_RETURN(REJECT_SERVER);
76 CASE_RETURN(REJECT_OTHER);
77 CASE_RETURN(ACCEPT);
78 default:
79 return "<Unknown Response>";
83 /**
84 * Returns a string corresponding to the name of the content type constant, or
85 * "<Unknown Type>" if an unknown content type value is given.
87 * The return value is static and must not be freed.
89 * @param contentType the content type code
90 * @return the name of the given content type code
92 inline const char* NS_CP_ContentTypeName(nsContentPolicyType contentType) {
93 switch (contentType) {
94 CASE_RETURN(TYPE_OTHER);
95 CASE_RETURN(TYPE_SCRIPT);
96 CASE_RETURN(TYPE_IMAGE);
97 CASE_RETURN(TYPE_STYLESHEET);
98 CASE_RETURN(TYPE_OBJECT);
99 CASE_RETURN(TYPE_DOCUMENT);
100 CASE_RETURN(TYPE_SUBDOCUMENT);
101 CASE_RETURN(TYPE_PING);
102 CASE_RETURN(TYPE_XMLHTTPREQUEST);
103 CASE_RETURN(TYPE_OBJECT_SUBREQUEST);
104 CASE_RETURN(TYPE_DTD);
105 CASE_RETURN(TYPE_FONT);
106 CASE_RETURN(TYPE_MEDIA);
107 CASE_RETURN(TYPE_WEBSOCKET);
108 CASE_RETURN(TYPE_CSP_REPORT);
109 CASE_RETURN(TYPE_XSLT);
110 CASE_RETURN(TYPE_BEACON);
111 CASE_RETURN(TYPE_FETCH);
112 CASE_RETURN(TYPE_IMAGESET);
113 CASE_RETURN(TYPE_WEB_MANIFEST);
114 CASE_RETURN(TYPE_INTERNAL_SCRIPT);
115 CASE_RETURN(TYPE_INTERNAL_WORKER);
116 CASE_RETURN(TYPE_INTERNAL_SHARED_WORKER);
117 CASE_RETURN(TYPE_INTERNAL_EMBED);
118 CASE_RETURN(TYPE_INTERNAL_OBJECT);
119 CASE_RETURN(TYPE_INTERNAL_FRAME);
120 CASE_RETURN(TYPE_INTERNAL_IFRAME);
121 CASE_RETURN(TYPE_INTERNAL_AUDIO);
122 CASE_RETURN(TYPE_INTERNAL_VIDEO);
123 CASE_RETURN(TYPE_INTERNAL_TRACK);
124 CASE_RETURN(TYPE_INTERNAL_XMLHTTPREQUEST);
125 CASE_RETURN(TYPE_INTERNAL_EVENTSOURCE);
126 CASE_RETURN(TYPE_INTERNAL_SERVICE_WORKER);
127 CASE_RETURN(TYPE_INTERNAL_SCRIPT_PRELOAD);
128 CASE_RETURN(TYPE_INTERNAL_IMAGE);
129 CASE_RETURN(TYPE_INTERNAL_IMAGE_PRELOAD);
130 CASE_RETURN(TYPE_INTERNAL_IMAGE_FAVICON);
131 CASE_RETURN(TYPE_INTERNAL_STYLESHEET);
132 CASE_RETURN(TYPE_INTERNAL_STYLESHEET_PRELOAD);
133 CASE_RETURN(TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS);
134 CASE_RETURN(TYPE_SAVEAS_DOWNLOAD);
135 CASE_RETURN(TYPE_SPECULATIVE);
136 CASE_RETURN(TYPE_INTERNAL_MODULE);
137 CASE_RETURN(TYPE_INTERNAL_MODULE_PRELOAD);
138 CASE_RETURN(TYPE_INTERNAL_DTD);
139 CASE_RETURN(TYPE_INTERNAL_FORCE_ALLOWED_DTD);
140 CASE_RETURN(TYPE_INTERNAL_AUDIOWORKLET);
141 CASE_RETURN(TYPE_INTERNAL_PAINTWORKLET);
142 CASE_RETURN(TYPE_INTERNAL_FONT_PRELOAD);
143 CASE_RETURN(TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT);
144 CASE_RETURN(TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT);
145 CASE_RETURN(TYPE_INTERNAL_FETCH_PRELOAD);
146 CASE_RETURN(TYPE_UA_FONT);
147 CASE_RETURN(TYPE_INTERNAL_WORKER_STATIC_MODULE);
148 CASE_RETURN(TYPE_PROXIED_WEBRTC_MEDIA);
149 CASE_RETURN(TYPE_WEB_IDENTITY);
150 CASE_RETURN(TYPE_WEB_TRANSPORT);
151 CASE_RETURN(TYPE_END);
152 case nsIContentPolicy::TYPE_INVALID:
153 break;
154 // Do not add default: so that compilers can catch the missing case.
156 return "<Unknown Type>";
159 #undef CASE_RETURN
161 inline const char* NS_CP_ContentTypeName(ExtContentPolicyType contentType) {
162 return NS_CP_ContentTypeName(static_cast<nsContentPolicyType>(contentType));
165 /* Passes on parameters from its "caller"'s context. */
166 #define CHECK_CONTENT_POLICY(action) \
167 PR_BEGIN_MACRO \
168 nsCOMPtr<nsIContentPolicy> policy = \
169 do_GetService(NS_CONTENTPOLICY_CONTRACTID); \
170 if (!policy) return NS_ERROR_FAILURE; \
172 return policy->action(contentLocation, loadInfo, mimeType, decision); \
173 PR_END_MACRO
175 /* Passes on parameters from its "caller"'s context. */
176 #define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \
177 PR_BEGIN_MACRO \
178 return _policy->action(contentLocation, loadInfo, mimeType, decision); \
179 PR_END_MACRO
182 * Check whether we can short-circuit this check and bail out. If not, get the
183 * origin URI to use.
185 * Note: requestOrigin is scoped outside the PR_BEGIN_MACRO/PR_END_MACRO on
186 * purpose */
187 #define CHECK_PRINCIPAL_CSP_AND_DATA(action) \
188 PR_BEGIN_MACRO \
189 if (loadingPrincipal && loadingPrincipal->IsSystemPrincipal()) { \
190 /* We exempt most loads into any document with the system principal \
191 * from content policy (except CSP) checks, mostly as an optimization. \
192 * Which means that we need to apply this check to the loading principal, \
193 * not the principal that triggered the load. */ \
194 /* Check CSP for System Privileged pages */ \
195 CSPService::ConsultCSP(contentLocation, loadInfo, mimeType, decision); \
196 if (NS_CP_REJECTED(*decision)) { \
197 return NS_OK; \
199 if (contentType != nsIContentPolicy::TYPE_DOCUMENT && \
200 contentType != nsIContentPolicy::TYPE_UA_FONT) { \
201 *decision = nsIContentPolicy::ACCEPT; \
202 nsCOMPtr<nsINode> n = do_QueryInterface(context); \
203 if (!n) { \
204 nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(context); \
205 n = win ? win->GetExtantDoc() : nullptr; \
207 if (n) { \
208 mozilla::dom::Document* d = n->OwnerDoc(); \
209 if (d->IsLoadedAsData() || d->IsBeingUsedAsImage() || \
210 d->IsResourceDoc()) { \
211 nsCOMPtr<nsIContentPolicy> dataPolicy = \
212 do_GetService("@mozilla.org/data-document-content-policy;1"); \
213 if (dataPolicy) { \
214 dataPolicy->action(contentLocation, loadInfo, mimeType, decision); \
219 return NS_OK; \
221 PR_END_MACRO
224 * Alias for calling ShouldLoad on the content policy service. Parameters are
225 * the same as nsIContentPolicy::shouldLoad, except for the loadingPrincipal
226 * and triggeringPrincipal parameters (which should be non-null if possible,
227 * and have the same semantics as in nsLoadInfo), and the last parameter,
228 * which can be used to pass in a pointer to a useful service if the caller
229 * already has it. The origin URI to pass to shouldLoad will be the URI of
230 * loadingPrincipal, unless loadingPrincipal is null (in which case a null
231 * origin URI will be passed).
233 inline nsresult NS_CheckContentLoadPolicy(
234 nsIURI* contentLocation, nsILoadInfo* loadInfo, const nsACString& mimeType,
235 int16_t* decision, nsIContentPolicy* policyService = nullptr) {
236 nsIPrincipal* loadingPrincipal = loadInfo->GetLoadingPrincipal();
237 nsCOMPtr<nsISupports> context = loadInfo->GetLoadingContext();
238 nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
239 CHECK_PRINCIPAL_CSP_AND_DATA(ShouldLoad);
240 if (policyService) {
241 CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldLoad, policyService);
243 CHECK_CONTENT_POLICY(ShouldLoad);
247 * Alias for calling ShouldProcess on the content policy service.
249 inline nsresult NS_CheckContentProcessPolicy(
250 nsIURI* contentLocation, nsILoadInfo* loadInfo, const nsACString& mimeType,
251 int16_t* decision, nsIContentPolicy* policyService = nullptr) {
252 nsIPrincipal* loadingPrincipal = loadInfo->GetLoadingPrincipal();
253 nsCOMPtr<nsISupports> context = loadInfo->GetLoadingContext();
254 nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
255 CHECK_PRINCIPAL_CSP_AND_DATA(ShouldProcess);
256 if (policyService) {
257 CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldProcess, policyService);
259 CHECK_CONTENT_POLICY(ShouldProcess);
262 #undef CHECK_CONTENT_POLICY
263 #undef CHECK_CONTENT_POLICY_WITH_SERVICE
266 * Helper function to get an nsIDocShell given a context.
267 * If the context is a document or window, the corresponding docshell will be
268 * returned.
269 * If the context is a non-document DOM node, the docshell of its ownerDocument
270 * will be returned.
272 * @param aContext the context to find a docshell for (can be null)
274 * @return a WEAK pointer to the docshell, or nullptr if it could
275 * not be obtained
277 * @note As of this writing, calls to nsIContentPolicy::Should{Load,Process}
278 * for TYPE_DOCUMENT and TYPE_SUBDOCUMENT pass in an aContext that either
279 * points to the frameElement of the window the load is happening in
280 * (in which case NS_CP_GetDocShellFromContext will return the parent of the
281 * docshell the load is happening in), or points to the window the load is
282 * happening in (in which case NS_CP_GetDocShellFromContext will return
283 * the docshell the load is happening in). It's up to callers to QI aContext
284 * and handle things accordingly if they want the docshell the load is
285 * happening in. These are somewhat odd semantics, and bug 466687 has been
286 * filed to consider improving them.
288 inline nsIDocShell* NS_CP_GetDocShellFromContext(nsISupports* aContext) {
289 if (!aContext) {
290 return nullptr;
293 nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aContext);
295 if (!window) {
296 // Our context might be a document.
297 nsCOMPtr<mozilla::dom::Document> doc = do_QueryInterface(aContext);
298 if (!doc) {
299 // we were not a document after all, get our ownerDocument,
300 // hopefully
301 nsCOMPtr<nsIContent> content = do_QueryInterface(aContext);
302 if (content) {
303 doc = content->OwnerDoc();
307 if (doc) {
308 if (doc->GetDisplayDocument()) {
309 doc = doc->GetDisplayDocument();
312 window = doc->GetWindow();
316 if (!window) {
317 return nullptr;
320 return window->GetDocShell();
323 #endif /* __nsContentPolicyUtils_h__ */