Skip to content

Commit 55ccc87

Browse files
committed
Save iframe resources with same URL in different files
https://bugs.webkit.org/show_bug.cgi?id=263220 rdar://116882637 Reviewed by Ryosuke Niwa. In current implementation, if multiple iframe elements point to the same URL, we only create one file and make all the elements point to that file. However, iframe content is usually modified by script, which means iframe pages with the same URL usually have different content. To ensure the content is correctly captured, we now create one file for each iframe main resource. This also matches behavior of other browsers. Test: WebArchive.SaveResourcesIframesWithSameURL * Source/WebCore/editing/MarkupAccumulator.cpp: (WebCore::MarkupAccumulator::resolveURLIfNeeded const): * Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp: (WebCore::LegacyWebArchive::create): * Tools/TestWebKitAPI/Tests/WebKitCocoa/CreateWebArchive.mm: Canonical link: https://commits.webkit.org/269472@main
1 parent ce816cc commit 55ccc87

File tree

3 files changed

+101
-9
lines changed

3 files changed

+101
-9
lines changed

Source/WebCore/editing/MarkupAccumulator.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,9 @@ String MarkupAccumulator::resolveURLIfNeeded(const Element& element, const Strin
277277
{
278278
if (!m_replacementURLStrings.isEmpty()) {
279279
if (auto frame = frameForAttributeReplacement(element)) {
280-
if (frame->loader().documentLoader()->response().url().protocolIsData()) {
281-
auto replacementString = m_replacementURLStrings.get(frame->frameID().toString());
282-
if (!replacementString.isEmpty())
283-
return replacementString;
284-
}
280+
auto replacementString = m_replacementURLStrings.get(frame->frameID().toString());
281+
if (!replacementString.isEmpty())
282+
return replacementString;
285283
}
286284

287285
auto resolvedURLString = element.resolveURLStringIfNeeded(urlString);

Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,7 @@ RefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Lo
569569
auto subframeMainResourceURL = subframeMainResource ? subframeMainResource->url() : URL { };
570570
if (!subframeMainResourceURL.isEmpty()) {
571571
auto subframeMainResourceRelativePath = frame.isMainFrame() ? subframeMainResource->relativeFilePath() : FileSystem::lastComponentOfPathIgnoringTrailingSlash(subframeMainResource->relativeFilePath());
572-
if (subframeMainResourceURL.isAboutSrcDoc() || subframeMainResourceURL.isAboutBlank() || subframeMainResourceURL.protocolIsData())
573-
uniqueSubresources.add(childFrame->frameID().toString(), subframeMainResourceRelativePath);
574-
else
575-
uniqueSubresources.add(subframeMainResourceURL.string(), subframeMainResourceRelativePath);
572+
uniqueSubresources.add(childFrame->frameID().toString(), subframeMainResourceRelativePath);
576573
}
577574
subframeArchives.append(subframeArchive.releaseNonNull());
578575
} else

Tools/TestWebKitAPI/Tests/WebKitCocoa/CreateWebArchive.mm

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,103 @@ function frameLoaded() {
852852
Util::run(&saved);
853853
}
854854

855+
static const char* htmlDataBytesForIframesWithSameURL = R"TESTRESOURCE(
856+
<script>
857+
count = 0;
858+
messageCount = 0;
859+
function frameLoaded() {
860+
if (++count == 3) {
861+
const iframes = document.getElementsByTagName("iframe");
862+
for (let i = 0; i < iframes.length; ++i)
863+
iframes[i].contentWindow.postMessage("thisisiframe" + (i + 1), "*");
864+
}
865+
}
866+
window.addEventListener("message", function(event) {
867+
if (++messageCount == 3)
868+
window.webkit.messageHandlers.testHandler.postMessage("done");
869+
});
870+
</script>
871+
<iframe onload="frameLoaded();" src="iframe.html"></iframe>
872+
<iframe onload="frameLoaded();" src="iframe.html"></iframe>
873+
<iframe onload="frameLoaded();" src="iframe.html"></iframe>
874+
)TESTRESOURCE";
875+
static const char* iframeHTMLDataBytesForIframesWithSameURL = R"TESTRESOURCE(
876+
<head>
877+
<script>
878+
window.addEventListener("message", function(event) {
879+
if (!document.body.innerHTML)
880+
document.body.innerHTML = "<p>" + event.data + "</p>";
881+
window.parent.postMessage("done", "*");
882+
});
883+
</script>
884+
</head>
885+
)TESTRESOURCE";
886+
887+
TEST(WebArchive, SaveResourcesIframesWithSameURL)
888+
{
889+
RetainPtr<NSURL> directoryURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"SaveResourcesTest"] isDirectory:YES];
890+
NSFileManager *fileManager = [NSFileManager defaultManager];
891+
[fileManager removeItemAtURL:directoryURL.get() error:nil];
892+
893+
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
894+
auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
895+
[configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"webarchivetest"];
896+
NSData *htmlData = [NSData dataWithBytes:htmlDataBytesForIframesWithSameURL length:strlen(htmlDataBytesForIframesWithSameURL)];
897+
NSData *iframeHTMLData = [NSData dataWithBytes:iframeHTMLDataBytesForIframesWithSameURL length:strlen(iframeHTMLDataBytesForIframesWithSameURL)];
898+
[schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
899+
NSData *data = nil;
900+
NSString *mimeType = nil;
901+
if ([task.request.URL.absoluteString isEqualToString:@"webarchivetest://host/main.html"]) {
902+
mimeType = @"text/html";
903+
data = htmlData;
904+
} else if ([task.request.URL.absoluteString isEqualToString:@"webarchivetest://host/iframe.html"]) {
905+
mimeType = @"text/html";
906+
data = iframeHTMLData;
907+
} else
908+
FAIL();
909+
910+
auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:mimeType expectedContentLength:data.length textEncodingName:nil]);
911+
[task didReceiveResponse:response.get()];
912+
[task didReceiveData:data];
913+
[task didFinish];
914+
}];
915+
916+
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
917+
static bool messageReceived = false;
918+
[webView performAfterReceivingMessage:@"done" action:[&] {
919+
messageReceived = true;
920+
}];
921+
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"webarchivetest://host/main.html"]]];
922+
Util::run(&messageReceived);
923+
924+
static bool saved = false;
925+
[webView _saveResources:directoryURL.get() suggestedFileName:@"host" completionHandler:^(NSError *error) {
926+
EXPECT_NULL(error);
927+
NSString *mainResourcePath = [directoryURL URLByAppendingPathComponent:@"host.html"].path;
928+
EXPECT_TRUE([fileManager fileExistsAtPath:mainResourcePath]);
929+
930+
NSString *resourceDirectoryName = @"host_files";
931+
NSString *resourceDirectoryPath = [directoryURL URLByAppendingPathComponent:resourceDirectoryName].path;
932+
NSArray *resourceFileNames = [fileManager contentsOfDirectoryAtPath:resourceDirectoryPath error:0];
933+
EXPECT_EQ(3llu, resourceFileNames.count);
934+
935+
NSMutableSet *frameResourceContentsToFind = [NSMutableSet set];
936+
[frameResourceContentsToFind addObjectsFromArray:[NSArray arrayWithObjects:@"thisisiframe1", @"thisisiframe2", @"thisisiframe3", nil]];
937+
for (NSString *fileName in resourceFileNames) {
938+
EXPECT_TRUE([fileName containsString:@"frame_"]);
939+
NSString *resourceFilePath = [resourceDirectoryPath stringByAppendingPathComponent:fileName];
940+
NSString* savedSubframeResource = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:resourceFilePath] encoding:NSUTF8StringEncoding];
941+
NSRange range = [savedSubframeResource rangeOfString:@"thisisiframe"];
942+
EXPECT_NE(NSNotFound, (long)range.location);
943+
NSString *iframeContent = [savedSubframeResource substringWithRange:NSMakeRange(range.location, range.length + 1)];
944+
[frameResourceContentsToFind removeObject:iframeContent];
945+
}
946+
EXPECT_EQ(0u, frameResourceContentsToFind.count);
947+
saved = true;
948+
}];
949+
Util::run(&saved);
950+
}
951+
855952
} // namespace TestWebKitAPI
856953

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

0 commit comments

Comments
 (0)