REGRESSION(r219045): A partially loaded image may not be repainted when its complete...
[WebKit-https.git] / Source / WebCore / loader / cache / CachedImage.h
1 /*
2     Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3     Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
4     Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
5     Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22
23 #pragma once
24
25 #include "CachedResource.h"
26 #include "Image.h"
27 #include "ImageObserver.h"
28 #include "IntRect.h"
29 #include "IntSizeHash.h"
30 #include "LayoutSize.h"
31 #include "SVGImageCache.h"
32 #include <wtf/HashMap.h>
33
34 namespace WebCore {
35
36 class CachedImageClient;
37 class CachedResourceLoader;
38 class FloatSize;
39 class MemoryCache;
40 class RenderElement;
41 class RenderObject;
42 class SecurityOrigin;
43
44 struct Length;
45
46 class CachedImage final : public CachedResource {
47     friend class MemoryCache;
48
49 public:
50     CachedImage(CachedResourceRequest&&, SessionID);
51     CachedImage(Image*, SessionID);
52     // Constructor to use for manually cached images.
53     CachedImage(const URL&, Image*, SessionID);
54     virtual ~CachedImage();
55
56     WEBCORE_EXPORT Image* image(); // Returns the nullImage() if the image is not available yet.
57     WEBCORE_EXPORT Image* imageForRenderer(const RenderObject*); // Returns the nullImage() if the image is not available yet.
58     bool hasImage() const { return m_image.get(); }
59     bool currentFrameKnownToBeOpaque(const RenderElement*);
60
61     std::pair<Image*, float> brokenImage(float deviceScaleFactor) const; // Returns an image and the image's resolution scale factor.
62     bool willPaintBrokenImage() const;
63
64     bool canRender(const RenderElement* renderer, float multiplier) { return !errorOccurred() && !imageSizeForRenderer(renderer, multiplier).isEmpty(); }
65
66     void setContainerSizeForRenderer(const CachedImageClient*, const LayoutSize&, float);
67     bool usesImageContainerSize() const { return m_image && m_image->usesContainerSize(); }
68     bool imageHasRelativeWidth() const { return m_image && m_image->hasRelativeWidth(); }
69     bool imageHasRelativeHeight() const { return m_image && m_image->hasRelativeHeight(); }
70
71     void addDataBuffer(SharedBuffer&) override;
72     void finishLoading(SharedBuffer*) override;
73
74     enum SizeType {
75         UsedSize,
76         IntrinsicSize
77     };
78     // This method takes a zoom multiplier that can be used to increase the natural size of the image by the zoom.
79     LayoutSize imageSizeForRenderer(const RenderElement*, float multiplier, SizeType = UsedSize); // returns the size of the complete image.
80     void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
81
82     bool isManuallyCached() const { return m_isManuallyCached; }
83     RevalidationDecision makeRevalidationDecision(CachePolicy) const override;
84     void load(CachedResourceLoader&) override;
85
86     bool isOriginClean(SecurityOrigin*);
87
88     void addPendingImageDrawingClient(CachedImageClient&);
89
90 private:
91     void clear();
92
93     CachedImage(CachedImage&, const ResourceRequest&, SessionID);
94
95     void setBodyDataFrom(const CachedResource&) final;
96
97     void createImage();
98     void clearImage();
99     // If not null, changeRect is the changed part of the image.
100     void notifyObservers(const IntRect* changeRect = nullptr);
101     void checkShouldPaintBrokenImage();
102
103     void switchClientsToRevalidatedResource() final;
104     bool mayTryReplaceEncodedData() const final { return true; }
105
106     void didAddClient(CachedResourceClient&) final;
107     void didRemoveClient(CachedResourceClient&) final;
108
109     void allClientsRemoved() override;
110     void destroyDecodedData() override;
111
112     EncodedDataStatus setImageDataBuffer(SharedBuffer*, bool allDataReceived);
113     void addData(const char* data, unsigned length) override;
114     void error(CachedResource::Status) override;
115     void responseReceived(const ResourceResponse&) override;
116
117     // For compatibility, images keep loading even if there are HTTP errors.
118     bool shouldIgnoreHTTPStatusCodeErrors() const override { return true; }
119
120     bool stillNeedsLoad() const override { return !errorOccurred() && status() == Unknown && !isLoading(); }
121
122     class CachedImageObserver final : public RefCounted<CachedImageObserver>, public ImageObserver {
123     public:
124         static Ref<CachedImageObserver> create(CachedImage& image) { return adoptRef(*new CachedImageObserver(image)); }
125         HashSet<CachedImage*>& cachedImages() { return m_cachedImages; }
126         const HashSet<CachedImage*>& cachedImages() const { return m_cachedImages; }
127
128     private:
129         explicit CachedImageObserver(CachedImage&);
130
131         // ImageObserver API
132         URL sourceUrl() const override { return !m_cachedImages.isEmpty() ? (*m_cachedImages.begin())->url() : URL(); }
133         void decodedSizeChanged(const Image&, long long delta) final;
134         void didDraw(const Image&) final;
135
136         bool canDestroyDecodedData(const Image&) final;
137         void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* changeRect = nullptr, DecodingStatus = DecodingStatus::Invalid) final;
138         void changedInRect(const Image&, const IntRect*) final;
139
140         HashSet<CachedImage*> m_cachedImages;
141     };
142
143     void decodedSizeChanged(const Image&, long long delta);
144     void didDraw(const Image&);
145     bool canDestroyDecodedData(const Image&);
146     void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* changeRect = nullptr, DecodingStatus = DecodingStatus::Invalid);
147     void changedInRect(const Image&, const IntRect*);
148
149     void addIncrementalDataBuffer(SharedBuffer&);
150
151     void didReplaceSharedBufferContents() override;
152
153     typedef std::pair<LayoutSize, float> SizeAndZoom;
154     typedef HashMap<const CachedImageClient*, SizeAndZoom> ContainerSizeRequests;
155     ContainerSizeRequests m_pendingContainerSizeRequests;
156
157     HashSet<CachedImageClient*> m_pendingImageDrawingClients;
158
159     RefPtr<CachedImageObserver> m_imageObserver;
160     RefPtr<Image> m_image;
161     std::unique_ptr<SVGImageCache> m_svgImageCache;
162     bool m_isManuallyCached { false };
163     bool m_shouldPaintBrokenImage { true };
164 };
165
166 } // namespace WebCore
167
168 SPECIALIZE_TYPE_TRAITS_CACHED_RESOURCE(CachedImage, CachedResource::ImageResource)