- Revision
- 243340
- Author
- [email protected]
- Date
- 2019-03-21 15:54:25 -0700 (Thu, 21 Mar 2019)
Log Message
Web Automation: support uploading non-local file paths
https://bugs.webkit.org/show_bug.cgi?id=196081
<rdar://problem/45819897>
Reviewed by Devin Rousso and Joseph Pecoraro.
To support cases where supplied file paths do not exist on the session host, add support for
receiving file contents via Automation.setFilesToSelectForFileUpload.
* UIProcess/Automation/Automation.json: Add new parameter.
* UIProcess/Automation/WebAutomationSession.h:
* UIProcess/Automation/WebAutomationSession.cpp:
(WebKit::WebAutomationSession::setFilesToSelectForFileUpload):
Add support for receiving and saving file contents to a temporary directory. Rewrite the used paths so
that WebCore knows to look at the revised paths where the file contents have been saved.
(WebKit::WebAutomationSession::platformGenerateLocalFilePathForRemoteFile):
Since WebKit does not have usable FileSystem implementations for all ports, shell out the actual
saving of base64-encoded file data. Provide a Cocoa implementation, since that's what I can test.
* UIProcess/Automation/cocoa/WebAutomationSessionCocoa.mm:
(WebKit::WebAutomationSession::platformGenerateLocalFilePathForRemoteFile):
Use WTF::FileSystem to create a temporary directory, and use Cocoa methods to actually write the file.
Modified Paths
Diff
Modified: trunk/Source/WebKit/ChangeLog (243339 => 243340)
--- trunk/Source/WebKit/ChangeLog 2019-03-21 22:52:18 UTC (rev 243339)
+++ trunk/Source/WebKit/ChangeLog 2019-03-21 22:54:25 UTC (rev 243340)
@@ -1,3 +1,30 @@
+2019-03-21 Brian Burg <[email protected]>
+
+ Web Automation: support uploading non-local file paths
+ https://bugs.webkit.org/show_bug.cgi?id=196081
+ <rdar://problem/45819897>
+
+ Reviewed by Devin Rousso and Joseph Pecoraro.
+
+ To support cases where supplied file paths do not exist on the session host, add support for
+ receiving file contents via Automation.setFilesToSelectForFileUpload.
+
+ * UIProcess/Automation/Automation.json: Add new parameter.
+
+ * UIProcess/Automation/WebAutomationSession.h:
+ * UIProcess/Automation/WebAutomationSession.cpp:
+ (WebKit::WebAutomationSession::setFilesToSelectForFileUpload):
+ Add support for receiving and saving file contents to a temporary directory. Rewrite the used paths so
+ that WebCore knows to look at the revised paths where the file contents have been saved.
+
+ (WebKit::WebAutomationSession::platformGenerateLocalFilePathForRemoteFile):
+ Since WebKit does not have usable FileSystem implementations for all ports, shell out the actual
+ saving of base64-encoded file data. Provide a Cocoa implementation, since that's what I can test.
+
+ * UIProcess/Automation/cocoa/WebAutomationSessionCocoa.mm:
+ (WebKit::WebAutomationSession::platformGenerateLocalFilePathForRemoteFile):
+ Use WTF::FileSystem to create a temporary directory, and use Cocoa methods to actually write the file.
+
2019-03-21 Youenn Fablet <[email protected]>
Cache API and IDB space usages should be initialized on first quota check
Modified: trunk/Source/WebKit/UIProcess/Automation/Automation.json (243339 => 243340)
--- trunk/Source/WebKit/UIProcess/Automation/Automation.json 2019-03-21 22:52:18 UTC (rev 243339)
+++ trunk/Source/WebKit/UIProcess/Automation/Automation.json 2019-03-21 22:54:25 UTC (rev 243340)
@@ -619,7 +619,8 @@
"description": "Sets the files to be selected when a file input type element becomes active in a browsing context.",
"parameters": [
{ "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." },
- { "name": "filenames", "type": "array", "items": { "$ref": "string" }, "description": "Absolute paths to the files that should be selected." }
+ { "name": "filenames", "type": "array", "items": { "type": "string" }, "description": "Absolute paths to the files that should be selected." },
+ { "name": "fileContents", "type": "array", "items": { "type" : "string" }, "optional": true, "description": "An array of Base64-encoded binary data for each file to be selected. If this property is provided, it is assumed that 'filenames' are not real file paths on the session host's filesystem, and this binary data will be used instead." }
]
},
{
Modified: trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp (243339 => 243340)
--- trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp 2019-03-21 22:52:18 UTC (rev 243339)
+++ trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp 2019-03-21 22:54:25 UTC (rev 243340)
@@ -1238,17 +1238,33 @@
m_client->setUserInputForCurrentJavaScriptPromptOnPage(*this, *page, promptValue);
}
-void WebAutomationSession::setFilesToSelectForFileUpload(ErrorString& errorString, const String& browsingContextHandle, const JSON::Array& filenames)
+void WebAutomationSession::setFilesToSelectForFileUpload(ErrorString& errorString, const String& browsingContextHandle, const JSON::Array& filenames, const JSON::Array* fileContents)
{
Vector<String> newFileList;
newFileList.reserveInitialCapacity(filenames.length());
- for (const auto& item : filenames) {
+ if (fileContents && fileContents->length() != filenames.length())
+ SYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(InternalError, "The parameters 'filenames' and 'fileContents' must have equal length.");
+
+ for (size_t i = 0; i < filenames.length(); ++i) {
String filename;
- if (!item->asString(filename))
- SYNC_FAIL_WITH_PREDEFINED_ERROR(InternalError);
+ if (!filenames.get(i)->asString(filename))
+ SYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(InternalError, "The parameter 'filenames' contains a non-string value.");
- newFileList.append(filename);
+ if (!fileContents) {
+ newFileList.append(filename);
+ continue;
+ }
+
+ String fileData;
+ if (!fileContents->get(i)->asString(fileData))
+ SYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(InternalError, "The parameter 'fileContents' contains a non-string value.");
+
+ Optional<String> localFilePath = platformGenerateLocalFilePathForRemoteFile(filename, fileData);
+ if (!localFilePath)
+ SYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(InternalError, "The remote file could not be saved to a local temporary directory.");
+
+ newFileList.append(localFilePath.value());
}
m_filesToSelectForFileUpload.swap(newFileList);
@@ -2048,4 +2064,11 @@
}
#endif // !PLATFORM(COCOA) && !USE(CAIRO)
+#if !PLATFORM(COCOA)
+Optional<String> WebAutomationSession::platformGenerateLocalFilePathForRemoteFile(const String&, const String&)
+{
+ return WTF::nullopt;
+}
+#endif // !PLATFORM(COCOA)
+
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h (243339 => 243340)
--- trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h 2019-03-21 22:52:18 UTC (rev 243339)
+++ trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h 2019-03-21 22:54:25 UTC (rev 243340)
@@ -186,7 +186,7 @@
void acceptCurrentJavaScriptDialog(Inspector::ErrorString&, const String& browsingContextHandle) override;
void messageOfCurrentJavaScriptDialog(Inspector::ErrorString&, const String& browsingContextHandle, String* text) override;
void setUserInputForCurrentJavaScriptPrompt(Inspector::ErrorString&, const String& browsingContextHandle, const String& text) override;
- void setFilesToSelectForFileUpload(Inspector::ErrorString&, const String& browsingContextHandle, const JSON::Array& filenames) override;
+ void setFilesToSelectForFileUpload(Inspector::ErrorString&, const String& browsingContextHandle, const JSON::Array& filenames, const JSON::Array* optionalFileContents) override;
void getAllCookies(const String& browsingContextHandle, Ref<GetAllCookiesCallback>&&) override;
void deleteSingleCookie(const String& browsingContextHandle, const String& cookieName, Ref<DeleteSingleCookieCallback>&&) override;
void addSingleCookie(const String& browsingContextHandle, const JSON::Object& cookie, Ref<AddSingleCookieCallback>&&) override;
@@ -260,9 +260,13 @@
void platformSimulateKeySequence(WebPageProxy&, const String&);
#endif // ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS)
- // Get base64 encoded PNG data from a bitmap.
+ // Get base64-encoded PNG data from a bitmap.
Optional<String> platformGetBase64EncodedPNGData(const ShareableBitmap::Handle&);
+ // Save base64-encoded file contents to a local file path and return the path.
+ // This reuses the basename of the remote file path so that the filename exposed to DOM API remains the same.
+ Optional<String> platformGenerateLocalFilePathForRemoteFile(const String& remoteFilePath, const String& base64EncodedFileContents);
+
#if PLATFORM(COCOA)
// The type parameter of the NSArray argument is platform-dependent.
void sendSynthesizedEventsToPage(WebPageProxy&, NSArray *eventsToSend);
Modified: trunk/Source/WebKit/UIProcess/Automation/cocoa/WebAutomationSessionCocoa.mm (243339 => 243340)
--- trunk/Source/WebKit/UIProcess/Automation/cocoa/WebAutomationSessionCocoa.mm 2019-03-21 22:52:18 UTC (rev 243339)
+++ trunk/Source/WebKit/UIProcess/Automation/cocoa/WebAutomationSessionCocoa.mm 2019-03-21 22:54:25 UTC (rev 243340)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016, 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-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
@@ -28,6 +28,8 @@
#if PLATFORM(COCOA)
+#import <wtf/FileSystem.h>
+
#if PLATFORM(IOS_FAMILY)
#include <ImageIO/CGImageDestination.h>
#include <MobileCoreServices/UTCoreTypes.h>
@@ -55,6 +57,28 @@
return String([imageData base64EncodedStringWithOptions:0]);
}
+Optional<String> WebAutomationSession::platformGenerateLocalFilePathForRemoteFile(const String& remoteFilePath, const String& base64EncodedFileContents)
+{
+ RetainPtr<NSData> fileContents = adoptNS([[NSData alloc] initWithBase64EncodedString:base64EncodedFileContents options:0]);
+ if (!fileContents) {
+ LOG_ERROR("WebAutomationSession: unable to decode base64-encoded file contents.");
+ return WTF::nullopt;
+ }
+
+ NSString *temporaryDirectory = FileSystem::createTemporaryDirectory(@"WebDriver");
+ NSURL *remoteFile = [NSURL fileURLWithPath:remoteFilePath isDirectory:NO];
+ NSString *localFilePath = [temporaryDirectory stringByAppendingPathComponent:remoteFile.lastPathComponent];
+
+ NSError *fileWriteError;
+ [fileContents.get() writeToFile:localFilePath options:NSDataWritingAtomic error:&fileWriteError];
+ if (fileWriteError) {
+ LOG_ERROR("WebAutomationSession: Error writing image data to temporary file: %@", fileWriteError);
+ return WTF::nullopt;
+ }
+
+ return String(localFilePath);
+}
+
Optional<unichar> WebAutomationSession::charCodeForVirtualKey(Inspector::Protocol::Automation::VirtualKey key) const
{
switch (key) {