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
/* ***** BEGIN LICENSE BLOCK *****
4
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 1.1 (the "License"); you may not use this file except in compliance with
8
* the License. You may obtain a copy of the License at
9
* http://www.mozilla.org/MPL/
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
16
* The Original Code is Mozilla code.
18
* The Initial Developer of the Original Code is
19
* Zero-Knowledge Systems, Inc.
20
* Portions created by the Initial Developer are Copyright (C) 2000
21
* the Initial Developer. All Rights Reserved.
25
* Alternatively, the contents of this file may be used under the terms of
26
* either of the GNU General Public License Version 2 or later (the "GPL"),
27
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the MPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the MPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
41
#include "nsISupports.h"
43
#include "nsISupportsPrimitives.h"
44
#include "nsXPIDLString.h"
45
#include "nsContentPolicyUtils.h"
46
#include "nsContentPolicy.h"
47
#include "nsICategoryManager.h"
49
#include "nsIDOMNode.h"
50
#include "nsIDOMWindow.h"
52
NS_IMPL_ISUPPORTS1(nsContentPolicy, nsIContentPolicy)
55
static PRLogModuleInfo* gConPolLog;
59
NS_NewContentPolicy(nsIContentPolicy **aResult)
61
*aResult = new nsContentPolicy;
63
return NS_ERROR_OUT_OF_MEMORY;
69
* This constructor does far too much. I wish there was a way to get
70
* an Init method called by the service manager after the factory
71
* returned the new object, so that errors could be propagated back to
72
* the caller correctly.
74
nsContentPolicy::nsContentPolicy()
78
gConPolLog = PR_NewLogModule("nsContentPolicy");
82
nsCOMPtr<nsICategoryManager> catman =
83
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
85
return; /* log an error? */
88
* I'd like to use GetCategoryContents, so that I can size the array
89
* correctly on the first go and avoid the enumerator overhead, but it's
90
* not yet implemented (see nsCategoryManager.cpp). No biggie, I guess.
92
nsCOMPtr<nsISimpleEnumerator> catEnum;
93
rv = catman->EnumerateCategory(NS_CONTENTPOLICY_CATEGORY,
94
getter_AddRefs(catEnum));
96
return; /* no category, no problem */
99
if (NS_FAILED(catEnum->HasMoreElements(&hasMore)) || !hasMore)
103
* Populate mPolicies with policy services named by contractids in the
104
* "content-policy" category.
106
nsCOMPtr<nsISupports> item;
107
while (NS_SUCCEEDED(catEnum->GetNext(getter_AddRefs(item)))) {
108
nsCOMPtr<nsISupportsCString> string = do_QueryInterface(item, &rv);
112
nsCAutoString contractid;
113
if (NS_FAILED(string->GetData(contractid)))
116
PR_LOG(gConPolLog, PR_LOG_DEBUG,
117
("POLICY: loading %s\n", contractid.get()));
120
* Create this policy service and add to mPolicies.
122
* Should we try to parse as a CID, in case the component prefers to be
123
* registered that way?
125
nsCOMPtr<nsIContentPolicy> policy = do_GetService(contractid.get(),
127
if (NS_SUCCEEDED(rv) && policy) {
128
mPolicies.AppendObject(policy);
134
nsContentPolicy::~nsContentPolicy()
139
#define WARN_IF_URI_UNINITIALIZED(uri,name) \
142
nsCAutoString spec; \
143
(uri)->GetAsciiSpec(spec); \
144
if (spec.IsEmpty()) { \
145
NS_WARNING(name " is uninitialized, fix caller"); \
150
#else // ! defined(DEBUG)
152
#define WARN_IF_URI_UNINITIALIZED(uri,name)
154
#endif // defined(DEBUG)
157
nsContentPolicy::CheckPolicy(CPMethod policyMethod,
158
PRUint32 contentType,
159
nsIURI *contentLocation,
160
nsIURI *requestingLocation,
161
nsISupports *requestingContext,
162
const nsACString &mimeType,
166
//sanity-check passed-through parameters
167
NS_PRECONDITION(decision, "Null out pointer");
168
WARN_IF_URI_UNINITIALIZED(contentLocation, "Request URI");
169
WARN_IF_URI_UNINITIALIZED(requestingLocation, "Requesting URI");
173
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext));
174
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
175
NS_ASSERTION(!requestingContext || node || window,
176
"Context should be a DOM node or a DOM window!");
180
PRInt32 count = mPolicies.Count();
184
* Enumerate mPolicies and ask each of them, taking the logical AND of
187
for (PRInt32 i = 0; i < count; i++) {
188
nsIContentPolicy *policy = mPolicies[i];
189
if (!policy) { //shouldn't happen
190
NS_ERROR("Somehow a null policy got into the list");
194
/* check the appropriate policy */
195
rv = (policy->*policyMethod)(contentType, contentLocation,
196
requestingLocation, requestingContext,
197
mimeType, extra, decision);
199
if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
200
/* policy says no, no point continuing to check */
205
// everyone returned failure, or no policies: sanitize result
206
*decision = nsIContentPolicy::ACCEPT;
212
//uses the parameters from ShouldXYZ to produce and log a message
213
//logType must be a literal string constant
214
#define LOG_CHECK(logType) \
216
/* skip all this nonsense if the call failed */ \
217
if (NS_SUCCEEDED(rv)) { \
218
const char *resultName; \
220
resultName = NS_CP_ResponseName(*decision); \
222
resultName = "(null ptr)"; \
224
nsCAutoString spec("None"); \
225
if (contentLocation) { \
226
contentLocation->GetSpec(spec); \
228
nsCAutoString refSpec("None"); \
229
if (requestingLocation) { \
230
requestingLocation->GetSpec(refSpec); \
232
PR_LOG(gConPolLog, PR_LOG_DEBUG, \
233
("Content Policy: " logType ": <%s> <Ref:%s> result=%s", \
234
spec.get(), refSpec.get(), resultName) \
239
#else //!defined(PR_LOGGING)
241
#define LOG_CHECK(logType)
243
#endif //!defined(PR_LOGGING)
246
nsContentPolicy::ShouldLoad(PRUint32 contentType,
247
nsIURI *contentLocation,
248
nsIURI *requestingLocation,
249
nsISupports *requestingContext,
250
const nsACString &mimeType,
254
// ShouldProcess does not need a content location, but we do
255
NS_PRECONDITION(contentLocation, "Must provide request location");
256
nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldLoad, contentType,
257
contentLocation, requestingLocation,
258
requestingContext, mimeType, extra, decision);
259
LOG_CHECK("ShouldLoad");
265
nsContentPolicy::ShouldProcess(PRUint32 contentType,
266
nsIURI *contentLocation,
267
nsIURI *requestingLocation,
268
nsISupports *requestingContext,
269
const nsACString &mimeType,
273
nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldProcess, contentType,
274
contentLocation, requestingLocation,
275
requestingContext, mimeType, extra, decision);
276
LOG_CHECK("ShouldProcess");