Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / dom / CompositorProxy.cpp
blob4084c44447e5de0e4a4a4a97c5181838b1fcd01d
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "config.h"
6 #include "core/dom/CompositorProxy.h"
8 #include "bindings/core/v8/ExceptionMessages.h"
9 #include "bindings/core/v8/ExceptionState.h"
10 #include "core/dom/DOMNodeIds.h"
11 #include "core/dom/ExceptionCode.h"
12 #include "core/dom/ExecutionContext.h"
13 #include "platform/ThreadSafeFunctional.h"
14 #include "public/platform/Platform.h"
15 #include "public/platform/WebTraceLocation.h"
17 namespace blink {
19 struct AttributeFlagMapping {
20 const char* name;
21 unsigned length;
22 CompositorProxy::Attributes attribute;
25 static AttributeFlagMapping allowedAttributes[] = {
26 { "opacity", 7, CompositorProxy::Attributes::OPACITY },
27 { "scrollleft", 10, CompositorProxy::Attributes::SCROLL_LEFT },
28 { "scrolltop", 9, CompositorProxy::Attributes::SCROLL_TOP },
29 { "touch", 5, CompositorProxy::Attributes::TOUCH },
30 { "transform", 8, CompositorProxy::Attributes::TRANSFORM },
33 static bool CompareAttributeName(const AttributeFlagMapping& attribute, StringImpl* attributeLower)
35 ASSERT(attributeLower->is8Bit());
36 return memcmp(attribute.name, attributeLower->characters8(), std::min(attribute.length, attributeLower->length())) < 0;
39 static CompositorProxy::Attributes attributeFlagForName(const String& attributeName)
41 CompositorProxy::Attributes attributeFlag = CompositorProxy::Attributes::NONE;
42 const String attributeLower = attributeName.lower();
43 const AttributeFlagMapping* start = allowedAttributes;
44 const AttributeFlagMapping* end = allowedAttributes + WTF_ARRAY_LENGTH(allowedAttributes);
45 if (attributeLower.impl()->is8Bit()) {
46 const AttributeFlagMapping* match = std::lower_bound(start, end, attributeLower.impl(), CompareAttributeName);
47 if (match != end)
48 attributeFlag = match->attribute;
50 return attributeFlag;
53 static bool isControlThread()
55 return !isMainThread();
58 static bool isCallingCompositorFrameCallback()
60 // TODO(sad): Check that the requestCompositorFrame callbacks are currently being called.
61 return true;
64 static void decrementCountForElement(uint64_t elementId)
66 ASSERT(isMainThread());
67 Node* node = DOMNodeIds::nodeForId(elementId);
68 if (!node)
69 return;
70 Element* element = toElement(node);
71 element->decrementProxyCount();
74 static void incrementProxyCountForElement(uint64_t elementId)
76 ASSERT(isMainThread());
77 Node* node = DOMNodeIds::nodeForId(elementId);
78 if (!node)
79 return;
80 Element* element = toElement(node);
81 element->incrementProxyCount();
84 static bool raiseExceptionIfMutationNotAllowed(ExceptionState& exceptionState)
86 if (!isControlThread()) {
87 exceptionState.throwDOMException(NoModificationAllowedError, "Cannot mutate a proxy attribute from the main page.");
88 return true;
90 if (!isCallingCompositorFrameCallback()) {
91 exceptionState.throwDOMException(NoModificationAllowedError, "Cannot mutate a proxy attribute outside of a requestCompositorFrame callback.");
92 return true;
94 return false;
97 static uint32_t attributesBitfieldFromNames(const Vector<String>& attributeArray)
99 uint32_t attributesBitfield = 0;
100 for (const auto& attribute : attributeArray) {
101 attributesBitfield |= static_cast<uint32_t>(attributeFlagForName(attribute));
103 return attributesBitfield;
106 #if ENABLE(ASSERT)
107 static bool sanityCheckAttributeFlags(uint32_t attributeFlags)
109 uint32_t sanityCheckAttributes = attributeFlags;
110 for (unsigned i = 0; i < arraysize(allowedAttributes); ++i) {
111 sanityCheckAttributes &= ~static_cast<uint32_t>(allowedAttributes[i].attribute);
113 return !sanityCheckAttributes;
115 #endif
117 CompositorProxy* CompositorProxy::create(ExecutionContext* context, Element* element, const Vector<String>& attributeArray, ExceptionState& exceptionState)
119 if (!context->isDocument()) {
120 exceptionState.throwTypeError(ExceptionMessages::failedToConstruct("CompositorProxy", "Can only be created from the main context."));
121 exceptionState.throwIfNeeded();
122 return nullptr;
125 return new CompositorProxy(*element, attributeArray);
128 CompositorProxy* CompositorProxy::create(uint64_t elementId, uint32_t attributeFlags)
130 return new CompositorProxy(elementId, attributeFlags);
133 CompositorProxy::CompositorProxy(Element& element, const Vector<String>& attributeArray)
134 : m_elementId(DOMNodeIds::idForNode(&element))
135 , m_bitfieldsSupported(attributesBitfieldFromNames(attributeArray))
137 ASSERT(isMainThread());
138 ASSERT(m_bitfieldsSupported);
139 ASSERT(sanityCheckAttributeFlags(m_bitfieldsSupported));
141 incrementProxyCountForElement(m_elementId);
144 CompositorProxy::CompositorProxy(uint64_t elementId, uint32_t attributeFlags)
145 : m_elementId(elementId)
146 , m_bitfieldsSupported(attributeFlags)
148 ASSERT(isControlThread());
149 ASSERT(sanityCheckAttributeFlags(m_bitfieldsSupported));
150 Platform::current()->mainThread()->taskRunner()->postTask(FROM_HERE, threadSafeBind(&incrementProxyCountForElement, m_elementId));
153 CompositorProxy::~CompositorProxy()
155 if (m_connected)
156 disconnect();
159 bool CompositorProxy::supports(const String& attributeName) const
161 return !!(m_bitfieldsSupported & static_cast<uint32_t>(attributeFlagForName(attributeName)));
164 double CompositorProxy::opacity(ExceptionState& exceptionState) const
166 if (raiseExceptionIfMutationNotAllowed(exceptionState))
167 return 0.0;
168 if (raiseExceptionIfNotMutable(Attributes::OPACITY, exceptionState))
169 return 0.0;
170 return m_opacity;
173 double CompositorProxy::scrollLeft(ExceptionState& exceptionState) const
175 if (raiseExceptionIfMutationNotAllowed(exceptionState))
176 return 0.0;
177 if (raiseExceptionIfNotMutable(Attributes::SCROLL_LEFT, exceptionState))
178 return 0.0;
179 return m_scrollLeft;
182 double CompositorProxy::scrollTop(ExceptionState& exceptionState) const
184 if (raiseExceptionIfMutationNotAllowed(exceptionState))
185 return 0.0;
186 if (raiseExceptionIfNotMutable(Attributes::SCROLL_TOP, exceptionState))
187 return 0.0;
188 return m_scrollTop;
191 DOMMatrix* CompositorProxy::transform(ExceptionState& exceptionState) const
193 if (raiseExceptionIfMutationNotAllowed(exceptionState))
194 return nullptr;
195 if (raiseExceptionIfNotMutable(Attributes::TRANSFORM, exceptionState))
196 return nullptr;
197 return m_transform;
200 void CompositorProxy::setOpacity(double opacity, ExceptionState& exceptionState)
202 if (raiseExceptionIfMutationNotAllowed(exceptionState))
203 return;
204 if (raiseExceptionIfNotMutable(Attributes::OPACITY, exceptionState))
205 return;
206 m_opacity = std::min(1., std::max(0., opacity));
207 m_mutatedAttributes |= static_cast<uint32_t>(Attributes::OPACITY);
210 void CompositorProxy::setScrollLeft(double scrollLeft, ExceptionState& exceptionState)
212 if (raiseExceptionIfMutationNotAllowed(exceptionState))
213 return;
214 if (raiseExceptionIfNotMutable(Attributes::SCROLL_LEFT, exceptionState))
215 return;
216 m_scrollLeft = scrollLeft;
217 m_mutatedAttributes |= static_cast<uint32_t>(Attributes::SCROLL_LEFT);
220 void CompositorProxy::setScrollTop(double scrollTop, ExceptionState& exceptionState)
222 if (raiseExceptionIfMutationNotAllowed(exceptionState))
223 return;
224 if (raiseExceptionIfNotMutable(Attributes::SCROLL_TOP, exceptionState))
225 return;
226 m_scrollTop = scrollTop;
227 m_mutatedAttributes |= static_cast<uint32_t>(Attributes::SCROLL_TOP);
230 void CompositorProxy::setTransform(DOMMatrix* transform, ExceptionState& exceptionState)
232 if (raiseExceptionIfMutationNotAllowed(exceptionState))
233 return;
234 if (raiseExceptionIfNotMutable(Attributes::TRANSFORM, exceptionState))
235 return;
236 m_transform = transform;
237 m_mutatedAttributes |= static_cast<uint32_t>(Attributes::TRANSFORM);
240 bool CompositorProxy::raiseExceptionIfNotMutable(Attributes attribute, ExceptionState& exceptionState) const
242 if (m_connected && (m_bitfieldsSupported & static_cast<uint32_t>(attribute)))
243 return false;
244 exceptionState.throwDOMException(NoModificationAllowedError,
245 m_connected ? "Attempted to mutate non-mutable attribute." : "Attempted to mutate attribute on a disconnected proxy.");
246 return true;
249 void CompositorProxy::disconnect()
251 m_connected = false;
252 if (isMainThread())
253 decrementCountForElement(m_elementId);
254 else
255 Platform::current()->mainThread()->taskRunner()->postTask(FROM_HERE, threadSafeBind(&decrementCountForElement, m_elementId));
258 } // namespace blink