Diff
Modified: trunk/LayoutTests/ChangeLog (261411 => 261412)
--- trunk/LayoutTests/ChangeLog 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/LayoutTests/ChangeLog 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1,3 +1,14 @@
+2020-05-08 Nikos Mouchtaris <[email protected]>
+
+ Implement web-share v2 for files
+ https://bugs.webkit.org/show_bug.cgi?id=209265
+
+ Reviewed by Andy Estes.
+
+ Modified to no longer use url of image.
+
+ * fast/web-share/share-with-files.html:
+
2020-05-08 Jason Lawrence <[email protected]>
REGRESSION [ iOS ] fast/forms/validationMessage.html is flaky and timing out
Modified: trunk/LayoutTests/fast/web-share/share-with-files.html (261411 => 261412)
--- trunk/LayoutTests/fast/web-share/share-with-files.html 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/LayoutTests/fast/web-share/share-with-files.html 2020-05-08 20:46:10 UTC (rev 261412)
@@ -2,6 +2,7 @@
<html>
<meta name="viewport" content="initial-scale=5, width=device-width">
+
<head>
<script src=""
@@ -16,10 +17,12 @@
function runTest()
{
- const textFile = new File(['hello'], 'hello.txt', {type:'text/plain'});
+
+ var blob = this.response;
+ const textFile = new File(['This is a text file'], 'TextFile.txt', {type:'text/html'});
document.getElementById("target").addEventListener("click", () => {
- navigator.share({text: "sadf", files: [textFile]}).then((result) => {
- write("PASS: Share sheet invoked.");
+ navigator.share({text: "This is a text file", files: [textFile]}).then((result) => {
+ write("PASS: Share sheet invoked.");
testRunner.notifyDone();
});
});
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (261411 => 261412)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1,3 +1,15 @@
+2020-05-08 Nikos Mouchtaris <[email protected]>
+
+ Implement web-share v2 for files
+ https://bugs.webkit.org/show_bug.cgi?id=209265
+
+ Reviewed by Andy Estes.
+
+ Updated test expectations for new behavior.
+
+ * ios-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt :
+ * mac-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt :
+
2020-05-08 Ryan Haddad <[email protected]>
Unreviewed, reverting r261341 and r261392.
Modified: trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt (261411 => 261412)
--- trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1,8 +1,8 @@
PASS canShare with single file
PASS canShare with empty file list
-FAIL canShare with single file list assert_equals: expected true but got false
-FAIL canShare with file list assert_equals: expected true but got false
-FAIL canShare with repeated file assert_equals: expected true but got false
+PASS canShare with single file list
+PASS canShare with file list
+PASS canShare with repeated file
PASS canShare with file list and url
Modified: trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt (261411 => 261412)
--- trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/web-share/canShare-files.https-expected.txt 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1,8 +1,8 @@
PASS canShare with single file
PASS canShare with empty file list
-FAIL canShare with single file list assert_equals: expected true but got false
-FAIL canShare with file list assert_equals: expected true but got false
-FAIL canShare with repeated file assert_equals: expected true but got false
+PASS canShare with single file list
+PASS canShare with file list
+PASS canShare with repeated file
PASS canShare with file list and url
Modified: trunk/Source/WTF/wtf/PlatformEnable.h (261411 => 261412)
--- trunk/Source/WTF/wtf/PlatformEnable.h 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WTF/wtf/PlatformEnable.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -547,6 +547,10 @@
#define ENABLE_DATA_DETECTION 0
#endif
+#if !defined(ENABLE_FILE_SHARE)
+#define ENABLE_FILE_SHARE 1
+#endif
+
/*
* Enable this to put each IsoHeap and other allocation categories into their own malloc heaps, so that tools like vmmap can show how big each heap is.
* Turn BENABLE_MALLOC_HEAP_BREAKDOWN on in bmalloc together when using this.
Modified: trunk/Source/WebCore/ChangeLog (261411 => 261412)
--- trunk/Source/WebCore/ChangeLog 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebCore/ChangeLog 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1,3 +1,34 @@
+2020-05-08 Nikos Mouchtaris <[email protected]>
+
+ Implement web-share v2 for files
+ https://bugs.webkit.org/show_bug.cgi?id=209265
+
+ Reviewed by Andy Estes.
+
+ Modified existing tests for new behavior.
+
+ Added support for handling of files in share/canShare,
+ and implemented asynchronous reading of data from blobs on
+ disk into memory.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * page/Navigator.cpp:
+ (WebCore::Navigator::canShare):
+ (WebCore::Navigator::share):
+ (WebCore::Navigator::finishedLoad):
+ * page/Navigator.h:
+ * page/ReadShareDataAsync.cpp: Added.
+ (WebCore::ReadShareDataAsync::readInternal):
+ (WebCore::ReadShareDataAsync::ReadShareDataAsync):
+ (WebCore::ReadShareDataAsync::~ReadShareDataAsync):
+ (WebCore::ReadShareDataAsync::start):
+ (WebCore::ReadShareDataAsync::didFinishLoading):
+ (WebCore::ReadShareDataAsync::didReceiveData):
+ (WebCore::ReadShareDataAsync::didStartLoading):
+ (WebCore::ReadShareDataAsync::didFail):
+ * page/ReadShareDataAsync.hpp: Added.
+ * page/ShareData.h:
+
2020-05-08 Ryan Haddad <[email protected]>
Unreviewed, reverting r261341 and r261392.
Modified: trunk/Source/WebCore/Sources.txt (261411 => 261412)
--- trunk/Source/WebCore/Sources.txt 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebCore/Sources.txt 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1688,6 +1688,7 @@
page/SecurityOriginData.cpp
page/SecurityPolicy.cpp
page/SettingsBase.cpp
+page/ShareDataReader.cpp
page/SocketProvider.cpp
page/SpatialNavigation.cpp
page/SuspendableTimer.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (261411 => 261412)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-05-08 20:46:10 UTC (rev 261412)
@@ -6175,6 +6175,8 @@
1A2A68220B5BEDE70002A480 /* ProgressTracker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProgressTracker.h; sourceTree = "<group>"; };
1A2AAC560DC2A3B100A20D9A /* ApplicationCacheStorage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ApplicationCacheStorage.cpp; sourceTree = "<group>"; };
1A2AAC570DC2A3B100A20D9A /* ApplicationCacheStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationCacheStorage.h; sourceTree = "<group>"; };
+ 1A2C6671242AFEF7003055EC /* ShareDataReader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ShareDataReader.cpp; sourceTree = "<group>"; };
+ 1A2C6673242AFEF8003055EC /* ShareDataReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareDataReader.h; sourceTree = "<group>"; };
1A2E6E580CC55213004A2062 /* SQLValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLValue.h; sourceTree = "<group>"; };
1A2E6E780CC556D5004A2062 /* SQLiteAuthorizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteAuthorizer.cpp; sourceTree = "<group>"; };
1A3586DD15264C450022A659 /* RenderMultiColumnFlow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMultiColumnFlow.cpp; sourceTree = "<group>"; };
@@ -21167,6 +21169,8 @@
7C6EFEEA1F946A2E00FFAD41 /* SettingsDefaultValues.h */,
1DC55400211BA8C8004B780E /* ShareData.h */,
1DC553FF211BA841004B780E /* ShareData.idl */,
+ 1A2C6671242AFEF7003055EC /* ShareDataReader.cpp */,
+ 1A2C6673242AFEF8003055EC /* ShareDataReader.h */,
5C688AA21D38126F000B54FA /* SocketProvider.cpp */,
5C7C88D71D0F1F2B009D2F6D /* SocketProvider.h */,
626CDE0C1140424C001E5A68 /* SpatialNavigation.cpp */,
Modified: trunk/Source/WebCore/page/Navigator.cpp (261411 => 261412)
--- trunk/Source/WebCore/page/Navigator.cpp 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebCore/page/Navigator.cpp 2020-05-08 20:46:10 UTC (rev 261412)
@@ -43,6 +43,8 @@
#include "SecurityOrigin.h"
#include "Settings.h"
#include "ShareData.h"
+#include "ShareDataReader.h"
+#include "SharedBuffer.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/Language.h>
#include <wtf/StdLibExtras.h>
@@ -112,8 +114,13 @@
if (!frame || !frame->page())
return false;
if (data.title.isNull() && data.url.isNull() && data.text.isNull()) {
- if (!data.files.isEmpty())
+ if (!data.files.isEmpty()) {
+#if ENABLE(FILE_SHARE)
+ return true;
+#else
return false;
+#endif
+ }
return false;
}
@@ -139,7 +146,7 @@
auto* window = this->window();
// Note that the specification does not indicate we should consume user activation. We are intentionally stricter here.
- if (!window || !window->consumeTransientActivation()) {
+ if (!window || !window->consumeTransientActivation() || m_hasPendingShare) {
promise->reject(NotAllowedError);
return;
}
@@ -147,10 +154,39 @@
ShareDataWithParsedURL shareData = {
data,
url,
+ { },
};
+#if ENABLE(FILE_SHARE)
+ if (!data.files.isEmpty()) {
+ if (m_loader)
+ m_loader->cancel();
+
+ m_loader = ShareDataReader::create([this, promise = WTFMove(promise)] (ExceptionOr<ShareDataWithParsedURL&> readData) mutable {
+ showShareData(readData, WTFMove(promise));
+ });
+ m_loader->start(frame()->document(), WTFMove(shareData));
+ return;
+ }
+#endif
+ this->showShareData(shareData, WTFMove(promise));
+}
+
+void Navigator::showShareData(ExceptionOr<ShareDataWithParsedURL&> readData, Ref<DeferredPromise>&& promise)
+{
+ if (readData.hasException()) {
+ promise->reject(readData.releaseException());
+ return;
+ }
auto* frame = this->frame();
- frame->page()->chrome().showShareSheet(shareData, [promise = WTFMove(promise)] (bool completed) {
+ if (!frame || !frame->page())
+ return;
+
+ m_hasPendingShare = true;
+ auto shareData = readData.returnValue();
+
+ frame->page()->chrome().showShareSheet(shareData, [promise = WTFMove(promise), this] (bool completed) {
+ m_hasPendingShare = false;
if (completed) {
promise->resolve();
return;
Modified: trunk/Source/WebCore/page/Navigator.h (261411 => 261412)
--- trunk/Source/WebCore/page/Navigator.h 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebCore/page/Navigator.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -22,15 +22,17 @@
#include "DOMWindowProperty.h"
#include "NavigatorBase.h"
#include "ScriptWrappable.h"
+#include "ShareData.h"
#include "Supplementable.h"
#include <wtf/IsoMalloc.h>
namespace WebCore {
+class Blob;
class DeferredPromise;
class DOMMimeTypeArray;
class DOMPluginArray;
-struct ShareData;
+class ShareDataReader;
class Navigator final : public NavigatorBase, public ScriptWrappable, public DOMWindowProperty, public Supplementable<Navigator> {
WTF_MAKE_ISO_ALLOCATED(Navigator);
@@ -63,12 +65,14 @@
#endif
private:
+ void showShareData(ExceptionOr<ShareDataWithParsedURL&>, Ref<DeferredPromise>&&);
explicit Navigator(ScriptExecutionContext*, DOMWindow&);
+ mutable RefPtr<ShareDataReader> m_loader;
+ mutable bool m_hasPendingShare { false };
mutable RefPtr<DOMPluginArray> m_plugins;
mutable RefPtr<DOMMimeTypeArray> m_mimeTypes;
mutable String m_userAgent;
mutable String m_platform;
};
-
}
Modified: trunk/Source/WebCore/page/ShareData.h (261411 => 261412)
--- trunk/Source/WebCore/page/ShareData.h 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebCore/page/ShareData.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -25,6 +25,7 @@
#pragma once
#include "File.h"
+#include "SharedBuffer.h"
#include <wtf/URL.h>
namespace WebCore {
@@ -35,10 +36,16 @@
String url;
Vector<RefPtr<File>> files;
};
+
+struct RawFile {
+ String fileName;
+ RefPtr<SharedBuffer> fileData;
+};
struct ShareDataWithParsedURL {
ShareData shareData;
Optional<URL> url;
+ Vector<RawFile> files;
};
}
Added: trunk/Source/WebCore/page/ShareDataReader.cpp (0 => 261412)
--- trunk/Source/WebCore/page/ShareDataReader.cpp (rev 0)
+++ trunk/Source/WebCore/page/ShareDataReader.cpp 2020-05-08 20:46:10 UTC (rev 261412)
@@ -0,0 +1,88 @@
+/*
+* Copyright (C) 2020 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.
+*/
+
+#include "config.h"
+#include "ShareDataReader.h"
+
+#include "BlobLoader.h"
+#include "Document.h"
+#include "SharedBuffer.h"
+
+namespace WebCore {
+
+ShareDataReader::ShareDataReader(CompletionHandler<void(ExceptionOr<ShareDataWithParsedURL&>)>&& completionHandler)
+ : m_completionHandler(WTFMove(completionHandler))
+{
+
+}
+
+ShareDataReader::~ShareDataReader()
+{
+ cancel();
+}
+
+void ShareDataReader::start(Document* document, ShareDataWithParsedURL&& shareData)
+{
+ m_filesReadSoFar = 0;
+ m_shareData = WTFMove(shareData);
+ int count = 0;
+ m_pendingFileLoads.reserveInitialCapacity(m_shareData.shareData.files.size());
+ for (auto& blob : m_shareData.shareData.files) {
+ m_pendingFileLoads.uncheckedAppend(makeUniqueRef<BlobLoader>(document, *blob, [this, count, fileName = blob->name()] {
+ this->didFinishLoading(count, fileName);
+ }));
+ count++;
+ }
+}
+
+void ShareDataReader::didFinishLoading(int loadIndex, const String& fileName)
+{
+ if (m_pendingFileLoads[loadIndex]->errorCode()) {
+ if (auto completionHandler = std::exchange(m_completionHandler, { }))
+ completionHandler(Exception { AbortError, "Abort due to error while reading files."_s });
+ cancel();
+ return;
+ }
+
+ auto arrayBuffer = m_pendingFileLoads[loadIndex]->result();
+
+ RawFile file;
+ file.fileName = fileName;
+ file.fileData = SharedBuffer::create(static_cast<const unsigned char*>(arrayBuffer->data()), arrayBuffer->byteLength());
+ m_shareData.files.append(WTFMove(file));
+ m_filesReadSoFar++;
+
+ if (m_filesReadSoFar == static_cast<int>(m_pendingFileLoads.size())) {
+ m_pendingFileLoads.clear();
+ if (auto completionHandler = std::exchange(m_completionHandler, { }))
+ completionHandler(m_shareData);
+ }
+}
+
+void ShareDataReader::cancel()
+{
+ m_pendingFileLoads.clear();
+}
+}
Added: trunk/Source/WebCore/page/ShareDataReader.h (0 => 261412)
--- trunk/Source/WebCore/page/ShareDataReader.h (rev 0)
+++ trunk/Source/WebCore/page/ShareDataReader.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -0,0 +1,56 @@
+/*
+* Copyright (C) 2020 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.
+*/
+
+#pragma once
+
+#include "ShareData.h"
+
+#include <wtf/CompletionHandler.h>
+
+namespace WebCore {
+
+class Blob;
+class BlobLoader;
+class Document;
+class ScriptExecutionContext;
+
+class ShareDataReader : public RefCounted<ShareDataReader> {
+public:
+ static Ref<ShareDataReader> create(CompletionHandler<void(ExceptionOr<ShareDataWithParsedURL&>)>&& completionHandler) { return adoptRef(*new ShareDataReader(WTFMove(completionHandler))); }
+ ~ShareDataReader();
+ void start(Document*, ShareDataWithParsedURL&&);
+ void cancel();
+
+private:
+ explicit ShareDataReader(CompletionHandler<void(ExceptionOr<ShareDataWithParsedURL&>)>&&);
+ void didFinishLoading(int, const String& fileName);
+
+ CompletionHandler<void(ExceptionOr<ShareDataWithParsedURL&>)> m_completionHandler;
+ ShareDataWithParsedURL m_shareData;
+ int m_filesReadSoFar;
+ Vector<UniqueRef<BlobLoader>> m_pendingFileLoads;
+};
+
+}
Modified: trunk/Source/WebKit/ChangeLog (261411 => 261412)
--- trunk/Source/WebKit/ChangeLog 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebKit/ChangeLog 2020-05-08 20:46:10 UTC (rev 261412)
@@ -1,3 +1,33 @@
+2020-05-08 Nikos Mouchtaris <[email protected]>
+
+ Implement web-share v2 for files
+ https://bugs.webkit.org/show_bug.cgi?id=209265
+
+ Reviewed by Andy Estes.
+
+ Added support for passing file objects over IPC and
+ sharing of files to share sheet.
+
+ * Shared/WebCoreArgumentCoders.cpp:
+ (IPC::ArgumentCoder<Vector<RawFile>>::encode):
+ (IPC::ArgumentCoder<Vector<RawFile>>::decode):
+ (IPC::ArgumentCoder<ShareDataWithParsedURL>::encode):
+ (IPC::ArgumentCoder<ShareDataWithParsedURL>::decode):
+ * Shared/WebCoreArgumentCoders.h:
+ * UIProcess/Cocoa/ShareableFileWrite.h: Added.
+ * UIProcess/Cocoa/ShareableFileWrite.mm: Added.
+ (+[WKShareableFileWrite getSharingDirectoryPath]):
+ (+[WKShareableFileWrite getFileDirectoryForSharing]):
+ (+[WKShareableFileWrite removeFileDirectoryForSharing]):
+ (+[WKShareableFileWrite setQuarantineInformationForFilePath:]):
+ (+[WKShareableFileWrite applyQuarantineSandboxAndDownloadFlagsToFileAtPath:]):
+ (+[WKShareableFileWrite createFilename:]):
+ (+[WKShareableFileWrite writeFileToShareableURL:data:]):
+ * UIProcess/Cocoa/WKShareSheet.mm:
+ (-[WKShareSheet presentWithParameters:inRect:completionHandler:]):
+ (-[WKShareSheet _didCompleteWithSuccess:]):
+ * WebKit.xcodeproj/project.pbxproj:
+
2020-05-08 Brent Fulgham <[email protected]>
Revise sandbox to stop logging some commonly-used properties
Modified: trunk/Source/WebKit/Platform/spi/mac/QuarantineSPI.h (261411 => 261412)
--- trunk/Source/WebKit/Platform/spi/mac/QuarantineSPI.h 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebKit/Platform/spi/mac/QuarantineSPI.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -34,6 +34,7 @@
#else
enum qtn_flags {
+ QTN_FLAG_DOWNLOAD = 0x0001,
QTN_FLAG_SANDBOX = 0x0002,
};
@@ -43,10 +44,15 @@
#define qtn_proc_init _qtn_proc_init
#define qtn_proc_init_with_self _qtn_proc_init_with_self
#define qtn_proc_set_flags _qtn_proc_set_flags
-
+#define qtn_file_alloc _qtn_file_alloc
+#define qtn_file_init_with_path _qtn_file_init_with_path
+#define qtn_file_free _qtn_file_free
+#define qtn_file_apply_to_path _qtn_file_apply_to_path
+#define qtn_file_set_flags _qtn_file_set_flags
#endif
typedef struct _qtn_proc *qtn_proc_t;
+typedef struct _qtn_file *qtn_file_t;
WTF_EXTERN_C_BEGIN
@@ -56,6 +62,11 @@
int qtn_proc_set_flags(qtn_proc_t, uint32_t flags);
qtn_proc_t qtn_proc_alloc();
void qtn_proc_free(qtn_proc_t);
+qtn_file_t qtn_file_alloc(void);
+void qtn_file_free(qtn_file_t qf);
+int qtn_file_set_flags(qtn_file_t qf, uint32_t flags);
+int qtn_file_apply_to_path(qtn_file_t qf, const char *path);
+int qtn_file_init_with_path(qtn_file_t qf, const char *path);
WTF_EXTERN_C_END
Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (261411 => 261412)
--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp 2020-05-08 20:46:10 UTC (rev 261412)
@@ -46,6 +46,7 @@
#include <WebCore/DragData.h>
#include <WebCore/EventTrackingRegions.h>
#include <WebCore/FetchOptions.h>
+#include <WebCore/File.h>
#include <WebCore/FileChooser.h>
#include <WebCore/FilterOperation.h>
#include <WebCore/FilterOperations.h>
@@ -2019,6 +2020,21 @@
return true;
}
+
+void ArgumentCoder<RawFile>::encode(Encoder& encoder, const RawFile& file)
+{
+ encoder << file.fileName;
+ encodeSharedBuffer(encoder, file.fileData.get());
+}
+
+bool ArgumentCoder<RawFile>::decode(Decoder& decoder, RawFile& file)
+{
+ if (!decoder.decode(file.fileName))
+ return false;
+ if (!decodeSharedBuffer(decoder, file.fileData))
+ return false;
+ return true;
+}
void ArgumentCoder<ShareData>::encode(Encoder& encoder, const ShareData& settings)
{
@@ -2042,6 +2058,7 @@
{
encoder << settings.shareData;
encoder << settings.url;
+ encoder << settings.files;
}
bool ArgumentCoder<ShareDataWithParsedURL>::decode(Decoder& decoder, ShareDataWithParsedURL& settings)
@@ -2050,6 +2067,8 @@
return false;
if (!decoder.decode(settings.url))
return false;
+ if (!decoder.decode(settings.files))
+ return false;
return true;
}
Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h (261411 => 261412)
--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -81,6 +81,7 @@
class Cursor;
class DatabaseDetails;
class DragData;
+class File;
class FilterOperation;
class FilterOperations;
class FloatPoint;
@@ -126,6 +127,7 @@
struct ExceptionDetails;
struct FontAttributes;
struct FileChooserSettings;
+struct RawFile;
struct ShareData;
struct ShareDataWithParsedURL;
struct Length;
@@ -555,6 +557,11 @@
static WARN_UNUSED_RETURN bool decode(Decoder&, WebCore::FileChooserSettings&);
};
+template<> struct ArgumentCoder<WebCore::RawFile> {
+ static void encode(Encoder&, const WebCore::RawFile&);
+ static WARN_UNUSED_RETURN bool decode(Decoder&, WebCore::RawFile&);
+};
+
template<> struct ArgumentCoder<WebCore::ShareData> {
static void encode(Encoder&, const WebCore::ShareData&);
static WARN_UNUSED_RETURN bool decode(Decoder&, WebCore::ShareData&);
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WKShareSheet.h (261411 => 261412)
--- trunk/Source/WebKit/UIProcess/Cocoa/WKShareSheet.h 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WKShareSheet.h 2020-05-08 20:46:10 UTC (rev 261412)
@@ -42,7 +42,6 @@
- (void)dismiss;
@property (nonatomic, weak) id <WKShareSheetDelegate> delegate;
-
@end
@protocol WKShareSheetDelegate <NSObject>
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WKShareSheet.mm (261411 => 261412)
--- trunk/Source/WebKit/UIProcess/Cocoa/WKShareSheet.mm 2020-05-08 20:43:00 UTC (rev 261411)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WKShareSheet.mm 2020-05-08 20:46:10 UTC (rev 261412)
@@ -28,10 +28,14 @@
#if PLATFORM(COCOA) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
+#import "QuarantineSPI.h"
#import "WKWebViewInternal.h"
#import "WebPageProxy.h"
+#import <WebCore/RuntimeApplicationChecks.h>
#import <WebCore/ShareData.h>
#import <wtf/RetainPtr.h>
+#import <wtf/Scope.h>
+#import <wtf/UUID.h>
#import <wtf/WeakObjCPtr.h>
#if PLATFORM(IOS_FAMILY)
@@ -47,6 +51,7 @@
#endif
@implementation WKShareSheet {
+ RetainPtr<NSURL> _temporaryFileShareDirectory;
WeakObjCPtr<WKWebView> _webView;
WeakObjCPtr<id <WKShareSheetDelegate> > _delegate;
WTF::CompletionHandler<void(bool)> _completionHandler;
@@ -106,10 +111,49 @@
return;
}
+ if (data.files.size()) {
+ _temporaryFileShareDirectory = [WKShareSheet createTemporarySharingDirectory];
+
+ auto fileWriteGroup = adoptOSObject(dispatch_group_create());
+ auto queue = adoptOSObject(dispatch_queue_create("com.apple.WebKit.WKShareSheet.ShareableFileWriter", DISPATCH_QUEUE_SERIAL));
+
+ __block bool successful = true;
+
+ int index = 0;
+ for (auto file : data.files) {
+ dispatch_group_async(fileWriteGroup.get(), queue.get(), ^{
+ if (!successful)
+ return;
+ NSURL *fileURL = [WKShareSheet writeFileToShareableURL:WebCore::ResourceResponseBase::sanitizeSuggestedFilename(file.fileName) data:file.fileData->createNSData().get() temporaryDirectory:_temporaryFileShareDirectory.get()];
+ if (!fileURL) {
+ successful = false;
+ return;
+ }
+ [shareDataArray addObject:fileURL];
+ });
+ index++;
+ }
+
+ dispatch_group_notify(fileWriteGroup.get(), dispatch_get_main_queue(), ^{
+ if (!successful) {
+ [self _didCompleteWithSuccess:NO];
+ [self dismiss];
+ return;
+ }
+ [self presentWithShareDataArray:shareDataArray.get() inRect:rect];
+ });
+ return;
+ }
+
+ [self presentWithShareDataArray:shareDataArray.get() inRect:rect];
+}
+
+- (void)presentWithShareDataArray:(NSArray *)sharingItems inRect:(WTF::Optional<WebCore::FloatRect>)rect
+{
WKWebView *webView = _webView.getAutoreleased();
#if PLATFORM(MAC)
- _sharingServicePicker = adoptNS([[NSSharingServicePicker alloc] initWithItems:shareDataArray.get()]);
+ _sharingServicePicker = adoptNS([[NSSharingServicePicker alloc] initWithItems:sharingItems]);
_sharingServicePicker.get().delegate = self;
// WKShareSheet can be released under NSSharingServicePicker delegate callbacks.
@@ -126,7 +170,7 @@
}
[_sharingServicePicker showRelativeToRect:presentationRect ofView:webView preferredEdge:NSMinYEdge];
#else
- _shareSheetViewController = adoptNS([[UIActivityViewController alloc] initWithActivityItems:shareDataArray.get() applicationActivities:nil]);
+ _shareSheetViewController = adoptNS([[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil]);
[_shareSheetViewController setCompletionWithItemsHandler:^(NSString *, BOOL completed, NSArray *, NSError *) {
[self _didCompleteWithSuccess:completed];
[self dispatchDidDismiss];
@@ -183,6 +227,18 @@
auto completionHandler = WTFMove(_completionHandler);
if (completionHandler)
completionHandler(success);
+
+ if (success) {
+ // <rdar://problem/63030288>: didShareItems callback for NSSharingServiceDelegate currently is called
+ // before the temporary files are copied, so we can't delete them here. UIActivityViewController doesn't
+ // have this problem, so we can delete immediately for iOS.
+#if PLATFORM(IOS_FAMILY)
+ [[NSFileManager defaultManager] removeItemAtURL:_temporaryFileShareDirectory.get() error:nil];
+#endif
+ } else
+ [[NSFileManager defaultManager] removeItemAtURL:_temporaryFileShareDirectory.get() error:nil];
+
+ _temporaryFileShareDirectory = nullptr;
}
- (void)dismiss
@@ -215,6 +271,86 @@
[_delegate shareSheetDidDismiss:self];
}
+#if PLATFORM(MAC)
++ (BOOL)setQuarantineInformationForFilePath:(NSURL *)fileURL
+{
+ auto quarantineProperties = @{
+ (__bridge NSString *)kLSQuarantineTypeKey: (__bridge NSString *)kLSQuarantineTypeWebDownload,
+ (__bridge NSString *)kLSQuarantineAgentBundleIdentifierKey: WebCore::applicationBundleIdentifier()
+ };
+
+ if (![fileURL setResourceValue:quarantineProperties forKey:NSURLQuarantinePropertiesKey error:nil])
+ return NO;
+
+ // Whether the file was downloaded by sandboxed WebProcess or not, LSSetItemAttribute resets the flags to 0 (advisory QTN_FLAG_DOWNLOAD,
+ // which can be then removed by WebProcess). Replace the flags with sandbox quarantine ones, which cannot be removed by sandboxed processes.
+ return [WKShareSheet applyQuarantineSandboxAndDownloadFlagsToFileAtPath:fileURL];
+}
+
++ (BOOL)applyQuarantineSandboxAndDownloadFlagsToFileAtPath:(NSURL *)fileURL
+{
+ qtn_file_t fq = qtn_file_alloc();
+ auto scopeExit = WTF::makeScopeExit([&] {
+ qtn_file_free(fq);
+ });
+
+ int quarantineError = qtn_file_init_with_path(fq, fileURL.fileSystemRepresentation);
+ if (quarantineError)
+ return NO;
+
+ quarantineError = qtn_file_set_flags(fq, QTN_FLAG_SANDBOX | QTN_FLAG_DOWNLOAD);
+ if (quarantineError)
+ return NO;
+
+ quarantineError = qtn_file_apply_to_path(fq, fileURL.fileSystemRepresentation);
+
+ return YES;
+}
+#endif
+
++ (NSURL *)createTemporarySharingDirectory
+{
+ NSString *temporaryDirectory = FileSystem::createTemporaryDirectory(@"WKFileShare");
+
+ if (![temporaryDirectory length])
+ return nil;
+
+ return [NSURL fileURLWithPath:temporaryDirectory isDirectory:YES];
+}
+
++ (NSURL *)createRandomSharingDirectoryForFile:(NSURL *)temporaryDirectory
+{
+ NSString *randomDirectory = createCanonicalUUIDString();
+ if (![randomDirectory length] || !temporaryDirectory)
+ return nil;
+ NSURL *dataPath = [temporaryDirectory URLByAppendingPathComponent:randomDirectory];
+
+ if (![[NSFileManager defaultManager] createDirectoryAtURL:dataPath withIntermediateDirectories:NO attributes:nil error:nil])
+ return nil;
+ return dataPath;
+}
+
++ (NSURL *)writeFileToShareableURL:(NSString *)fileName data:(NSData *)fileData temporaryDirectory:(NSURL *)temporaryDirectory
+{
+ ASSERT(!RunLoop::isMain());
+ if (!temporaryDirectory || ![fileName length] || !fileData)
+ return nil;
+
+ NSURL *temporaryDirectoryForFile = [WKShareSheet createRandomSharingDirectoryForFile:temporaryDirectory];
+ if (!temporaryDirectoryForFile)
+ return nil;
+
+ NSURL *fileURL = [temporaryDirectoryForFile URLByAppendingPathComponent:fileName];
+
+ if (![fileData writeToURL:fileURL options:NSDataWritingAtomic error:nil])
+ return nil;
+#if PLATFORM(MAC)
+ if (![WKShareSheet setQuarantineInformationForFilePath:fileURL])
+ return nil;
+#endif
+ return fileURL;
+}
+
@end
#endif // PLATFORM(COCOA) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)