Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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.
9 *
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...
12 */
14 #ifndef __nsContentPolicyUtils_h__
15 #define __nsContentPolicyUtils_h__
17 #include "nsIContentPolicy.h"
18 #include "nsIContent.h"
19 #include "nsIScriptSecurityManager.h"
20 #include "nsIURI.h"
21 #include "nsServiceManagerUtils.h"
23 //XXXtw sadly, this makes consumers of nsContentPolicyUtils depend on widget
24 #include "nsIDocument.h"
25 #include "nsPIDOMWindow.h"
27 class nsACString;
28 class nsIPrincipal;
30 #define NS_CONTENTPOLICY_CONTRACTID "@mozilla.org/layout/content-policy;1"
31 #define NS_CONTENTPOLICY_CATEGORY "content-policy"
32 #define NS_CONTENTPOLICY_CID \
33 {0x0e3afd3d, 0xeb60, 0x4c2b, \
34 { 0x96, 0x3b, 0x56, 0xd7, 0xc4, 0x39, 0xf1, 0x24 }}
36 /**
37 * Evaluates to true if val is ACCEPT.
38 *
39 * @param val the status returned from shouldProcess/shouldLoad
40 */
41 #define NS_CP_ACCEPTED(val) ((val) == nsIContentPolicy::ACCEPT)
43 /**
44 * Evaluates to true if val is a REJECT_* status
45 *
46 * @param val the status returned from shouldProcess/shouldLoad
47 */
48 #define NS_CP_REJECTED(val) ((val) != nsIContentPolicy::ACCEPT)
50 // Offer convenient translations of constants -> const char*
52 // convenience macro to reduce some repetative typing...
53 // name is the name of a constant from this interface
54 #define CASE_RETURN(name) \
55 case nsIContentPolicy:: name : \
56 return #name
58 #ifdef PR_LOGGING
59 /**
60 * Returns a string corresponding to the name of the response constant, or
61 * "<Unknown Response>" if an unknown response value is given.
62 *
63 * The return value is static and must not be freed.
64 *
65 * @param response the response code
66 * @return the name of the given response code
67 */
68 inline const char *
69 NS_CP_ResponseName(int16_t response)
70 {
71 switch (response) {
72 CASE_RETURN( REJECT_REQUEST );
73 CASE_RETURN( REJECT_TYPE );
74 CASE_RETURN( REJECT_SERVER );
75 CASE_RETURN( REJECT_OTHER );
76 CASE_RETURN( ACCEPT );
77 default:
78 return "<Unknown Response>";
79 }
80 }
82 /**
83 * Returns a string corresponding to the name of the content type constant, or
84 * "<Unknown Type>" if an unknown content type value is given.
85 *
86 * The return value is static and must not be freed.
87 *
88 * @param contentType the content type code
89 * @return the name of the given content type code
90 */
91 inline const char *
92 NS_CP_ContentTypeName(uint32_t contentType)
93 {
94 switch (contentType) {
95 CASE_RETURN( TYPE_OTHER );
96 CASE_RETURN( TYPE_SCRIPT );
97 CASE_RETURN( TYPE_IMAGE );
98 CASE_RETURN( TYPE_STYLESHEET );
99 CASE_RETURN( TYPE_OBJECT );
100 CASE_RETURN( TYPE_DOCUMENT );
101 CASE_RETURN( TYPE_SUBDOCUMENT );
102 CASE_RETURN( TYPE_REFRESH );
103 CASE_RETURN( TYPE_XBL );
104 CASE_RETURN( TYPE_PING );
105 CASE_RETURN( TYPE_XMLHTTPREQUEST );
106 CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
107 CASE_RETURN( TYPE_DTD );
108 CASE_RETURN( TYPE_FONT );
109 CASE_RETURN( TYPE_MEDIA );
110 CASE_RETURN( TYPE_WEBSOCKET );
111 CASE_RETURN( TYPE_CSP_REPORT );
112 CASE_RETURN( TYPE_XSLT );
113 CASE_RETURN( TYPE_BEACON );
114 default:
115 return "<Unknown Type>";
116 }
117 }
119 #endif // defined(PR_LOGGING)
121 #undef CASE_RETURN
123 /* Passes on parameters from its "caller"'s context. */
124 #define CHECK_CONTENT_POLICY(action) \
125 PR_BEGIN_MACRO \
126 nsCOMPtr<nsIContentPolicy> policy = \
127 do_GetService(NS_CONTENTPOLICY_CONTRACTID); \
128 if (!policy) \
129 return NS_ERROR_FAILURE; \
130 \
131 return policy-> action (contentType, contentLocation, requestOrigin, \
132 context, mimeType, extra, originPrincipal, \
133 decision); \
134 PR_END_MACRO
136 /* Passes on parameters from its "caller"'s context. */
137 #define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \
138 PR_BEGIN_MACRO \
139 return _policy-> action (contentType, contentLocation, requestOrigin, \
140 context, mimeType, extra, originPrincipal, \
141 decision); \
142 PR_END_MACRO
144 /**
145 * Check whether we can short-circuit this check and bail out. If not, get the
146 * origin URI to use.
147 *
148 * Note: requestOrigin is scoped outside the PR_BEGIN_MACRO/PR_END_MACRO on
149 * purpose */
150 #define CHECK_PRINCIPAL_AND_DATA(action) \
151 nsCOMPtr<nsIURI> requestOrigin; \
152 PR_BEGIN_MACRO \
153 if (originPrincipal) { \
154 nsCOMPtr<nsIScriptSecurityManager> secMan = aSecMan; \
155 if (!secMan) { \
156 secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); \
157 } \
158 if (secMan) { \
159 bool isSystem; \
160 nsresult rv = secMan->IsSystemPrincipal(originPrincipal, \
161 &isSystem); \
162 NS_ENSURE_SUCCESS(rv, rv); \
163 if (isSystem) { \
164 *decision = nsIContentPolicy::ACCEPT; \
165 nsCOMPtr<nsINode> n = do_QueryInterface(context); \
166 if (!n) { \
167 nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(context); \
168 n = win ? win->GetExtantDoc() : nullptr; \
169 } \
170 if (n) { \
171 nsIDocument* d = n->OwnerDoc(); \
172 if (d->IsLoadedAsData() || d->IsBeingUsedAsImage() || \
173 d->IsResourceDoc()) { \
174 nsCOMPtr<nsIContentPolicy> dataPolicy = \
175 do_GetService( \
176 "@mozilla.org/data-document-content-policy;1"); \
177 if (dataPolicy) { \
178 dataPolicy-> action (contentType, contentLocation, \
179 requestOrigin, context, \
180 mimeType, extra, \
181 originPrincipal, decision); \
182 } \
183 } \
184 } \
185 return NS_OK; \
186 } \
187 } \
188 nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin)); \
189 NS_ENSURE_SUCCESS(rv, rv); \
190 } \
191 PR_END_MACRO
193 /**
194 * Alias for calling ShouldLoad on the content policy service. Parameters are
195 * the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
196 * parameter, which should be non-null if possible, and the last two
197 * parameters, which can be used to pass in pointer to some useful services if
198 * the caller already has them. The origin URI to pass to shouldLoad will be
199 * the URI of originPrincipal, unless originPrincipal is null (in which case a
200 * null origin URI will be passed).
201 */
202 inline nsresult
203 NS_CheckContentLoadPolicy(uint32_t contentType,
204 nsIURI *contentLocation,
205 nsIPrincipal *originPrincipal,
206 nsISupports *context,
207 const nsACString &mimeType,
208 nsISupports *extra,
209 int16_t *decision,
210 nsIContentPolicy *policyService = nullptr,
211 nsIScriptSecurityManager* aSecMan = nullptr)
212 {
213 CHECK_PRINCIPAL_AND_DATA(ShouldLoad);
214 if (policyService) {
215 CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldLoad, policyService);
216 }
217 CHECK_CONTENT_POLICY(ShouldLoad);
218 }
220 /**
221 * Alias for calling ShouldProcess on the content policy service. Parameters
222 * are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
223 * parameter, which should be non-null if possible, and the last two
224 * parameters, which can be used to pass in pointer to some useful services if
225 * the caller already has them. The origin URI to pass to shouldLoad will be
226 * the URI of originPrincipal, unless originPrincipal is null (in which case a
227 * null origin URI will be passed).
228 */
229 inline nsresult
230 NS_CheckContentProcessPolicy(uint32_t contentType,
231 nsIURI *contentLocation,
232 nsIPrincipal *originPrincipal,
233 nsISupports *context,
234 const nsACString &mimeType,
235 nsISupports *extra,
236 int16_t *decision,
237 nsIContentPolicy *policyService = nullptr,
238 nsIScriptSecurityManager* aSecMan = nullptr)
239 {
240 CHECK_PRINCIPAL_AND_DATA(ShouldProcess);
241 if (policyService) {
242 CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldProcess, policyService);
243 }
244 CHECK_CONTENT_POLICY(ShouldProcess);
245 }
247 #undef CHECK_CONTENT_POLICY
248 #undef CHECK_CONTENT_POLICY_WITH_SERVICE
250 /**
251 * Helper function to get an nsIDocShell given a context.
252 * If the context is a document or window, the corresponding docshell will be
253 * returned.
254 * If the context is a non-document DOM node, the docshell of its ownerDocument
255 * will be returned.
256 *
257 * @param aContext the context to find a docshell for (can be null)
258 *
259 * @return a WEAK pointer to the docshell, or nullptr if it could
260 * not be obtained
261 *
262 * @note As of this writing, calls to nsIContentPolicy::Should{Load,Process}
263 * for TYPE_DOCUMENT and TYPE_SUBDOCUMENT pass in an aContext that either
264 * points to the frameElement of the window the load is happening in
265 * (in which case NS_CP_GetDocShellFromContext will return the parent of the
266 * docshell the load is happening in), or points to the window the load is
267 * happening in (in which case NS_CP_GetDocShellFromContext will return
268 * the docshell the load is happening in). It's up to callers to QI aContext
269 * and handle things accordingly if they want the docshell the load is
270 * happening in. These are somewhat odd semantics, and bug 466687 has been
271 * filed to consider improving them.
272 */
273 inline nsIDocShell*
274 NS_CP_GetDocShellFromContext(nsISupports *aContext)
275 {
276 if (!aContext) {
277 return nullptr;
278 }
280 nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
282 if (!window) {
283 // our context might be a document (which also QIs to nsIDOMNode), so
284 // try that first
285 nsCOMPtr<nsIDocument> doc = do_QueryInterface(aContext);
286 if (!doc) {
287 // we were not a document after all, get our ownerDocument,
288 // hopefully
289 nsCOMPtr<nsIContent> content = do_QueryInterface(aContext);
290 if (content) {
291 doc = content->OwnerDoc();
292 }
293 }
295 if (doc) {
296 if (doc->GetDisplayDocument()) {
297 doc = doc->GetDisplayDocument();
298 }
300 window = doc->GetWindow();
301 }
302 }
304 if (!window) {
305 return nullptr;
306 }
308 return window->GetDocShell();
309 }
311 #endif /* __nsContentPolicyUtils_h__ */