Skip to content

Commit

Permalink
Serialize content of inline style with URL replacement
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=264185
rdar://117926863

Reviewed by Ryosuke Niwa.

We need to replace URLs in inline style when saving web page to disk.

API Test: WebArchive.SaveResourcesInlineStyle

* Source/WebCore/dom/StyledElement.cpp:
(WebCore::StyledElement::replaceURLsInAttributeValue const):
* Source/WebCore/dom/StyledElement.h:
* Tools/TestWebKitAPI/Tests/WebKitCocoa/CreateWebArchive.mm:

Canonical link: https://commits.webkit.org/270281@main
  • Loading branch information
szewai committed Nov 6, 2023
1 parent 16714da commit 9db4989
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 2 deletions.
19 changes: 19 additions & 0 deletions Source/WebCore/dom/StyledElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,25 @@ void StyledElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
});
}

Attribute StyledElement::replaceURLsInAttributeValue(const Attribute& attribute, const HashMap<String, String>& replacementURLStrings) const
{
if (replacementURLStrings.isEmpty())
return attribute;

if (attribute.name() != styleAttr)
return attribute;

RefPtr properties = this->inlineStyle();
if (!properties)
return attribute;

auto mutableProperties = properties->mutableCopy();
mutableProperties->setReplacementURLForSubresources(replacementURLStrings);
auto inlineStyleString = mutableProperties->asText();
mutableProperties->clearReplacementURLForSubresources();
return Attribute { styleAttr, AtomString { inlineStyleString } };
}

const ImmutableStyleProperties* StyledElement::presentationalHintStyle() const
{
if (!elementData())
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/dom/StyledElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class StyledElement : public Element {
void addPropertyToPresentationalHintStyle(MutableStyleProperties&, CSSPropertyID, const String& value);

void addSubresourceAttributeURLs(ListHashSet<URL>&) const override;
Attribute replaceURLsInAttributeValue(const Attribute&, const HashMap<String, String>&) const override;

private:
void styleAttributeChanged(const AtomString& newStyleString, AttributeModificationReason);
Expand Down
75 changes: 73 additions & 2 deletions Tools/TestWebKitAPI/Tests/WebKitCocoa/CreateWebArchive.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ function loaded() {
Util::run(&saved);
}

static const char* htmlDataBytesForCSS = R"TESTRESOURCE(
static const char* htmlDataBytesForStyle = R"TESTRESOURCE(
<style>
@font-face {
font-family: "WebFont";
Expand Down Expand Up @@ -1120,7 +1120,7 @@ function loaded() {
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
[configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"webarchivetest"];
NSData *htmlData = [NSData dataWithBytes:htmlDataBytesForCSS length:strlen(htmlDataBytesForCSS)];
NSData *htmlData = [NSData dataWithBytes:htmlDataBytesForStyle length:strlen(htmlDataBytesForStyle)];
NSData *imageData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"400x400-green" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"]];
NSData *fontData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"Ahem-10000A" withExtension:@"ttf" subdirectory:@"TestWebKitAPI.resources"]];
[schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
Expand Down Expand Up @@ -1174,6 +1174,77 @@ function loaded() {
Util::run(&saved);
}

static const char* htmlDataBytesForInlineStyle = R"TESTRESOURCE(
<div id="div" style="background-image:url('image.png');width:50%;height:50%;color:red">Hello</div>
<script>
div = document.getElementById("div");
div.style.color = "fuchsia";
imageURL = getComputedStyle(div).backgroundImage;
window.webkit.messageHandlers.testHandler.postMessage("done");
</script>
)TESTRESOURCE";

TEST(WebArchive, SaveResourcesInlineStyle)
{
RetainPtr<NSURL> directoryURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"SaveResourcesTest"] isDirectory:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:directoryURL.get() error:nil];

auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
[configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"webarchivetest"];
NSData *htmlData = [NSData dataWithBytes:htmlDataBytesForInlineStyle length:strlen(htmlDataBytesForInlineStyle)];
NSData *imageData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"400x400-green" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"]];
[schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
NSData *data = nil;
NSString *mimeType = nil;
if ([task.request.URL.absoluteString isEqualToString:@"webarchivetest://host/main.html"]) {
mimeType = @"text/html";
data = htmlData;
} else if ([task.request.URL.absoluteString isEqualToString:@"webarchivetest://host/image.png"]) {
mimeType = @"image/png";
data = imageData;
} else
FAIL();

auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:mimeType expectedContentLength:data.length textEncodingName:nil]);
[task didReceiveResponse:response.get()];
[task didReceiveData:data];
[task didFinish];
}];

auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
static bool messageReceived = false;
[webView performAfterReceivingMessage:@"done" action:[&] {
messageReceived = true;
}];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"webarchivetest://host/main.html"]]];
Util::run(&messageReceived);

static bool saved = false;
[webView _saveResources:directoryURL.get() suggestedFileName:@"host" completionHandler:^(NSError *error) {
EXPECT_NULL(error);
NSString *mainResourcePath = [directoryURL URLByAppendingPathComponent:@"host.html"].path;
EXPECT_TRUE([fileManager fileExistsAtPath:mainResourcePath]);

NSString *savedMainResource = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:mainResourcePath] encoding:NSUTF8StringEncoding];
EXPECT_TRUE([savedMainResource containsString:@"color: fuchsia"]);

NSString *resourceDirectoryName = @"host_files";
NSString *resourceDirectoryPath = [directoryURL URLByAppendingPathComponent:resourceDirectoryName].path;
NSArray *resourceFileNames = [fileManager contentsOfDirectoryAtPath:resourceDirectoryPath error:0];
EXPECT_EQ(1llu, resourceFileNames.count);

for (NSString *fileName in resourceFileNames) {
NSString *replacementPath = [resourceDirectoryName stringByAppendingPathComponent:fileName];
EXPECT_TRUE([savedMainResource containsString:replacementPath]);
}

saved = true;
}];
Util::run(&saved);
}

} // namespace TestWebKitAPI

#endif // PLATFORM(MAC) || PLATFORM(IOS_FAMILY)

0 comments on commit 9db4989

Please sign in to comment.