Make it possible to edit images inline
[WebKit-https.git] / Source / WebKit / UIProcess / RemoteLayerTree / RemoteLayerTreeHost.mm
1 /*
2  * Copyright (C) 2012-2017 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 #import "config.h"
27 #import "RemoteLayerTreeHost.h"
28
29 #import "Logging.h"
30 #import "RemoteLayerTreeDrawingAreaProxy.h"
31 #import "RemoteLayerTreePropertyApplier.h"
32 #import "RemoteLayerTreeTransaction.h"
33 #import "ShareableBitmap.h"
34 #import "WKAnimationDelegate.h"
35 #import "WebPageProxy.h"
36 #import "WebProcessProxy.h"
37 #import <QuartzCore/QuartzCore.h>
38 #import <WebCore/GraphicsContextCG.h>
39 #import <WebCore/IOSurface.h>
40 #import <WebCore/PlatformLayer.h>
41 #import <WebCore/WebActionDisablingCALayerDelegate.h>
42 #import <WebCore/WebCoreCALayerExtras.h>
43 #import <pal/spi/cocoa/QuartzCoreSPI.h>
44
45 #if PLATFORM(IOS_FAMILY)
46 #import <UIKit/UIView.h>
47 #endif
48
49 namespace WebKit {
50 using namespace WebCore;
51
52 #define RELEASE_LOG_IF_ALLOWED(...) RELEASE_LOG_IF(m_drawingArea && m_drawingArea->isAlwaysOnLoggingAllowed(), ViewState, __VA_ARGS__)
53
54 RemoteLayerTreeHost::RemoteLayerTreeHost(RemoteLayerTreeDrawingAreaProxy& drawingArea)
55     : m_drawingArea(&drawingArea)
56 {
57 }
58
59 RemoteLayerTreeHost::~RemoteLayerTreeHost()
60 {
61     for (auto& delegate : m_animationDelegates.values())
62         [delegate.get() invalidate];
63
64     clearLayers();
65 }
66
67 bool RemoteLayerTreeHost::updateLayerTree(const RemoteLayerTreeTransaction& transaction, float indicatorScaleFactor)
68 {
69     if (!m_drawingArea)
70         return false;
71
72     for (const auto& createdLayer : transaction.createdLayers()) {
73         const RemoteLayerTreeTransaction::LayerProperties* properties = transaction.changedLayerProperties().get(createdLayer.layerID);
74         createLayer(createdLayer, properties);
75     }
76
77     bool rootLayerChanged = false;
78     LayerOrView *rootLayer = getLayer(transaction.rootLayerID());
79     
80     if (!rootLayer)
81         RELEASE_LOG_IF_ALLOWED("%p RemoteLayerTreeHost::updateLayerTree - failed to find root layer with ID %llu", this, transaction.rootLayerID());
82
83     if (m_rootLayer != rootLayer) {
84         m_rootLayer = rootLayer;
85         rootLayerChanged = true;
86     }
87
88     typedef std::pair<GraphicsLayer::PlatformLayerID, GraphicsLayer::PlatformLayerID> LayerIDPair;
89     Vector<LayerIDPair> clonesToUpdate;
90
91 #if PLATFORM(MAC) || PLATFORM(IOSMAC)
92     // Can't use the iOS code on macOS yet: rdar://problem/31247730
93     auto layerContentsType = RemoteLayerBackingStore::LayerContentsType::IOSurface;
94 #else
95     auto layerContentsType = m_drawingArea->hasDebugIndicator() ? RemoteLayerBackingStore::LayerContentsType::IOSurface : RemoteLayerBackingStore::LayerContentsType::CAMachPort;
96 #endif
97     
98     for (auto& changedLayer : transaction.changedLayerProperties()) {
99         auto layerID = changedLayer.key;
100         const RemoteLayerTreeTransaction::LayerProperties& properties = *changedLayer.value;
101
102         LayerOrView *layer = getLayer(layerID);
103         ASSERT(layer);
104
105         RemoteLayerTreePropertyApplier::RelatedLayerMap relatedLayers;
106         if (properties.changedProperties & RemoteLayerTreeTransaction::ChildrenChanged) {
107             for (auto& child : properties.children)
108                 relatedLayers.set(child, (__bridge CFTypeRef)getLayer(child));
109         }
110
111         if (properties.changedProperties & RemoteLayerTreeTransaction::MaskLayerChanged && properties.maskLayerID)
112             relatedLayers.set(properties.maskLayerID, (__bridge CFTypeRef)getLayer(properties.maskLayerID));
113
114         if (properties.changedProperties & RemoteLayerTreeTransaction::ClonedContentsChanged && properties.clonedLayerID)
115             clonesToUpdate.append(LayerIDPair(layerID, properties.clonedLayerID));
116
117         if (m_isDebugLayerTreeHost) {
118             RemoteLayerTreePropertyApplier::applyProperties(layer, this, properties, relatedLayers, layerContentsType);
119
120             if (properties.changedProperties & RemoteLayerTreeTransaction::BorderWidthChanged)
121                 asLayer(layer).borderWidth = properties.borderWidth / indicatorScaleFactor;
122             asLayer(layer).masksToBounds = false;
123         } else
124             RemoteLayerTreePropertyApplier::applyProperties(layer, this, properties, relatedLayers, layerContentsType);
125     }
126     
127     for (const auto& layerPair : clonesToUpdate) {
128         LayerOrView *layer = getLayer(layerPair.first);
129         LayerOrView *clonedLayer = getLayer(layerPair.second);
130         asLayer(layer).contents = asLayer(clonedLayer).contents;
131     }
132
133     for (auto& destroyedLayer : transaction.destroyedLayers())
134         layerWillBeRemoved(destroyedLayer);
135
136     // Drop the contents of any layers which were unparented; the Web process will re-send
137     // the backing store in the commit that reparents them.
138     for (auto& newlyUnreachableLayerID : transaction.layerIDsWithNewlyUnreachableBackingStore())
139         asLayer(getLayer(newlyUnreachableLayerID)).contents = nullptr;
140
141     return rootLayerChanged;
142 }
143
144 LayerOrView *RemoteLayerTreeHost::getLayer(GraphicsLayer::PlatformLayerID layerID) const
145 {
146     if (!layerID)
147         return nil;
148
149     return m_layers.get(layerID).get();
150 }
151
152 void RemoteLayerTreeHost::layerWillBeRemoved(WebCore::GraphicsLayer::PlatformLayerID layerID)
153 {
154     auto animationDelegateIter = m_animationDelegates.find(layerID);
155     if (animationDelegateIter != m_animationDelegates.end()) {
156         [animationDelegateIter->value invalidate];
157         m_animationDelegates.remove(animationDelegateIter);
158     }
159
160     auto embeddedViewIter = m_layerToEmbeddedViewMap.find(layerID);
161     if (embeddedViewIter != m_layerToEmbeddedViewMap.end()) {
162         m_embeddedViews.remove(embeddedViewIter->value);
163         m_layerToEmbeddedViewMap.remove(embeddedViewIter);
164     }
165
166     m_layers.remove(layerID);
167 }
168
169 void RemoteLayerTreeHost::animationDidStart(WebCore::GraphicsLayer::PlatformLayerID layerID, CAAnimation *animation, MonotonicTime startTime)
170 {
171     if (!m_drawingArea)
172         return;
173
174     CALayer *layer = asLayer(getLayer(layerID));
175     if (!layer)
176         return;
177
178     String animationKey;
179     for (NSString *key in [layer animationKeys]) {
180         if ([layer animationForKey:key] == animation) {
181             animationKey = key;
182             break;
183         }
184     }
185
186     if (!animationKey.isEmpty())
187         m_drawingArea->acceleratedAnimationDidStart(layerID, animationKey, startTime);
188 }
189
190 void RemoteLayerTreeHost::animationDidEnd(WebCore::GraphicsLayer::PlatformLayerID layerID, CAAnimation *animation)
191 {
192     if (!m_drawingArea)
193         return;
194
195     CALayer *layer = asLayer(getLayer(layerID));
196     if (!layer)
197         return;
198
199     String animationKey;
200     for (NSString *key in [layer animationKeys]) {
201         if ([layer animationForKey:key] == animation) {
202             animationKey = key;
203             break;
204         }
205     }
206
207     if (!animationKey.isEmpty())
208         m_drawingArea->acceleratedAnimationDidEnd(layerID, animationKey);
209 }
210
211 void RemoteLayerTreeHost::detachFromDrawingArea()
212 {
213     m_drawingArea = nullptr;
214 }
215
216 void RemoteLayerTreeHost::clearLayers()
217 {
218     for (auto& idLayer : m_layers) {
219         m_animationDelegates.remove(idLayer.key);
220 #if PLATFORM(IOS_FAMILY)
221         [idLayer.value.get() removeFromSuperview];
222 #else
223         [asLayer(idLayer.value.get()) removeFromSuperlayer];
224 #endif
225     }
226
227     m_layers.clear();
228     m_embeddedViews.clear();
229     m_layerToEmbeddedViewMap.clear();
230     m_rootLayer = nullptr;
231 }
232
233 LayerOrView* RemoteLayerTreeHost::layerWithIDForTesting(uint64_t layerID) const
234 {
235     return getLayer(layerID);
236 }
237
238 static NSString* const WKLayerIDPropertyKey = @"WKLayerID";
239
240 void RemoteLayerTreeHost::setLayerID(CALayer *layer, WebCore::GraphicsLayer::PlatformLayerID layerID)
241 {
242     [layer setValue:[NSNumber numberWithUnsignedLongLong:layerID] forKey:WKLayerIDPropertyKey];
243 }
244
245 WebCore::GraphicsLayer::PlatformLayerID RemoteLayerTreeHost::layerID(CALayer* layer)
246 {
247     return [[layer valueForKey:WKLayerIDPropertyKey] unsignedLongLongValue];
248 }
249
250 #if !PLATFORM(IOS_FAMILY)
251 LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::LayerCreationProperties& properties, const RemoteLayerTreeTransaction::LayerProperties*)
252 {
253     RetainPtr<CALayer>& layer = m_layers.add(properties.layerID, nullptr).iterator->value;
254
255     ASSERT(!layer);
256
257     switch (properties.type) {
258     case PlatformCALayer::LayerTypeLayer:
259     case PlatformCALayer::LayerTypeWebLayer:
260     case PlatformCALayer::LayerTypeRootLayer:
261     case PlatformCALayer::LayerTypeSimpleLayer:
262     case PlatformCALayer::LayerTypeTiledBackingLayer:
263     case PlatformCALayer::LayerTypePageTiledBackingLayer:
264     case PlatformCALayer::LayerTypeTiledBackingTileLayer:
265     case PlatformCALayer::LayerTypeScrollingLayer:
266     case PlatformCALayer::LayerTypeEditableImageLayer:
267         layer = adoptNS([[CALayer alloc] init]);
268         break;
269     case PlatformCALayer::LayerTypeTransformLayer:
270         layer = adoptNS([[CATransformLayer alloc] init]);
271         break;
272     case PlatformCALayer::LayerTypeBackdropLayer:
273     case PlatformCALayer::LayerTypeLightSystemBackdropLayer:
274     case PlatformCALayer::LayerTypeDarkSystemBackdropLayer:
275 #if ENABLE(FILTERS_LEVEL_2)
276         layer = adoptNS([[CABackdropLayer alloc] init]);
277 #else
278         ASSERT_NOT_REACHED();
279         layer = adoptNS([[CALayer alloc] init]);
280 #endif
281         break;
282     case PlatformCALayer::LayerTypeCustom:
283     case PlatformCALayer::LayerTypeAVPlayerLayer:
284     case PlatformCALayer::LayerTypeContentsProvidedLayer:
285         if (!m_isDebugLayerTreeHost)
286             layer = [CALayer _web_renderLayerWithContextID:properties.hostingContextID];
287         else
288             layer = adoptNS([[CALayer alloc] init]);
289         break;
290     case PlatformCALayer::LayerTypeShapeLayer:
291         layer = adoptNS([[CAShapeLayer alloc] init]);
292         break;
293     default:
294         ASSERT_NOT_REACHED();
295     }
296
297     [layer setDelegate:[WebActionDisablingCALayerDelegate shared]];
298     setLayerID(layer.get(), properties.layerID);
299
300     return layer.get();
301 }
302 #endif
303
304 void RemoteLayerTreeHost::detachRootLayer()
305 {
306 #if PLATFORM(IOS_FAMILY)
307     [m_rootLayer removeFromSuperview];
308 #else
309     [asLayer(m_rootLayer) removeFromSuperlayer];
310 #endif
311     m_rootLayer = nullptr;
312 }
313
314 #if HAVE(IOSURFACE)
315 static void recursivelyMapIOSurfaceBackingStore(CALayer *layer)
316 {
317     if (layer.contents && CFGetTypeID((__bridge CFTypeRef)layer.contents) == CAMachPortGetTypeID()) {
318         MachSendRight port = MachSendRight::create(CAMachPortGetPort((__bridge CAMachPortRef)layer.contents));
319         auto surface = WebCore::IOSurface::createFromSendRight(WTFMove(port), sRGBColorSpaceRef());
320         layer.contents = surface ? surface->asLayerContents() : nil;
321     }
322
323     for (CALayer *sublayer in layer.sublayers)
324         recursivelyMapIOSurfaceBackingStore(sublayer);
325 }
326 #endif
327
328 void RemoteLayerTreeHost::mapAllIOSurfaceBackingStore()
329 {
330 #if HAVE(IOSURFACE)
331     recursivelyMapIOSurfaceBackingStore(asLayer(m_rootLayer));
332 #endif
333 }
334
335 } // namespace WebKit
336
337 #undef RELEASE_LOG_IF_ALLOWED