/*
 * Copyright (C) 2014 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"
#import "WebPasteboardProxy.h"

#import "Connection.h"
#import "SandboxExtension.h"
#import "WebPageProxy.h"
#import "WebPreferences.h"
#import "WebProcessProxy.h"
#import <WebCore/Color.h>
#import <WebCore/Pasteboard.h>
#import <WebCore/PasteboardItemInfo.h>
#import <WebCore/PlatformPasteboard.h>
#import <WebCore/SharedBuffer.h>
#import <wtf/URL.h>

#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, (&connection))
#define MESSAGE_CHECK_WITH_RETURN_VALUE(assertion, returnValue) MESSAGE_CHECK_WITH_RETURN_VALUE_BASE(assertion, (&connection), returnValue)
#define MESSAGE_CHECK_COMPLETION(assertion, completion) MESSAGE_CHECK_COMPLETION_BASE(assertion, (&connection), completion)

namespace WebKit {
using namespace WebCore;

void WebPasteboardProxy::grantAccessToCurrentData(WebProcessProxy& process, const String& pasteboardName)
{
    if (!m_webProcessProxyList.contains(&process))
        return;

    if (pasteboardName.isEmpty()) {
        ASSERT_NOT_REACHED();
        return;
    }

    auto changeCount = PlatformPasteboard(pasteboardName).changeCount();
    auto changeCountsAndProcesses = m_pasteboardNameToChangeCountAndProcessesMap.find(pasteboardName);
    if (changeCountsAndProcesses != m_pasteboardNameToChangeCountAndProcessesMap.end() && changeCountsAndProcesses->value.first == changeCount) {
        changeCountsAndProcesses->value.second.add(process);
        return;
    }

    WeakHashSet<WebProcessProxy> processes;
    processes.add(process);
    m_pasteboardNameToChangeCountAndProcessesMap.set(pasteboardName, std::make_pair(changeCount, WTFMove(processes)));
}

void WebPasteboardProxy::revokeAccessToAllData(WebProcessProxy& process)
{
    for (auto& changeCountAndProcesses : m_pasteboardNameToChangeCountAndProcessesMap.values())
        changeCountAndProcesses.second.remove(process);
}

bool WebPasteboardProxy::canAccessPasteboardData(IPC::Connection& connection, const String& pasteboardName) const
{
    MESSAGE_CHECK_WITH_RETURN_VALUE(!pasteboardName.isEmpty(), false);

    auto* process = webProcessProxyForConnection(connection);
    MESSAGE_CHECK_WITH_RETURN_VALUE(process, false);

    for (auto* page : process->pages()) {
        auto& preferences = page->preferences();
        if (!preferences.domPasteAllowed() || !preferences.javaScriptCanAccessClipboard())
            continue;

        // If a web page already allows JavaScript to programmatically read pasteboard data,
        // then it is possible for any other web page residing in the same web process to send
        // IPC messages that can read pasteboard data by pretending to be the page that has
        // allowed unmitigated pasteboard access from script. As such, there is no security
        // benefit in limiting the scope of pasteboard data access to only the web page that
        // enables programmatic pasteboard access.
        return true;
    }

    auto changeCountAndProcesses = m_pasteboardNameToChangeCountAndProcessesMap.find(pasteboardName);
    if (changeCountAndProcesses == m_pasteboardNameToChangeCountAndProcessesMap.end())
        return false;

    auto& [changeCount, processes] = changeCountAndProcesses->value;
    return changeCount == PlatformPasteboard(pasteboardName).changeCount() && processes.contains(*process);
}

void WebPasteboardProxy::didModifyContentsOfPasteboard(IPC::Connection& connection, const String& pasteboardName, int64_t previousChangeCount, int64_t newChangeCount)
{
    MESSAGE_CHECK(!pasteboardName.isEmpty());

    auto* process = webProcessProxyForConnection(connection);
    MESSAGE_CHECK(process);

    auto changeCountAndProcesses = m_pasteboardNameToChangeCountAndProcessesMap.find(pasteboardName);
    if (changeCountAndProcesses != m_pasteboardNameToChangeCountAndProcessesMap.end() && previousChangeCount == changeCountAndProcesses->value.first) {
        WeakHashSet<WebProcessProxy> processes;
        processes.add(process);
        changeCountAndProcesses->value = std::make_pair(newChangeCount, WTFMove(processes));
    }
}

void WebPasteboardProxy::getPasteboardTypes(const String& pasteboardName, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
{
    Vector<String> pasteboardTypes;
    PlatformPasteboard(pasteboardName).getTypes(pasteboardTypes);
    completionHandler(WTFMove(pasteboardTypes));
}

void WebPasteboardProxy::getPasteboardPathnamesForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType,
    CompletionHandler<void(Vector<String>&& pathnames, SandboxExtension::HandleArray&& sandboxExtensions)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler({ }, { });

    // FIXME: This should consult canAccessPasteboardData() as well, and avoid responding with file paths if it returns false.
    Vector<String> pathnames;
    SandboxExtension::HandleArray sandboxExtensions;
    if (webProcessProxyForConnection(connection)) {
        PlatformPasteboard(pasteboardName).getPathnamesForType(pathnames, pasteboardType);

#if PLATFORM(MAC)
        // On iOS, files are copied into app's container upon paste.
        sandboxExtensions.allocate(pathnames.size());
        for (size_t i = 0; i < pathnames.size(); i++) {
            auto& filename = pathnames[i];
            if (![[NSFileManager defaultManager] fileExistsAtPath:filename])
                continue;
            SandboxExtension::createHandle(filename, SandboxExtension::Type::ReadOnly, sandboxExtensions[i]);
        }
#endif
    }
    completionHandler(WTFMove(pathnames), WTFMove(sandboxExtensions));
}

void WebPasteboardProxy::getPasteboardStringForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, CompletionHandler<void(String&&)>&& completionHandler)
{
    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ });

    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler({ });

    completionHandler(PlatformPasteboard(pasteboardName).stringForType(pasteboardType));
}

void WebPasteboardProxy::getPasteboardStringsForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler({ });

    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ });

    completionHandler(PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType));
}

void WebPasteboardProxy::getPasteboardBufferForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, CompletionHandler<void(SharedMemory::Handle&&, uint64_t)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler({ }, 0);

    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ }, 0);

    RefPtr<SharedBuffer> buffer = PlatformPasteboard(pasteboardName).bufferForType(pasteboardType);
    if (!buffer)
        return completionHandler({ }, 0);
    uint64_t size = buffer->size();
    if (!size)
        return completionHandler({ }, 0);
    RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
    if (!sharedMemoryBuffer)
        return completionHandler({ }, 0);
    memcpy(sharedMemoryBuffer->data(), buffer->data(), size);
    SharedMemory::Handle handle;
    sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly);
    completionHandler(WTFMove(handle), size);
}

void WebPasteboardProxy::getPasteboardChangeCount(const String& pasteboardName, CompletionHandler<void(int64_t)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).changeCount());
}

void WebPasteboardProxy::getPasteboardColor(IPC::Connection& connection, const String& pasteboardName, CompletionHandler<void(WebCore::Color&&)>&& completionHandler)
{
    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ });

    completionHandler(PlatformPasteboard(pasteboardName).color());
}

void WebPasteboardProxy::getPasteboardURL(IPC::Connection& connection, const String& pasteboardName, CompletionHandler<void(const String&)>&& completionHandler)
{
    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ });

    completionHandler(PlatformPasteboard(pasteboardName).url().string());
}

void WebPasteboardProxy::addPasteboardTypes(IPC::Connection& connection, const String& pasteboardName, const Vector<String>& pasteboardTypes, CompletionHandler<void(int64_t)>&& completionHandler)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    auto newChangeCount = PlatformPasteboard(pasteboardName).addTypes(pasteboardTypes);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, previousChangeCount);
    completionHandler(newChangeCount);
}

void WebPasteboardProxy::setPasteboardTypes(IPC::Connection& connection, const String& pasteboardName, const Vector<String>& pasteboardTypes, CompletionHandler<void(int64_t)>&& completionHandler)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    auto newChangeCount = PlatformPasteboard(pasteboardName).setTypes(pasteboardTypes);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
    completionHandler(newChangeCount);
}

void WebPasteboardProxy::setPasteboardURL(IPC::Connection& connection, const PasteboardURL& pasteboardURL, const String& pasteboardName, CompletionHandler<void(int64_t)>&& completionHandler)
{
    if (auto* webProcessProxy = webProcessProxyForConnection(connection)) {
        if (!webProcessProxy->checkURLReceivedFromWebProcess(pasteboardURL.url.string()))
            return completionHandler(0);

        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
        auto newChangeCount = PlatformPasteboard(pasteboardName).setURL(pasteboardURL);
        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
        return completionHandler(newChangeCount);
    }
    completionHandler(0);
}

void WebPasteboardProxy::setPasteboardColor(IPC::Connection& connection, const String& pasteboardName, const WebCore::Color& color, CompletionHandler<void(int64_t)>&& completionHandler)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    auto newChangeCount = PlatformPasteboard(pasteboardName).setColor(color);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
    completionHandler(newChangeCount);
}

void WebPasteboardProxy::setPasteboardStringForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, const String& string, CompletionHandler<void(int64_t)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler(0);

    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    auto newChangeCount = PlatformPasteboard(pasteboardName).setStringForType(string, pasteboardType);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
    completionHandler(newChangeCount);
}

void WebPasteboardProxy::containsURLStringSuitableForLoading(const String& pasteboardName, CompletionHandler<void(bool)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).containsURLStringSuitableForLoading());
}

void WebPasteboardProxy::urlStringSuitableForLoading(IPC::Connection& connection, const String& pasteboardName, CompletionHandler<void(String&& url, String&& title)>&& completionHandler)
{
    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ }, { });

    String title;
    auto urlString = PlatformPasteboard(pasteboardName).urlStringSuitableForLoading(title);
    completionHandler(WTFMove(urlString), WTFMove(title));
}

void WebPasteboardProxy::setPasteboardBufferForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, const SharedMemory::Handle& handle, uint64_t size, CompletionHandler<void(int64_t)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler(0);

    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    if (handle.isNull()) {
        auto newChangeCount = PlatformPasteboard(pasteboardName).setBufferForType(nullptr, pasteboardType);
        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
        return completionHandler(newChangeCount);
    }

    // SharedMemory::Handle::size() is rounded up to the nearest page.
    MESSAGE_CHECK_COMPLETION(size <= handle.size(), completionHandler(0));

    RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
    if (!sharedMemoryBuffer)
        return completionHandler(0);
    auto buffer = SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), static_cast<size_t>(size));
    auto newChangeCount = PlatformPasteboard(pasteboardName).setBufferForType(buffer.ptr(), pasteboardType);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
    completionHandler(newChangeCount);
}

void WebPasteboardProxy::getNumberOfFiles(const String& pasteboardName, CompletionHandler<void(uint64_t)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).numberOfFiles());
}

void WebPasteboardProxy::typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
{
    ASSERT(!origin.isNull());
    if (origin.isNull())
        return completionHandler({ });

    completionHandler(PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(origin));
}

void WebPasteboardProxy::writeCustomData(IPC::Connection& connection, const Vector<PasteboardCustomData>& data, const String& pasteboardName, CompletionHandler<void(int64_t)>&& completionHandler)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    auto newChangeCount = PlatformPasteboard(pasteboardName).write(data);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
    completionHandler(newChangeCount);
}

void WebPasteboardProxy::allPasteboardItemInfo(const String& pasteboardName, int64_t changeCount, CompletionHandler<void(Optional<Vector<PasteboardItemInfo>>&&)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).allPasteboardItemInfo(changeCount));
}

void WebPasteboardProxy::informationForItemAtIndex(size_t index, const String& pasteboardName, int64_t changeCount, CompletionHandler<void(Optional<PasteboardItemInfo>&&)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).informationForItemAtIndex(index, changeCount));
}

void WebPasteboardProxy::getPasteboardItemsCount(const String& pasteboardName, CompletionHandler<void(uint64_t)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).count());
}

void WebPasteboardProxy::readStringFromPasteboard(IPC::Connection& connection, size_t index, const String& pasteboardType, const String& pasteboardName, CompletionHandler<void(String&&)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler({ });

    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ });

    completionHandler(PlatformPasteboard(pasteboardName).readString(index, pasteboardType));
}

void WebPasteboardProxy::readURLFromPasteboard(IPC::Connection& connection, size_t index, const String& pasteboardName, CompletionHandler<void(String&& url, String&& title)>&& completionHandler)
{
    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ }, { });

    String title;
    String url = PlatformPasteboard(pasteboardName).readURL(index, title);
    completionHandler(WTFMove(url), WTFMove(title));
}

void WebPasteboardProxy::readBufferFromPasteboard(IPC::Connection& connection, size_t index, const String& pasteboardType, const String& pasteboardName, CompletionHandler<void(SharedMemory::Handle&&, uint64_t size)>&& completionHandler)
{
    ASSERT(!pasteboardType.isNull());
    if (pasteboardType.isNull())
        return completionHandler({ }, 0);

    if (!canAccessPasteboardData(connection, pasteboardName))
        return completionHandler({ }, 0);

    RefPtr<SharedBuffer> buffer = PlatformPasteboard(pasteboardName).readBuffer(index, pasteboardType);
    if (!buffer)
        return completionHandler({ }, 0);
    uint64_t size = buffer->size();
    if (!size)
        return completionHandler({ }, 0);
    RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
    if (!sharedMemoryBuffer)
        return completionHandler({ }, 0);
    memcpy(sharedMemoryBuffer->data(), buffer->data(), size);
    SharedMemory::Handle handle;
    sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly);
    completionHandler(WTFMove(handle), size);
}

void WebPasteboardProxy::containsStringSafeForDOMToReadForType(const String& type, const String& pasteboardName, CompletionHandler<void(bool)>&& completionHandler)
{
    completionHandler(PlatformPasteboard(pasteboardName).containsStringSafeForDOMToReadForType(type));
}

#if PLATFORM(IOS_FAMILY)

void WebPasteboardProxy::writeURLToPasteboard(IPC::Connection& connection, const PasteboardURL& url, const String& pasteboardName)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    PlatformPasteboard(pasteboardName).write(url);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
}

void WebPasteboardProxy::writeWebContentToPasteboard(IPC::Connection& connection, const WebCore::PasteboardWebContent& content, const String& pasteboardName)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    PlatformPasteboard(pasteboardName).write(content);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
}

void WebPasteboardProxy::writeImageToPasteboard(IPC::Connection& connection, const WebCore::PasteboardImage& pasteboardImage, const String& pasteboardName)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    PlatformPasteboard(pasteboardName).write(pasteboardImage);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
}

void WebPasteboardProxy::writeStringToPasteboard(IPC::Connection& connection, const String& pasteboardType, const String& text, const String& pasteboardName)
{
    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
    PlatformPasteboard(pasteboardName).write(pasteboardType, text);
    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
}

void WebPasteboardProxy::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName)
{
    PlatformPasteboard(pasteboardName).updateSupportedTypeIdentifiers(identifiers);
}

#endif // PLATFORM(IOS_FAMILY)

} // namespace WebKit

#undef MESSAGE_CHECK
