b36bfcc788e85f9a030a82c6c82b148fef437fd5
[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/ScrollingStateFrameScrollingNode.h>
36 #include <WebCore/ScrollingStateOverflowScrollingNode.h>
37 #include <WebCore/ScrollingStateStickyNode.h>
38 #include <WebCore/ScrollingStateTree.h>
39 #include <WebCore/TextStream.h>
40 #include <wtf/text/CString.h>
41 #include <wtf/text/StringBuilder.h>
42
43 #include <wtf/HashMap.h>
44
45 using namespace WebCore;
46
47 #if ENABLE(ASYNC_SCROLLING)
48
49 namespace IPC {
50
51 template<> struct ArgumentCoder<ScrollingStateNode> {
52     static void encode(ArgumentEncoder&, const ScrollingStateNode&);
53     static bool decode(ArgumentDecoder&, ScrollingStateNode&);
54 };
55
56 template<> struct ArgumentCoder<ScrollingStateScrollingNode> {
57     static void encode(ArgumentEncoder&, const ScrollingStateScrollingNode&);
58     static bool decode(ArgumentDecoder&, ScrollingStateScrollingNode&);
59 };
60     
61 template<> struct ArgumentCoder<ScrollingStateFrameScrollingNode> {
62     static void encode(ArgumentEncoder&, const ScrollingStateFrameScrollingNode&);
63     static bool decode(ArgumentDecoder&, ScrollingStateFrameScrollingNode&);
64 };
65     
66 template<> struct ArgumentCoder<ScrollingStateOverflowScrollingNode> {
67     static void encode(ArgumentEncoder&, const ScrollingStateOverflowScrollingNode&);
68     static bool decode(ArgumentDecoder&, ScrollingStateOverflowScrollingNode&);
69 };
70     
71 template<> struct ArgumentCoder<ScrollingStateFixedNode> {
72     static void encode(ArgumentEncoder&, const ScrollingStateFixedNode&);
73     static bool decode(ArgumentDecoder&, ScrollingStateFixedNode&);
74 };
75
76 template<> struct ArgumentCoder<ScrollingStateStickyNode> {
77     static void encode(ArgumentEncoder&, const ScrollingStateStickyNode&);
78     static bool decode(ArgumentDecoder&, ScrollingStateStickyNode&);
79 };
80
81 } // namespace IPC
82
83 using namespace IPC;
84
85 void ArgumentCoder<ScrollingStateNode>::encode(ArgumentEncoder& encoder, const ScrollingStateNode& node)
86 {
87     encoder.encodeEnum(node.nodeType());
88     encoder << node.scrollingNodeID();
89     encoder << node.parentNodeID();
90     encoder << node.changedProperties();
91     
92     if (node.hasChangedProperty(ScrollingStateNode::ScrollLayer))
93         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.layer());
94 }
95
96 bool ArgumentCoder<ScrollingStateNode>::decode(ArgumentDecoder& decoder, ScrollingStateNode& node)
97 {
98     // nodeType, scrollingNodeID and parentNodeID have already been decoded by the caller in order to create the node.
99     ScrollingStateNode::ChangedProperties changedProperties;
100     if (!decoder.decode(changedProperties))
101         return false;
102
103     node.setChangedProperties(changedProperties);
104     if (node.hasChangedProperty(ScrollingStateNode::ScrollLayer)) {
105         GraphicsLayer::PlatformLayerID layerID;
106         if (!decoder.decode(layerID))
107             return false;
108         node.setLayer(layerID);
109     }
110
111     return true;
112 }
113
114 #define SCROLLING_NODE_ENCODE(property, getter) \
115     if (node.hasChangedProperty(property)) \
116         encoder << node.getter();
117
118 #define SCROLLING_NODE_ENCODE_ENUM(property, getter) \
119     if (node.hasChangedProperty(property)) \
120         encoder.encodeEnum(node.getter());
121
122 void ArgumentCoder<ScrollingStateScrollingNode>::encode(ArgumentEncoder& encoder, const ScrollingStateScrollingNode& node)
123 {
124     encoder << static_cast<const ScrollingStateNode&>(node);
125     
126     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollableAreaSize, scrollableAreaSize)
127     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::TotalContentsSize, totalContentsSize)
128     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ReachableContentsSize, reachableContentsSize)
129     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollPosition, scrollPosition)
130     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollOrigin, scrollOrigin)
131 #if ENABLE(CSS_SCROLL_SNAP)
132     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, horizontalSnapOffsets)
133     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::VerticalSnapOffsets, verticalSnapOffsets)
134 #endif
135     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollableAreaParams, scrollableAreaParameters)
136     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPosition)
137     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPositionRepresentsProgrammaticScroll)
138 }
139
140 void ArgumentCoder<ScrollingStateFrameScrollingNode>::encode(ArgumentEncoder& encoder, const ScrollingStateFrameScrollingNode& node)
141 {
142     encoder << static_cast<const ScrollingStateScrollingNode&>(node);
143     
144     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::FrameScaleFactor, frameScaleFactor)
145     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::NonFastScrollableRegion, nonFastScrollableRegion)
146     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::WheelEventHandlerCount, wheelEventHandlerCount)
147     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::ReasonsForSynchronousScrolling, synchronousScrollingReasons)
148     SCROLLING_NODE_ENCODE_ENUM(ScrollingStateFrameScrollingNode::BehaviorForFixedElements, scrollBehaviorForFixedElements)
149     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::HeaderHeight, headerHeight)
150     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::FooterHeight, footerHeight)
151     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::TopContentInset, topContentInset)
152
153     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::ScrolledContentsLayer))
154         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer());
155
156     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::CounterScrollingLayer))
157         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.counterScrollingLayer());
158
159     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::InsetClipLayer))
160         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.insetClipLayer());
161
162     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::ContentShadowLayer))
163         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.contentShadowLayer());
164 }
165
166 void ArgumentCoder<ScrollingStateOverflowScrollingNode>::encode(ArgumentEncoder& encoder, const ScrollingStateOverflowScrollingNode& node)
167 {
168     encoder << static_cast<const ScrollingStateScrollingNode&>(node);
169     
170     if (node.hasChangedProperty(ScrollingStateOverflowScrollingNode::ScrolledContentsLayer))
171         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer());
172 }
173
174 #define SCROLLING_NODE_DECODE(property, type, setter) \
175     if (node.hasChangedProperty(property)) { \
176         type decodedValue; \
177         if (!decoder.decode(decodedValue)) \
178             return false; \
179         node.setter(decodedValue); \
180     }
181
182 #define SCROLLING_NODE_DECODE_ENUM(property, type, setter) \
183     if (node.hasChangedProperty(property)) { \
184         type decodedValue; \
185         if (!decoder.decodeEnum(decodedValue)) \
186             return false; \
187         node.setter(decodedValue); \
188     }
189
190 bool ArgumentCoder<ScrollingStateScrollingNode>::decode(ArgumentDecoder& decoder, ScrollingStateScrollingNode& node)
191 {
192     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
193         return false;
194
195     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollableAreaSize, FloatSize, setScrollableAreaSize);
196     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::TotalContentsSize, FloatSize, setTotalContentsSize);
197     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ReachableContentsSize, FloatSize, setReachableContentsSize);
198     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollPosition, FloatPoint, setScrollPosition);
199     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollOrigin, IntPoint, setScrollOrigin);
200 #if ENABLE(CSS_SCROLL_SNAP)
201     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::HorizontalSnapOffsets, Vector<float>, setHorizontalSnapOffsets);
202     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::VerticalSnapOffsets, Vector<float>, setVerticalSnapOffsets);
203 #endif
204     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
205     
206     if (node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
207         FloatPoint scrollPosition;
208         if (!decoder.decode(scrollPosition))
209             return false;
210
211         bool representsProgrammaticScroll;
212         if (!decoder.decode(representsProgrammaticScroll))
213             return false;
214
215         node.setRequestedScrollPosition(scrollPosition, representsProgrammaticScroll);
216     }
217
218     return true;
219 }
220
221 bool ArgumentCoder<ScrollingStateFrameScrollingNode>::decode(ArgumentDecoder& decoder, ScrollingStateFrameScrollingNode& node)
222 {
223     if (!decoder.decode(static_cast<ScrollingStateScrollingNode&>(node)))
224         return false;
225
226     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::FrameScaleFactor, float, setFrameScaleFactor);
227     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::NonFastScrollableRegion, Region, setNonFastScrollableRegion);
228     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::WheelEventHandlerCount, int, setWheelEventHandlerCount);
229     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::ReasonsForSynchronousScrolling, SynchronousScrollingReasons, setSynchronousScrollingReasons);
230     SCROLLING_NODE_DECODE_ENUM(ScrollingStateFrameScrollingNode::BehaviorForFixedElements, ScrollBehaviorForFixedElements, setScrollBehaviorForFixedElements);
231
232     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::HeaderHeight, int, setHeaderHeight);
233     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::FooterHeight, int, setFooterHeight);
234     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::TopContentInset, float, setTopContentInset);
235
236     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::ScrolledContentsLayer)) {
237         GraphicsLayer::PlatformLayerID layerID;
238         if (!decoder.decode(layerID))
239             return false;
240         node.setScrolledContentsLayer(layerID);
241     }
242
243     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::CounterScrollingLayer)) {
244         GraphicsLayer::PlatformLayerID layerID;
245         if (!decoder.decode(layerID))
246             return false;
247         node.setCounterScrollingLayer(layerID);
248     }
249
250     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::InsetClipLayer)) {
251         GraphicsLayer::PlatformLayerID layerID;
252         if (!decoder.decode(layerID))
253             return false;
254         node.setInsetClipLayer(layerID);
255     }
256
257     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::ContentShadowLayer)) {
258         GraphicsLayer::PlatformLayerID layerID;
259         if (!decoder.decode(layerID))
260             return false;
261         node.setContentShadowLayer(layerID);
262     }
263
264     return true;
265 }
266
267 bool ArgumentCoder<ScrollingStateOverflowScrollingNode>::decode(ArgumentDecoder& decoder, ScrollingStateOverflowScrollingNode& node)
268 {
269     if (!decoder.decode(static_cast<ScrollingStateScrollingNode&>(node)))
270         return false;
271
272     if (node.hasChangedProperty(ScrollingStateOverflowScrollingNode::ScrolledContentsLayer)) {
273         GraphicsLayer::PlatformLayerID layerID;
274         if (!decoder.decode(layerID))
275             return false;
276         node.setScrolledContentsLayer(layerID);
277     }
278
279     return true;
280 }
281
282 void ArgumentCoder<ScrollingStateFixedNode>::encode(ArgumentEncoder& encoder, const ScrollingStateFixedNode& node)
283 {
284     encoder << static_cast<const ScrollingStateNode&>(node);
285     
286     if (node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
287         encoder << node.viewportConstraints();
288 }
289
290 bool ArgumentCoder<ScrollingStateFixedNode>::decode(ArgumentDecoder& decoder, ScrollingStateFixedNode& node)
291 {
292     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
293         return false;
294
295     if (node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints)) {
296         FixedPositionViewportConstraints decodedValue;
297         if (!decoder.decode(decodedValue))
298             return false;
299         node.updateConstraints(decodedValue);
300     }
301
302     return true;
303 }
304
305 void ArgumentCoder<ScrollingStateStickyNode>::encode(ArgumentEncoder& encoder, const ScrollingStateStickyNode& node)
306 {
307     encoder << static_cast<const ScrollingStateNode&>(node);
308     
309     if (node.hasChangedProperty(ScrollingStateStickyNode::ViewportConstraints))
310         encoder << node.viewportConstraints();
311 }
312
313 bool ArgumentCoder<ScrollingStateStickyNode>::decode(ArgumentDecoder& decoder, ScrollingStateStickyNode& node)
314 {
315     if (!decoder.decode(static_cast<ScrollingStateNode&>(node)))
316         return false;
317
318     if (node.hasChangedProperty(ScrollingStateStickyNode::ViewportConstraints)) {
319         StickyPositionViewportConstraints decodedValue;
320         if (!decoder.decode(decodedValue))
321             return false;
322         node.updateConstraints(decodedValue);
323     }
324
325     return true;
326 }
327
328 namespace WebKit {
329
330 static void encodeNodeAndDescendants(IPC::ArgumentEncoder& encoder, const ScrollingStateNode& stateNode, int& encodedNodeCount)
331 {
332     ++encodedNodeCount;
333
334     switch (stateNode.nodeType()) {
335     case FrameScrollingNode:
336         encoder << downcast<ScrollingStateFrameScrollingNode>(stateNode);
337         break;
338     case OverflowScrollingNode:
339         encoder << downcast<ScrollingStateOverflowScrollingNode>(stateNode);
340         break;
341     case FixedNode:
342         encoder << downcast<ScrollingStateFixedNode>(stateNode);
343         break;
344     case StickyNode:
345         encoder << downcast<ScrollingStateStickyNode>(stateNode);
346         break;
347     }
348
349     if (!stateNode.children())
350         return;
351
352     for (const auto& child : *stateNode.children())
353         encodeNodeAndDescendants(encoder, *child.get(), encodedNodeCount);
354 }
355
356 void RemoteScrollingCoordinatorTransaction::encode(IPC::ArgumentEncoder& encoder) const
357 {
358     int numNodes = m_scrollingStateTree ? m_scrollingStateTree->nodeCount() : 0;
359     encoder << numNodes;
360     
361     bool hasNewRootNode = m_scrollingStateTree ? m_scrollingStateTree->hasNewRootStateNode() : false;
362     encoder << hasNewRootNode;
363
364     if (m_scrollingStateTree) {
365         encoder << m_scrollingStateTree->hasChangedProperties();
366
367         int numNodesEncoded = 0;
368         if (const ScrollingStateNode* rootNode = m_scrollingStateTree->rootStateNode())
369             encodeNodeAndDescendants(encoder, *rootNode, numNodesEncoded);
370
371         ASSERT_UNUSED(numNodesEncoded, numNodesEncoded == numNodes);
372         encoder << m_scrollingStateTree->removedNodes();
373     } else
374         encoder << Vector<ScrollingNodeID>();
375 }
376
377 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteScrollingCoordinatorTransaction& transaction)
378 {
379     return transaction.decode(decoder);
380 }
381
382 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder)
383 {
384     int numNodes;
385     if (!decoder.decode(numNodes))
386         return false;
387
388     bool hasNewRootNode;
389     if (!decoder.decode(hasNewRootNode))
390         return false;
391     
392     m_scrollingStateTree = std::make_unique<ScrollingStateTree>();
393
394     bool hasChangedProperties;
395     if (!decoder.decode(hasChangedProperties))
396         return false;
397
398     m_scrollingStateTree->setHasChangedProperties(hasChangedProperties);
399
400     for (int i = 0; i < numNodes; ++i) {
401         ScrollingNodeType nodeType;
402         if (!decoder.decodeEnum(nodeType))
403             return false;
404
405         ScrollingNodeID nodeID;
406         if (!decoder.decode(nodeID))
407             return false;
408
409         ScrollingNodeID parentNodeID;
410         if (!decoder.decode(parentNodeID))
411             return false;
412
413         m_scrollingStateTree->attachNode(nodeType, nodeID, parentNodeID);
414         ScrollingStateNode* newNode = m_scrollingStateTree->stateNodeForID(nodeID);
415         ASSERT(newNode);
416         ASSERT(!parentNodeID || newNode->parent());
417         
418         switch (nodeType) {
419         case FrameScrollingNode:
420             if (!decoder.decode(downcast<ScrollingStateFrameScrollingNode>(*newNode)))
421                 return false;
422             break;
423         case OverflowScrollingNode:
424             if (!decoder.decode(downcast<ScrollingStateOverflowScrollingNode>(*newNode)))
425                 return false;
426             break;
427         case FixedNode:
428             if (!decoder.decode(downcast<ScrollingStateFixedNode>(*newNode)))
429                 return false;
430             break;
431         case StickyNode:
432             if (!decoder.decode(downcast<ScrollingStateStickyNode>(*newNode)))
433                 return false;
434             break;
435         }
436     }
437
438     m_scrollingStateTree->setHasNewRootStateNode(hasNewRootNode);
439
440     // Removed nodes
441     HashSet<ScrollingNodeID> removedNodes;
442     if (!decoder.decode(removedNodes))
443         return false;
444     
445     if (removedNodes.size())
446         m_scrollingStateTree->setRemovedNodes(removedNodes);
447
448     return true;
449 }
450
451 #if !defined(NDEBUG) || !LOG_DISABLED
452
453 class RemoteScrollingTreeTextStream : public TextStream {
454 public:
455     using TextStream::operator<<;
456
457     RemoteScrollingTreeTextStream()
458         : m_indent(0)
459     {
460     }
461
462     RemoteScrollingTreeTextStream& operator<<(FloatRect);
463     RemoteScrollingTreeTextStream& operator<<(ScrollingNodeType);
464
465     RemoteScrollingTreeTextStream& operator<<(const FixedPositionViewportConstraints&);
466     RemoteScrollingTreeTextStream& operator<<(const StickyPositionViewportConstraints&);
467
468     void dump(const ScrollingStateTree&, bool changedPropertiesOnly = true);
469
470     void dump(const ScrollingStateNode&, bool changedPropertiesOnly = true);
471     void dump(const ScrollingStateScrollingNode&, bool changedPropertiesOnly = true);
472     void dump(const ScrollingStateFrameScrollingNode&, bool changedPropertiesOnly = true);
473     void dump(const ScrollingStateOverflowScrollingNode&, bool changedPropertiesOnly = true);
474     void dump(const ScrollingStateFixedNode&, bool changedPropertiesOnly = true);
475     void dump(const ScrollingStateStickyNode&, bool changedPropertiesOnly = true);
476
477     void increaseIndent() { ++m_indent; }
478     void decreaseIndent() { --m_indent; ASSERT(m_indent >= 0); }
479
480     void writeIndent();
481
482 private:
483     void recursiveDumpNodes(const ScrollingStateNode&, bool changedPropertiesOnly);
484
485     int m_indent;
486 };
487
488 void RemoteScrollingTreeTextStream::writeIndent()
489 {
490     for (int i = 0; i < m_indent; ++i)
491         *this << "  ";
492 }
493
494 template <class T>
495 static void dumpProperty(RemoteScrollingTreeTextStream& ts, String name, T value)
496 {
497     ts << "\n";
498     ts.increaseIndent();
499     ts.writeIndent();
500     ts << "(" << name << " ";
501     ts << value << ")";
502     ts.decreaseIndent();
503 }
504
505 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(FloatRect rect)
506 {
507     RemoteScrollingTreeTextStream& ts = *this;
508     ts << rect.x() << " " << rect.y() << " " << rect.width() << " " << rect.height();
509     return ts;
510 }
511
512 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(ScrollingNodeType nodeType)
513 {
514     RemoteScrollingTreeTextStream& ts = *this;
515
516     switch (nodeType) {
517     case FrameScrollingNode: ts << "frame-scrolling"; break;
518     case OverflowScrollingNode: ts << "overflow-scrolling"; break;
519     case FixedNode: ts << "fixed"; break;
520     case StickyNode: ts << "sticky"; break;
521     }
522
523     return ts;
524 }
525
526 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(const FixedPositionViewportConstraints& constraints)
527 {
528     RemoteScrollingTreeTextStream& ts = *this;
529
530     dumpProperty(ts, "viewport-rect-at-last-layout", constraints.viewportRectAtLastLayout());
531     dumpProperty(ts, "layer-position-at-last-layout", constraints.layerPositionAtLastLayout());
532
533     return ts;
534 }
535
536 RemoteScrollingTreeTextStream& RemoteScrollingTreeTextStream::operator<<(const StickyPositionViewportConstraints& constraints)
537 {
538     RemoteScrollingTreeTextStream& ts = *this;
539
540     dumpProperty(ts, "sticky-position-at-last-layout", constraints.stickyOffsetAtLastLayout());
541     dumpProperty(ts, "layer-position-at-last-layout", constraints.layerPositionAtLastLayout());
542
543     return ts;
544 }
545
546 void RemoteScrollingTreeTextStream::dump(const ScrollingStateNode& node, bool changedPropertiesOnly)
547 {
548     RemoteScrollingTreeTextStream& ts = *this;
549
550     ts << "(node " << node.scrollingNodeID();
551
552     dumpProperty(ts, "type", node.nodeType());
553
554     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateNode::ScrollLayer))
555         dumpProperty(ts, "layer", static_cast<GraphicsLayer::PlatformLayerID>(node.layer()));
556     
557     switch (node.nodeType()) {
558     case FrameScrollingNode:
559         dump(downcast<ScrollingStateFrameScrollingNode>(node), changedPropertiesOnly);
560         break;
561     case OverflowScrollingNode:
562         dump(downcast<ScrollingStateOverflowScrollingNode>(node), changedPropertiesOnly);
563         break;
564     case FixedNode:
565         dump(downcast<ScrollingStateFixedNode>(node), changedPropertiesOnly);
566         break;
567     case StickyNode:
568         dump(downcast<ScrollingStateStickyNode>(node), changedPropertiesOnly);
569         break;
570     }
571 }
572     
573 void RemoteScrollingTreeTextStream::dump(const ScrollingStateScrollingNode& node, bool changedPropertiesOnly)
574 {
575     RemoteScrollingTreeTextStream& ts = *this;
576     
577     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollableAreaSize))
578         dumpProperty(ts, "scrollable-area-size", node.scrollableAreaSize());
579
580     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize))
581         dumpProperty(ts, "total-contents-size", node.totalContentsSize());
582
583     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ReachableContentsSize))
584         dumpProperty(ts, "reachable-contents-size", node.reachableContentsSize());
585
586     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition))
587         dumpProperty(ts, "scroll-position", node.scrollPosition());
588
589     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin))
590         dumpProperty(ts, "scroll-origin", node.scrollOrigin());
591
592     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
593         dumpProperty(ts, "requested-scroll-position", node.requestedScrollPosition());
594         dumpProperty(ts, "requested-scroll-position-is-programatic", node.requestedScrollPositionRepresentsProgrammaticScroll());
595     }
596 }
597     
598 void RemoteScrollingTreeTextStream::dump(const ScrollingStateFrameScrollingNode& node, bool changedPropertiesOnly)
599 {
600     RemoteScrollingTreeTextStream& ts = *this;
601     
602     dump(static_cast<const ScrollingStateScrollingNode&>(node), changedPropertiesOnly);
603     
604     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::FrameScaleFactor))
605         dumpProperty(ts, "frame-scale-factor", node.frameScaleFactor());
606
607     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::NonFastScrollableRegion)) {
608         ts << "\n";
609         ts.increaseIndent();
610         ts.writeIndent();
611         ts << "(non-fast-scrollable-region";
612         ts.increaseIndent();
613         for (auto rect : node.nonFastScrollableRegion().rects()) {
614             ts << "\n";
615             ts.writeIndent();
616             ts << rect;
617         }
618         ts << ")\n";
619         ts.decreaseIndent();
620         ts.decreaseIndent();
621     }
622
623     // FIXME: dump wheelEventHandlerCount
624     // FIXME: dump synchronousScrollingReasons
625     // FIXME: dump scrollableAreaParameters
626     // FIXME: dump scrollBehaviorForFixedElements
627
628     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderHeight))
629         dumpProperty(ts, "header-height", node.headerHeight());
630
631     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterHeight))
632         dumpProperty(ts, "footer-height", node.footerHeight());
633
634     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::TopContentInset))
635         dumpProperty(ts, "top-content-inset", node.topContentInset());
636
637     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::FrameScaleFactor))
638         dumpProperty(ts, "frame-scale-factor", node.frameScaleFactor());
639
640     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::ScrolledContentsLayer))
641         dumpProperty(ts, "scrolled-contents-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer()));
642
643     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::InsetClipLayer))
644         dumpProperty(ts, "clip-inset-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.insetClipLayer()));
645
646     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::ContentShadowLayer))
647         dumpProperty(ts, "content-shadow-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.contentShadowLayer()));
648
649     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderLayer))
650         dumpProperty(ts, "header-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.headerLayer()));
651
652     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterLayer))
653         dumpProperty(ts, "footer-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.footerLayer()));
654 }
655     
656 void RemoteScrollingTreeTextStream::dump(const ScrollingStateOverflowScrollingNode& node, bool changedPropertiesOnly)
657 {
658     RemoteScrollingTreeTextStream& ts = *this;
659     
660     dump(static_cast<const ScrollingStateScrollingNode&>(node), changedPropertiesOnly);
661     
662     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateOverflowScrollingNode::ScrolledContentsLayer))
663         dumpProperty(ts, "scrolled-contents-layer", static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer()));
664 }
665
666 void RemoteScrollingTreeTextStream::dump(const ScrollingStateFixedNode& node, bool changedPropertiesOnly)
667 {
668     RemoteScrollingTreeTextStream& ts = *this;
669
670     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
671         ts << node.viewportConstraints();
672 }
673
674 void RemoteScrollingTreeTextStream::dump(const ScrollingStateStickyNode& node, bool changedPropertiesOnly)
675 {
676     RemoteScrollingTreeTextStream& ts = *this;
677
678     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFixedNode::ViewportConstraints))
679         ts << node.viewportConstraints();
680 }
681
682 void RemoteScrollingTreeTextStream::recursiveDumpNodes(const ScrollingStateNode& node, bool changedPropertiesOnly)
683 {
684     RemoteScrollingTreeTextStream& ts = *this;
685
686     ts << "\n";
687     ts.increaseIndent();
688     ts.writeIndent();
689     dump(node, changedPropertiesOnly);
690
691     if (node.children()) {
692         ts << "\n";
693         ts.increaseIndent();
694         ts.writeIndent();
695         ts << "(children";
696         ts.increaseIndent();
697
698         for (auto& childNode : *node.children())
699             recursiveDumpNodes(*childNode, changedPropertiesOnly);
700
701         ts << ")";
702         ts.decreaseIndent();
703         ts.decreaseIndent();
704     }
705
706     ts << ")";
707     ts.decreaseIndent();
708 }
709
710 void RemoteScrollingTreeTextStream::dump(const ScrollingStateTree& stateTree, bool changedPropertiesOnly)
711 {
712     RemoteScrollingTreeTextStream& ts = *this;
713
714     dumpProperty(ts, "has changed properties", stateTree.hasChangedProperties());
715     dumpProperty(ts, "has new root node", stateTree.hasNewRootStateNode());
716
717     if (stateTree.rootStateNode())
718         recursiveDumpNodes(*stateTree.rootStateNode(), changedPropertiesOnly);
719
720     if (!stateTree.removedNodes().isEmpty()) {
721         Vector<ScrollingNodeID> removedNodes;
722         copyToVector(stateTree.removedNodes(), removedNodes);
723         dumpProperty<Vector<ScrollingNodeID>>(ts, "removed-nodes", removedNodes);
724     }
725 }
726
727 WTF::CString RemoteScrollingCoordinatorTransaction::description() const
728 {
729     RemoteScrollingTreeTextStream ts;
730
731     ts << "(\n";
732     ts.increaseIndent();
733     ts.writeIndent();
734     ts << "(scrolling state tree";
735
736     if (m_scrollingStateTree) {
737         if (!m_scrollingStateTree->hasChangedProperties())
738             ts << " - no changes";
739         else
740             ts.dump(*m_scrollingStateTree.get());
741     } else
742         ts << " - none";
743
744     ts << ")\n";
745     ts.decreaseIndent();
746
747     return ts.release().utf8();
748 }
749
750 void RemoteScrollingCoordinatorTransaction::dump() const
751 {
752     fprintf(stderr, "%s", description().data());
753 }
754 #endif
755
756 } // namespace WebKit
757
758 #else // !ENABLE(ASYNC_SCROLLING)
759
760 namespace WebKit {
761
762 void RemoteScrollingCoordinatorTransaction::encode(IPC::ArgumentEncoder&) const
763 {
764 }
765
766 bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteScrollingCoordinatorTransaction& transaction)
767 {
768     return true;
769 }
770
771 } // namespace WebKit
772
773 #endif // ENABLE(ASYNC_SCROLLING)