content/base/public/nsContentPolicyUtils.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial