1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Zero-Knowledge Systems, Inc.
19 : * Portions created by the Initial Developer are Copyright (C) 2000
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Timothy Watt <riceman+moz@mail.rit.edu>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : /*
40 : * Utility routines for checking content load/process policy settings,
41 : * and routines helpful for content policy implementors.
42 : *
43 : * XXXbz it would be nice if some of this stuff could be out-of-lined in
44 : * nsContentUtils. That would work for almost all the callers...
45 : */
46 :
47 : #ifndef __nsContentPolicyUtils_h__
48 : #define __nsContentPolicyUtils_h__
49 :
50 : #include "nsIContentPolicy.h"
51 : #include "nsIServiceManager.h"
52 : #include "nsIContent.h"
53 : #include "nsIScriptSecurityManager.h"
54 : #include "nsIPrincipal.h"
55 :
56 : //XXXtw sadly, this makes consumers of nsContentPolicyUtils depend on widget
57 : #include "nsIDocument.h"
58 : #include "nsPIDOMWindow.h"
59 :
60 : class nsACString;
61 :
62 : #define NS_CONTENTPOLICY_CONTRACTID "@mozilla.org/layout/content-policy;1"
63 : #define NS_CONTENTPOLICY_CATEGORY "content-policy"
64 : #define NS_CONTENTPOLICY_CID \
65 : {0x0e3afd3d, 0xeb60, 0x4c2b, \
66 : { 0x96, 0x3b, 0x56, 0xd7, 0xc4, 0x39, 0xf1, 0x24 }}
67 :
68 : /**
69 : * Evaluates to true if val is ACCEPT.
70 : *
71 : * @param val the status returned from shouldProcess/shouldLoad
72 : */
73 : #define NS_CP_ACCEPTED(val) ((val) == nsIContentPolicy::ACCEPT)
74 :
75 : /**
76 : * Evaluates to true if val is a REJECT_* status
77 : *
78 : * @param val the status returned from shouldProcess/shouldLoad
79 : */
80 : #define NS_CP_REJECTED(val) ((val) != nsIContentPolicy::ACCEPT)
81 :
82 : // Offer convenient translations of constants -> const char*
83 :
84 : // convenience macro to reduce some repetative typing...
85 : // name is the name of a constant from this interface
86 : #define CASE_RETURN(name) \
87 : case nsIContentPolicy:: name : \
88 : return #name
89 :
90 : #ifdef PR_LOGGING
91 : /**
92 : * Returns a string corresponding to the name of the response constant, or
93 : * "<Unknown Response>" if an unknown response value is given.
94 : *
95 : * The return value is static and must not be freed.
96 : *
97 : * @param response the response code
98 : * @return the name of the given response code
99 : */
100 : inline const char *
101 10 : NS_CP_ResponseName(PRInt16 response)
102 : {
103 10 : switch (response) {
104 0 : CASE_RETURN( REJECT_REQUEST );
105 0 : CASE_RETURN( REJECT_TYPE );
106 0 : CASE_RETURN( REJECT_SERVER );
107 0 : CASE_RETURN( REJECT_OTHER );
108 10 : CASE_RETURN( ACCEPT );
109 : default:
110 0 : return "<Unknown Response>";
111 : }
112 : }
113 :
114 : /**
115 : * Returns a string corresponding to the name of the content type constant, or
116 : * "<Unknown Type>" if an unknown content type value is given.
117 : *
118 : * The return value is static and must not be freed.
119 : *
120 : * @param contentType the content type code
121 : * @return the name of the given content type code
122 : */
123 : inline const char *
124 : NS_CP_ContentTypeName(PRUint32 contentType)
125 : {
126 : switch (contentType) {
127 : CASE_RETURN( TYPE_OTHER );
128 : CASE_RETURN( TYPE_SCRIPT );
129 : CASE_RETURN( TYPE_IMAGE );
130 : CASE_RETURN( TYPE_STYLESHEET );
131 : CASE_RETURN( TYPE_OBJECT );
132 : CASE_RETURN( TYPE_DOCUMENT );
133 : CASE_RETURN( TYPE_SUBDOCUMENT );
134 : CASE_RETURN( TYPE_REFRESH );
135 : CASE_RETURN( TYPE_XBL );
136 : CASE_RETURN( TYPE_PING );
137 : CASE_RETURN( TYPE_XMLHTTPREQUEST );
138 : CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
139 : CASE_RETURN( TYPE_DTD );
140 : CASE_RETURN( TYPE_FONT );
141 : CASE_RETURN( TYPE_MEDIA );
142 : CASE_RETURN( TYPE_WEBSOCKET );
143 : default:
144 : return "<Unknown Type>";
145 : }
146 : }
147 :
148 : #endif // defined(PR_LOGGING)
149 :
150 : #undef CASE_RETURN
151 :
152 : /* Passes on parameters from its "caller"'s context. */
153 : #define CHECK_CONTENT_POLICY(action) \
154 : PR_BEGIN_MACRO \
155 : nsCOMPtr<nsIContentPolicy> policy = \
156 : do_GetService(NS_CONTENTPOLICY_CONTRACTID); \
157 : if (!policy) \
158 : return NS_ERROR_FAILURE; \
159 : \
160 : return policy-> action (contentType, contentLocation, requestOrigin, \
161 : context, mimeType, extra, decision); \
162 : PR_END_MACRO
163 :
164 : /* Passes on parameters from its "caller"'s context. */
165 : #define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \
166 : PR_BEGIN_MACRO \
167 : return _policy-> action (contentType, contentLocation, requestOrigin, \
168 : context, mimeType, extra, decision); \
169 : PR_END_MACRO
170 :
171 : /**
172 : * Check whether we can short-circuit this check and bail out. If not, get the
173 : * origin URI to use.
174 : *
175 : * Note: requestOrigin is scoped outside the PR_BEGIN_MACRO/PR_END_MACRO on
176 : * purpose */
177 : #define CHECK_PRINCIPAL \
178 : nsCOMPtr<nsIURI> requestOrigin; \
179 : PR_BEGIN_MACRO \
180 : if (originPrincipal) { \
181 : nsCOMPtr<nsIScriptSecurityManager> secMan = aSecMan; \
182 : if (!secMan) { \
183 : secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); \
184 : } \
185 : if (secMan) { \
186 : bool isSystem; \
187 : nsresult rv = secMan->IsSystemPrincipal(originPrincipal, \
188 : &isSystem); \
189 : NS_ENSURE_SUCCESS(rv, rv); \
190 : if (isSystem) { \
191 : *decision = nsIContentPolicy::ACCEPT; \
192 : return NS_OK; \
193 : } \
194 : } \
195 : nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin)); \
196 : NS_ENSURE_SUCCESS(rv, rv); \
197 : } \
198 : PR_END_MACRO
199 :
200 : /**
201 : * Alias for calling ShouldLoad on the content policy service. Parameters are
202 : * the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
203 : * parameter, which should be non-null if possible, and the last two
204 : * parameters, which can be used to pass in pointer to some useful services if
205 : * the caller already has them. The origin URI to pass to shouldLoad will be
206 : * the URI of originPrincipal, unless originPrincipal is null (in which case a
207 : * null origin URI will be passed).
208 : */
209 : inline nsresult
210 608 : NS_CheckContentLoadPolicy(PRUint32 contentType,
211 : nsIURI *contentLocation,
212 : nsIPrincipal *originPrincipal,
213 : nsISupports *context,
214 : const nsACString &mimeType,
215 : nsISupports *extra,
216 : PRInt16 *decision,
217 : nsIContentPolicy *policyService = nsnull,
218 : nsIScriptSecurityManager* aSecMan = nsnull)
219 : {
220 1216 : CHECK_PRINCIPAL;
221 10 : if (policyService) {
222 0 : CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldLoad, policyService);
223 : }
224 10 : CHECK_CONTENT_POLICY(ShouldLoad);
225 : }
226 :
227 : /**
228 : * Alias for calling ShouldProcess on the content policy service. Parameters
229 : * are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
230 : * parameter, which should be non-null if possible, and the last two
231 : * parameters, which can be used to pass in pointer to some useful services if
232 : * the caller already has them. The origin URI to pass to shouldLoad will be
233 : * the URI of originPrincipal, unless originPrincipal is null (in which case a
234 : * null origin URI will be passed).
235 : */
236 : inline nsresult
237 0 : NS_CheckContentProcessPolicy(PRUint32 contentType,
238 : nsIURI *contentLocation,
239 : nsIPrincipal *originPrincipal,
240 : nsISupports *context,
241 : const nsACString &mimeType,
242 : nsISupports *extra,
243 : PRInt16 *decision,
244 : nsIContentPolicy *policyService = nsnull,
245 : nsIScriptSecurityManager* aSecMan = nsnull)
246 : {
247 0 : CHECK_PRINCIPAL;
248 0 : if (policyService) {
249 0 : CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldProcess, policyService);
250 : }
251 0 : CHECK_CONTENT_POLICY(ShouldProcess);
252 : }
253 :
254 : #undef CHECK_CONTENT_POLICY
255 : #undef CHECK_CONTENT_POLICY_WITH_SERVICE
256 :
257 : /**
258 : * Helper function to get an nsIDocShell given a context.
259 : * If the context is a document or window, the corresponding docshell will be
260 : * returned.
261 : * If the context is a non-document DOM node, the docshell of its ownerDocument
262 : * will be returned.
263 : *
264 : * @param aContext the context to find a docshell for (can be null)
265 : *
266 : * @return a WEAK pointer to the docshell, or nsnull if it could
267 : * not be obtained
268 : *
269 : * @note As of this writing, calls to nsIContentPolicy::Should{Load,Process}
270 : * for TYPE_DOCUMENT and TYPE_SUBDOCUMENT pass in an aContext that either
271 : * points to the frameElement of the window the load is happening in
272 : * (in which case NS_CP_GetDocShellFromContext will return the parent of the
273 : * docshell the load is happening in), or points to the window the load is
274 : * happening in (in which case NS_CP_GetDocShellFromContext will return
275 : * the docshell the load is happening in). It's up to callers to QI aContext
276 : * and handle things accordingly if they want the docshell the load is
277 : * happening in. These are somewhat odd semantics, and bug 466687 has been
278 : * filed to consider improving them.
279 : */
280 : inline nsIDocShell*
281 10 : NS_CP_GetDocShellFromContext(nsISupports *aContext)
282 : {
283 10 : if (!aContext) {
284 2 : return nsnull;
285 : }
286 :
287 16 : nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
288 :
289 8 : if (!window) {
290 : // our context might be a document (which also QIs to nsIDOMNode), so
291 : // try that first
292 16 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(aContext);
293 8 : if (!doc) {
294 : // we were not a document after all, get our ownerDocument,
295 : // hopefully
296 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(aContext);
297 0 : if (content) {
298 0 : doc = content->OwnerDoc();
299 : }
300 : }
301 :
302 8 : if (doc) {
303 8 : if (doc->GetDisplayDocument()) {
304 0 : doc = doc->GetDisplayDocument();
305 : }
306 :
307 8 : window = doc->GetWindow();
308 : }
309 : }
310 :
311 8 : if (!window) {
312 8 : return nsnull;
313 : }
314 :
315 0 : return window->GetDocShell();
316 : }
317 :
318 : #endif /* __nsContentPolicyUtils_h__ */
|