Diff
Modified: trunk/Source/WTF/ChangeLog (248138 => 248139)
--- trunk/Source/WTF/ChangeLog 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WTF/ChangeLog 2019-08-01 22:29:52 UTC (rev 248139)
@@ -1,3 +1,19 @@
+2019-08-01 Alex Christensen <[email protected]>
+
+ Move FormData zip file generation to NetworkProcess and enable it for all WebKit clients for uploading directories
+ https://bugs.webkit.org/show_bug.cgi?id=200102
+ <rdar://problem/53275114>
+
+ Reviewed by Darin Adler.
+
+ Move code from BlobDataFileReference::generateReplacementFile to FileSystem::createZipArchive.
+
+ * wtf/FileSystem.cpp:
+ (WTF::FileSystemImpl::createZipArchive):
+ * wtf/FileSystem.h:
+ * wtf/cocoa/FileSystemCocoa.mm:
+ (WTF::FileSystemImpl::createZipArchive):
+
2019-08-01 Per Arne Vollan <[email protected]>
Initialize memory pressure flag in MemoryPressureHandler
Modified: trunk/Source/WTF/wtf/FileSystem.cpp (248138 => 248139)
--- trunk/Source/WTF/wtf/FileSystem.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WTF/wtf/FileSystem.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -385,5 +385,12 @@
}
#endif
+#if !PLATFORM(COCOA)
+String createTemporaryZipArchive(const String& directory)
+{
+ return { };
+}
+#endif
+
} // namespace FileSystemImpl
} // namespace WTF
Modified: trunk/Source/WTF/wtf/FileSystem.h (248138 => 248139)
--- trunk/Source/WTF/wtf/FileSystem.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WTF/wtf/FileSystem.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -124,6 +124,7 @@
WTF_EXPORT_PRIVATE bool getVolumeFreeSpace(const String&, uint64_t&);
WTF_EXPORT_PRIVATE Optional<int32_t> getFileDeviceId(const CString&);
WTF_EXPORT_PRIVATE bool createSymbolicLink(const String& targetPath, const String& symbolicLinkPath);
+WTF_EXPORT_PRIVATE String createTemporaryZipArchive(const String& directory);
WTF_EXPORT_PRIVATE void setMetadataURL(const String& path, const String& urlString, const String& referrer = { });
Modified: trunk/Source/WTF/wtf/cocoa/FileSystemCocoa.mm (248138 => 248139)
--- trunk/Source/WTF/wtf/cocoa/FileSystemCocoa.mm 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WTF/wtf/cocoa/FileSystemCocoa.mm 2019-08-01 22:29:52 UTC (rev 248139)
@@ -29,6 +29,24 @@
#import "config.h"
#import <wtf/FileSystem.h>
+#include <wtf/SoftLinking.h>
+
+#if USE(APPLE_INTERNAL_SDK)
+#include <Bom/BOMCopier.h>
+#endif
+
+typedef struct _BOMCopier* BOMCopier;
+
+SOFT_LINK_PRIVATE_FRAMEWORK(Bom)
+SOFT_LINK(Bom, BOMCopierNew, BOMCopier, (), ())
+SOFT_LINK(Bom, BOMCopierFree, void, (BOMCopier copier), (copier))
+SOFT_LINK(Bom, BOMCopierCopyWithOptions, int, (BOMCopier copier, const char* fromObj, const char* toObj, CFDictionaryRef options), (copier, fromObj, toObj, options))
+
+#define kBOMCopierOptionCreatePKZipKey CFSTR("createPKZip")
+#define kBOMCopierOptionSequesterResourcesKey CFSTR("sequesterResources")
+#define kBOMCopierOptionKeepParentKey CFSTR("keepParent")
+#define kBOMCopierOptionCopyResourcesKey CFSTR("copyResources")
+
@interface WTFWebFileManagerDelegate : NSObject <NSFileManagerDelegate>
@end
@@ -48,6 +66,32 @@
namespace FileSystemImpl {
+String createTemporaryZipArchive(const String& path)
+{
+ String temporaryFile;
+
+ RetainPtr<NSFileCoordinator> coordinator = adoptNS([[NSFileCoordinator alloc] initWithFilePresenter:nil]);
+ [coordinator coordinateReadingItemAtURL:[NSURL fileURLWithPath:path] options:NSFileCoordinatorReadingWithoutChanges error:nullptr byAccessor:[&](NSURL *newURL) mutable {
+ CString archivePath([NSTemporaryDirectory() stringByAppendingPathComponent:@"WebKitGeneratedFileXXXXXX"].fileSystemRepresentation);
+ if (mkstemp(archivePath.mutableData()) == -1)
+ return;
+
+ NSDictionary *options = @{
+ (__bridge id)kBOMCopierOptionCreatePKZipKey : @YES,
+ (__bridge id)kBOMCopierOptionSequesterResourcesKey : @YES,
+ (__bridge id)kBOMCopierOptionKeepParentKey : @YES,
+ (__bridge id)kBOMCopierOptionCopyResourcesKey : @YES,
+ };
+
+ BOMCopier copier = BOMCopierNew();
+ if (!BOMCopierCopyWithOptions(copier, newURL.path.fileSystemRepresentation, archivePath.data(), (__bridge CFDictionaryRef)options))
+ temporaryFile = String::fromUTF8(archivePath);
+ BOMCopierFree(copier);
+ }];
+
+ return temporaryFile;
+}
+
String homeDirectoryPath()
{
return NSHomeDirectory();
Modified: trunk/Source/WebCore/ChangeLog (248138 => 248139)
--- trunk/Source/WebCore/ChangeLog 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/ChangeLog 2019-08-01 22:29:52 UTC (rev 248139)
@@ -1,3 +1,71 @@
+2019-08-01 Alex Christensen <[email protected]>
+
+ Move FormData zip file generation to NetworkProcess and enable it for all WebKit clients for uploading directories
+ https://bugs.webkit.org/show_bug.cgi?id=200102
+ <rdar://problem/53275114>
+
+ Reviewed by Darin Adler.
+
+ To enable directory uploading in WebKit2, we extended WebKit1's model of asking the application to generate a file for uploading.
+ This means the WebProcess needed access to everything necessary to zip a whole directory, and clients that have not implemented
+ the strange WKBundlePageUIClient callbacks won't be able to upload directories. Safari's implementation had already been copied
+ to BlobDataFileReference::generateReplacementFile, so I reused that code to do the zipping. Instead of a complicated model of
+ keeping track of a filename, possibly a generated filename, and whether we think we own the file or not and having nobody clean up,
+ we now do the generation, use, and cleaning up in the network process starting with a new function generateFilesForUpload.
+ This removes unimplemented SPI in WebUIDelegatePrivate in WebKitLegacy and stops calling the WKBundlePageUIClient related to upload
+ file generation and replaces them with automatic behavior equivalent to Safari's implementation of the WKBundlePageUIClient calls.
+ Since we no longer need to do these file operations in the WebProcess, I am also reverting r245322 and r246077 which tightens the sandbox.
+
+ Covered by an API test.
+
+ * Modules/fetch/FetchBody.cpp:
+ (WebCore::FetchBody::extract):
+ (WebCore::FetchBody::bodyAsFormData const):
+ * loader/FormSubmission.cpp:
+ (WebCore::FormSubmission::create):
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::submitForm):
+ (WebCore::FrameLoader::loadDifferentDocumentItem):
+ * loader/ResourceLoader.cpp:
+ (WebCore::ResourceLoader::didReceiveResponse):
+ (WebCore::ResourceLoader::cleanupForError):
+ * page/Chrome.cpp:
+ (WebCore::ChromeClient::shouldReplaceWithGeneratedFileForUpload): Deleted.
+ (WebCore::ChromeClient::generateReplacementFile): Deleted.
+ * page/ChromeClient.h:
+ * platform/network/FormData.cpp:
+ (WebCore::FormData::FormData):
+ (WebCore::FormData::~FormData):
+ (WebCore::FormData::createMultiPart):
+ (WebCore::FormDataElement::lengthInBytes const):
+ (WebCore::FormData::appendFile):
+ (WebCore::FormData::appendFileRange):
+ (WebCore::FormData::appendMultiPartFileValue):
+ (WebCore::FormData::appendMultiPartKeyValuePairItems):
+ (WebCore::FormData::resolveBlobReferences):
+ (WebCore::generateFileForUpload):
+ (WebCore::FormData::generateFilesForUpload):
+ (WebCore::FormData::generateFiles): Deleted.
+ (WebCore::FormData::hasGeneratedFiles const): Deleted.
+ (WebCore::FormData::hasOwnedGeneratedFiles const): Deleted.
+ (WebCore::FormData::removeGeneratedFilesIfNeeded): Deleted.
+ * platform/network/FormData.h:
+ (WebCore::FormDataElement::FormDataElement):
+ (WebCore::FormDataElement::EncodedFileData::isolatedCopy const):
+ (WebCore::FormDataElement::EncodedFileData::operator== const):
+ (WebCore::FormDataElement::EncodedFileData::encode const):
+ (WebCore::FormDataElement::EncodedFileData::decode):
+ * platform/network/cf/FormDataStreamCFNet.cpp:
+ (WebCore::advanceCurrentStream):
+ (WebCore::formCreate):
+ (WebCore::formFinalize):
+ (WebCore::createHTTPBodyCFReadStream):
+ * platform/network/mac/BlobDataFileReferenceMac.mm:
+ (WebCore::generateFileForUpload):
+ (WebCore::BlobDataFileReference::generateReplacementFile):
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::send):
+
2019-08-01 Wenson Hsieh <[email protected]>
[Text autosizing] [iPadOS] Add targeted hacks to address some remaining text autosizing issues
Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.cpp (248138 => 248139)
--- trunk/Source/WebCore/Modules/fetch/FetchBody.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -40,7 +40,7 @@
namespace WebCore {
-FetchBody FetchBody::extract(ScriptExecutionContext& context, Init&& value, String& contentType)
+FetchBody FetchBody::extract(ScriptExecutionContext&, Init&& value, String& contentType)
{
return WTF::switchOn(value, [&](RefPtr<Blob>& value) mutable {
Ref<const Blob> blob = value.releaseNonNull();
@@ -49,7 +49,7 @@
return FetchBody(WTFMove(blob));
}, [&](RefPtr<DOMFormData>& value) mutable {
Ref<DOMFormData> domFormData = value.releaseNonNull();
- auto formData = FormData::createMultiPart(domFormData.get(), &downcast<Document>(context));
+ auto formData = FormData::createMultiPart(domFormData.get());
contentType = makeString("multipart/form-data; boundary=", formData->boundary().data());
return FetchBody(WTFMove(formData));
}, [&](RefPtr<URLSearchParams>& value) mutable {
@@ -250,9 +250,8 @@
if (isArrayBufferView())
return FormData::create(arrayBufferViewBody().baseAddress(), arrayBufferViewBody().byteLength());
if (isFormData()) {
- ASSERT(!context.isWorkerGlobalScope());
+ ASSERT_UNUSED(context, !context.isWorkerGlobalScope());
auto body = makeRef(const_cast<FormData&>(formDataBody()));
- body->generateFiles(&downcast<Document>(context));
return body;
}
if (auto* data = ""
Modified: trunk/Source/WebCore/loader/FormSubmission.cpp (248138 => 248139)
--- trunk/Source/WebCore/loader/FormSubmission.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/loader/FormSubmission.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -198,7 +198,7 @@
String boundary;
if (isMultiPartForm) {
- formData = FormData::createMultiPart(domFormData, &document);
+ formData = FormData::createMultiPart(domFormData);
boundary = formData->boundary().data();
} else {
formData = FormData::create(domFormData, attributes.method() == Method::Get ? FormData::FormURLEncoded : FormData::parseEncodingType(encodingType));
Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (248138 => 248139)
--- trunk/Source/WebCore/loader/FrameLoader.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -473,7 +473,6 @@
m_submittedFormURL = submission->requestURL();
}
- submission->data().generateFiles(m_frame.document());
submission->setReferrer(outgoingReferrer());
submission->setOrigin(outgoingOrigin());
@@ -3773,8 +3772,6 @@
// If this was a repost that failed the page cache, we might try to repost the form.
NavigationAction action;
if (formData) {
- formData->generateFiles(m_frame.document());
-
request.setHTTPMethod("POST");
request.setHTTPBody(WTFMove(formData));
request.setHTTPContentType(item.formContentType());
Modified: trunk/Source/WebCore/loader/ResourceLoader.cpp (248138 => 248139)
--- trunk/Source/WebCore/loader/ResourceLoader.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/loader/ResourceLoader.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -492,9 +492,6 @@
m_response = r;
- if (FormData* data = ""
- data->removeGeneratedFilesIfNeeded();
-
if (m_options.sendLoadCallbacks == SendCallbackPolicy::SendCallbacks)
frameLoader()->notifier().didReceiveResponse(this, m_response);
}
@@ -579,9 +576,6 @@
void ResourceLoader::cleanupForError(const ResourceError& error)
{
- if (FormData* data = ""
- data->removeGeneratedFilesIfNeeded();
-
if (m_notifiedLoadComplete)
return;
m_notifiedLoadComplete = true;
Modified: trunk/Source/WebCore/page/Chrome.cpp (248138 => 248139)
--- trunk/Source/WebCore/page/Chrome.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/page/Chrome.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -525,17 +525,6 @@
#endif
}
-bool ChromeClient::shouldReplaceWithGeneratedFileForUpload(const String&, String&)
-{
- return false;
-}
-
-String ChromeClient::generateReplacementFile(const String&)
-{
- ASSERT_NOT_REACHED();
- return String();
-}
-
bool Chrome::selectItemWritingDirectionIsNatural()
{
return m_client.selectItemWritingDirectionIsNatural();
Modified: trunk/Source/WebCore/page/ChromeClient.h (248138 => 248139)
--- trunk/Source/WebCore/page/ChromeClient.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/page/ChromeClient.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -235,9 +235,6 @@
// the new cache.
virtual void reachedApplicationCacheOriginQuota(SecurityOrigin&, int64_t totalSpaceNeeded) = 0;
- virtual bool shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename);
- virtual String generateReplacementFile(const String& path);
-
#if ENABLE(IOS_TOUCH_EVENTS)
virtual void didPreventDefaultForEvent() = 0;
#endif
Modified: trunk/Source/WebCore/platform/network/FormData.cpp (248138 => 248139)
--- trunk/Source/WebCore/platform/network/FormData.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/platform/network/FormData.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -27,7 +27,6 @@
#include "Chrome.h"
#include "ChromeClient.h"
#include "DOMFormData.h"
-#include "Document.h"
#include "File.h"
#include "FormDataBuilder.h"
#include "Page.h"
@@ -50,22 +49,10 @@
, m_alwaysStream(false)
, m_containsPasswordData(data.m_containsPasswordData)
{
- // We shouldn't be copying FormData that hasn't already removed its generated files
- // but just in case, make sure the new FormData is ready to generate its own files.
- for (auto& element : m_elements) {
- if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) {
- fileData->generatedFilename = { };
- fileData->ownsGeneratedFile = false;
- }
- }
}
FormData::~FormData()
{
- // This cleanup should've happened when the form submission finished.
- // Just in case, let's assert, and do the cleanup anyway in release builds.
- ASSERT(!hasOwnedGeneratedFiles());
- removeGeneratedFilesIfNeeded();
}
Ref<FormData> FormData::create()
@@ -109,10 +96,10 @@
return result;
}
-Ref<FormData> FormData::createMultiPart(const DOMFormData& formData, Document* document)
+Ref<FormData> FormData::createMultiPart(const DOMFormData& formData)
{
auto result = create();
- result->appendMultiPartKeyValuePairItems(formData, document);
+ result->appendMultiPartKeyValuePairItems(formData);
return result;
}
@@ -146,7 +133,7 @@
if (fileData.fileLength != BlobDataItem::toEndOfFile)
return static_cast<uint64_t>(fileData.fileLength);
long long fileSize;
- if (FileSystem::getFileSize(fileData.shouldGenerateFile ? fileData.generatedFilename : fileData.filename, fileSize))
+ if (FileSystem::getFileSize(fileData.filename, fileSize))
return static_cast<uint64_t>(fileSize);
return static_cast<uint64_t>(0);
}, [] (const FormDataElement::EncodedBlobData& blobData) {
@@ -184,15 +171,15 @@
m_elements.append(WTFMove(vector));
}
-void FormData::appendFile(const String& filename, bool shouldGenerateFile)
+void FormData::appendFile(const String& filename)
{
- m_elements.append(FormDataElement(filename, 0, BlobDataItem::toEndOfFile, WTF::nullopt, shouldGenerateFile));
+ m_elements.append(FormDataElement(filename, 0, BlobDataItem::toEndOfFile, WTF::nullopt));
m_lengthInBytes = WTF::nullopt;
}
-void FormData::appendFileRange(const String& filename, long long start, long long length, Optional<WallTime> expectedModificationTime, bool shouldGenerateFile)
+void FormData::appendFileRange(const String& filename, long long start, long long length, Optional<WallTime> expectedModificationTime)
{
- m_elements.append(FormDataElement(filename, start, length, expectedModificationTime, shouldGenerateFile));
+ m_elements.append(FormDataElement(filename, start, length, expectedModificationTime));
m_lengthInBytes = WTF::nullopt;
}
@@ -207,22 +194,10 @@
return normalizeLineEndingsToCRLF(encoding.encode(value, UnencodableHandling::Entities));
}
-void FormData::appendMultiPartFileValue(const File& file, Vector<char>& header, TextEncoding& encoding, Document* document)
+void FormData::appendMultiPartFileValue(const File& file, Vector<char>& header, TextEncoding& encoding)
{
auto name = file.name();
- // Let the application specify a filename if it's going to generate a replacement file for the upload.
- bool shouldGenerateFile = false;
- auto& path = file.path();
- if (!path.isEmpty()) {
- if (Page* page = document->page()) {
- String generatedFileName;
- shouldGenerateFile = page->chrome().client().shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
- if (shouldGenerateFile)
- name = generatedFileName;
- }
- }
-
// We have to include the filename=".." part in the header, even if the filename is empty
FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, name);
@@ -238,7 +213,7 @@
appendData(header.data(), header.size());
if (!file.path().isEmpty())
- appendFile(file.path(), shouldGenerateFile);
+ appendFile(file.path());
else if (file.size())
appendBlob(file.url());
}
@@ -252,7 +227,7 @@
appendData(normalizedStringData.data(), normalizedStringData.size());
}
-void FormData::appendMultiPartKeyValuePairItems(const DOMFormData& formData, Document* document)
+void FormData::appendMultiPartKeyValuePairItems(const DOMFormData& formData)
{
m_boundary = FormDataBuilder::generateUniqueBoundaryString();
@@ -266,7 +241,7 @@
FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), normalizedName);
if (WTF::holds_alternative<RefPtr<File>>(item.data))
- appendMultiPartFileValue(*WTF::get<RefPtr<File>>(item.data), header, encoding, document);
+ appendMultiPartFileValue(*WTF::get<RefPtr<File>>(item.data), header, encoding);
else
appendMultiPartStringValue(WTF::get<String>(item.data), header, encoding);
@@ -359,7 +334,7 @@
[&] (const Vector<char>& bytes) {
newFormData->appendData(bytes.data(), bytes.size());
}, [&] (const FormDataElement::EncodedFileData& fileData) {
- newFormData->appendFileRange(fileData.filename, fileData.fileStart, fileData.fileLength, fileData.expectedFileModificationTime, fileData.shouldGenerateFile);
+ newFormData->appendFileRange(fileData.filename, fileData.fileStart, fileData.fileLength, fileData.expectedFileModificationTime);
}, [&] (const FormDataElement::EncodedBlobData& blobData) {
appendBlobResolved(blobRegistry, newFormData.get(), blobData.url);
}
@@ -368,66 +343,41 @@
return newFormData;
}
-void FormData::generateFiles(Document* document)
+FormDataForUpload FormData::prepareForUpload()
{
- Page* page = document->page();
- if (!page)
- return;
-
+ Vector<String> generatedFiles;
for (auto& element : m_elements) {
- if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) {
- if (fileData->shouldGenerateFile) {
- ASSERT(!fileData->ownsGeneratedFile);
- ASSERT(fileData->generatedFilename.isEmpty());
- if (!fileData->generatedFilename.isEmpty())
- continue;
- fileData->generatedFilename = page->chrome().client().generateReplacementFile(fileData->filename);
- if (!fileData->generatedFilename.isEmpty())
- fileData->ownsGeneratedFile = true;
- }
- }
- }
-}
+ auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data);
+ if (!fileData)
+ continue;
+ if (!FileSystem::fileIsDirectory(fileData->filename, FileSystem::ShouldFollowSymbolicLinks::Yes))
+ continue;
+ if (fileData->fileStart || fileData->fileLength != BlobDataItem::toEndOfFile)
+ continue;
+ if (!fileData->fileModificationTimeMatchesExpectation())
+ continue;
-bool FormData::hasGeneratedFiles() const
-{
- for (auto& element : m_elements) {
- if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) {
- if (!fileData->generatedFilename.isEmpty())
- return true;
- }
+ auto generatedFilename = FileSystem::createTemporaryZipArchive(fileData->filename);
+ if (!generatedFilename)
+ continue;
+ fileData->filename = generatedFilename;
+ generatedFiles.append(WTFMove(generatedFilename));
}
- return false;
+
+ return { *this, WTFMove(generatedFiles) };
}
-bool FormData::hasOwnedGeneratedFiles() const
+FormDataForUpload::FormDataForUpload(FormData& data, Vector<String>&& temporaryZipFiles)
+ : m_data(data)
+ , m_temporaryZipFiles(WTFMove(temporaryZipFiles))
{
- for (auto& element : m_elements) {
- if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) {
- if (fileData->ownsGeneratedFile) {
- ASSERT(!fileData->generatedFilename.isEmpty());
- return true;
- }
- }
- }
- return false;
}
-void FormData::removeGeneratedFilesIfNeeded()
+FormDataForUpload::~FormDataForUpload()
{
- for (auto& element : m_elements) {
- if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) {
- if (fileData->ownsGeneratedFile) {
- ASSERT(!fileData->generatedFilename.isEmpty());
- ASSERT(fileData->shouldGenerateFile);
- String directory = FileSystem::directoryName(fileData->generatedFilename);
- FileSystem::deleteFile(fileData->generatedFilename);
- FileSystem::deleteEmptyDirectory(directory);
- fileData->generatedFilename = String();
- fileData->ownsGeneratedFile = false;
- }
- }
- }
+ ASSERT(isMainThread());
+ for (auto& file : m_temporaryZipFiles)
+ FileSystem::deleteFile(file);
}
uint64_t FormData::lengthInBytes() const
@@ -460,4 +410,19 @@
return { };
}
+bool FormDataElement::EncodedFileData::fileModificationTimeMatchesExpectation() const
+{
+ if (!expectedFileModificationTime)
+ return true;
+
+ auto fileModificationTime = FileSystem::getFileModificationTime(filename);
+ if (!fileModificationTime)
+ return false;
+
+ if (fileModificationTime->secondsSinceEpoch().secondsAs<time_t>() != expectedFileModificationTime->secondsSinceEpoch().secondsAs<time_t>())
+ return false;
+
+ return true;
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/network/FormData.h (248138 => 248139)
--- trunk/Source/WebCore/platform/network/FormData.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/platform/network/FormData.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -31,7 +31,6 @@
class BlobRegistry;
class DOMFormData;
-class Document;
class File;
class SharedBuffer;
class TextEncoding;
@@ -46,8 +45,8 @@
: data(WTFMove(data)) { }
explicit FormDataElement(Vector<char>&& array)
: data(WTFMove(array)) { }
- FormDataElement(const String& filename, int64_t fileStart, int64_t fileLength, Optional<WallTime> expectedFileModificationTime, bool shouldGenerateFile)
- : data(EncodedFileData { filename, fileStart, fileLength, expectedFileModificationTime, { }, shouldGenerateFile, false }) { }
+ FormDataElement(const String& filename, int64_t fileStart, int64_t fileLength, Optional<WallTime> expectedFileModificationTime)
+ : data(EncodedFileData { filename, fileStart, fileLength, expectedFileModificationTime }) { }
explicit FormDataElement(const URL& blobURL)
: data(EncodedBlobData { blobURL }) { }
@@ -73,17 +72,12 @@
int64_t fileStart { 0 };
int64_t fileLength { 0 };
Optional<WallTime> expectedFileModificationTime;
- String generatedFilename;
- bool shouldGenerateFile { false };
- bool ownsGeneratedFile { false };
- // FIXME: Generated file support in FormData is almost identical to Blob, they should be merged.
- // We can't just switch to using Blobs for all files because EncodedFile form data elements do not
- // have a valid expectedFileModificationTime, meaning we always upload the latest content from disk.
+ bool fileModificationTimeMatchesExpectation() const;
EncodedFileData isolatedCopy() const
{
- return { filename.isolatedCopy(), fileStart, fileLength, expectedFileModificationTime, generatedFilename.isolatedCopy(), shouldGenerateFile, ownsGeneratedFile };
+ return { filename.isolatedCopy(), fileStart, fileLength, expectedFileModificationTime };
}
bool operator==(const EncodedFileData& other) const
@@ -91,14 +85,11 @@
return filename == other.filename
&& fileStart == other.fileStart
&& fileLength == other.fileLength
- && expectedFileModificationTime == other.expectedFileModificationTime
- && generatedFilename == other.generatedFilename
- && shouldGenerateFile == other.shouldGenerateFile
- && ownsGeneratedFile == other.ownsGeneratedFile;
+ && expectedFileModificationTime == other.expectedFileModificationTime;
}
template<typename Encoder> void encode(Encoder& encoder) const
{
- encoder << filename << fileStart << fileLength << expectedFileModificationTime << generatedFilename << shouldGenerateFile;
+ encoder << filename << fileStart << fileLength << expectedFileModificationTime;
}
template<typename Decoder> static Optional<EncodedFileData> decode(Decoder& decoder)
{
@@ -121,27 +112,12 @@
decoder >> expectedFileModificationTime;
if (!expectedFileModificationTime)
return WTF::nullopt;
-
- Optional<String> generatedFilename;
- decoder >> generatedFilename;
- if (!generatedFilename)
- return WTF::nullopt;
- Optional<bool> shouldGenerateFile;
- decoder >> shouldGenerateFile;
- if (!shouldGenerateFile)
- return WTF::nullopt;
-
- bool ownsGeneratedFile = false;
-
return {{
WTFMove(*filename),
WTFMove(*fileStart),
WTFMove(*fileLength),
- WTFMove(*expectedFileModificationTime),
- WTFMove(*generatedFilename),
- WTFMove(*shouldGenerateFile),
- WTFMove(ownsGeneratedFile)
+ WTFMove(*expectedFileModificationTime)
}};
}
@@ -189,6 +165,22 @@
Data data;
};
+class FormData;
+
+struct FormDataForUpload {
+public:
+ FormDataForUpload(FormDataForUpload&&) = default;
+ ~FormDataForUpload();
+
+ FormData& data() { return m_data.get(); }
+private:
+ friend class FormData;
+ FormDataForUpload(FormData&, Vector<String>&&);
+
+ Ref<FormData> m_data;
+ Vector<String> m_temporaryZipFiles;
+};
+
class FormData : public RefCounted<FormData> {
public:
enum EncodingType {
@@ -204,7 +196,7 @@
static Ref<FormData> create(const Vector<char>&);
static Ref<FormData> create(const Vector<uint8_t>&);
static Ref<FormData> create(const DOMFormData&, EncodingType = FormURLEncoded);
- static Ref<FormData> createMultiPart(const DOMFormData&, Document*);
+ static Ref<FormData> createMultiPart(const DOMFormData&);
WEBCORE_EXPORT ~FormData();
// FIXME: Both these functions perform a deep copy of m_elements, but differ in handling of other data members.
@@ -218,8 +210,8 @@
static RefPtr<FormData> decode(Decoder&);
WEBCORE_EXPORT void appendData(const void* data, size_t);
- void appendFile(const String& filePath, bool shouldGenerateFile = false);
- WEBCORE_EXPORT void appendFileRange(const String& filename, long long start, long long length, Optional<WallTime> expectedModificationTime, bool shouldGenerateFile = false);
+ void appendFile(const String& filePath);
+ WEBCORE_EXPORT void appendFileRange(const String& filename, long long start, long long length, Optional<WallTime> expectedModificationTime);
WEBCORE_EXPORT void appendBlob(const URL& blobURL);
WEBCORE_EXPORT Vector<char> flatten() const; // omits files
@@ -229,6 +221,8 @@
// If the FormData has no blob references to resolve, this is returned.
WEBCORE_EXPORT Ref<FormData> resolveBlobReferences(BlobRegistry&);
+ WEBCORE_EXPORT FormDataForUpload prepareForUpload();
+
bool isEmpty() const { return m_elements.isEmpty(); }
const Vector<FormDataElement>& elements() const { return m_elements; }
const Vector<char>& boundary() const { return m_boundary; }
@@ -235,9 +229,6 @@
RefPtr<SharedBuffer> asSharedBuffer() const;
- void generateFiles(Document*);
- void removeGeneratedFilesIfNeeded();
-
bool alwaysStream() const { return m_alwaysStream; }
void setAlwaysStream(bool alwaysStream) { m_alwaysStream = alwaysStream; }
@@ -266,14 +257,11 @@
FormData();
FormData(const FormData&);
- void appendMultiPartFileValue(const File&, Vector<char>& header, TextEncoding&, Document*);
+ void appendMultiPartFileValue(const File&, Vector<char>& header, TextEncoding&);
void appendMultiPartStringValue(const String&, Vector<char>& header, TextEncoding&);
- void appendMultiPartKeyValuePairItems(const DOMFormData&, Document*);
+ void appendMultiPartKeyValuePairItems(const DOMFormData&);
void appendNonMultiPartKeyValuePairItems(const DOMFormData&, EncodingType);
- bool hasGeneratedFiles() const;
- bool hasOwnedGeneratedFiles() const;
-
Vector<FormDataElement> m_elements;
int64_t m_identifier { 0 };
Modified: trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp (248138 => 248139)
--- trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -92,20 +92,23 @@
}
struct FormCreationContext {
- RefPtr<FormData> formData;
+ FormDataForUpload data;
unsigned long long streamLength;
};
struct FormStreamFields {
- RefPtr<FormData> formData;
+ FormStreamFields(FormDataForUpload&& data)
+ : data(WTFMove(data)) { }
+
+ FormDataForUpload data;
SchedulePairHashSet scheduledRunLoopPairs;
Vector<FormDataElement> remainingElements; // in reverse order
- CFReadStreamRef currentStream;
- long long currentStreamRangeLength;
+ CFReadStreamRef currentStream { nullptr };
+ long long currentStreamRangeLength { BlobDataItem::toEndOfFile };
MallocPtr<char> currentData;
- CFReadStreamRef formStream;
- unsigned long long streamLength;
- unsigned long long bytesSent;
+ CFReadStreamRef formStream { nullptr };
+ unsigned long long streamLength { 0 };
+ unsigned long long bytesSent { 0 };
Lock streamIsBeingOpenedOrClosedLock;
};
@@ -145,15 +148,11 @@
form->currentData = WTFMove(data);
return true;
}, [form] (const FormDataElement::EncodedFileData& fileData) {
- // Check if the file has been changed or not if required.
- if (fileData.expectedFileModificationTime) {
- auto fileModificationTime = FileSystem::getFileModificationTime(fileData.filename);
- if (!fileModificationTime)
- return false;
- if (fileModificationTime->secondsSinceEpoch().secondsAs<time_t>() != fileData.expectedFileModificationTime->secondsSinceEpoch().secondsAs<time_t>())
- return false;
- }
- const String& path = fileData.shouldGenerateFile ? fileData.generatedFilename : fileData.filename;
+ // Check if the file has been changed.
+ if (!fileData.fileModificationTimeMatchesExpectation())
+ return false;
+
+ const String& path = fileData.filename;
form->currentStream = CFReadStreamCreateWithFile(0, FileSystem::pathAsURL(path).get());
if (!form->currentStream) {
// The file must have been removed or become unreadable.
@@ -208,14 +207,10 @@
static void* formCreate(CFReadStreamRef stream, void* context)
{
FormCreationContext* formContext = static_cast<FormCreationContext*>(context);
-
- FormStreamFields* newInfo = new FormStreamFields;
- newInfo->formData = WTFMove(formContext->formData);
- newInfo->currentStream = 0;
- newInfo->currentStreamRangeLength = BlobDataItem::toEndOfFile;
+
+ FormStreamFields* newInfo = new FormStreamFields(WTFMove(formContext->data));
newInfo->formStream = stream; // Don't retain. That would create a reference cycle.
newInfo->streamLength = formContext->streamLength;
- newInfo->bytesSent = 0;
callOnMainThread([formContext] {
delete formContext;
@@ -222,10 +217,10 @@
});
// Append in reverse order since we remove elements from the end.
- size_t size = newInfo->formData->elements().size();
+ size_t size = newInfo->data.data().elements().size();
newInfo->remainingElements.reserveInitialCapacity(size);
for (size_t i = 0; i < size; ++i)
- newInfo->remainingElements.uncheckedAppend(newInfo->formData->elements()[size - i - 1]);
+ newInfo->remainingElements.uncheckedAppend(newInfo->data.data().elements()[size - i - 1]);
return newInfo;
}
@@ -317,7 +312,7 @@
FormStreamFields* form = static_cast<FormStreamFields*>(context);
if (kCFCompareEqualTo == CFStringCompare(propertyName, formDataPointerPropertyName, 0)) {
- long long formDataAsNumber = static_cast<long long>(reinterpret_cast<intptr_t>(form->formData.get()));
+ long long formDataAsNumber = static_cast<long long>(reinterpret_cast<intptr_t>(&form->data.data()));
return CFNumberCreate(0, kCFNumberLongLongType, &formDataAsNumber);
}
@@ -378,13 +373,14 @@
RetainPtr<CFReadStreamRef> createHTTPBodyCFReadStream(FormData& formData)
{
auto resolvedFormData = formData.resolveBlobReferences(blobRegistry());
+ auto dataForUpload = resolvedFormData->prepareForUpload();
// Precompute the content length so CFNetwork doesn't use chunked mode.
unsigned long long length = 0;
- for (auto& element : resolvedFormData->elements())
+ for (auto& element : dataForUpload.data().elements())
length += element.lengthInBytes();
- FormCreationContext* formContext = new FormCreationContext { WTFMove(resolvedFormData), length };
+ FormCreationContext* formContext = new FormCreationContext { WTFMove(dataForUpload), length };
CFReadStreamCallBacksV1 callBacks = { 1, formCreate, formFinalize, nullptr, formOpen, nullptr, formRead, nullptr, formCanRead, formClose, formCopyProperty, nullptr, nullptr, formSchedule, formUnschedule };
return adoptCF(CFReadStreamCreate(nullptr, static_cast<const void*>(&callBacks), formContext));
}
Modified: trunk/Source/WebCore/platform/network/mac/BlobDataFileReferenceMac.mm (248138 => 248139)
--- trunk/Source/WebCore/platform/network/mac/BlobDataFileReferenceMac.mm 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/platform/network/mac/BlobDataFileReferenceMac.mm 2019-08-01 22:29:52 UTC (rev 248139)
@@ -30,25 +30,8 @@
#include <wtf/FileMetadata.h>
#include <wtf/FileSystem.h>
-#include <wtf/SoftLinking.h>
#include <wtf/text/CString.h>
-#if USE(APPLE_INTERNAL_SDK)
-#include <Bom/BOMCopier.h>
-#endif
-
-typedef struct _BOMCopier* BOMCopier;
-
-SOFT_LINK_PRIVATE_FRAMEWORK(Bom)
-SOFT_LINK(Bom, BOMCopierNew, BOMCopier, (), ())
-SOFT_LINK(Bom, BOMCopierFree, void, (BOMCopier copier), (copier))
-SOFT_LINK(Bom, BOMCopierCopyWithOptions, int, (BOMCopier copier, const char* fromObj, const char* toObj, CFDictionaryRef options), (copier, fromObj, toObj, options))
-
-#define kBOMCopierOptionCreatePKZipKey CFSTR("createPKZip")
-#define kBOMCopierOptionSequesterResourcesKey CFSTR("sequesterResources")
-#define kBOMCopierOptionKeepParentKey CFSTR("keepParent")
-#define kBOMCopierOptionCopyResourcesKey CFSTR("copyResources")
-
namespace WebCore {
void BlobDataFileReference::generateReplacementFile()
@@ -58,26 +41,10 @@
prepareForFileAccess();
- RetainPtr<NSFileCoordinator> coordinator = adoptNS([[NSFileCoordinator alloc] initWithFilePresenter:nil]);
- [coordinator coordinateReadingItemAtURL:[NSURL fileURLWithPath:m_path] options:NSFileCoordinatorReadingWithoutChanges error:nullptr byAccessor:^(NSURL *newURL) {
- // The archive is put into a subdirectory of temporary directory for historic reasons. Changing this will require WebCore to change at the same time.
- CString archivePath([NSTemporaryDirectory() stringByAppendingPathComponent:@"WebKitGeneratedFileXXXXXX"].fileSystemRepresentation);
- if (mkstemp(archivePath.mutableData()) == -1)
- return;
+ auto generatedFile = FileSystem::createTemporaryZipArchive(m_path);
+ if (!generatedFile.isNull())
+ m_replacementPath = WTFMove(generatedFile);
- NSDictionary *options = @{
- (__bridge id)kBOMCopierOptionCreatePKZipKey : @YES,
- (__bridge id)kBOMCopierOptionSequesterResourcesKey : @YES,
- (__bridge id)kBOMCopierOptionKeepParentKey : @YES,
- (__bridge id)kBOMCopierOptionCopyResourcesKey : @YES,
- };
-
- BOMCopier copier = BOMCopierNew();
- if (!BOMCopierCopyWithOptions(copier, newURL.path.fileSystemRepresentation, archivePath.data(), (__bridge CFDictionaryRef)options))
- m_replacementPath = String::fromUTF8(archivePath);
- BOMCopierFree(copier);
- }];
-
m_replacementShouldBeGenerated = false;
if (!m_replacementPath.isNull()) {
if (auto metadata = FileSystem::fileMetadataFollowingSymlinks(m_replacementPath))
Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (248138 => 248139)
--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -533,8 +533,7 @@
return WTFMove(result.value());
if (m_method != "GET" && m_method != "HEAD") {
- m_requestEntityBody = FormData::createMultiPart(body, document());
- m_requestEntityBody->generateFiles(document());
+ m_requestEntityBody = FormData::createMultiPart(body);
if (!m_requestHeaders.contains(HTTPHeaderName::ContentType))
m_requestHeaders.set(HTTPHeaderName::ContentType, makeString("multipart/form-data; boundary=", m_requestEntityBody->boundary().data()));
}
Modified: trunk/Source/WebKit/ChangeLog (248138 => 248139)
--- trunk/Source/WebKit/ChangeLog 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/ChangeLog 2019-08-01 22:29:52 UTC (rev 248139)
@@ -1,3 +1,29 @@
+2019-08-01 Alex Christensen <[email protected]>
+
+ Move FormData zip file generation to NetworkProcess and enable it for all WebKit clients for uploading directories
+ https://bugs.webkit.org/show_bug.cgi?id=200102
+ <rdar://problem/53275114>
+
+ Reviewed by Darin Adler.
+
+ * NetworkProcess/NetworkResourceLoadParameters.cpp:
+ (WebKit::NetworkResourceLoadParameters::encode const):
+ * Platform/IPC/FormDataReference.h:
+ (IPC::FormDataReference::encode const):
+ * Resources/SandboxProfiles/ios/com.apple.WebKit.Networking.sb:
+ * WebProcess/InjectedBundle/API/APIInjectedBundlePageUIClient.h:
+ (API::InjectedBundle::PageUIClient::shouldGenerateFileForUpload): Deleted.
+ (API::InjectedBundle::PageUIClient::generateFileForUpload): Deleted.
+ * WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp:
+ (WebKit::InjectedBundlePageUIClient::shouldGenerateFileForUpload): Deleted.
+ (WebKit::InjectedBundlePageUIClient::generateFileForUpload): Deleted.
+ * WebProcess/InjectedBundle/InjectedBundlePageUIClient.h:
+ * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+ (WebKit::WebChromeClient::shouldReplaceWithGeneratedFileForUpload): Deleted.
+ (WebKit::WebChromeClient::generateReplacementFile): Deleted.
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/com.apple.WebProcess.sb.in:
+
2019-08-01 Tim Horton <[email protected]>
REGRESSION: HSBC Personal Banking download/print dialog is usually positioned off screen on iPad
Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp (248138 => 248139)
--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -57,7 +57,7 @@
for (size_t i = 0, count = elements.size(); i < count; ++i) {
const FormDataElement& element = elements[i];
if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) {
- const String& path = fileData->shouldGenerateFile ? fileData->generatedFilename : fileData->filename;
+ const String& path = fileData->filename;
SandboxExtension::createHandle(path, SandboxExtension::Type::ReadOnly, requestBodySandboxExtensions[extensionIndex++]);
}
}
Modified: trunk/Source/WebKit/Platform/IPC/FormDataReference.h (248138 => 248139)
--- trunk/Source/WebKit/Platform/IPC/FormDataReference.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/Platform/IPC/FormDataReference.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -60,7 +60,7 @@
size_t extensionIndex = 0;
for (auto& element : elements) {
if (auto* fileData = WTF::get_if<WebCore::FormDataElement::EncodedFileData>(element.data)) {
- const String& path = fileData->shouldGenerateFile ? fileData->generatedFilename : fileData->filename;
+ const String& path = fileData->filename;
WebKit::SandboxExtension::createHandle(path, WebKit::SandboxExtension::Type::ReadOnly, sandboxExtensionHandles[extensionIndex++]);
}
}
Modified: trunk/Source/WebKit/Resources/SandboxProfiles/ios/com.apple.WebKit.Networking.sb (248138 => 248139)
--- trunk/Source/WebKit/Resources/SandboxProfiles/ios/com.apple.WebKit.Networking.sb 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/Resources/SandboxProfiles/ios/com.apple.WebKit.Networking.sb 2019-08-01 22:29:52 UTC (rev 248139)
@@ -83,6 +83,7 @@
(global-name "com.apple.passd.library"))
(allow mach-lookup
+ (global-name "com.apple.FileCoordination")
(global-name "com.apple.dmd.policy")
(global-name "com.apple.siri.context.service")
(global-name "com.apple.ctcategories.service"))
Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/APIInjectedBundlePageUIClient.h (248138 => 248139)
--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/APIInjectedBundlePageUIClient.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/APIInjectedBundlePageUIClient.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -58,9 +58,6 @@
virtual void mouseDidMoveOverElement(WebKit::WebPage*, const WebCore::HitTestResult&, OptionSet<WebKit::WebEvent::Modifier>, RefPtr<API::Object>& userData) { UNUSED_PARAM(userData); }
virtual void pageDidScroll(WebKit::WebPage*) { }
- virtual WTF::String shouldGenerateFileForUpload(WebKit::WebPage*, const WTF::String& originalFilePath) { UNUSED_PARAM(originalFilePath); return WTF::String(); }
- virtual WTF::String generateFileForUpload(WebKit::WebPage*, const WTF::String& originalFilePath) { UNUSED_PARAM(originalFilePath); return emptyString(); }
-
enum class UIElementVisibility {
Unknown,
Visible,
Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp (248138 => 248139)
--- trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -93,22 +93,6 @@
m_client.pageDidScroll(toAPI(page), m_client.base.clientInfo);
}
-String InjectedBundlePageUIClient::shouldGenerateFileForUpload(WebPage* page, const String& originalFilePath)
-{
- if (!m_client.shouldGenerateFileForUpload)
- return String();
- RefPtr<API::String> generatedFilePath = adoptRef(toImpl(m_client.shouldGenerateFileForUpload(toAPI(page), toAPI(originalFilePath.impl()), m_client.base.clientInfo)));
- return generatedFilePath ? generatedFilePath->string() : String();
-}
-
-String InjectedBundlePageUIClient::generateFileForUpload(WebPage* page, const String& originalFilePath)
-{
- if (!m_client.generateFileForUpload)
- return String();
- RefPtr<API::String> generatedFilePath = adoptRef(toImpl(m_client.generateFileForUpload(toAPI(page), toAPI(originalFilePath.impl()), m_client.base.clientInfo)));
- return generatedFilePath ? generatedFilePath->string() : String();
-}
-
static API::InjectedBundle::PageUIClient::UIElementVisibility toUIElementVisibility(WKBundlePageUIElementVisibility visibility)
{
switch (visibility) {
Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageUIClient.h (248138 => 248139)
--- trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageUIClient.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageUIClient.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -54,9 +54,6 @@
void mouseDidMoveOverElement(WebPage*, const WebCore::HitTestResult&, OptionSet<WebEvent::Modifier>, RefPtr<API::Object>& userData) override;
void pageDidScroll(WebPage*) override;
- String shouldGenerateFileForUpload(WebPage*, const String& originalFilePath) override;
- String generateFileForUpload(WebPage*, const String& originalFilePath) override;
-
UIElementVisibility statusBarIsVisible(WebPage*) override;
UIElementVisibility menuBarIsVisible(WebPage*) override;
UIElementVisibility toolbarsAreVisible(WebPage*) override;
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (248138 => 248139)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp 2019-08-01 22:29:52 UTC (rev 248139)
@@ -789,17 +789,6 @@
cacheStorage.storeUpdatedQuotaForOrigin(&origin, newQuota);
}
-bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
-{
- generatedFilename = m_page.injectedBundleUIClient().shouldGenerateFileForUpload(&m_page, path);
- return !generatedFilename.isNull();
-}
-
-String WebChromeClient::generateReplacementFile(const String& path)
-{
- return m_page.injectedBundleUIClient().generateFileForUpload(&m_page, path);
-}
-
#if ENABLE(INPUT_TYPE_COLOR)
std::unique_ptr<ColorChooser> WebChromeClient::createColorChooser(ColorChooserClient& client, const Color& initialColor)
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (248138 => 248139)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -142,9 +142,6 @@
void reachedMaxAppCacheSize(int64_t spaceNeeded) final;
void reachedApplicationCacheOriginQuota(WebCore::SecurityOrigin&, int64_t spaceNeeded) final;
-
- bool shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename) final;
- String generateReplacementFile(const String& path) final;
#if ENABLE(INPUT_TYPE_COLOR)
std::unique_ptr<WebCore::ColorChooser> createColorChooser(WebCore::ColorChooserClient&, const WebCore::Color&) final;
Modified: trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in (248138 => 248139)
--- trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in 2019-08-01 22:29:52 UTC (rev 248139)
@@ -587,9 +587,6 @@
(allow mach-lookup
(global-name "com.apple.webinspector"))
-(allow mach-lookup
- (global-name "com.apple.FileCoordination"))
-
;; Various services required by AppKit and other frameworks
(allow mach-lookup
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101400
@@ -978,18 +975,9 @@
(syscall-number SYS_stat64_extended) ;; <rdar://problem/50473330>
(syscall-number SYS_lstat_extended)
(syscall-number SYS_lstat64_extended)
- (syscall-number SYS_iopolicysys)
- (syscall-number SYS_workq_open)
- (syscall-number SYS_getgroups)
(syscall-number SYS_fgetattrlist) ;; <rdar://problem/50931110>
(syscall-number SYS_kqueue) ;; <rdar://problem/49609201>
(syscall-number SYS_kqueue_workloop_ctl) ;; <rdar://problem/50999499>
- (syscall-number SYS_open_dprotected_np)
- (syscall-number SYS_flistxattr)
- (syscall-number SYS_fsetattrlist)
- (syscall-number SYS_fchown)
- (syscall-number SYS_fchflags)
- (syscall-number SYS_fstat64_extended)
)
)
Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (248138 => 248139)
--- trunk/Source/WebKitLegacy/mac/ChangeLog 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog 2019-08-01 22:29:52 UTC (rev 248139)
@@ -1,3 +1,20 @@
+2019-08-01 Alex Christensen <[email protected]>
+
+ Move FormData zip file generation to NetworkProcess and enable it for all WebKit clients for uploading directories
+ https://bugs.webkit.org/show_bug.cgi?id=200102
+ <rdar://problem/53275114>
+
+ Reviewed by Darin Adler.
+
+ * DefaultDelegates/WebDefaultUIDelegate.mm:
+ (-[WebDefaultUIDelegate webView:shouldReplaceUploadFile:usingGeneratedFilename:]): Deleted.
+ (-[WebDefaultUIDelegate webView:generateReplacementFile:]): Deleted.
+ * WebCoreSupport/WebChromeClient.h:
+ * WebCoreSupport/WebChromeClient.mm:
+ (WebChromeClient::shouldReplaceWithGeneratedFileForUpload): Deleted.
+ (WebChromeClient::generateReplacementFile): Deleted.
+ * WebView/WebUIDelegatePrivate.h:
+
2019-07-25 Dean Jackson <[email protected]>
Add helper for ignoring deprecated implementation warnings
Modified: trunk/Source/WebKitLegacy/mac/DefaultDelegates/WebDefaultUIDelegate.mm (248138 => 248139)
--- trunk/Source/WebKitLegacy/mac/DefaultDelegates/WebDefaultUIDelegate.mm 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKitLegacy/mac/DefaultDelegates/WebDefaultUIDelegate.mm 2019-08-01 22:29:52 UTC (rev 248139)
@@ -256,16 +256,6 @@
{
}
-- (BOOL)webView:(WebView *)sender shouldReplaceUploadFile:(NSString *)path usingGeneratedFilename:(NSString **)filename
-{
- return NO;
-}
-
-- (NSString *)webView:(WebView *)sender generateReplacementFile:(NSString *)path
-{
- return nil;
-}
-
#if PLATFORM(IOS_FAMILY)
- (void)webViewSupportedOrientationsUpdated:(WebView *)sender
{
Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h (248138 => 248139)
--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -158,9 +158,6 @@
void enableSuddenTermination() final;
void disableSuddenTermination() final;
- bool shouldReplaceWithGeneratedFileForUpload(const String& path, String &generatedFilename) final;
- String generateReplacementFile(const String& path) final;
-
#if !PLATFORM(IOS_FAMILY)
void elementDidFocus(WebCore::Element&) override;
void elementDidBlur(WebCore::Element&) override;
Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm (248138 => 248139)
--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm 2019-08-01 22:29:52 UTC (rev 248139)
@@ -855,20 +855,6 @@
#endif
}
-bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
-{
- NSString* filename;
- if (![[m_webView _UIDelegateForwarder] webView:m_webView shouldReplaceUploadFile:path usingGeneratedFilename:&filename])
- return false;
- generatedFilename = filename;
- return true;
-}
-
-String WebChromeClient::generateReplacementFile(const String& path)
-{
- return [[m_webView _UIDelegateForwarder] webView:m_webView generateReplacementFile:path];
-}
-
#if !PLATFORM(IOS_FAMILY)
void WebChromeClient::elementDidFocus(WebCore::Element& element)
{
Modified: trunk/Source/WebKitLegacy/mac/WebView/WebUIDelegatePrivate.h (248138 => 248139)
--- trunk/Source/WebKitLegacy/mac/WebView/WebUIDelegatePrivate.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebUIDelegatePrivate.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -248,9 +248,6 @@
- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features;
-- (BOOL)webView:(WebView *)sender shouldReplaceUploadFile:(NSString *)path usingGeneratedFilename:(NSString **)filename;
-- (NSString *)webView:(WebView *)sender generateReplacementFile:(NSString *)path;
-
/*!
@method webView:decidePolicyForGeolocationRequestFromOrigin:frame:listener:
@param webView The WebView sending the delegate method.
Modified: trunk/Tools/ChangeLog (248138 => 248139)
--- trunk/Tools/ChangeLog 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Tools/ChangeLog 2019-08-01 22:29:52 UTC (rev 248139)
@@ -1,3 +1,24 @@
+2019-08-01 Alex Christensen <[email protected]>
+
+ Move FormData zip file generation to NetworkProcess and enable it for all WebKit clients for uploading directories
+ https://bugs.webkit.org/show_bug.cgi?id=200102
+ <rdar://problem/53275114>
+
+ Reviewed by Darin Adler.
+
+ Add an API test that is Mac-only right now because runOpenPanelWithParameters is only supported on Mac for some reason
+ and because clicking on a TestWKWebView only works on Mac.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/UploadDirectory.mm: Added.
+ (-[UploadDelegate initWithDirectory:]):
+ (-[UploadDelegate webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:]):
+ (-[UploadDelegate sentDirectory]):
+ (TEST):
+ * TestWebKitAPI/cocoa/TestWKWebView.h:
+ * TestWebKitAPI/cocoa/TestWKWebView.mm:
+ (-[TestWKWebView sendClickAtPoint:]):
+
2019-08-01 Zhifei Fang <[email protected]>
[results.webkit.org] Timeline.CanvasXAxisComponent height should be defined by option
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (248138 => 248139)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-08-01 22:29:52 UTC (rev 248139)
@@ -342,6 +342,7 @@
5C23DF0B2246015800F454B6 /* Challenge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C23DF0A2245C9D700F454B6 /* Challenge.mm */; };
5C2936931D5BF70D00DEAB1E /* CookieAcceptPolicy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C2936911D5BF63E00DEAB1E /* CookieAcceptPolicy.mm */; };
5C2936961D5C00ED00DEAB1E /* CookieMessage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5C2936941D5BFD1900DEAB1E /* CookieMessage.html */; };
+ 5C3A77AA22F20BEA003827FF /* UploadDirectory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C3A77A922F20B8A003827FF /* UploadDirectory.mm */; };
5C3B1D2622A74F6700BCF4D0 /* ContextMenus.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C3B1D2522A74EA400BCF4D0 /* ContextMenus.mm */; };
5C4259462266A68A0039AA7A /* BasicProposedCredentialPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */; };
5C4A84951F7EEFFC00ACFC54 /* Configuration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C4A84941F7EEFD400ACFC54 /* Configuration.mm */; };
@@ -1819,6 +1820,7 @@
5C23DF0A2245C9D700F454B6 /* Challenge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Challenge.mm; sourceTree = "<group>"; };
5C2936911D5BF63E00DEAB1E /* CookieAcceptPolicy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CookieAcceptPolicy.mm; sourceTree = "<group>"; };
5C2936941D5BFD1900DEAB1E /* CookieMessage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = CookieMessage.html; sourceTree = "<group>"; };
+ 5C3A77A922F20B8A003827FF /* UploadDirectory.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UploadDirectory.mm; sourceTree = "<group>"; };
5C3B1D2522A74EA400BCF4D0 /* ContextMenus.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContextMenus.mm; sourceTree = "<group>"; };
5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BasicProposedCredentialPlugIn.mm; sourceTree = "<group>"; };
5C4A84941F7EEFD400ACFC54 /* Configuration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Configuration.mm; sourceTree = "<group>"; };
@@ -2828,6 +2830,7 @@
F4CD74C820FDB49600DE3794 /* TestURLSchemeHandler.mm */,
C22FA32A228F8708009D7988 /* TextWidth.mm */,
5CB40B4D1F4B98BE007DC7B9 /* UIDelegate.mm */,
+ 5C3A77A922F20B8A003827FF /* UploadDirectory.mm */,
7CC3E1FA197E234100BE6252 /* UserContentController.mm */,
7C882E031C80C624006BF731 /* UserContentWorld.mm */,
7C882E041C80C624006BF731 /* UserContentWorldPlugIn.mm */,
@@ -4686,6 +4689,7 @@
5C9D923A22D7E2B0008E9266 /* UnifiedSource4-mm.mm in Sources */,
5C9D923C22D7E2B0008E9266 /* UnifiedSource5-mm.mm in Sources */,
5C9D923D22D7E2B0008E9266 /* UnifiedSource5.cpp in Sources */,
+ 5C3A77AA22F20BEA003827FF /* UploadDirectory.mm in Sources */,
5C6E27A7224EEBEA00128736 /* URLCanonicalization.mm in Sources */,
E3A1E77F21B25B39008C6007 /* URLParserTextEncoding.cpp in Sources */,
7CCE7F271A411AF600447C4C /* UserContentController.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UploadDirectory.mm (0 => 248139)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UploadDirectory.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UploadDirectory.mm 2019-08-01 22:29:52 UTC (rev 248139)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if PLATFORM(MAC)
+
+#import "DragAndDropSimulator.h"
+#import "TCPServer.h"
+#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
+#import "Utilities.h"
+#import <WebKit/WebKit.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
+
+@interface UploadDelegate : NSObject <WKUIDelegate>
+- (instancetype)initWithDirectory:(NSURL *)directory;
+- (BOOL)sentDirectory;
+@end
+
+@implementation UploadDelegate {
+ RetainPtr<NSURL> _directory;
+ BOOL _sentDirectory;
+}
+
+- (instancetype)initWithDirectory:(NSURL *)directory
+{
+ if (!(self = [super init]))
+ return nil;
+ _directory = directory;
+ return self;
+}
+
+- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * _Nullable URLs))completionHandler
+{
+ completionHandler(@[_directory.get()]);
+ _sentDirectory = YES;
+}
+
+- (BOOL)sentDirectory
+{
+ return _sentDirectory;
+}
+
+@end
+
+TEST(WebKit, UploadDirectory)
+{
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ NSError *error = nil;
+ NSURL *directory = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"UploadDirectory"] isDirectory:YES];
+ EXPECT_FALSE([fileManager fileExistsAtPath:directory.path]);
+ EXPECT_TRUE([fileManager createDirectoryAtURL:directory withIntermediateDirectories:YES attributes:nil error:&error]);
+ EXPECT_FALSE(error);
+ NSData *testData = [@"testdata" dataUsingEncoding:NSUTF8StringEncoding];
+ EXPECT_TRUE([fileManager createFileAtPath:[directory.path stringByAppendingPathComponent:@"testfile"] contents:testData attributes:nil]);
+
+ {
+ using namespace TestWebKitAPI;
+ TCPServer server([] (int socket) {
+ TCPServer::read(socket);
+ const char* response =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 123\r\n\r\n"
+ "<form id='form' action='' method='post' enctype='multipart/form-data'><input type='file' name='testname'></form>";
+ TCPServer::write(socket, response, strlen(response));
+
+ auto header = TCPServer::read(socket);
+ EXPECT_TRUE(String(header.data(), header.size()).contains("Content-Length: 543"));
+ size_t bodyBytesRead = 0;
+ while (bodyBytesRead < 543)
+ bodyBytesRead += TCPServer::read(socket).size();
+ EXPECT_EQ(bodyBytesRead, 543ull);
+ const char* secondResponse =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 0\r\n\r\n";
+ TCPServer::write(socket, secondResponse, strlen(secondResponse));
+ });
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
+ auto delegate = adoptNS([[UploadDelegate alloc] initWithDirectory:directory]);
+ [webView setUIDelegate:delegate.get()];
+
+ [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()]]]];
+
+ auto chooseFileButtonLocation = NSMakePoint(10, 590);
+ [webView sendClickAtPoint:chooseFileButtonLocation];
+ while (![delegate sentDirectory])
+ TestWebKitAPI::Util::spinRunLoop();
+ [webView evaluateJavaScript:@"document.getElementById('form').submit()" completionHandler:nil];
+ [webView _test_waitForDidFinishNavigation];
+ }
+
+ EXPECT_TRUE([fileManager removeItemAtPath:directory.path error:&error]);
+ EXPECT_FALSE(error);
+}
+
+#endif
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (248138 => 248139)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h 2019-08-01 22:29:52 UTC (rev 248139)
@@ -106,6 +106,7 @@
- (void)mouseUpAtPoint:(NSPoint)pointInWindow;
- (void)mouseMoveToPoint:(NSPoint)pointInWindow withFlags:(NSEventModifierFlags)flags;
- (void)sendClicksAtPoint:(NSPoint)pointInWindow numberOfClicks:(NSUInteger)numberOfClicks;
+- (void)sendClickAtPoint:(NSPoint)pointInWindow;
- (NSWindow *)hostWindow;
- (void)typeCharacter:(char)character;
@end
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (248138 => 248139)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2019-08-01 22:27:27 UTC (rev 248138)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2019-08-01 22:29:52 UTC (rev 248139)
@@ -593,6 +593,11 @@
}
}
+- (void)sendClickAtPoint:(NSPoint)pointInWindow
+{
+ [self sendClicksAtPoint:pointInWindow numberOfClicks:1];
+}
+
- (void)mouseEnterAtPoint:(NSPoint)pointInWindow
{
[self mouseEntered:[self _mouseEventWithType:NSEventTypeMouseEntered atLocation:pointInWindow]];