blob: 75836b879143b60a7f3519703207b6ad3d8d4f85 [file] [log] [blame]
/*
* 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>([this, count, fileName = blob->name()](BlobLoader&) {
this->didFinishLoading(count, fileName);
}));
m_pendingFileLoads.last()->start(*blob, document, FileReaderLoader::ReadAsArrayBuffer);
++count;
}
}
void ShareDataReader::didFinishLoading(int loadIndex, const String& fileName)
{
if (m_pendingFileLoads.isEmpty()) {
// cancel() was called.
return;
}
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]->arrayBufferResult();
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()
{
// Don't call m_pendingFileLoads.clear() here since destroying a BlobLoader will cause its completion handler
// to get called, which will call didFinishLoading() and try to access m_pendingFileLoads.
std::exchange(m_pendingFileLoads, { });
}
}