Skip to content

Commit

Permalink
Images in image-set are not saved when saving web page resources
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=271299
rdar://problem/125064898

Reviewed by Ryosuke Niwa.

CSSImageSetOptionValue has two enclosed CSSValues (one of which is a CSSImageValue) that do not get visited by custom
functions. As a result, the subresource is not collected and URL is not replaced when web page is saved. To fix this,
add implementation for the custom functions in CSSImageSetOptionValue.

* Source/WebCore/css/CSSImageSetOptionValue.cpp:
(WebCore::CSSImageSetOptionValue::customTraverseSubresources const):
(WebCore::CSSImageSetOptionValue::customSetReplacementURLForSubresources):
(WebCore::CSSImageSetOptionValue::customClearReplacementURLForSubresources):
* Source/WebCore/css/CSSImageSetOptionValue.h:
* Tools/TestWebKitAPI/Tests/WebKitCocoa/CreateWebArchive.mm:

Canonical link: https://commits.webkit.org/276472@main
  • Loading branch information
szewai committed Mar 21, 2024
1 parent ec4dec5 commit 501aaeb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
17 changes: 17 additions & 0 deletions Source/WebCore/css/CSSImageSetOptionValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,21 @@ void CSSImageSetOptionValue::setType(String type)
m_mimeType = WTFMove(type);
}

bool CSSImageSetOptionValue::customTraverseSubresources(const Function<bool(const CachedResource&)>& handler) const
{
return m_resolution->traverseSubresources(handler) || m_image->traverseSubresources(handler);
}

void CSSImageSetOptionValue::customSetReplacementURLForSubresources(const HashMap<String, String>& replacementURLStrings)
{
m_image->setReplacementURLForSubresources(replacementURLStrings);
m_resolution->setReplacementURLForSubresources(replacementURLStrings);
}

void CSSImageSetOptionValue::customClearReplacementURLForSubresources()
{
m_image->clearReplacementURLForSubresources();
m_resolution->clearReplacementURLForSubresources();
}

} // namespace WebCore
3 changes: 3 additions & 0 deletions Source/WebCore/css/CSSImageSetOptionValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class CSSImageSetOptionValue final : public CSSValue {
return IterationStatus::Done;
return IterationStatus::Continue;
}
bool customTraverseSubresources(const Function<bool(const CachedResource&)>&) const;
void customSetReplacementURLForSubresources(const HashMap<String, String>&);
void customClearReplacementURLForSubresources();

private:
CSSImageSetOptionValue(Ref<CSSValue>&&, Ref<CSSPrimitiveValue>&&);
Expand Down
40 changes: 23 additions & 17 deletions Tools/TestWebKitAPI/Tests/WebKitCocoa/CreateWebArchive.mm
Original file line number Diff line number Diff line change
Expand Up @@ -606,30 +606,36 @@ function createIframe() {
}

static const char* htmlDataBytesForResponsiveImages = R"TESTRESOURCE(
<head>
<script>
const dpr = window.devicePixelRatio;
// Use image-set for div.
style = document.createElement('style');
style.innerHTML = "div { background-image:image-set('div1.png' " + dpr + "x, 'div2.png' " + (dpr + 1) + "x)}";
document.getElementsByTagName("head")[0].appendChild(style);
</script>
</head>
<body>
<div id="div">Hello</div>
<script>
count = 0;
function replaceImg() {
img = document.getElementById("img_id");
const ratio = window.devicePixelRatio;
img.removeAttribute("src");
img.srcset = 'image2.png ' + ratio + 'x,' + ' image1.png ' + (ratio + 1) + 'x';
img2 = document.getElementById("img_id2");
document.body.removeChild(img2);
function addSrcsetToImage() {
image = document.getElementById("image");
image.removeAttribute("src");
image.srcset = "image2.png " + dpr + "x, image1.png " + (dpr + 1) + "x";
}
function onImageLoad() {
++count;
if (count == 3)
replaceImg();
if (count == 4)
if (count == 2) // image1.png and picture2.png are loaded.
addSrcsetToImage();
if (count == 3) // image2.png is loaded.
window.webkit.messageHandlers.testHandler.postMessage("done");
}
</script>
<img id="img_id" src="image1.png" onload="onImageLoad()">
<img id="img_id2" src="image3.png" onload="onImageLoad()">
<picture>
<source srcset="image3.png" media="(min-width: 3000px)">
<img src="image4.png" onload="onImageLoad()">
<img id="image" src="image1.png" onload="onImageLoad()">
<picture id="picture">
<source srcset="picture1.png" media="(min-width: 3000px)">
<img src="picture2.png" onload="onImageLoad()">
</picture>
</body>
)TESTRESOURCE";
Expand All @@ -651,7 +657,7 @@ function onImageLoad() {
if ([task.request.URL.absoluteString isEqualToString:@"webarchivetest://host/main.html"]) {
mimeType = @"text/html";
data = htmlData;
} else if ([task.request.URL.absoluteString containsString:@"image"]) {
} else if ([task.request.URL.absoluteString containsString:@"png"]) {
mimeType = @"image/png";
data = imageData;
} else
Expand Down Expand Up @@ -679,7 +685,7 @@ function onImageLoad() {
NSString *resourceDirectoryName = @"host_files";
NSString *resourceDirectoryPath = [directoryURL URLByAppendingPathComponent:resourceDirectoryName].path;
NSArray *resourceFileNames = [fileManager contentsOfDirectoryAtPath:resourceDirectoryPath error:0];
NSSet *expectedFileNames = [NSSet setWithArray:[NSArray arrayWithObjects:@"image1.png", @"image2.png", @"image3.png", @"image4.png", nil]];
NSSet *expectedFileNames = [NSSet setWithArray:[NSArray arrayWithObjects:@"image1.png", @"image2.png", @"picture2.png", @"div1.png", nil]];
NSSet *savedFileNames = [NSSet setWithArray:resourceFileNames];
EXPECT_TRUE([savedFileNames isEqualToSet:expectedFileNames]);

Expand Down

0 comments on commit 501aaeb

Please sign in to comment.