1f25c0d2d9277654f073f8ef0ce1de633ada95a1
[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
138 #define SCROLLING_NODE_DECODE(property, type, setter) \
139     if (node.hasChangedProperty(ScrollingStateScrollingNode::property)) { \
140         type decodedValue; \
141         if (!decoder.decode(decodedValue)) \
142             return false; \
143         node.setter(decodedValue); \
144     }
145
146 #define SCROLLING_NODE_DECODE_ENUM(property, type, setter) \
147     if (node.hasChangedProperty(ScrollingStateScrollingNode::property)) { \
148         type decodedValue; \
149         if (!decoder.decodeEnum(decodedValue)) \
150             return false; \
151         node.setter(decodedValue); \
152     }
153
154 bool ArgumentCoder<ScrollingStateScrollingNode>::decode(ArgumentDecoder& decoder, ScrollingStateScrollingNode& node)
155 {
156     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
157         return false;
158
159     SCROLLING_NODE_DECODE(ViewportSize, FloatSize, setViewportSize);
160     SCROLLING_NODE_DECODE(TotalContentsSize, IntSize, setTotalContentsSize);
161     SCROLLING_NODE_DECODE(ScrollPosition, FloatPoint, setScrollPosition);
162     SCROLLING_NODE_DECODE(ScrollOrigin, IntPoint, setScrollOrigin);
163     SCROLLING_NODE_DECODE(FrameScaleFactor, float, setFrameScaleFactor);
164     SCROLLING_NODE_DECODE(NonFastScrollableRegion, Region, setNonFastScrollableRegion);
165     SCROLLING_NODE_DECODE(WheelEventHandlerCount, int, setWheelEventHandlerCount);
166     SCROLLING_NODE_DECODE(ReasonsForSynchronousScrolling, SynchronousScrollingReasons, setSynchronousScrollingReasons);
167     SCROLLING_NODE_DECODE(ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
168     SCROLLING_NODE_DECODE_ENUM(BehaviorForFixedElements, ScrollBehaviorForFixedElements, setScrollBehaviorForFixedElements);
169
170     if (node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
171         FloatPoint scrollPosition;
172         if (!decoder.decode(scrollPosition))
173             return false;
174
175         bool representsProgrammaticScroll;
176         if (!decoder.decode(representsProgrammaticScroll))
177             return false;
178
179         node.setRequestedScrollPosition(scrollPosition, representsProgrammaticScroll);
180     }
181
182     SCROLLING_NODE_DECODE(HeaderHeight, int, setHeaderHeight);
183     SCROLLING_NODE_DECODE(FooterHeight, int, setFooterHeight);
184     SCROLLING_NODE_DECODE(TopContentInset, float, setTopContentInset);
185
186     if (node.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer)) {
187         GraphicsLayer::PlatformLayerID layerID;
188         if (!decoder.decode(layerID))
189             return false;
190         node.setScrolledContentsLayer(layerID);
191     }
192
193     if (node.hasChangedProperty(ScrollingStateScrollingNode::CounterScrollingLayer)) {
194         GraphicsLayer::PlatformLayerID layerID;
195         if (!decoder.decode(layerID))
196             return false;
197         node.setCounterScrollingLayer(layerID);
198     }
199
200     return true;
201 }
202
203 void ArgumentCoder<ScrollingStateFixedNode>::encode(ArgumentEncoder& encoder, const ScrollingStateFixedNode& node)
204 {
205     encoder << static_cast<const ScrollingStateNode&>(node);
206     
207     if (node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
208         encoder << node.viewportConstraints();
209 }
210
211 bool ArgumentCoder<ScrollingStateFixedNode>::decode(ArgumentDecoder& decoder, ScrollingStateFixedNode& node)
212 {
213     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
214         return false;
215
216     if (node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints)) {
217         FixedPositionViewportConstraints decodedValue;
218         if (!decoder.decode(decodedValue))
219             return false;
220         node.updateConstraints(decodedValue);
221     }
222
223     return true;
224 }
225
226 void ArgumentCoder<ScrollingStateStickyNode>::encode(ArgumentEncoder& encoder, const ScrollingStateStickyNode& node)
227 {
228     encoder << static_cast<const ScrollingStateNode&>(node);
229     
230     if (node.hasChangedProperty(ScrollingStateStickyNode::ViewportConstraints))
231         encoder << node.viewportConstraints();
232 }
233
234 bool ArgumentCoder<ScrollingStateStickyNode>::decode(ArgumentDecoder& decoder, ScrollingStateStickyNode& node)
235 {
236     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
237         return false;
238
239     if (node.hasChangedProperty(ScrollingStateStickyNode::ViewportConstraints)) {
240         StickyPositionViewportConstraints decodedValue;
241         if (!decoder.decode(decodedValue))
242             return false;
243         node.updateConstraints(decodedValue);
244     }
245
246     return true;
247 }
248
249 namespace WebKit {
250
251 static void encodeNodeAndDescendants(IPC::ArgumentEncoder& encoder, const ScrollingStateNode& stateNode)
252 {
253     switch (stateNode.nodeType()) {
254     case FrameScrollingNode:
255     case OverflowScrollingNode:
256         encoder << toScrollingStateScrollingNode(stateNode);
257         break;
258     case FixedNode:
259         encoder << toScrollingStateFixedNode(stateNode);
260         break;
261     case StickyNode:
262         encoder << toScrollingStateStickyNode(stateNode);
263         break;
264     }
265
266     if (!stateNode.children())
267         return;
268
269     for (size_t i = 0; i < stateNode.children()->size(); ++i) {
270         const OwnPtr<ScrollingStateNode>& child = stateNode.children()->at(i);
271         encodeNodeAndDescendants(encoder, *child.get());
272     }
273 }
274
275 void RemoteScrollingCoordinatorTransaction::encode(IPC::ArgumentEncoder& encoder) const
276 {
277     int numNodes = m_scrollingStateTree ? m_scrollingStateTree->nodeCount() : 0;
278     encoder << numNodes;
279     
280     bool hasNewRootNode = m_scrollingStateTree ? m_scrollingStateTree->hasNewRootStateNode() : false;
281     encoder << hasNewRootNode;
282
283     if (m_scrollingStateTree) {
284         encoder << m_scrollingStateTree->hasChangedProperties();
285
286         if (const ScrollingStateNode* rootNode = m_scrollingStateTree->rootStateNode())
287             encodeNodeAndDescendants(encoder, *rootNode);
288
289         encoder << m_scrollingStateTree->removedNodes();
290     } else
291         encoder << Vector<ScrollingNodeID>();
292 }
293
294 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteScrollingCoordinatorTransaction& transaction)
295 {
296     return transaction.decode(decoder);
297 }
298
299 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder)
300 {
301     int numNodes;
302     if (!decoder.decode(numNodes))
303         return false;
304
305     bool hasNewRootNode;
306     if (!decoder.decode(hasNewRootNode))
307         return false;
308     
309     m_scrollingStateTree = ScrollingStateTree::create();
310
311     bool hasChangedProperties;
312     if (!decoder.decode(hasChangedProperties))
313         return false;
314
315     m_scrollingStateTree->setHasChangedProperties(hasChangedProperties);
316
317     for (int i = 0; i < numNodes; ++i) {
318         ScrollingNodeType nodeType;
319         if (!decoder.decodeEnum(nodeType))
320             return false;
321
322         ScrollingNodeID nodeID;
323         if (!decoder.decode(nodeID))
324             return false;
325
326         ScrollingNodeID parentNodeID;
327         if (!decoder.decode(parentNodeID))
328             return false;
329
330         m_scrollingStateTree->attachNode(nodeType, nodeID, parentNodeID);
331         ScrollingStateNode* newNode = m_scrollingStateTree->stateNodeForID(nodeID);
332         ASSERT(newNode);
333         ASSERT(!parentNodeID || newNode->parent());
334         
335         switch (nodeType) {
336         case FrameScrollingNode:
337         case OverflowScrollingNode:
338             if (!decoder.decode(*toScrollingStateScrollingNode(newNode)))
339                 return false;
340             break;
341         case FixedNode:
342             if (!decoder.decode(*toScrollingStateFixedNode(newNode)))
343                 return false;
344             break;
345         case StickyNode:
346             if (!decoder.decode(*toScrollingStateStickyNode(newNode)))
347                 return false;
348             break;
349         }
350     }
351
352     m_scrollingStateTree->setHasNewRootStateNode(hasNewRootNode);
353
354     // Removed nodes
355     Vector<ScrollingNodeID> removedNodes;
356     if (!decoder.decode(removedNodes))
357         return false;
358     
359     if (removedNodes.size())
360         m_scrollingStateTree->setRemovedNodes(removedNodes);
361
362     return true;
363 }
364
365 #if !defined(NDEBUG) || !LOG_DISABLED
366
367 class RemoteScrollingTreeTextStream : public TextStream {
368 public:
369     using TextStream::operator<<;
370
371     RemoteScrollingTreeTextStream()
372         : m_indent(0)
373     {
374     }
375
376     RemoteScrollingTreeTextStream& operator<<(FloatRect);
377     RemoteScrollingTreeTextStream& operator<<(ScrollingNodeType);
378
379     RemoteScrollingTreeTextStream& operator<<(const FixedPositionViewportConstraints&);
380     RemoteScrollingTreeTextStream& operator<<(const StickyPositionViewportConstraints&);
381
382     void dump(const ScrollingStateTree&, bool changedPropertiesOnly = true);
383
384     void dump(const ScrollingStateNode&, bool changedPropertiesOnly = true);
385     void dump(const ScrollingStateScrollingNode&, bool changedPropertiesOnly = true);
386     void dump(const ScrollingStateFixedNode&, bool changedPropertiesOnly = true);
387     void dump(const ScrollingStateStickyNode&, bool changedPropertiesOnly = true);
388
389     void increaseIndent() { ++m_indent; }
390     void decreaseIndent() { --m_indent; ASSERT(m_indent >= 0); }
391
392     void writeIndent();
393
394 private:
395     void recursiveDumpNodes(const ScrollingStateNode&, bool changedPropertiesOnly);
396
397     int m_indent;
398 };
399
400 void RemoteScrollingTreeTextStream::writeIndent()
401 {
402     for (int i = 0; i < m_indent; ++i)
403         *this << "  ";
404 }
405
406 template <class T>
407 static void dumpProperty(RemoteScrollingTreeTextStream& ts, String name, T value)
408 {
409     ts << "\n";
410     ts.increaseIndent();
411     ts.writeIndent();
412     ts << "(" << name << " ";
413     ts << value << ")";
414     ts.decreaseIndent();
415 }
416
417 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(FloatRect rect)
418 {
419     RemoteScrollingTreeTextStream& ts = *this;
420     ts << rect.x() << " " << rect.y() << " " << rect.width() << " " << rect.height();
421     return ts;
422 }
423
424 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(ScrollingNodeType nodeType)
425 {
426     RemoteScrollingTreeTextStream& ts = *this;
427
428     switch (nodeType) {
429     case FrameScrollingNode: ts << "frame-scrolling"; break;
430     case OverflowScrollingNode: ts << "overflow-scrolling"; break;
431     case FixedNode: ts << "fixed"; break;
432     case StickyNode: ts << "sticky"; break;
433     }
434
435     return ts;
436 }
437
438 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(const FixedPositionViewportConstraints& constraints)
439 {
440     RemoteScrollingTreeTextStream& ts = *this;
441
442     dumpProperty(ts, "viewport-rect-at-last-layout", constraints.viewportRectAtLastLayout());
443     dumpProperty(ts, "layer-position-at-last-layout", constraints.layerPositionAtLastLayout());
444
445     return ts;
446 }
447
448 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(const StickyPositionViewportConstraints& constraints)
449 {
450     RemoteScrollingTreeTextStream& ts = *this;
451
452     dumpProperty(ts, "sticky-position-at-last-layout", constraints.stickyOffsetAtLastLayout());
453     dumpProperty(ts, "layer-position-at-last-layout", constraints.layerPositionAtLastLayout());
454
455     return ts;
456 }
457
458 void RemoteScrollingTreeTextStream::dump(const ScrollingStateNode& node, bool changedPropertiesOnly)
459 {
460     RemoteScrollingTreeTextStream& ts = *this;
461
462     ts << "(node " << node.scrollingNodeID();
463
464     dumpProperty(ts, "type", node.nodeType());
465
466     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateNode::ScrollLayer))
467         dumpProperty(ts, "layer", static_cast<GraphicsLayer::PlatformLayerID>(node.layer()));
468     
469     switch (node.nodeType()) {
470     case FrameScrollingNode:
471     case OverflowScrollingNode:
472         dump(toScrollingStateScrollingNode(node), changedPropertiesOnly);
473         break;
474     case FixedNode:
475         dump(toScrollingStateFixedNode(node), changedPropertiesOnly);
476         break;
477     case StickyNode:
478         dump(toScrollingStateStickyNode(node), changedPropertiesOnly);
479         break;
480     }
481 }
482
483 void RemoteScrollingTreeTextStream::dump(const ScrollingStateScrollingNode& node, bool changedPropertiesOnly)
484 {
485     RemoteScrollingTreeTextStream& ts = *this;
486
487     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ViewportSize))
488         dumpProperty(ts, "viewport-size", node.viewportSize());
489
490     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize))
491         dumpProperty(ts, "total-contents-size", node.totalContentsSize());
492
493     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition))
494         dumpProperty(ts, "scroll-position", node.scrollPosition());
495
496     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
497         dumpProperty(ts, "scroll-origin", node.scrollOrigin());
498
499     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::FrameScaleFactor))
500         dumpProperty(ts, "frame-scale-factor", node.frameScaleFactor());
501
502     // FIXME: dump nonFastScrollableRegion
503     // FIXME: dump wheelEventHandlerCount
504     // FIXME: dump synchronousScrollingReasons
505     // FIXME: dump scrollableAreaParameters
506     // FIXME: dump scrollBehaviorForFixedElements
507
508     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
509         dumpProperty(ts, "requested-scroll-position", node.requestedScrollPosition());
510         dumpProperty(ts, "requested-scroll-position-is-programatic", node.requestedScrollPositionRepresentsProgrammaticScroll());
511     }
512
513     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::HeaderHeight))
514         dumpProperty(ts, "header-height", node.headerHeight());
515
516     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::FooterHeight))
517         dumpProperty(ts, "footer-height", node.footerHeight());
518
519     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::TopContentInset))
520         dumpProperty(ts, "top-content-inset", node.topContentInset());
521
522     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
523         dumpProperty(ts, "scrolled-contents-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer()));
524
525     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::CounterScrollingLayer))
526         dumpProperty(ts, "counter-scrolling-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.counterScrollingLayer()));
527
528     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::InsetClipLayer))
529         dumpProperty(ts, "clip-inset-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.insetClipLayer()));
530
531     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::HeaderLayer))
532         dumpProperty(ts, "header-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.headerLayer()));
533
534     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::FooterLayer))
535         dumpProperty(ts, "footer-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.footerLayer()));
536 }
537
538 void RemoteScrollingTreeTextStream::dump(const ScrollingStateFixedNode& node, bool changedPropertiesOnly)
539 {
540     RemoteScrollingTreeTextStream& ts = *this;
541
542     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
543         ts << node.viewportConstraints();
544 }
545
546 void RemoteScrollingTreeTextStream::dump(const ScrollingStateStickyNode& node, bool changedPropertiesOnly)
547 {
548     RemoteScrollingTreeTextStream& ts = *this;
549
550     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
551         ts << node.viewportConstraints();
552 }
553
554 void RemoteScrollingTreeTextStream::recursiveDumpNodes(const ScrollingStateNode& node, bool changedPropertiesOnly)
555 {
556     RemoteScrollingTreeTextStream& ts = *this;
557
558     ts << "\n";
559     ts.increaseIndent();
560     ts.writeIndent();
561     dump(node, changedPropertiesOnly);
562
563     if (node.children()) {
564         ts << "\n";
565         ts.increaseIndent();
566         ts.writeIndent();
567         ts << "(children";
568         ts.increaseIndent();
569
570         for (auto& childNode : *node.children())
571             recursiveDumpNodes(*childNode, changedPropertiesOnly);
572
573         ts << ")";
574         ts.decreaseIndent();
575         ts.decreaseIndent();
576     }
577
578     ts << ")";
579     ts.decreaseIndent();
580 }
581
582 void RemoteScrollingTreeTextStream::dump(const ScrollingStateTree& stateTree, bool changedPropertiesOnly)
583 {
584     RemoteScrollingTreeTextStream& ts = *this;
585
586     dumpProperty(ts, "has changed properties", stateTree.hasChangedProperties());
587     dumpProperty(ts, "has new root node", stateTree.hasNewRootStateNode());
588
589     if (stateTree.rootStateNode())
590         recursiveDumpNodes(*stateTree.rootStateNode(), changedPropertiesOnly);
591
592     if (!stateTree.removedNodes().isEmpty())
593         dumpProperty<Vector<ScrollingNodeID>>(ts, "removed-nodes", stateTree.removedNodes());
594 }
595
596 WTF::CString RemoteScrollingCoordinatorTransaction::description() const
597 {
598     RemoteScrollingTreeTextStream ts;
599
600     ts << "(\n";
601     ts.increaseIndent();
602     ts.writeIndent();
603     ts << "(scrolling state tree";
604
605     if (m_scrollingStateTree) {
606         if (!m_scrollingStateTree->hasChangedProperties())
607             ts << " - no changes";
608         else
609             ts.dump(*m_scrollingStateTree.get());
610     } else
611         ts << " - none";
612
613     ts << ")\n";
614     ts.decreaseIndent();
615
616     return ts.release().utf8();
617 }
618
619 void RemoteScrollingCoordinatorTransaction::dump() const
620 {
621     fprintf(stderr, "%s", description().data());
622 }
623 #endif
624
625 } // namespace WebKit
626
627 #else // !ENABLE(ASYNC_SCROLLING)
628
629 namespace WebKit {
630
631 void RemoteScrollingCoordinatorTransaction::encode(IPC::ArgumentEncoder&) const
632 {
633 }
634
635 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteScrollingCoordinatorTransaction& transaction)
636 {
637     return true;
638 }
639
640 } // namespace WebKit
641
642 #endif // ENABLE(ASYNC_SCROLLING)