Fix "ASSERTION FAILED: m_representation == PlatformLayerRepresentation" with UI-side...
[WebKit-https.git] / Source / WebKit2 / Shared / Scrolling / RemoteScrollingCoordinatorTransaction.cpp
1 /*
2  * Copyright (C) 2014 Apple 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 APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RemoteScrollingCoordinatorTransaction.h"
28
29 #include "ArgumentCoders.h"
30 #include "MessageDecoder.h"
31 #include "MessageEncoder.h"
32 #include "WebCoreArgumentCoders.h"
33 #include <WebCore/GraphicsLayer.h>
34 #include <WebCore/ScrollingStateFixedNode.h>
35 #include <WebCore/ScrollingStateScrollingNode.h>
36 #include <WebCore/ScrollingStateStickyNode.h>
37 #include <WebCore/ScrollingStateTree.h>
38 #include <WebCore/TextStream.h>
39 #include <wtf/text/CString.h>
40 #include <wtf/text/StringBuilder.h>
41
42 #include <wtf/HashMap.h>
43
44 using namespace WebCore;
45
46 #if ENABLE(ASYNC_SCROLLING)
47
48 namespace IPC {
49
50 template<> struct ArgumentCoder<ScrollingStateNode> {
51     static void encode(ArgumentEncoder&, const ScrollingStateNode&);
52     static bool decode(ArgumentDecoder&, ScrollingStateNode&);
53 };
54
55 template<> struct ArgumentCoder<ScrollingStateScrollingNode> {
56     static void encode(ArgumentEncoder&, const ScrollingStateScrollingNode&);
57     static bool decode(ArgumentDecoder&, ScrollingStateScrollingNode&);
58 };
59
60 template<> struct ArgumentCoder<ScrollingStateFixedNode> {
61     static void encode(ArgumentEncoder&, const ScrollingStateFixedNode&);
62     static bool decode(ArgumentDecoder&, ScrollingStateFixedNode&);
63 };
64
65 template<> struct ArgumentCoder<ScrollingStateStickyNode> {
66     static void encode(ArgumentEncoder&, const ScrollingStateStickyNode&);
67     static bool decode(ArgumentDecoder&, ScrollingStateStickyNode&);
68 };
69
70 } // namespace IPC
71
72 using namespace IPC;
73
74 void ArgumentCoder<ScrollingStateNode>::encode(ArgumentEncoder& encoder, const ScrollingStateNode& node)
75 {
76     encoder.encodeEnum(node.nodeType());
77     encoder << node.scrollingNodeID();
78     encoder << node.parentNodeID();
79     encoder << node.changedProperties();
80     
81     if (node.hasChangedProperty(ScrollingStateNode::ScrollLayer))
82         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.layer());
83 }
84
85 bool ArgumentCoder<ScrollingStateNode>::decode(ArgumentDecoder& decoder, ScrollingStateNode& node)
86 {
87     // nodeType, scrollingNodeID and parentNodeID have already been decoded by the caller in order to create the node.
88     ScrollingStateNode::ChangedProperties changedProperties;
89     if (!decoder.decode(changedProperties))
90         return false;
91
92     node.setChangedProperties(changedProperties);
93     if (node.hasChangedProperty(ScrollingStateNode::ScrollLayer)) {
94         GraphicsLayer::PlatformLayerID layerID;
95         if (!decoder.decode(layerID))
96             return false;
97         node.setLayer(layerID);
98     }
99
100     return true;
101 }
102
103 #define SCROLLING_NODE_ENCODE(property, getter) \
104     if (node.hasChangedProperty(ScrollingStateScrollingNode::property)) \
105         encoder << node.getter();
106
107 #define SCROLLING_NODE_ENCODE_ENUM(property, getter) \
108     if (node.hasChangedProperty(ScrollingStateScrollingNode::property)) \
109         encoder.encodeEnum(node.getter());
110
111 void ArgumentCoder<ScrollingStateScrollingNode>::encode(ArgumentEncoder& encoder, const ScrollingStateScrollingNode& node)
112 {
113     encoder << static_cast<const ScrollingStateNode&>(node);
114     
115     SCROLLING_NODE_ENCODE(ViewportSize, viewportSize)
116     SCROLLING_NODE_ENCODE(TotalContentsSize, totalContentsSize)
117     SCROLLING_NODE_ENCODE(ScrollPosition, scrollPosition)
118     SCROLLING_NODE_ENCODE(ScrollOrigin, scrollOrigin)
119     SCROLLING_NODE_ENCODE(FrameScaleFactor, frameScaleFactor)
120     SCROLLING_NODE_ENCODE(NonFastScrollableRegion, nonFastScrollableRegion)
121     SCROLLING_NODE_ENCODE(WheelEventHandlerCount, wheelEventHandlerCount)
122     SCROLLING_NODE_ENCODE(ReasonsForSynchronousScrolling, synchronousScrollingReasons)
123     SCROLLING_NODE_ENCODE(ScrollableAreaParams, scrollableAreaParameters)
124     SCROLLING_NODE_ENCODE_ENUM(BehaviorForFixedElements, scrollBehaviorForFixedElements)
125     SCROLLING_NODE_ENCODE(RequestedScrollPosition, requestedScrollPosition)
126     SCROLLING_NODE_ENCODE(RequestedScrollPosition, requestedScrollPositionRepresentsProgrammaticScroll)
127     SCROLLING_NODE_ENCODE(HeaderHeight, headerHeight)
128     SCROLLING_NODE_ENCODE(FooterHeight, footerHeight)
129     SCROLLING_NODE_ENCODE(TopContentInset, topContentInset)
130
131     if (node.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
132         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer());
133
134     if (node.hasChangedProperty(ScrollingStateScrollingNode::CounterScrollingLayer))
135         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.counterScrollingLayer());
136
137     if (node.hasChangedProperty(ScrollingStateScrollingNode::InsetClipLayer))
138         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.insetClipLayer());
139
140     if (node.hasChangedProperty(ScrollingStateScrollingNode::ContentShadowLayer))
141         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.contentShadowLayer());
142 }
143
144 #define SCROLLING_NODE_DECODE(property, type, setter) \
145     if (node.hasChangedProperty(ScrollingStateScrollingNode::property)) { \
146         type decodedValue; \
147         if (!decoder.decode(decodedValue)) \
148             return false; \
149         node.setter(decodedValue); \
150     }
151
152 #define SCROLLING_NODE_DECODE_ENUM(property, type, setter) \
153     if (node.hasChangedProperty(ScrollingStateScrollingNode::property)) { \
154         type decodedValue; \
155         if (!decoder.decodeEnum(decodedValue)) \
156             return false; \
157         node.setter(decodedValue); \
158     }
159
160 bool ArgumentCoder<ScrollingStateScrollingNode>::decode(ArgumentDecoder& decoder, ScrollingStateScrollingNode& node)
161 {
162     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
163         return false;
164
165     SCROLLING_NODE_DECODE(ViewportSize, FloatSize, setViewportSize);
166     SCROLLING_NODE_DECODE(TotalContentsSize, IntSize, setTotalContentsSize);
167     SCROLLING_NODE_DECODE(ScrollPosition, FloatPoint, setScrollPosition);
168     SCROLLING_NODE_DECODE(ScrollOrigin, IntPoint, setScrollOrigin);
169     SCROLLING_NODE_DECODE(FrameScaleFactor, float, setFrameScaleFactor);
170     SCROLLING_NODE_DECODE(NonFastScrollableRegion, Region, setNonFastScrollableRegion);
171     SCROLLING_NODE_DECODE(WheelEventHandlerCount, int, setWheelEventHandlerCount);
172     SCROLLING_NODE_DECODE(ReasonsForSynchronousScrolling, SynchronousScrollingReasons, setSynchronousScrollingReasons);
173     SCROLLING_NODE_DECODE(ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
174     SCROLLING_NODE_DECODE_ENUM(BehaviorForFixedElements, ScrollBehaviorForFixedElements, setScrollBehaviorForFixedElements);
175
176     if (node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
177         FloatPoint scrollPosition;
178         if (!decoder.decode(scrollPosition))
179             return false;
180
181         bool representsProgrammaticScroll;
182         if (!decoder.decode(representsProgrammaticScroll))
183             return false;
184
185         node.setRequestedScrollPosition(scrollPosition, representsProgrammaticScroll);
186     }
187
188     SCROLLING_NODE_DECODE(HeaderHeight, int, setHeaderHeight);
189     SCROLLING_NODE_DECODE(FooterHeight, int, setFooterHeight);
190     SCROLLING_NODE_DECODE(TopContentInset, float, setTopContentInset);
191
192     if (node.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer)) {
193         GraphicsLayer::PlatformLayerID layerID;
194         if (!decoder.decode(layerID))
195             return false;
196         node.setScrolledContentsLayer(layerID);
197     }
198
199     if (node.hasChangedProperty(ScrollingStateScrollingNode::CounterScrollingLayer)) {
200         GraphicsLayer::PlatformLayerID layerID;
201         if (!decoder.decode(layerID))
202             return false;
203         node.setCounterScrollingLayer(layerID);
204     }
205
206     if (node.hasChangedProperty(ScrollingStateScrollingNode::InsetClipLayer)) {
207         GraphicsLayer::PlatformLayerID layerID;
208         if (!decoder.decode(layerID))
209             return false;
210         node.setInsetClipLayer(layerID);
211     }
212
213     if (node.hasChangedProperty(ScrollingStateScrollingNode::ContentShadowLayer)) {
214         GraphicsLayer::PlatformLayerID layerID;
215         if (!decoder.decode(layerID))
216             return false;
217         node.setContentShadowLayer(layerID);
218     }
219
220     return true;
221 }
222
223 void ArgumentCoder<ScrollingStateFixedNode>::encode(ArgumentEncoder& encoder, const ScrollingStateFixedNode& node)
224 {
225     encoder << static_cast<const ScrollingStateNode&>(node);
226     
227     if (node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
228         encoder << node.viewportConstraints();
229 }
230
231 bool ArgumentCoder<ScrollingStateFixedNode>::decode(ArgumentDecoder& decoder, ScrollingStateFixedNode& node)
232 {
233     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
234         return false;
235
236     if (node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints)) {
237         FixedPositionViewportConstraints decodedValue;
238         if (!decoder.decode(decodedValue))
239             return false;
240         node.updateConstraints(decodedValue);
241     }
242
243     return true;
244 }
245
246 void ArgumentCoder<ScrollingStateStickyNode>::encode(ArgumentEncoder& encoder, const ScrollingStateStickyNode& node)
247 {
248     encoder << static_cast<const ScrollingStateNode&>(node);
249     
250     if (node.hasChangedProperty(ScrollingStateStickyNode::ViewportConstraints))
251         encoder << node.viewportConstraints();
252 }
253
254 bool ArgumentCoder<ScrollingStateStickyNode>::decode(ArgumentDecoder& decoder, ScrollingStateStickyNode& node)
255 {
256     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
257         return false;
258
259     if (node.hasChangedProperty(ScrollingStateStickyNode::ViewportConstraints)) {
260         StickyPositionViewportConstraints decodedValue;
261         if (!decoder.decode(decodedValue))
262             return false;
263         node.updateConstraints(decodedValue);
264     }
265
266     return true;
267 }
268
269 namespace WebKit {
270
271 static void encodeNodeAndDescendants(IPC::ArgumentEncoder& encoder, const ScrollingStateNode& stateNode)
272 {
273     switch (stateNode.nodeType()) {
274     case FrameScrollingNode:
275     case OverflowScrollingNode:
276         encoder << toScrollingStateScrollingNode(stateNode);
277         break;
278     case FixedNode:
279         encoder << toScrollingStateFixedNode(stateNode);
280         break;
281     case StickyNode:
282         encoder << toScrollingStateStickyNode(stateNode);
283         break;
284     }
285
286     if (!stateNode.children())
287         return;
288
289     for (size_t i = 0; i < stateNode.children()->size(); ++i) {
290         const OwnPtr<ScrollingStateNode>& child = stateNode.children()->at(i);
291         encodeNodeAndDescendants(encoder, *child.get());
292     }
293 }
294
295 void RemoteScrollingCoordinatorTransaction::encode(IPC::ArgumentEncoder& encoder) const
296 {
297     int numNodes = m_scrollingStateTree ? m_scrollingStateTree->nodeCount() : 0;
298     encoder << numNodes;
299     
300     bool hasNewRootNode = m_scrollingStateTree ? m_scrollingStateTree->hasNewRootStateNode() : false;
301     encoder << hasNewRootNode;
302
303     if (m_scrollingStateTree) {
304         encoder << m_scrollingStateTree->hasChangedProperties();
305
306         if (const ScrollingStateNode* rootNode = m_scrollingStateTree->rootStateNode())
307             encodeNodeAndDescendants(encoder, *rootNode);
308
309         encoder << m_scrollingStateTree->removedNodes();
310     } else
311         encoder << Vector<ScrollingNodeID>();
312 }
313
314 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteScrollingCoordinatorTransaction& transaction)
315 {
316     return transaction.decode(decoder);
317 }
318
319 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder)
320 {
321     int numNodes;
322     if (!decoder.decode(numNodes))
323         return false;
324
325     bool hasNewRootNode;
326     if (!decoder.decode(hasNewRootNode))
327         return false;
328     
329     m_scrollingStateTree = ScrollingStateTree::create();
330
331     bool hasChangedProperties;
332     if (!decoder.decode(hasChangedProperties))
333         return false;
334
335     m_scrollingStateTree->setHasChangedProperties(hasChangedProperties);
336
337     for (int i = 0; i < numNodes; ++i) {
338         ScrollingNodeType nodeType;
339         if (!decoder.decodeEnum(nodeType))
340             return false;
341
342         ScrollingNodeID nodeID;
343         if (!decoder.decode(nodeID))
344             return false;
345
346         ScrollingNodeID parentNodeID;
347         if (!decoder.decode(parentNodeID))
348             return false;
349
350         m_scrollingStateTree->attachNode(nodeType, nodeID, parentNodeID);
351         ScrollingStateNode* newNode = m_scrollingStateTree->stateNodeForID(nodeID);
352         ASSERT(newNode);
353         ASSERT(!parentNodeID || newNode->parent());
354         
355         switch (nodeType) {
356         case FrameScrollingNode:
357         case OverflowScrollingNode:
358             if (!decoder.decode(*toScrollingStateScrollingNode(newNode)))
359                 return false;
360             break;
361         case FixedNode:
362             if (!decoder.decode(*toScrollingStateFixedNode(newNode)))
363                 return false;
364             break;
365         case StickyNode:
366             if (!decoder.decode(*toScrollingStateStickyNode(newNode)))
367                 return false;
368             break;
369         }
370     }
371
372     m_scrollingStateTree->setHasNewRootStateNode(hasNewRootNode);
373
374     // Removed nodes
375     Vector<ScrollingNodeID> removedNodes;
376     if (!decoder.decode(removedNodes))
377         return false;
378     
379     if (removedNodes.size())
380         m_scrollingStateTree->setRemovedNodes(removedNodes);
381
382     return true;
383 }
384
385 #if !defined(NDEBUG) || !LOG_DISABLED
386
387 class RemoteScrollingTreeTextStream : public TextStream {
388 public:
389     using TextStream::operator<<;
390
391     RemoteScrollingTreeTextStream()
392         : m_indent(0)
393     {
394     }
395
396     RemoteScrollingTreeTextStream& operator<<(FloatRect);
397     RemoteScrollingTreeTextStream& operator<<(ScrollingNodeType);
398
399     RemoteScrollingTreeTextStream& operator<<(const FixedPositionViewportConstraints&);
400     RemoteScrollingTreeTextStream& operator<<(const StickyPositionViewportConstraints&);
401
402     void dump(const ScrollingStateTree&, bool changedPropertiesOnly = true);
403
404     void dump(const ScrollingStateNode&, bool changedPropertiesOnly = true);
405     void dump(const ScrollingStateScrollingNode&, bool changedPropertiesOnly = true);
406     void dump(const ScrollingStateFixedNode&, bool changedPropertiesOnly = true);
407     void dump(const ScrollingStateStickyNode&, bool changedPropertiesOnly = true);
408
409     void increaseIndent() { ++m_indent; }
410     void decreaseIndent() { --m_indent; ASSERT(m_indent >= 0); }
411
412     void writeIndent();
413
414 private:
415     void recursiveDumpNodes(const ScrollingStateNode&, bool changedPropertiesOnly);
416
417     int m_indent;
418 };
419
420 void RemoteScrollingTreeTextStream::writeIndent()
421 {
422     for (int i = 0; i < m_indent; ++i)
423         *this << "  ";
424 }
425
426 template <class T>
427 static void dumpProperty(RemoteScrollingTreeTextStream& ts, String name, T value)
428 {
429     ts << "\n";
430     ts.increaseIndent();
431     ts.writeIndent();
432     ts << "(" << name << " ";
433     ts << value << ")";
434     ts.decreaseIndent();
435 }
436
437 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(FloatRect rect)
438 {
439     RemoteScrollingTreeTextStream& ts = *this;
440     ts << rect.x() << " " << rect.y() << " " << rect.width() << " " << rect.height();
441     return ts;
442 }
443
444 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(ScrollingNodeType nodeType)
445 {
446     RemoteScrollingTreeTextStream& ts = *this;
447
448     switch (nodeType) {
449     case FrameScrollingNode: ts << "frame-scrolling"; break;
450     case OverflowScrollingNode: ts << "overflow-scrolling"; break;
451     case FixedNode: ts << "fixed"; break;
452     case StickyNode: ts << "sticky"; break;
453     }
454
455     return ts;
456 }
457
458 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(const FixedPositionViewportConstraints& constraints)
459 {
460     RemoteScrollingTreeTextStream& ts = *this;
461
462     dumpProperty(ts, "viewport-rect-at-last-layout", constraints.viewportRectAtLastLayout());
463     dumpProperty(ts, "layer-position-at-last-layout", constraints.layerPositionAtLastLayout());
464
465     return ts;
466 }
467
468 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(const StickyPositionViewportConstraints& constraints)
469 {
470     RemoteScrollingTreeTextStream& ts = *this;
471
472     dumpProperty(ts, "sticky-position-at-last-layout", constraints.stickyOffsetAtLastLayout());
473     dumpProperty(ts, "layer-position-at-last-layout", constraints.layerPositionAtLastLayout());
474
475     return ts;
476 }
477
478 void RemoteScrollingTreeTextStream::dump(const ScrollingStateNode& node, bool changedPropertiesOnly)
479 {
480     RemoteScrollingTreeTextStream& ts = *this;
481
482     ts << "(node " << node.scrollingNodeID();
483
484     dumpProperty(ts, "type", node.nodeType());
485
486     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateNode::ScrollLayer))
487         dumpProperty(ts, "layer", static_cast<GraphicsLayer::PlatformLayerID>(node.layer()));
488     
489     switch (node.nodeType()) {
490     case FrameScrollingNode:
491     case OverflowScrollingNode:
492         dump(toScrollingStateScrollingNode(node), changedPropertiesOnly);
493         break;
494     case FixedNode:
495         dump(toScrollingStateFixedNode(node), changedPropertiesOnly);
496         break;
497     case StickyNode:
498         dump(toScrollingStateStickyNode(node), changedPropertiesOnly);
499         break;
500     }
501 }
502
503 void RemoteScrollingTreeTextStream::dump(const ScrollingStateScrollingNode& node, bool changedPropertiesOnly)
504 {
505     RemoteScrollingTreeTextStream& ts = *this;
506
507     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ViewportSize))
508         dumpProperty(ts, "viewport-size", node.viewportSize());
509
510     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize))
511         dumpProperty(ts, "total-contents-size", node.totalContentsSize());
512
513     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition))
514         dumpProperty(ts, "scroll-position", node.scrollPosition());
515
516     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
517         dumpProperty(ts, "scroll-origin", node.scrollOrigin());
518
519     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::FrameScaleFactor))
520         dumpProperty(ts, "frame-scale-factor", node.frameScaleFactor());
521
522     // FIXME: dump nonFastScrollableRegion
523     // FIXME: dump wheelEventHandlerCount
524     // FIXME: dump synchronousScrollingReasons
525     // FIXME: dump scrollableAreaParameters
526     // FIXME: dump scrollBehaviorForFixedElements
527
528     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
529         dumpProperty(ts, "requested-scroll-position", node.requestedScrollPosition());
530         dumpProperty(ts, "requested-scroll-position-is-programatic", node.requestedScrollPositionRepresentsProgrammaticScroll());
531     }
532
533     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::HeaderHeight))
534         dumpProperty(ts, "header-height", node.headerHeight());
535
536     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::FooterHeight))
537         dumpProperty(ts, "footer-height", node.footerHeight());
538
539     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::TopContentInset))
540         dumpProperty(ts, "top-content-inset", node.topContentInset());
541
542     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
543         dumpProperty(ts, "scrolled-contents-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer()));
544
545     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::CounterScrollingLayer))
546         dumpProperty(ts, "counter-scrolling-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.counterScrollingLayer()));
547
548     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::InsetClipLayer))
549         dumpProperty(ts, "clip-inset-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.insetClipLayer()));
550
551     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ContentShadowLayer))
552         dumpProperty(ts, "content-shadow-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.contentShadowLayer()));
553
554     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::HeaderLayer))
555         dumpProperty(ts, "header-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.headerLayer()));
556
557     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::FooterLayer))
558         dumpProperty(ts, "footer-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.footerLayer()));
559 }
560
561 void RemoteScrollingTreeTextStream::dump(const ScrollingStateFixedNode& node, bool changedPropertiesOnly)
562 {
563     RemoteScrollingTreeTextStream& ts = *this;
564
565     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
566         ts << node.viewportConstraints();
567 }
568
569 void RemoteScrollingTreeTextStream::dump(const ScrollingStateStickyNode& node, bool changedPropertiesOnly)
570 {
571     RemoteScrollingTreeTextStream& ts = *this;
572
573     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
574         ts << node.viewportConstraints();
575 }
576
577 void RemoteScrollingTreeTextStream::recursiveDumpNodes(const ScrollingStateNode& node, bool changedPropertiesOnly)
578 {
579     RemoteScrollingTreeTextStream& ts = *this;
580
581     ts << "\n";
582     ts.increaseIndent();
583     ts.writeIndent();
584     dump(node, changedPropertiesOnly);
585
586     if (node.children()) {
587         ts << "\n";
588         ts.increaseIndent();
589         ts.writeIndent();
590         ts << "(children";
591         ts.increaseIndent();
592
593         for (auto& childNode : *node.children())
594             recursiveDumpNodes(*childNode, changedPropertiesOnly);
595
596         ts << ")";
597         ts.decreaseIndent();
598         ts.decreaseIndent();
599     }
600
601     ts << ")";
602     ts.decreaseIndent();
603 }
604
605 void RemoteScrollingTreeTextStream::dump(const ScrollingStateTree& stateTree, bool changedPropertiesOnly)
606 {
607     RemoteScrollingTreeTextStream& ts = *this;
608
609     dumpProperty(ts, "has changed properties", stateTree.hasChangedProperties());
610     dumpProperty(ts, "has new root node", stateTree.hasNewRootStateNode());
611
612     if (stateTree.rootStateNode())
613         recursiveDumpNodes(*stateTree.rootStateNode(), changedPropertiesOnly);
614
615     if (!stateTree.removedNodes().isEmpty())
616         dumpProperty<Vector<ScrollingNodeID>>(ts, "removed-nodes", stateTree.removedNodes());
617 }
618
619 WTF::CString RemoteScrollingCoordinatorTransaction::description() const
620 {
621     RemoteScrollingTreeTextStream ts;
622
623     ts << "(\n";
624     ts.increaseIndent();
625     ts.writeIndent();
626     ts << "(scrolling state tree";
627
628     if (m_scrollingStateTree) {
629         if (!m_scrollingStateTree->hasChangedProperties())
630             ts << " - no changes";
631         else
632             ts.dump(*m_scrollingStateTree.get());
633     } else
634         ts << " - none";
635
636     ts << ")\n";
637     ts.decreaseIndent();
638
639     return ts.release().utf8();
640 }
641
642 void RemoteScrollingCoordinatorTransaction::dump() const
643 {
644     fprintf(stderr, "%s", description().data());
645 }
646 #endif
647
648 } // namespace WebKit
649
650 #else // !ENABLE(ASYNC_SCROLLING)
651
652 namespace WebKit {
653
654 void RemoteScrollingCoordinatorTransaction::encode(IPC::ArgumentEncoder&) const
655 {
656 }
657
658 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteScrollingCoordinatorTransaction& transaction)
659 {
660     return true;
661 }
662
663 } // namespace WebKit
664
665 #endif // ENABLE(ASYNC_SCROLLING)