Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/nsContentPolicy.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
// vim: ft=cpp tw=78 sw=4 et ts=8
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/*
8
 * Implementation of the "@mozilla.org/layout/content-policy;1" contract.
9
 */
10
11
#include "mozilla/Logging.h"
12
13
#include "nsISupports.h"
14
#include "nsXPCOM.h"
15
#include "nsContentPolicyUtils.h"
16
#include "mozilla/dom/nsCSPService.h"
17
#include "nsContentPolicy.h"
18
#include "nsIURI.h"
19
#include "nsIDocShell.h"
20
#include "nsIDOMWindow.h"
21
#include "nsITabChild.h"
22
#include "nsIContent.h"
23
#include "nsIImageLoadingContent.h"
24
#include "nsILoadContext.h"
25
#include "nsCOMArray.h"
26
#include "nsContentUtils.h"
27
#include "mozilla/dom/nsMixedContentBlocker.h"
28
#include "nsIContentSecurityPolicy.h"
29
#include "mozilla/dom/TabGroup.h"
30
#include "mozilla/TaskCategory.h"
31
32
using mozilla::LogLevel;
33
34
NS_IMPL_ISUPPORTS(nsContentPolicy, nsIContentPolicy)
35
36
static mozilla::LazyLogModule gConPolLog("nsContentPolicy");
37
38
nsresult
39
NS_NewContentPolicy(nsIContentPolicy **aResult)
40
1
{
41
1
  *aResult = new nsContentPolicy;
42
1
  NS_ADDREF(*aResult);
43
1
  return NS_OK;
44
1
}
45
46
nsContentPolicy::nsContentPolicy()
47
    : mPolicies(NS_CONTENTPOLICY_CATEGORY)
48
1
{
49
1
}
50
51
nsContentPolicy::~nsContentPolicy()
52
0
{
53
0
}
54
55
#ifdef DEBUG
56
#define WARN_IF_URI_UNINITIALIZED(uri,name)                         \
57
  PR_BEGIN_MACRO                                                    \
58
    if ((uri)) {                                                    \
59
        nsAutoCString spec;                                         \
60
        (uri)->GetAsciiSpec(spec);                                  \
61
        if (spec.IsEmpty()) {                                       \
62
            NS_WARNING(name " is uninitialized, fix caller");       \
63
        }                                                           \
64
    }                                                               \
65
  PR_END_MACRO
66
67
#else  // ! defined(DEBUG)
68
69
#define WARN_IF_URI_UNINITIALIZED(uri,name)
70
71
#endif // defined(DEBUG)
72
73
inline nsresult
74
nsContentPolicy::CheckPolicy(CPMethod          policyMethod,
75
                             nsIURI           *contentLocation,
76
                             nsILoadInfo      *loadInfo,
77
                             const nsACString &mimeType,
78
                             int16_t           *decision)
79
0
{
80
0
    nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
81
0
    nsCOMPtr<nsISupports> requestingContext = loadInfo->GetLoadingContext();
82
0
    nsCOMPtr<nsIPrincipal> requestPrincipal = loadInfo->TriggeringPrincipal();
83
0
    nsCOMPtr<nsIURI> requestingLocation;
84
0
    nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal();
85
0
    if (loadingPrincipal) {
86
0
      loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
87
0
    }
88
0
89
0
    //sanity-check passed-through parameters
90
0
    MOZ_ASSERT(decision, "Null out pointer");
91
0
    WARN_IF_URI_UNINITIALIZED(contentLocation, "Request URI");
92
0
    WARN_IF_URI_UNINITIALIZED(requestingLocation, "Requesting URI");
93
0
94
#ifdef DEBUG
95
    {
96
        nsCOMPtr<nsINode> node(do_QueryInterface(requestingContext));
97
        nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
98
        nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(requestingContext));
99
        NS_ASSERTION(!requestingContext || node || window || tabChild,
100
                     "Context should be a DOM node, DOM window or a tabChild!");
101
    }
102
#endif
103
104
0
    /*
105
0
     * There might not be a requestinglocation. This can happen for
106
0
     * iframes with an image as src. Get the uri from the dom node.
107
0
     * See bug 254510
108
0
     */
109
0
    if (!requestingLocation) {
110
0
        nsCOMPtr<nsIDocument> doc;
111
0
        nsCOMPtr<nsIContent> node = do_QueryInterface(requestingContext);
112
0
        if (node) {
113
0
            doc = node->OwnerDoc();
114
0
        }
115
0
        if (!doc) {
116
0
            doc = do_QueryInterface(requestingContext);
117
0
        }
118
0
        if (doc) {
119
0
            requestingLocation = doc->GetDocumentURI();
120
0
        }
121
0
    }
122
0
123
0
    nsContentPolicyType externalType =
124
0
        nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
