9b2b77f660054cc09092e1d939e5d2c929cbb986
[WebKit.git] / Source / WebCore / dom / ScriptDisallowedScope.h
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 namespace WebCore {
30
31 class ScriptDisallowedScope {
32 public:
33     // This variant is expensive. Use ScriptDisallowedScope::InMainThread whenever possible.
34     ScriptDisallowedScope()
35     {
36         if (!isMainThread())
37             return;
38         ++s_count;
39     }
40
41     ScriptDisallowedScope(const ScriptDisallowedScope&)
42         : ScriptDisallowedScope()
43     {
44     }
45
46     ~ScriptDisallowedScope()
47     {
48         if (!isMainThread())
49             return;
50         ASSERT(s_count);
51         s_count--;
52     }
53
54     static bool isEventAllowedInMainThread()
55     {
56         return !isMainThread() || !s_count;
57     }
58
59     class InMainThread {
60     public:
61         InMainThread()
62         {
63             ASSERT(isMainThread());
64             ++s_count;
65         }
66
67         ~InMainThread()
68         {
69             ASSERT(isMainThread());
70             ASSERT(s_count);
71             --s_count;
72         }
73
74         // Don't enable this assertion in release since it's O(n).
75         // Release asserts in canExecuteScript should be sufficient for security defense purposes.
76         static bool isEventDispatchAllowedInSubtree(Node& node)
77         {
78 #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
79             return isScriptAllowed() || EventAllowedScope::isAllowedNode(node);
80 #else
81             UNUSED_PARAM(node);
82             return true;
83 #endif
84         }
85
86         static bool isScriptAllowed()
87         {
88             ASSERT(isMainThread());
89             return !s_count;
90         }
91     };
92     
93 #if !ASSERT_DISABLED
94     class EventAllowedScope {
95     public:
96         explicit EventAllowedScope(ContainerNode& userAgentContentRoot)
97             : m_eventAllowedTreeRoot(userAgentContentRoot)
98             , m_previousScope(s_currentScope)
99         {
100             s_currentScope = this;
101         }
102
103         ~EventAllowedScope()
104         {
105             s_currentScope = m_previousScope;
106         }
107
108         static bool isAllowedNode(Node& node)
109         {
110             return s_currentScope && s_currentScope->isAllowedNodeInternal(node);
111         }
112
113     private:
114         bool isAllowedNodeInternal(Node& node)
115         {
116             return m_eventAllowedTreeRoot->contains(&node) || (m_previousScope && m_previousScope->isAllowedNodeInternal(node));
117         }
118
119         Ref<ContainerNode> m_eventAllowedTreeRoot;
120
121         EventAllowedScope* m_previousScope;
122         static EventAllowedScope* s_currentScope;
123     };
124 #else
125     class EventAllowedScope {
126     public:
127         explicit EventAllowedScope(ContainerNode&) { }
128         static bool isAllowedNode(Node&) { return true; }
129     };
130 #endif
131
132     // FIXME: Remove this class once the sync layout inside SVGImage::draw is removed,
133     // CachedSVGFont::ensureCustomFontData no longer synchronously creates a document during style resolution,
134     // and refactored the code in RenderFrameBase::performLayoutWithFlattening.
135     class DisableAssertionsInScope {
136     public:
137         DisableAssertionsInScope()
138         {
139             ASSERT(isMainThread());
140             std::swap(s_count, m_originalCount);
141         }
142
143         ~DisableAssertionsInScope()
144         {
145             s_count = m_originalCount;
146         }
147     private:
148         unsigned m_originalCount { 0 };
149     };
150
151     // FIXME: Remove all uses of this class.
152     class LayoutAssertionDisableScope {
153     public:
154         LayoutAssertionDisableScope()
155         {
156             s_layoutAssertionDisableCount++;
157         }
158
159         ~LayoutAssertionDisableScope()
160         {
161             s_layoutAssertionDisableCount--;
162         }
163
164         static bool shouldDisable() { return s_layoutAssertionDisableCount; }
165
166     private:
167         static unsigned s_layoutAssertionDisableCount;
168     };
169
170 private:
171     WEBCORE_EXPORT static unsigned s_count;
172 };
173
174 } // namespace WebCore