Limit user-agent interactions based on the touch-action property on iOS
[WebKit-https.git] / Source / WebKit / UIProcess / RemoteLayerTree / RemoteScrollingCoordinatorProxy.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 "RemoteScrollingCoordinatorProxy.h"
28
29 #if ENABLE(ASYNC_SCROLLING)
30
31 #include "ArgumentCoders.h"
32 #include "RemoteLayerTreeDrawingAreaProxy.h"
33 #include "RemoteScrollingCoordinator.h"
34 #include "RemoteScrollingCoordinatorMessages.h"
35 #include "RemoteScrollingCoordinatorTransaction.h"
36 #include "WebPageProxy.h"
37 #include "WebProcessProxy.h"
38 #include <WebCore/ScrollingStateFrameScrollingNode.h>
39 #include <WebCore/ScrollingStateOverflowScrollingNode.h>
40 #include <WebCore/ScrollingStateTree.h>
41 #include <WebCore/ScrollingTreeScrollingNode.h>
42
43 namespace WebKit {
44 using namespace WebCore;
45
46 RemoteScrollingCoordinatorProxy::RemoteScrollingCoordinatorProxy(WebPageProxy& webPageProxy)
47     : m_webPageProxy(webPageProxy)
48     , m_scrollingTree(RemoteScrollingTree::create(*this))
49     , m_requestedScrollInfo(nullptr)
50     , m_propagatesMainFrameScrolls(true)
51 {
52 }
53
54 RemoteScrollingCoordinatorProxy::~RemoteScrollingCoordinatorProxy()
55 {
56 }
57
58 ScrollingNodeID RemoteScrollingCoordinatorProxy::rootScrollingNodeID() const
59 {
60     if (!m_scrollingTree->rootNode())
61         return 0;
62
63     return m_scrollingTree->rootNode()->scrollingNodeID();
64 }
65
66 const RemoteLayerTreeHost* RemoteScrollingCoordinatorProxy::layerTreeHost() const
67 {
68     DrawingAreaProxy* drawingArea = m_webPageProxy.drawingArea();
69     if (!is<RemoteLayerTreeDrawingAreaProxy>(drawingArea)) {
70         ASSERT_NOT_REACHED();
71         return nullptr;
72     }
73
74     RemoteLayerTreeDrawingAreaProxy& remoteDrawingArea = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea);
75     return &remoteDrawingArea.remoteLayerTreeHost();
76 }
77
78 void RemoteScrollingCoordinatorProxy::commitScrollingTreeState(const RemoteScrollingCoordinatorTransaction& transaction, RequestedScrollInfo& requestedScrollInfo)
79 {
80     m_requestedScrollInfo = &requestedScrollInfo;
81
82     // FIXME: There must be a better idiom for this.
83     std::unique_ptr<ScrollingStateTree> stateTree(const_cast<RemoteScrollingCoordinatorTransaction&>(transaction).scrollingStateTree().release());
84
85     const RemoteLayerTreeHost* layerTreeHost = this->layerTreeHost();
86     if (!layerTreeHost) {
87         ASSERT_NOT_REACHED();
88         return;
89     }
90
91     connectStateNodeLayers(*stateTree, *layerTreeHost);
92     m_scrollingTree->commitTreeState(WTFMove(stateTree));
93
94     m_requestedScrollInfo = nullptr;
95 }
96
97 #if !PLATFORM(IOS_FAMILY)
98
99 void RemoteScrollingCoordinatorProxy::connectStateNodeLayers(ScrollingStateTree& stateTree, const RemoteLayerTreeHost& layerTreeHost)
100 {
101     for (auto& currNode : stateTree.nodeMap().values()) {
102         if (currNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))
103             currNode->setLayer(layerTreeHost.layerForID(currNode->layer()));
104
105         switch (currNode->nodeType()) {
106         case ScrollingNodeType::MainFrame:
107         case ScrollingNodeType::Subframe: {
108             ScrollingStateFrameScrollingNode& scrollingStateNode = downcast<ScrollingStateFrameScrollingNode>(*currNode);
109             
110             if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
111                 scrollingStateNode.setScrolledContentsLayer(layerTreeHost.layerForID(scrollingStateNode.scrolledContentsLayer()));
112
113             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::CounterScrollingLayer))
114                 scrollingStateNode.setCounterScrollingLayer(layerTreeHost.layerForID(scrollingStateNode.counterScrollingLayer()));
115
116             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::InsetClipLayer))
117                 scrollingStateNode.setInsetClipLayer(layerTreeHost.layerForID(scrollingStateNode.insetClipLayer()));
118
119             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::ContentShadowLayer))
120                 scrollingStateNode.setContentShadowLayer(layerTreeHost.layerForID(scrollingStateNode.contentShadowLayer()));
121
122             // FIXME: we should never have header and footer layers coming from the WebProcess.
123             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderLayer))
124                 scrollingStateNode.setHeaderLayer(layerTreeHost.layerForID(scrollingStateNode.headerLayer()));
125
126             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterLayer))
127                 scrollingStateNode.setFooterLayer(layerTreeHost.layerForID(scrollingStateNode.footerLayer()));
128
129             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::VerticalScrollbarLayer))
130                 scrollingStateNode.setVerticalScrollbarLayer(layerTreeHost.layerForID(scrollingStateNode.verticalScrollbarLayer()));
131
132             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HorizontalScrollbarLayer))
133                 scrollingStateNode.setHorizontalScrollbarLayer(layerTreeHost.layerForID(scrollingStateNode.horizontalScrollbarLayer()));
134             break;
135         }
136         case ScrollingNodeType::Overflow: {
137             ScrollingStateOverflowScrollingNode& scrollingStateNode = downcast<ScrollingStateOverflowScrollingNode>(*currNode);
138
139             if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
140                 scrollingStateNode.setScrolledContentsLayer(layerTreeHost.layerForID(scrollingStateNode.scrolledContentsLayer()));
141             break;
142         }
143         case ScrollingNodeType::FrameHosting:
144         case ScrollingNodeType::Fixed:
145         case ScrollingNodeType::Sticky:
146             break;
147         }
148     }
149 }
150 #endif
151
152 bool RemoteScrollingCoordinatorProxy::handleWheelEvent(const PlatformWheelEvent& event)
153 {
154     ScrollingTree::EventResult result = m_scrollingTree->tryToHandleWheelEvent(event);
155     return result == ScrollingTree::DidHandleEvent; // FIXME: handle other values.
156 }
157
158 void RemoteScrollingCoordinatorProxy::handleMouseEvent(const WebCore::PlatformMouseEvent& event)
159 {
160     m_scrollingTree->handleMouseEvent(event);
161 }
162
163 TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(const AtomicString& eventName, IntPoint p) const
164 {
165     return m_scrollingTree->eventTrackingTypeForPoint(eventName, p);
166 }
167
168 void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& fixedPositionRect, double scale)
169 {
170     m_scrollingTree->viewportChangedViaDelegatedScrolling(nodeID, fixedPositionRect, scale);
171 }
172
173 void RemoteScrollingCoordinatorProxy::currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID nodeID, unsigned horizontal, unsigned vertical)
174 {
175     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::CurrentSnapPointIndicesChangedForNode(nodeID, horizontal, vertical));
176 }
177
178 // This comes from the scrolling tree.
179 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& newScrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, ScrollingLayerPositionAction scrollingLayerPositionAction)
180 {
181     // Scroll updates for the main frame are sent via WebPageProxy::updateVisibleContentRects()
182     // so don't send them here.
183     if (!m_propagatesMainFrameScrolls && scrolledNodeID == rootScrollingNodeID())
184         return;
185
186 #if PLATFORM(IOS_FAMILY)
187     m_webPageProxy.scrollingNodeScrollViewDidScroll();
188 #endif
189     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition, scrollingLayerPositionAction == ScrollingLayerPositionAction::Sync));
190 }
191
192 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
193 {
194     if (scrolledNodeID == rootScrollingNodeID() && m_requestedScrollInfo) {
195         m_requestedScrollInfo->requestsScrollPositionUpdate = true;
196         m_requestedScrollInfo->requestIsProgrammaticScroll = representsProgrammaticScroll;
197         m_requestedScrollInfo->requestedScrollPosition = scrollPosition;
198     }
199 }
200
201 String RemoteScrollingCoordinatorProxy::scrollingTreeAsText() const
202 {
203     if (m_scrollingTree)
204         return m_scrollingTree->scrollingTreeAsText();
205     
206     return emptyString();
207 }
208
209 #if ENABLE(POINTER_EVENTS)
210 Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataAtPoint(const IntPoint p) const
211 {
212     return m_scrollingTree->touchActionDataAtPoint(p);
213 }
214
215 Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID(ScrollingNodeID scrollingNodeID) const
216 {
217     for (auto& touchActionData : m_touchActionDataByTouchIdentifier.values()) {
218         if (touchActionData.scrollingNodeID == scrollingNodeID)
219             return touchActionData;
220     }
221     return WTF::nullopt;
222 }
223
224 void RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier(TouchActionData touchActionData, unsigned touchIdentifier)
225 {
226     m_touchActionDataByTouchIdentifier.set(touchIdentifier, touchActionData);
227 }
228
229 void RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier(unsigned touchIdentifier)
230 {
231     m_touchActionDataByTouchIdentifier.remove(touchIdentifier);
232 }
233
234 #endif
235
236 } // namespace WebKit
237
238 #endif // ENABLE(ASYNC_SCROLLING)