1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004-2016 Apple Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#pragma once
25
26#include "ContainerNode.h"
27#include <wtf/MainThread.h>
28
29#if PLATFORM(IOS_FAMILY)
30#include "WebCoreThread.h"
31#endif
32
33namespace WebCore {
34
35class ScriptDisallowedScope {
36public:
37 // This variant is expensive. Use ScriptDisallowedScope::InMainThread whenever possible.
38 ScriptDisallowedScope()
39 {
40 if (!isMainThread())
41 return;
42 ++s_count;
43 }
44
45 ScriptDisallowedScope(const ScriptDisallowedScope&)
46 : ScriptDisallowedScope()
47 {
48 }
49
50 ~ScriptDisallowedScope()
51 {
52 if (!isMainThread())
53 return;
54 ASSERT(s_count);
55 s_count--;
56 }
57
58 ScriptDisallowedScope& operator=(const ScriptDisallowedScope&)
59 {
60 return *this;
61 }
62
63 static bool isEventAllowedInMainThread()
64 {
65 return !isMainThread() || !s_count;
66 }
67
68 class InMainThread {
69 public:
70 InMainThread()
71 {
72 ASSERT(isMainThread());
73 ++s_count;
74 }
75
76 ~InMainThread()
77 {
78 ASSERT(isMainThread());
79 ASSERT(s_count);
80 --s_count;
81 }
82
83 // Don't enable this assertion in release since it's O(n).
84 // Release asserts in canExecuteScript should be sufficient for security defense purposes.
85 static bool isEventDispatchAllowedInSubtree(Node& node)
86 {
87#if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
88 return isScriptAllowed() || EventAllowedScope::isAllowedNode(node);
89#else
90 UNUSED_PARAM(node);
91 return true;
92#endif
93 }
94
95 static bool hasDisallowedScope()
96 {
97 ASSERT(isMainThread());
98 return s_count;
99 }
100
101 static bool isScriptAllowed()
102 {
103 ASSERT(isMainThread());
104#if PLATFORM(IOS_FAMILY)
105 return !s_count || webThreadDelegateMessageScopeCount;
106#else
107 return !s_count;
108#endif
109 }
110 };
111
112#if !ASSERT_DISABLED
113 class EventAllowedScope {
114 public:
115 explicit EventAllowedScope(ContainerNode& userAgentContentRoot)
116 : m_eventAllowedTreeRoot(userAgentContentRoot)
117 , m_previousScope(s_currentScope)
118 {
119 s_currentScope = this;
120 }
121
122 ~EventAllowedScope()
123 {
124 s_currentScope = m_previousScope;
125 }
126
127 static bool isAllowedNode(Node& node)
128 {
129 return s_currentScope && s_currentScope->isAllowedNodeInternal(node);
130 }
131
132 private:
133 bool isAllowedNodeInternal(Node& node)
134 {
135 return m_eventAllowedTreeRoot->contains(&node) || (m_previousScope && m_previousScope->isAllowedNodeInternal(node));
136 }
137
138 Ref<ContainerNode> m_eventAllowedTreeRoot;
139
140 EventAllowedScope* m_previousScope;
141 static EventAllowedScope* s_currentScope;
142 };
143#else
144 class EventAllowedScope {
145 public:
146 explicit EventAllowedScope(ContainerNode&) { }
147 static bool isAllowedNode(Node&) { return true; }
148 };
149#endif
150
151 // FIXME: Remove this class once the sync layout inside SVGImage::draw is removed,
152 // CachedSVGFont::ensureCustomFontData no longer synchronously creates a document during style resolution,
153 // and refactored the code in RenderFrameBase::performLayoutWithFlattening.
154 class DisableAssertionsInScope {
155 public:
156 DisableAssertionsInScope()
157 {
158 ASSERT(isMainThread());
159 std::swap(s_count, m_originalCount);
160 }
161
162 ~DisableAssertionsInScope()
163 {
164 s_count = m_originalCount;
165 }
166 private:
167 unsigned m_originalCount { 0 };
168 };
169
170private:
171 WEBCORE_EXPORT static unsigned s_count;
172};
173
174} // namespace WebCore
175