content/base/src/nsContentPolicy.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/src/nsContentPolicy.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,214 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +// vim: ft=cpp tw=78 sw=4 et ts=8
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* 
    1.11 + * Implementation of the "@mozilla.org/layout/content-policy;1" contract.
    1.12 + */
    1.13 +
    1.14 +#include "prlog.h"
    1.15 +
    1.16 +#include "nsISupports.h"
    1.17 +#include "nsXPCOM.h"
    1.18 +#include "nsContentPolicyUtils.h"
    1.19 +#include "nsContentPolicy.h"
    1.20 +#include "nsIURI.h"
    1.21 +#include "nsIDOMNode.h"
    1.22 +#include "nsIDOMWindow.h"
    1.23 +#include "nsIContent.h"
    1.24 +#include "nsCOMArray.h"
    1.25 +
    1.26 +NS_IMPL_ISUPPORTS(nsContentPolicy, nsIContentPolicy)
    1.27 +
    1.28 +#ifdef PR_LOGGING
    1.29 +static PRLogModuleInfo* gConPolLog;
    1.30 +#endif
    1.31 +
    1.32 +nsresult
    1.33 +NS_NewContentPolicy(nsIContentPolicy **aResult)
    1.34 +{
    1.35 +  *aResult = new nsContentPolicy;
    1.36 +  if (!*aResult)
    1.37 +      return NS_ERROR_OUT_OF_MEMORY;
    1.38 +  NS_ADDREF(*aResult);
    1.39 +  return NS_OK;
    1.40 +}
    1.41 +
    1.42 +nsContentPolicy::nsContentPolicy()
    1.43 +    : mPolicies(NS_CONTENTPOLICY_CATEGORY)
    1.44 +{
    1.45 +#ifdef PR_LOGGING
    1.46 +    if (! gConPolLog) {
    1.47 +        gConPolLog = PR_NewLogModule("nsContentPolicy");
    1.48 +    }
    1.49 +#endif
    1.50 +}
    1.51 +
    1.52 +nsContentPolicy::~nsContentPolicy()
    1.53 +{
    1.54 +}
    1.55 +
    1.56 +#ifdef DEBUG
    1.57 +#define WARN_IF_URI_UNINITIALIZED(uri,name)                         \
    1.58 +  PR_BEGIN_MACRO                                                    \
    1.59 +    if ((uri)) {                                                    \
    1.60 +        nsAutoCString spec;                                         \
    1.61 +        (uri)->GetAsciiSpec(spec);                                  \
    1.62 +        if (spec.IsEmpty()) {                                       \
    1.63 +            NS_WARNING(name " is uninitialized, fix caller");       \
    1.64 +        }                                                           \
    1.65 +    }                                                               \
    1.66 +  PR_END_MACRO
    1.67 +
    1.68 +#else  // ! defined(DEBUG)
    1.69 +
    1.70 +#define WARN_IF_URI_UNINITIALIZED(uri,name)
    1.71 +
    1.72 +#endif // defined(DEBUG)
    1.73 +
    1.74 +inline nsresult
    1.75 +nsContentPolicy::CheckPolicy(CPMethod          policyMethod,
    1.76 +                             uint32_t          contentType,
    1.77 +                             nsIURI           *contentLocation,
    1.78 +                             nsIURI           *requestingLocation,
    1.79 +                             nsISupports      *requestingContext,
    1.80 +                             const nsACString &mimeType,
    1.81 +                             nsISupports      *extra,
    1.82 +                             nsIPrincipal     *requestPrincipal,
    1.83 +                             int16_t           *decision)
    1.84 +{
    1.85 +    //sanity-check passed-through parameters
    1.86 +    NS_PRECONDITION(decision, "Null out pointer");
    1.87 +    WARN_IF_URI_UNINITIALIZED(contentLocation, "Request URI");
    1.88 +    WARN_IF_URI_UNINITIALIZED(requestingLocation, "Requesting URI");
    1.89 +
    1.90 +#ifdef DEBUG
    1.91 +    {
    1.92 +        nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext));
    1.93 +        nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
    1.94 +        NS_ASSERTION(!requestingContext || node || window,
    1.95 +                     "Context should be a DOM node or a DOM window!");
    1.96 +    }
    1.97 +#endif
    1.98 +
    1.99 +    /*
   1.100 +     * There might not be a requestinglocation. This can happen for
   1.101 +     * iframes with an image as src. Get the uri from the dom node.
   1.102 +     * See bug 254510
   1.103 +     */
   1.104 +    if (!requestingLocation) {
   1.105 +        nsCOMPtr<nsIDocument> doc;
   1.106 +        nsCOMPtr<nsIContent> node = do_QueryInterface(requestingContext);
   1.107 +        if (node) {
   1.108 +            doc = node->OwnerDoc();
   1.109 +        }
   1.110 +        if (!doc) {
   1.111 +            doc = do_QueryInterface(requestingContext);
   1.112 +        }
   1.113 +        if (doc) {
   1.114 +            requestingLocation = doc->GetDocumentURI();
   1.115 +        }
   1.116 +    }
   1.117 +
   1.118 +    /* 
   1.119 +     * Enumerate mPolicies and ask each of them, taking the logical AND of
   1.120 +     * their permissions.
   1.121 +     */
   1.122 +    nsresult rv;
   1.123 +    nsCOMArray<nsIContentPolicy> entries;
   1.124 +    mPolicies.GetEntries(entries);
   1.125 +    int32_t count = entries.Count();
   1.126 +    for (int32_t i = 0; i < count; i++) {
   1.127 +        /* check the appropriate policy */
   1.128 +        rv = (entries[i]->*policyMethod)(contentType, contentLocation,
   1.129 +                                         requestingLocation, requestingContext,
   1.130 +                                         mimeType, extra, requestPrincipal,
   1.131 +                                         decision);
   1.132 +
   1.133 +        if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
   1.134 +            /* policy says no, no point continuing to check */
   1.135 +            return NS_OK;
   1.136 +        }
   1.137 +    }
   1.138 +
   1.139 +    // everyone returned failure, or no policies: sanitize result
   1.140 +    *decision = nsIContentPolicy::ACCEPT;
   1.141 +    return NS_OK;
   1.142 +}
   1.143 +
   1.144 +#ifdef PR_LOGGING
   1.145 +
   1.146 +//uses the parameters from ShouldXYZ to produce and log a message
   1.147 +//logType must be a literal string constant
   1.148 +#define LOG_CHECK(logType)                                                    \
   1.149 +  PR_BEGIN_MACRO                                                              \
   1.150 +    /* skip all this nonsense if the call failed */                           \
   1.151 +    if (NS_SUCCEEDED(rv)) {                                                   \
   1.152 +      const char *resultName;                                                 \
   1.153 +      if (decision) {                                                         \
   1.154 +        resultName = NS_CP_ResponseName(*decision);                           \
   1.155 +      } else {                                                                \
   1.156 +        resultName = "(null ptr)";                                            \
   1.157 +      }                                                                       \
   1.158 +      nsAutoCString spec("None");                                             \
   1.159 +      if (contentLocation) {                                                  \
   1.160 +          contentLocation->GetSpec(spec);                                     \
   1.161 +      }                                                                       \
   1.162 +      nsAutoCString refSpec("None");                                          \
   1.163 +      if (requestingLocation) {                                               \
   1.164 +          requestingLocation->GetSpec(refSpec);                               \
   1.165 +      }                                                                       \
   1.166 +      PR_LOG(gConPolLog, PR_LOG_DEBUG,                                        \
   1.167 +             ("Content Policy: " logType ": <%s> <Ref:%s> result=%s",         \
   1.168 +              spec.get(), refSpec.get(), resultName)                          \
   1.169 +             );                                                               \
   1.170 +    }                                                                         \
   1.171 +  PR_END_MACRO
   1.172 +
   1.173 +#else //!defined(PR_LOGGING)
   1.174 +
   1.175 +#define LOG_CHECK(logType)
   1.176 +
   1.177 +#endif //!defined(PR_LOGGING)
   1.178 +
   1.179 +NS_IMETHODIMP
   1.180 +nsContentPolicy::ShouldLoad(uint32_t          contentType,
   1.181 +                            nsIURI           *contentLocation,
   1.182 +                            nsIURI           *requestingLocation,
   1.183 +                            nsISupports      *requestingContext,
   1.184 +                            const nsACString &mimeType,
   1.185 +                            nsISupports      *extra,
   1.186 +                            nsIPrincipal     *requestPrincipal,
   1.187 +                            int16_t          *decision)
   1.188 +{
   1.189 +    // ShouldProcess does not need a content location, but we do
   1.190 +    NS_PRECONDITION(contentLocation, "Must provide request location");
   1.191 +    nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldLoad, contentType,
   1.192 +                              contentLocation, requestingLocation,
   1.193 +                              requestingContext, mimeType, extra,
   1.194 +                              requestPrincipal, decision);
   1.195 +    LOG_CHECK("ShouldLoad");
   1.196 +
   1.197 +    return rv;
   1.198 +}
   1.199 +
   1.200 +NS_IMETHODIMP
   1.201 +nsContentPolicy::ShouldProcess(uint32_t          contentType,
   1.202 +                               nsIURI           *contentLocation,
   1.203 +                               nsIURI           *requestingLocation,
   1.204 +                               nsISupports      *requestingContext,
   1.205 +                               const nsACString &mimeType,
   1.206 +                               nsISupports      *extra,
   1.207 +                               nsIPrincipal     *requestPrincipal,
   1.208 +                               int16_t          *decision)
   1.209 +{
   1.210 +    nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldProcess, contentType,
   1.211 +                              contentLocation, requestingLocation,
   1.212 +                              requestingContext, mimeType, extra,
   1.213 +                              requestPrincipal, decision);
   1.214 +    LOG_CHECK("ShouldProcess");
   1.215 +
   1.216 +    return rv;
   1.217 +}

mercurial