/*
 * Copyright (C) 2010-2018 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 "PluginProcessProxy.h"

#if ENABLE(NETSCAPE_PLUGIN_API)

#include "AuxiliaryProcessMessages.h"
#include "PluginProcessConnectionManagerMessages.h"
#include "PluginProcessCreationParameters.h"
#include "PluginProcessManager.h"
#include "PluginProcessMessages.h"
#include "WebCoreArgumentCoders.h"
#include "WebProcessPool.h"
#include "WebProcessProxy.h"
#include "WebProcessProxyMessages.h"
#include <WebCore/NotImplemented.h>
#include <wtf/RunLoop.h>

namespace WebKit {
using namespace WebCore;

static const Seconds minimumLifetime { 2_min };
static const Seconds snapshottingMinimumLifetime { 30_s };

static const Seconds shutdownTimeout { 1_min };
static const Seconds snapshottingShutdownTimeout { 15_s };

static uint64_t generatePluginProcessCallbackID()
{
    static uint64_t callbackID;

    return ++callbackID;
}

Ref<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken)
{
    return adoptRef(*new PluginProcessProxy(PluginProcessManager, pluginProcessAttributes, pluginProcessToken));
}

PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken)
    : m_pluginProcessManager(PluginProcessManager)
    , m_pluginProcessAttributes(pluginProcessAttributes)
    , m_pluginProcessToken(pluginProcessToken)
    , m_numPendingConnectionRequests(0)
#if PLATFORM(COCOA)
    , m_modalWindowIsShowing(false)
    , m_fullscreenWindowIsShowing(false)
    , m_preFullscreenAppPresentationOptions(0)
#endif
{
    connect();
}

PluginProcessProxy::~PluginProcessProxy()
{
    if (m_connection)
        m_connection->invalidate();

    ASSERT(m_pendingFetchWebsiteDataRequests.isEmpty());
    ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
    ASSERT(m_pendingDeleteWebsiteDataRequests.isEmpty());
    ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
}

void PluginProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
{
    platformGetLaunchOptionsWithAttributes(launchOptions, m_pluginProcessAttributes);
    AuxiliaryProcessProxy::getLaunchOptions(launchOptions);
}

void PluginProcessProxy::processWillShutDown(IPC::Connection& connection)
{
    ASSERT_UNUSED(connection, this->connection() == &connection);
}

// Asks the plug-in process to create a new connection to a web process. The connection identifier will be 
// encoded in the given argument encoder and sent back to the connection of the given web process.
void PluginProcessProxy::getPluginProcessConnection(Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply&& reply)
{
    m_pendingConnectionReplies.append(WTFMove(reply));

    if (state() == State::Launching) {
        m_numPendingConnectionRequests++;
        return;
    }
    
    // Ask the plug-in process to create a connection. Since the plug-in can be waiting for a synchronous reply
    // we need to make sure that this message is always processed, even when the plug-in is waiting for a synchronus reply.
    m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
}

void PluginProcessProxy::fetchWebsiteData(CompletionHandler<void (Vector<String>)>&& completionHandler)
{
    uint64_t callbackID = generatePluginProcessCallbackID();
    m_pendingFetchWebsiteDataCallbacks.set(callbackID, WTFMove(completionHandler));

    if (state() == State::Launching) {
        m_pendingFetchWebsiteDataRequests.append(callbackID);
        return;
    }

    m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
}

void PluginProcessProxy::deleteWebsiteData(WallTime modifiedSince, CompletionHandler<void ()>&& completionHandler)
{
    uint64_t callbackID = generatePluginProcessCallbackID();
    m_pendingDeleteWebsiteDataCallbacks.set(callbackID, WTFMove(completionHandler));

    if (state() == State::Launching) {
        m_pendingDeleteWebsiteDataRequests.append({ modifiedSince, callbackID });
        return;
    }

    m_connection->send(Messages::PluginProcess::DeleteWebsiteData(modifiedSince, callbackID), 0);
}

void PluginProcessProxy::deleteWebsiteDataForHostNames(const Vector<String>& hostNames, CompletionHandler<void ()>&& completionHandler)
{
    uint64_t callbackID = generatePluginProcessCallbackID();
    m_pendingDeleteWebsiteDataForHostNamesCallbacks.set(callbackID, WTFMove(completionHandler));

    if (state() == State::Launching) {
        m_pendingDeleteWebsiteDataForHostNamesRequests.append({ hostNames, callbackID });
        return;
    }

    m_connection->send(Messages::PluginProcess::DeleteWebsiteDataForHostNames(hostNames, callbackID), 0);
}

#if OS(LINUX)
void PluginProcessProxy::sendMemoryPressureEvent(bool isCritical)
{
    if (state() == State::Launching)
        return;

    m_connection->send(Messages::AuxiliaryProcess::DidReceiveMemoryPressureEvent(isCritical), 0);
}
#endif

void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
{
    // The plug-in process must have crashed or exited, send any pending sync replies we might have.
    while (!m_pendingConnectionReplies.isEmpty()) {
        auto reply = m_pendingConnectionReplies.takeFirst();

#if USE(UNIX_DOMAIN_SOCKETS)
        reply(IPC::Attachment(), false);
#elif OS(DARWIN)
        reply(IPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND), false);
#else
        notImplemented();
#endif
    }

    m_pendingFetchWebsiteDataRequests.clear();
    for (auto&& callback : m_pendingFetchWebsiteDataCallbacks.values())
        callback({ });
    m_pendingFetchWebsiteDataCallbacks.clear();

    m_pendingDeleteWebsiteDataRequests.clear();
    for (auto&& callback : m_pendingDeleteWebsiteDataCallbacks.values())
        callback();
    m_pendingDeleteWebsiteDataRequests.clear();

    m_pendingDeleteWebsiteDataForHostNamesRequests.clear();
    for (auto&& callback : m_pendingDeleteWebsiteDataForHostNamesCallbacks.values())
        callback();
    m_pendingDeleteWebsiteDataForHostNamesCallbacks.clear();

    // Tell the plug-in process manager to forget about this plug-in process proxy. This may cause us to be deleted.
    m_pluginProcessManager->removePluginProcessProxy(this);
}

void PluginProcessProxy::didClose(IPC::Connection&)
{
#if PLATFORM(COCOA)
    if (m_modalWindowIsShowing)
        endModal();

    if (m_fullscreenWindowIsShowing)
        exitFullscreen();
#endif

    const Vector<WebProcessPool*>& processPools = WebProcessPool::allProcessPools();
    for (size_t i = 0; i < processPools.size(); ++i)
        processPools[i]->sendToAllProcesses(Messages::PluginProcessConnectionManager::PluginProcessCrashed(m_pluginProcessToken));

    // This will cause us to be deleted.
    pluginProcessCrashedOrFailedToLaunch();
}

void PluginProcessProxy::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
{
}

void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, IPC::Connection::Identifier connectionIdentifier)
{
    ASSERT(!m_connection);

    if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
        pluginProcessCrashedOrFailedToLaunch();
        return;
    }

    m_connection = IPC::Connection::createServerConnection(connectionIdentifier, *this);

    m_connection->open();
    
    PluginProcessCreationParameters parameters;
    parameters.processType = m_pluginProcessAttributes.processType;
    if (parameters.processType == PluginProcessTypeSnapshot) {
        parameters.minimumLifetime = snapshottingMinimumLifetime;
        parameters.terminationTimeout = snapshottingShutdownTimeout;
    } else {
        parameters.minimumLifetime = minimumLifetime;
        parameters.terminationTimeout = shutdownTimeout;
    }

    platformInitializePluginProcess(parameters);

    // Initialize the plug-in host process.
    m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0);

#if PLATFORM(COCOA)
    m_connection->send(Messages::PluginProcess::SetQOS(pluginProcessLatencyQOS(), pluginProcessThroughputQOS()), 0);
#endif

    for (auto callbackID : m_pendingFetchWebsiteDataRequests)
        m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
    m_pendingFetchWebsiteDataRequests.clear();

    for (auto& request : m_pendingDeleteWebsiteDataRequests)
        m_connection->send(Messages::PluginProcess::DeleteWebsiteData(request.modifiedSince, request.callbackID), 0);
    m_pendingDeleteWebsiteDataRequests.clear();

    for (auto& request : m_pendingDeleteWebsiteDataForHostNamesRequests)
        m_connection->send(Messages::PluginProcess::DeleteWebsiteDataForHostNames(request.hostNames, request.callbackID), 0);
    m_pendingDeleteWebsiteDataForHostNamesRequests.clear();

    for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
        m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0);
    
    m_numPendingConnectionRequests = 0;

#if PLATFORM(COCOA)
    if (!PluginProcessManager::singleton().processSuppressionDisabled())
        setProcessSuppressionEnabled(true);
#endif
}

void PluginProcessProxy::didCreateWebProcessConnection(const IPC::Attachment& connectionIdentifier, bool supportsAsynchronousPluginInitialization)
{
    ASSERT(!m_pendingConnectionReplies.isEmpty());

    // Grab the first pending connection reply.
    auto reply = m_pendingConnectionReplies.takeFirst();

#if USE(UNIX_DOMAIN_SOCKETS)
    reply(connectionIdentifier, supportsAsynchronousPluginInitialization);
#elif OS(DARWIN)
    reply(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND), supportsAsynchronousPluginInitialization);
#else
    notImplemented();
#endif
}

void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
{
    auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
    callback(sites);
}

void PluginProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
{
    auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
    callback();
}

void PluginProcessProxy::didDeleteWebsiteDataForHostNames(uint64_t callbackID)
{
    auto callback = m_pendingDeleteWebsiteDataForHostNamesCallbacks.take(callbackID);
    callback();
}

} // namespace WebKit

#endif // ENABLE(NETSCAPE_PLUGIN_API)
