content/base/public/nsContentPolicyUtils.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/public/nsContentPolicyUtils.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,311 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * Utility routines for checking content load/process policy settings,
    1.11 + * and routines helpful for content policy implementors.
    1.12 + *
    1.13 + * XXXbz it would be nice if some of this stuff could be out-of-lined in
    1.14 + * nsContentUtils.  That would work for almost all the callers...
    1.15 + */
    1.16 +
    1.17 +#ifndef __nsContentPolicyUtils_h__
    1.18 +#define __nsContentPolicyUtils_h__
    1.19 +
    1.20 +#include "nsIContentPolicy.h"
    1.21 +#include "nsIContent.h"
    1.22 +#include "nsIScriptSecurityManager.h"
    1.23 +#include "nsIURI.h"
    1.24 +#include "nsServiceManagerUtils.h"
    1.25 +
    1.26 +//XXXtw sadly, this makes consumers of nsContentPolicyUtils depend on widget
    1.27 +#include "nsIDocument.h"
    1.28 +#include "nsPIDOMWindow.h"
    1.29 +
    1.30 +class nsACString;
    1.31 +class nsIPrincipal;
    1.32 +
    1.33 +#define NS_CONTENTPOLICY_CONTRACTID   "@mozilla.org/layout/content-policy;1"
    1.34 +#define NS_CONTENTPOLICY_CATEGORY "content-policy"
    1.35 +#define NS_CONTENTPOLICY_CID                              \
    1.36 +  {0x0e3afd3d, 0xeb60, 0x4c2b,                            \
    1.37 +     { 0x96, 0x3b, 0x56, 0xd7, 0xc4, 0x39, 0xf1, 0x24 }}
    1.38 +
    1.39 +/**
    1.40 + * Evaluates to true if val is ACCEPT.
    1.41 + *
    1.42 + * @param val the status returned from shouldProcess/shouldLoad
    1.43 + */
    1.44 +#define NS_CP_ACCEPTED(val) ((val) == nsIContentPolicy::ACCEPT)
    1.45 +
    1.46 +/**
    1.47 + * Evaluates to true if val is a REJECT_* status
    1.48 + *
    1.49 + * @param val the status returned from shouldProcess/shouldLoad
    1.50 + */
    1.51 +#define NS_CP_REJECTED(val) ((val) != nsIContentPolicy::ACCEPT)
    1.52 +
    1.53 +// Offer convenient translations of constants -> const char*
    1.54 +
    1.55 +// convenience macro to reduce some repetative typing...
    1.56 +// name is the name of a constant from this interface
    1.57 +#define CASE_RETURN(name)          \
    1.58 +  case nsIContentPolicy:: name :   \
    1.59 +    return #name
    1.60 +
    1.61 +#ifdef PR_LOGGING
    1.62 +/**
    1.63 + * Returns a string corresponding to the name of the response constant, or
    1.64 + * "<Unknown Response>" if an unknown response value is given.
    1.65 + *
    1.66 + * The return value is static and must not be freed.
    1.67 + *
    1.68 + * @param response the response code
    1.69 + * @return the name of the given response code
    1.70 + */
    1.71 +inline const char *
    1.72 +NS_CP_ResponseName(int16_t response)
    1.73 +{
    1.74 +  switch (response) {
    1.75 +    CASE_RETURN( REJECT_REQUEST );
    1.76 +    CASE_RETURN( REJECT_TYPE    );
    1.77 +    CASE_RETURN( REJECT_SERVER  );
    1.78 +    CASE_RETURN( REJECT_OTHER   );
    1.79 +    CASE_RETURN( ACCEPT         );
    1.80 +  default:
    1.81 +    return "<Unknown Response>";
    1.82 +  }
    1.83 +}
    1.84 +
    1.85 +/**
    1.86 + * Returns a string corresponding to the name of the content type constant, or
    1.87 + * "<Unknown Type>" if an unknown content type value is given.
    1.88 + *
    1.89 + * The return value is static and must not be freed.
    1.90 + *
    1.91 + * @param contentType the content type code
    1.92 + * @return the name of the given content type code
    1.93 + */
    1.94 +inline const char *
    1.95 +NS_CP_ContentTypeName(uint32_t contentType)
    1.96 +{
    1.97 +  switch (contentType) {
    1.98 +    CASE_RETURN( TYPE_OTHER             );
    1.99 +    CASE_RETURN( TYPE_SCRIPT            );
   1.100 +    CASE_RETURN( TYPE_IMAGE             );
   1.101 +    CASE_RETURN( TYPE_STYLESHEET        );
   1.102 +    CASE_RETURN( TYPE_OBJECT            );
   1.103 +    CASE_RETURN( TYPE_DOCUMENT          );
   1.104 +    CASE_RETURN( TYPE_SUBDOCUMENT       );
   1.105 +    CASE_RETURN( TYPE_REFRESH           );
   1.106 +    CASE_RETURN( TYPE_XBL               );
   1.107 +    CASE_RETURN( TYPE_PING              );
   1.108 +    CASE_RETURN( TYPE_XMLHTTPREQUEST    );
   1.109 +    CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
   1.110 +    CASE_RETURN( TYPE_DTD               );
   1.111 +    CASE_RETURN( TYPE_FONT              );
   1.112 +    CASE_RETURN( TYPE_MEDIA             );
   1.113 +    CASE_RETURN( TYPE_WEBSOCKET         );
   1.114 +    CASE_RETURN( TYPE_CSP_REPORT        );
   1.115 +    CASE_RETURN( TYPE_XSLT              );
   1.116 +    CASE_RETURN( TYPE_BEACON            );
   1.117 +   default:
   1.118 +    return "<Unknown Type>";
   1.119 +  }
   1.120 +}
   1.121 +
   1.122 +#endif // defined(PR_LOGGING)
   1.123 +
   1.124 +#undef CASE_RETURN
   1.125 +
   1.126 +/* Passes on parameters from its "caller"'s context. */
   1.127 +#define CHECK_CONTENT_POLICY(action)                                          \
   1.128 +  PR_BEGIN_MACRO                                                              \
   1.129 +    nsCOMPtr<nsIContentPolicy> policy =                                       \
   1.130 +         do_GetService(NS_CONTENTPOLICY_CONTRACTID);                          \
   1.131 +    if (!policy)                                                              \
   1.132 +        return NS_ERROR_FAILURE;                                              \
   1.133 +                                                                              \
   1.134 +    return policy-> action (contentType, contentLocation, requestOrigin,      \
   1.135 +                            context, mimeType, extra, originPrincipal,        \
   1.136 +                            decision);                                        \
   1.137 +  PR_END_MACRO
   1.138 +
   1.139 +/* Passes on parameters from its "caller"'s context. */
   1.140 +#define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy)                    \
   1.141 +  PR_BEGIN_MACRO                                                              \
   1.142 +    return _policy-> action (contentType, contentLocation, requestOrigin,     \
   1.143 +                             context, mimeType, extra, originPrincipal,       \
   1.144 +                             decision);                                       \
   1.145 +  PR_END_MACRO
   1.146 +
   1.147 +/**
   1.148 + * Check whether we can short-circuit this check and bail out.  If not, get the
   1.149 + * origin URI to use.
   1.150 + *
   1.151 + * Note: requestOrigin is scoped outside the PR_BEGIN_MACRO/PR_END_MACRO on
   1.152 + * purpose */
   1.153 +#define CHECK_PRINCIPAL_AND_DATA(action)                                      \
   1.154 +  nsCOMPtr<nsIURI> requestOrigin;                                             \
   1.155 +  PR_BEGIN_MACRO                                                              \
   1.156 +  if (originPrincipal) {                                                      \
   1.157 +      nsCOMPtr<nsIScriptSecurityManager> secMan = aSecMan;                    \
   1.158 +      if (!secMan) {                                                          \
   1.159 +          secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);        \
   1.160 +      }                                                                       \
   1.161 +      if (secMan) {                                                           \
   1.162 +          bool isSystem;                                                      \
   1.163 +          nsresult rv = secMan->IsSystemPrincipal(originPrincipal,            \
   1.164 +                                                  &isSystem);                 \
   1.165 +          NS_ENSURE_SUCCESS(rv, rv);                                          \
   1.166 +          if (isSystem) {                                                     \
   1.167 +              *decision = nsIContentPolicy::ACCEPT;                           \
   1.168 +              nsCOMPtr<nsINode> n = do_QueryInterface(context);               \
   1.169 +              if (!n) {                                                       \
   1.170 +                  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(context);   \
   1.171 +                  n = win ? win->GetExtantDoc() : nullptr;                    \
   1.172 +              }                                                               \
   1.173 +              if (n) {                                                        \
   1.174 +                  nsIDocument* d = n->OwnerDoc();                             \
   1.175 +                  if (d->IsLoadedAsData() || d->IsBeingUsedAsImage() ||       \
   1.176 +                      d->IsResourceDoc()) {                                   \
   1.177 +                      nsCOMPtr<nsIContentPolicy> dataPolicy =                 \
   1.178 +                          do_GetService(                                      \
   1.179 +                              "@mozilla.org/data-document-content-policy;1"); \
   1.180 +                      if (dataPolicy) {                                       \
   1.181 +                          dataPolicy-> action (contentType, contentLocation,  \
   1.182 +                                               requestOrigin, context,        \
   1.183 +                                               mimeType, extra,               \
   1.184 +                                               originPrincipal, decision);    \
   1.185 +                      }                                                       \
   1.186 +                  }                                                           \
   1.187 +              }                                                               \
   1.188 +              return NS_OK;                                                   \
   1.189 +          }                                                                   \
   1.190 +      }                                                                       \
   1.191 +      nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin));   \
   1.192 +      NS_ENSURE_SUCCESS(rv, rv);                                              \
   1.193 +  }                                                                           \
   1.194 +  PR_END_MACRO
   1.195 +
   1.196 +/**
   1.197 + * Alias for calling ShouldLoad on the content policy service.  Parameters are
   1.198 + * the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
   1.199 + * parameter, which should be non-null if possible, and the last two
   1.200 + * parameters, which can be used to pass in pointer to some useful services if
   1.201 + * the caller already has them.  The origin URI to pass to shouldLoad will be
   1.202 + * the URI of originPrincipal, unless originPrincipal is null (in which case a
   1.203 + * null origin URI will be passed).
   1.204 + */
   1.205 +inline nsresult
   1.206 +NS_CheckContentLoadPolicy(uint32_t          contentType,
   1.207 +                          nsIURI           *contentLocation,
   1.208 +                          nsIPrincipal     *originPrincipal,
   1.209 +                          nsISupports      *context,
   1.210 +                          const nsACString &mimeType,
   1.211 +                          nsISupports      *extra,
   1.212 +                          int16_t          *decision,
   1.213 +                          nsIContentPolicy *policyService = nullptr,
   1.214 +                          nsIScriptSecurityManager* aSecMan = nullptr)
   1.215 +{
   1.216 +    CHECK_PRINCIPAL_AND_DATA(ShouldLoad);
   1.217 +    if (policyService) {
   1.218 +        CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldLoad, policyService);
   1.219 +    }
   1.220 +    CHECK_CONTENT_POLICY(ShouldLoad);
   1.221 +}
   1.222 +
   1.223 +/**
   1.224 + * Alias for calling ShouldProcess on the content policy service.  Parameters
   1.225 + * are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
   1.226 + * parameter, which should be non-null if possible, and the last two
   1.227 + * parameters, which can be used to pass in pointer to some useful services if
   1.228 + * the caller already has them.  The origin URI to pass to shouldLoad will be
   1.229 + * the URI of originPrincipal, unless originPrincipal is null (in which case a
   1.230 + * null origin URI will be passed).
   1.231 + */
   1.232 +inline nsresult
   1.233 +NS_CheckContentProcessPolicy(uint32_t          contentType,
   1.234 +                             nsIURI           *contentLocation,
   1.235 +                             nsIPrincipal     *originPrincipal,
   1.236 +                             nsISupports      *context,
   1.237 +                             const nsACString &mimeType,
   1.238 +                             nsISupports      *extra,
   1.239 +                             int16_t          *decision,
   1.240 +                             nsIContentPolicy *policyService = nullptr,
   1.241 +                             nsIScriptSecurityManager* aSecMan = nullptr)
   1.242 +{
   1.243 +    CHECK_PRINCIPAL_AND_DATA(ShouldProcess);
   1.244 +    if (policyService) {
   1.245 +        CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldProcess, policyService);
   1.246 +    }
   1.247 +    CHECK_CONTENT_POLICY(ShouldProcess);
   1.248 +}
   1.249 +
   1.250 +#undef CHECK_CONTENT_POLICY
   1.251 +#undef CHECK_CONTENT_POLICY_WITH_SERVICE
   1.252 +
   1.253 +/**
   1.254 + * Helper function to get an nsIDocShell given a context.
   1.255 + * If the context is a document or window, the corresponding docshell will be
   1.256 + * returned.
   1.257 + * If the context is a non-document DOM node, the docshell of its ownerDocument
   1.258 + * will be returned.
   1.259 + *
   1.260 + * @param aContext the context to find a docshell for (can be null)
   1.261 + *
   1.262 + * @return a WEAK pointer to the docshell, or nullptr if it could
   1.263 + *     not be obtained
   1.264 + *     
   1.265 + * @note  As of this writing, calls to nsIContentPolicy::Should{Load,Process}
   1.266 + * for TYPE_DOCUMENT and TYPE_SUBDOCUMENT pass in an aContext that either
   1.267 + * points to the frameElement of the window the load is happening in
   1.268 + * (in which case NS_CP_GetDocShellFromContext will return the parent of the
   1.269 + * docshell the load is happening in), or points to the window the load is
   1.270 + * happening in (in which case NS_CP_GetDocShellFromContext will return
   1.271 + * the docshell the load is happening in).  It's up to callers to QI aContext
   1.272 + * and handle things accordingly if they want the docshell the load is
   1.273 + * happening in.  These are somewhat odd semantics, and bug 466687 has been
   1.274 + * filed to consider improving them.
   1.275 + */
   1.276 +inline nsIDocShell*
   1.277 +NS_CP_GetDocShellFromContext(nsISupports *aContext)
   1.278 +{
   1.279 +    if (!aContext) {
   1.280 +        return nullptr;
   1.281 +    }
   1.282 +
   1.283 +    nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
   1.284 +
   1.285 +    if (!window) {
   1.286 +        // our context might be a document (which also QIs to nsIDOMNode), so
   1.287 +        // try that first
   1.288 +        nsCOMPtr<nsIDocument> doc = do_QueryInterface(aContext);
   1.289 +        if (!doc) {
   1.290 +            // we were not a document after all, get our ownerDocument,
   1.291 +            // hopefully
   1.292 +            nsCOMPtr<nsIContent> content = do_QueryInterface(aContext);
   1.293 +            if (content) {
   1.294 +                doc = content->OwnerDoc();
   1.295 +            }
   1.296 +        }
   1.297 +
   1.298 +        if (doc) {
   1.299 +            if (doc->GetDisplayDocument()) {
   1.300 +                doc = doc->GetDisplayDocument();
   1.301 +            }
   1.302 +            
   1.303 +            window = doc->GetWindow();
   1.304 +        }
   1.305 +    }
   1.306 +
   1.307 +    if (!window) {
   1.308 +        return nullptr;
   1.309 +    }
   1.310 +
   1.311 +    return window->GetDocShell();
   1.312 +}
   1.313 +
   1.314 +#endif /* __nsContentPolicyUtils_h__ */

mercurial