Skip to content

Commit

Permalink
Cherry-pick 252432.1019@safari-7614-branch (1988807). rdar://103307563
Browse files Browse the repository at this point in the history
    [Clipboard] Explicitly call completion on clearing ClipboardItemTypeLoader
    rdar://103307563

    Reviewed by Jonathan Bedard and Wenson Hsieh.

    In m_itemTypeLoaders.clear(), ClipboardItemBindingsDataSource::invokeCompletionHandler() is called after all m_itemTypeLoaders released
    and traverses the itemTypeLoaders after itemTypeLoaders is clear but before the size is updated, causing nullptr accessment.
    So we should explicitly call completion before itemTypeLoader is released.

    * LayoutTests/editing/async-clipboard/clipboard-clear-expected.txt: Added.
    * LayoutTests/editing/async-clipboard/clipboard-clear.html: Added.
    * Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp:
    (WebCore::ClipboardItemBindingsDataSource::clearItemTypeLoaders):
    (WebCore::ClipboardItemBindingsDataSource::collectDataForWriting):
    (WebCore::ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::~ClipboardItemTypeLoader):
    * Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h:

    Canonical link: https://commits.webkit.org/252432.1019@safari-7614-branch
  • Loading branch information
David-Li-Jy authored and aperezdc committed Apr 5, 2023
1 parent 6f56628 commit 1cf2bfc
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
@@ -0,0 +1 @@
PASS if no crash.
27 changes: 27 additions & 0 deletions LayoutTests/editing/async-clipboard/clipboard-clear.html
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<script>
function runTest() {
if (window.testRunner) {
testRunner.waitUntilDone();
window.testRunner.dumpAsText();
}

var clipboard = window.clientInformation.clipboard;
var textBlob = new Blob([ (new TextEncoder()).encode("a") ], { type : "text/plain" });
if (typeof ClipBoardItem !== "undefined") {
var cbi = new ClipboardItem({ "text/plain" : textBlob });
clipboard.write([cbi]);
clipboard.write([cbi]);
}

if (window.testRunner)
testRunner.notifyDone();
}
</script>
</head>
<body onload=runTest()>
<p>PASS if no crash.</p>
</body>
</html>
Expand Up @@ -123,9 +123,17 @@ void ClipboardItemBindingsDataSource::getType(const String& type, Ref<DeferredPr
});
}

void ClipboardItemBindingsDataSource::collectDataForWriting(Clipboard& destination, CompletionHandler<void(std::optional<PasteboardCustomData>)>&& completion)
void ClipboardItemBindingsDataSource::clearItemTypeLoaders()
{
for (auto& itemTypeLoader : m_itemTypeLoaders)
itemTypeLoader->invokeCompletionHandler();

m_itemTypeLoaders.clear();
}

void ClipboardItemBindingsDataSource::collectDataForWriting(Clipboard& destination, CompletionHandler<void(std::optional<PasteboardCustomData>)>&& completion)
{
clearItemTypeLoaders();
ASSERT(!m_completionHandler);
m_completionHandler = WTFMove(completion);
m_writingDestination = destination;
Expand Down Expand Up @@ -238,8 +246,8 @@ ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::~ClipboardItemTypeLoad
{
if (m_blobLoader)
m_blobLoader->cancel();

invokeCompletionHandler();
ASSERT(!m_completionHandler);
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didFinishLoading()
Expand Down
Expand Up @@ -51,6 +51,7 @@ class ClipboardItemBindingsDataSource : public ClipboardItemDataSource {
void getType(const String&, Ref<DeferredPromise>&&) final;
void collectDataForWriting(Clipboard& destination, CompletionHandler<void(std::optional<PasteboardCustomData>)>&&) final;

void clearItemTypeLoaders();
void invokeCompletionHandler();

using BufferOrString = std::variant<String, Ref<SharedBuffer>>;
Expand All @@ -67,14 +68,15 @@ class ClipboardItemBindingsDataSource : public ClipboardItemDataSource {
void didFailToResolve();
void didResolveToBlob(ScriptExecutionContext&, Ref<Blob>&&);

void invokeCompletionHandler();

const String& type() { return m_type; }
const BufferOrString& data() { return m_data; }

private:
ClipboardItemTypeLoader(const String& type, CompletionHandler<void()>&&);

void sanitizeDataIfNeeded();
void invokeCompletionHandler();

// FileReaderLoaderClient methods.
void didStartLoading() final { }
Expand Down

0 comments on commit 1cf2bfc

Please sign in to comment.