Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / css / CSSImageSetValue.cpp
1 /*
2  * Copyright (C) 2012, 2013 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 "CSSImageSetValue.h"
28
29 #include "CSSImageValue.h"
30 #include "CSSPrimitiveValue.h"
31 #include "CachedImage.h"
32 #include "CachedResourceLoader.h"
33 #include "CachedResourceRequest.h"
34 #include "CachedResourceRequestInitiators.h"
35 #include "Document.h"
36 #include "Page.h"
37 #include <wtf/text/StringBuilder.h>
38
39 namespace WebCore {
40
41 CSSImageSetValue::CSSImageSetValue()
42     : CSSValueList(ImageSetClass, CommaSeparator)
43 {
44 }
45
46 CSSImageSetValue::~CSSImageSetValue() = default;
47
48 void CSSImageSetValue::fillImageSet()
49 {
50     size_t length = this->length();
51     size_t i = 0;
52     while (i < length) {
53         CSSValue* imageValue = item(i);
54         URL imageURL = downcast<CSSImageValue>(*imageValue).url();
55
56         ++i;
57         ASSERT_WITH_SECURITY_IMPLICATION(i < length);
58         CSSValue* scaleFactorValue = item(i);
59         float scaleFactor = downcast<CSSPrimitiveValue>(*scaleFactorValue).floatValue();
60
61         ImageWithScale image;
62         image.imageURL = imageURL;
63         image.scaleFactor = scaleFactor;
64         m_imagesInSet.append(image);
65         ++i;
66     }
67
68     // Sort the images so that they are stored in order from lowest resolution to highest.
69     std::sort(m_imagesInSet.begin(), m_imagesInSet.end(), CSSImageSetValue::compareByScaleFactor);
70 }
71
72 CSSImageSetValue::ImageWithScale CSSImageSetValue::bestImageForScaleFactor()
73 {
74     if (!m_imagesInSet.size())
75         fillImageSet();
76
77     ImageWithScale image;
78     size_t numberOfImages = m_imagesInSet.size();
79     for (size_t i = 0; i < numberOfImages; ++i) {
80         image = m_imagesInSet.at(i);
81         if (image.scaleFactor >= m_deviceScaleFactor)
82             return image;
83     }
84     return image;
85 }
86
87 std::pair<CachedImage*, float> CSSImageSetValue::loadBestFitImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
88 {
89     Document* document = loader.document();
90     ASSERT(document);
91
92     updateDeviceScaleFactor(*document);
93
94     if (!m_accessedBestFitImage) {
95         m_accessedBestFitImage = true;
96
97         // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here.
98         // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(),
99         // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
100         ImageWithScale image = bestImageForScaleFactor();
101         CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options);
102         request.setInitiator(cachedResourceRequestInitiators().css);
103         if (options.mode == FetchOptions::Mode::Cors)
104             request.updateForAccessControl(*document);
105
106         m_cachedImage = loader.requestImage(WTFMove(request)).valueOr(nullptr);
107         m_bestFitImageScaleFactor = image.scaleFactor;
108     }
109     return { m_cachedImage.get(), m_bestFitImageScaleFactor };
110 }
111
112 void CSSImageSetValue::updateDeviceScaleFactor(const Document& document)
113 {
114     float deviceScaleFactor = document.page() ? document.page()->deviceScaleFactor() : 1;
115     if (deviceScaleFactor == m_deviceScaleFactor)
116         return;
117     m_deviceScaleFactor = deviceScaleFactor;
118     m_accessedBestFitImage = false;
119     m_cachedImage = nullptr;
120 }
121
122 String CSSImageSetValue::customCSSText() const
123 {
124     StringBuilder result;
125     result.appendLiteral("image-set(");
126
127     size_t length = this->length();
128     size_t i = 0;
129     while (i < length) {
130         if (i > 0)
131             result.appendLiteral(", ");
132
133         const CSSValue* imageValue = item(i);
134         result.append(imageValue->cssText());
135         result.append(' ');
136
137         ++i;
138         ASSERT_WITH_SECURITY_IMPLICATION(i < length);
139         const CSSValue* scaleFactorValue = item(i);
140         result.append(scaleFactorValue->cssText());
141         // FIXME: Eventually the scale factor should contain it's own unit http://wkb.ug/100120.
142         // For now 'x' is hard-coded in the parser, so we hard-code it here too.
143         result.append('x');
144
145         ++i;
146     }
147
148     result.append(')');
149     return result.toString();
150 }
151
152 bool CSSImageSetValue::traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const
153 {
154     if (!m_cachedImage)
155         return false;
156     return handler(*m_cachedImage);
157 }
158
159 } // namespace WebCore