content/base/public/nsContentPolicyUtils.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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__ */

mercurial