125
0
126
0
    /*
127
0
     * Enumerate mPolicies and ask each of them, taking the logical AND of
128
0
     * their permissions.
129
0
     */
130
0
    nsresult rv;
131
0
    const nsCOMArray<nsIContentPolicy>& entries = mPolicies.GetCachedEntries();
132
0
133
0
    nsCOMPtr<nsPIDOMWindowOuter> window;
134
0
    if (nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext)) {
135
0
        window = node->OwnerDoc()->GetWindow();
136
0
    } else {
137
0
        window = do_QueryInterface(requestingContext);
138
0
    }
139
0
140
0
    if (requestPrincipal) {
141
0
        nsCOMPtr<nsIContentSecurityPolicy> csp;
142
0
        requestPrincipal->GetCsp(getter_AddRefs(csp));
143
0
        if (csp && window) {
144
0
            csp->EnsureEventTarget(window->EventTargetFor(mozilla::TaskCategory::Other));
145
0
        }
146
0
    }
147
0
148
0
    int32_t count = entries.Count();
149
0
    for (int32_t i = 0; i < count; i++) {
150
0
        /* check the appropriate policy */
151
0
        rv = (entries[i]->*policyMethod)(contentLocation, loadInfo,
152
0
                                         mimeType, decision);
153
0
154
0
        if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
155
0
            // If we are blocking an image, we have to let the
156
0
            // ImageLoadingContent know that we blocked the load.
157
0
            if (externalType == nsIContentPolicy::TYPE_IMAGE ||
158
0
                externalType == nsIContentPolicy::TYPE_IMAGESET) {
159
0
              nsCOMPtr<nsIImageLoadingContent> img =
160
0
                do_QueryInterface(requestingContext);
161
0
              if (img) {
162
0
                img->SetBlockedRequest(*decision);
163
0
              }
164
0
            }
165
0
            /* policy says no, no point continuing to check */
166
0
            return NS_OK;
167
0
        }
168
0
    }
169
0
170
0
    // everyone returned failure, or no policies: sanitize result
171
0
    *decision = nsIContentPolicy::ACCEPT;
172
0
    return NS_OK;
173
0
}
174
175
//uses the parameters from ShouldXYZ to produce and log a message
176
//logType must be a literal string constant
177
#define LOG_CHECK(logType)                                                     \
178
0
  PR_BEGIN_MACRO                                                               \
179
0
    nsCOMPtr<nsIURI> requestingLocation;                                       \
180
0
    nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal();    \
181
0
    if (loadingPrincipal) {                                                    \
182
0
      loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));            \
183
0
    }                                                                          \
184
0
    /* skip all this nonsense if the call failed or logging is disabled */     \
185
0
    if (NS_SUCCEEDED(rv) && MOZ_LOG_TEST(gConPolLog, LogLevel::Debug)) {       \
186
0
      const char *resultName;                                                  \
187
0
      if (decision) {                                                          \
188
0
        resultName = NS_CP_ResponseName(*decision);                            \
189
0
      } else {                                                                 \
190
0
        resultName = "(null ptr)";                                             \
191
0
      }                                                                        \
192
0
      MOZ_LOG(gConPolLog, LogLevel::Debug,                                     \
193
0
             ("Content Policy: " logType ": <%s> <Ref:%s> result=%s",          \
194
0
              contentLocation ? contentLocation->GetSpecOrDefault().get()      \
195
0
                              : "None",                                        \
196
0
              requestingLocation ? requestingLocation->GetSpecOrDefault().get()\
197
0
                                 : "None",                                     \
198
0
              resultName)                                                      \
199
0
             );                                                                \
200
0
    }                                                                          \
201
0
  PR_END_MACRO
202
203
NS_IMETHODIMP
204
nsContentPolicy::ShouldLoad(nsIURI           *contentLocation,
205
                            nsILoadInfo      *loadInfo,
206
                            const nsACString &mimeType,
207
                            int16_t          *decision)
208
0
{
209
0
    // ShouldProcess does not need a content location, but we do
210
0
    MOZ_ASSERT(contentLocation, "Must provide request location");
211
0
    nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldLoad,
212
0
                              contentLocation, loadInfo,
213
0
                              mimeType, decision);
214
0
    LOG_CHECK("ShouldLoad");
215
0
216
0
    return rv;
217
0
}
218
219
NS_IMETHODIMP
220
nsContentPolicy::ShouldProcess(nsIURI           *contentLocation,
221
                               nsILoadInfo      *loadInfo,
222
                               const nsACString &mimeType,
223
                               int16_t          *decision)
224
0
{
225
0
    nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldProcess,
226
0
                              contentLocation, loadInfo,
227
0
                              mimeType, decision);
228
0
    LOG_CHECK("ShouldProcess");
229
0
230
0
    return rv;
231
0
}