1/*
2 * Copyright (C) 2012 Google, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "DOMSecurityPolicy.h"
28
29#include "ContentSecurityPolicy.h"
30#include "ContextDestructionObserver.h"
31#include "DOMStringList.h"
32#include "Frame.h"
33#include "ScriptCallStack.h"
34#include "ScriptExecutionContext.h"
35#include <wtf/text/TextPosition.h>
36#include <wtf/text/WTFString.h>
37
38namespace WebCore {
39
40namespace {
41
42bool isPolicyActiveInContext(ScriptExecutionContext* context)
43{
44    // If the ScriptExecutionContext has been destroyed, there's no active policy.
45    if (!context)
46        return false;
47
48    return context->contentSecurityPolicy()->isActive();
49}
50
51template<bool (ContentSecurityPolicy::*allowWithType)(const String&, const String&, const KURL&, ContentSecurityPolicy::ReportingStatus) const>
52bool isAllowedWithType(ScriptExecutionContext* context, const String& type)
53{
54    if (!isPolicyActiveInContext(context))
55        return true;
56
57    return (context->contentSecurityPolicy()->*allowWithType)(type, type, KURL(), ContentSecurityPolicy::SuppressReport);
58}
59
60template<bool (ContentSecurityPolicy::*allowWithURL)(const KURL&, ContentSecurityPolicy::ReportingStatus) const>
61bool isAllowedWithURL(ScriptExecutionContext* context, const String& url)
62{
63    if (!isPolicyActiveInContext(context))
64        return true;
65
66    KURL parsedURL = context->completeURL(url);
67    if (!parsedURL.isValid())
68        return false; // FIXME: Figure out how to throw a JavaScript error.
69
70    return (context->contentSecurityPolicy()->*allowWithURL)(parsedURL, ContentSecurityPolicy::SuppressReport);
71}
72
73template<bool (ContentSecurityPolicy::*allowWithContext)(const String&, const WTF::OrdinalNumber&, ContentSecurityPolicy::ReportingStatus) const>
74bool isAllowed(ScriptExecutionContext* context)
75{
76    if (!isPolicyActiveInContext(context))
77        return true;
78
79    return (context->contentSecurityPolicy()->*allowWithContext)(String(), WTF::OrdinalNumber::beforeFirst(), ContentSecurityPolicy::SuppressReport);
80}
81
82} // namespace
83
84DOMSecurityPolicy::DOMSecurityPolicy(ScriptExecutionContext* context)
85    : ContextDestructionObserver(context)
86{
87}
88
89DOMSecurityPolicy::~DOMSecurityPolicy()
90{
91}
92
93bool DOMSecurityPolicy::isActive() const
94{
95    return isPolicyActiveInContext(scriptExecutionContext());
96}
97
98PassRefPtr<DOMStringList> DOMSecurityPolicy::reportURIs() const
99{
100    RefPtr<DOMStringList> result = DOMStringList::create();
101
102    if (isActive())
103        scriptExecutionContext()->contentSecurityPolicy()->gatherReportURIs(*result.get());
104
105    return result.release();
106}
107
108bool DOMSecurityPolicy::allowsInlineScript() const
109{
110    return isAllowed<&ContentSecurityPolicy::allowInlineScript>(scriptExecutionContext());
111}
112
113bool DOMSecurityPolicy::allowsInlineStyle() const
114{
115    return isAllowed<&ContentSecurityPolicy::allowInlineStyle>(scriptExecutionContext());
116}
117
118bool DOMSecurityPolicy::allowsEval() const
119{
120    if (!isActive())
121        return true;
122
123    return scriptExecutionContext()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport);
124}
125
126
127bool DOMSecurityPolicy::allowsConnectionTo(const String& url) const
128{
129    return isAllowedWithURL<&ContentSecurityPolicy::allowConnectToSource>(scriptExecutionContext(), url);
130}
131
132bool DOMSecurityPolicy::allowsFontFrom(const String& url) const
133{
134    return isAllowedWithURL<&ContentSecurityPolicy::allowFontFromSource>(scriptExecutionContext(), url);
135}
136
137bool DOMSecurityPolicy::allowsFormAction(const String& url) const
138{
139    return isAllowedWithURL<&ContentSecurityPolicy::allowFormAction>(scriptExecutionContext(), url);
140}
141
142bool DOMSecurityPolicy::allowsFrameFrom(const String& url) const
143{
144    return isAllowedWithURL<&ContentSecurityPolicy::allowChildFrameFromSource>(scriptExecutionContext(), url);
145}
146
147bool DOMSecurityPolicy::allowsImageFrom(const String& url) const
148{
149    return isAllowedWithURL<&ContentSecurityPolicy::allowImageFromSource>(scriptExecutionContext(), url);
150}
151
152bool DOMSecurityPolicy::allowsMediaFrom(const String& url) const
153{
154    return isAllowedWithURL<&ContentSecurityPolicy::allowMediaFromSource>(scriptExecutionContext(), url);
155}
156
157bool DOMSecurityPolicy::allowsObjectFrom(const String& url) const
158{
159    return isAllowedWithURL<&ContentSecurityPolicy::allowObjectFromSource>(scriptExecutionContext(), url);
160}
161
162bool DOMSecurityPolicy::allowsPluginType(const String& type) const
163{
164    return isAllowedWithType<&ContentSecurityPolicy::allowPluginType>(scriptExecutionContext(), type);
165}
166
167bool DOMSecurityPolicy::allowsScriptFrom(const String& url) const
168{
169    return isAllowedWithURL<&ContentSecurityPolicy::allowScriptFromSource>(scriptExecutionContext(), url);
170}
171
172bool DOMSecurityPolicy::allowsStyleFrom(const String& url) const
173{
174    return isAllowedWithURL<&ContentSecurityPolicy::allowStyleFromSource>(scriptExecutionContext(), url);
175}
176
177} // namespace WebCore
178