/*
 * Copyright (C) 2010, 2014-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 "WebInspector.h"

#include "WebFrame.h"
#include "WebInspectorMessages.h"
#include "WebInspectorProxyMessages.h"
#include "WebInspectorUIMessages.h"
#include "WebPage.h"
#include "WebProcess.h"
#include <WebCore/Chrome.h>
#include <WebCore/Document.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameLoadRequest.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/FrameView.h>
#include <WebCore/InspectorController.h>
#include <WebCore/InspectorFrontendClient.h>
#include <WebCore/InspectorPageAgent.h>
#include <WebCore/NavigationAction.h>
#include <WebCore/NotImplemented.h>
#include <WebCore/Page.h>
#include <WebCore/ScriptController.h>
#include <WebCore/WindowFeatures.h>

static const float minimumAttachedHeight = 250;
static const float maximumAttachedHeightRatio = 0.75;
static const float minimumAttachedWidth = 500;

namespace WebKit {
using namespace WebCore;

Ref<WebInspector> WebInspector::create(WebPage* page)
{
    return adoptRef(*new WebInspector(page));
}

WebInspector::WebInspector(WebPage* page)
    : m_page(page)
{
}

WebInspector::~WebInspector()
{
    if (m_frontendConnection)
        m_frontendConnection->invalidate();
}

void WebInspector::openLocalInspectorFrontend(bool underTest)
{
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::OpenLocalInspectorFrontend(canAttachWindow(), underTest), m_page->identifier());
}

void WebInspector::setFrontendConnection(IPC::Attachment encodedConnectionIdentifier)
{
    // We might receive multiple updates if this web process got swapped into a WebPageProxy
    // shortly after another process established the connection.
    if (m_frontendConnection) {
        m_frontendConnection->invalidate();
        m_frontendConnection = nullptr;
    }

#if USE(UNIX_DOMAIN_SOCKETS)
    IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.releaseFileDescriptor());
#elif OS(DARWIN)
    IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
#elif OS(WINDOWS)
    IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.handle());
#else
    notImplemented();
    return;
#endif

    if (!IPC::Connection::identifierIsValid(connectionIdentifier))
        return;

    m_frontendConnection = IPC::Connection::createClientConnection(connectionIdentifier, *this);
    m_frontendConnection->open();

    for (auto& callback : m_frontendConnectionActions)
        callback();
    m_frontendConnectionActions.clear();
}

void WebInspector::closeFrontendConnection()
{
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_page->identifier());

    // If we tried to close the frontend before it was created, then no connection exists yet.
    if (m_frontendConnection) {
        m_frontendConnection->invalidate();
        m_frontendConnection = nullptr;
    }

    m_frontendConnectionActions.clear();

    m_attached = false;
    m_previousCanAttach = false;
}

void WebInspector::bringToFront()
{
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_page->identifier());
}

void WebInspector::whenFrontendConnectionEstablished(Function<void()>&& callback)
{
    if (m_frontendConnection) {
        callback();
        return;
    }

    m_frontendConnectionActions.append(WTFMove(callback));
}

// Called by WebInspector messages
void WebInspector::show()
{
    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().show();
}

void WebInspector::close()
{
    if (!m_page->corePage())
        return;

    // Close could be called multiple times during teardown.
    if (!m_frontendConnection)
        return;

    closeFrontendConnection();
}

void WebInspector::openInNewTab(const String& urlString)
{
    UserGestureIndicator indicator { ProcessingUserGesture };

    Page* inspectedPage = m_page->corePage();
    if (!inspectedPage)
        return;

    Frame& inspectedMainFrame = inspectedPage->mainFrame();
    FrameLoadRequest frameLoadRequest { *inspectedMainFrame.document(), inspectedMainFrame.document()->securityOrigin(), ResourceRequest { urlString }, "_blank"_s, LockHistory::No, LockBackForwardList::No, ReferrerPolicy::EmptyString, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };

    NavigationAction action { *inspectedMainFrame.document(), frameLoadRequest.resourceRequest(), frameLoadRequest.initiatedByMainFrame(), NavigationType::LinkClicked };
    Page* newPage = inspectedPage->chrome().createWindow(inspectedMainFrame, { }, action);
    if (!newPage)
        return;

    newPage->mainFrame().loader().load(WTFMove(frameLoadRequest));
}

void WebInspector::evaluateScriptForTest(const String& script)
{
    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().evaluateForTestInFrontend(script);
}

void WebInspector::showConsole()
{
    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().show();

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::ShowConsole(), 0);
    });
}

void WebInspector::showResources()
{
    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().show();

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::ShowResources(), 0);
    });
}

void WebInspector::showMainResourceForFrame(WebCore::FrameIdentifier frameIdentifier)
{
    WebFrame* frame = WebProcess::singleton().webFrame(frameIdentifier);
    if (!frame)
        return;

    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().show();

    String inspectorFrameIdentifier = m_page->corePage()->inspectorController().ensurePageAgent().frameId(frame->coreFrame());

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::ShowMainResourceForFrame(inspectorFrameIdentifier), 0);
    });
}

void WebInspector::startPageProfiling()
{
    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().show();

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::StartPageProfiling(), 0);
    });
}

void WebInspector::stopPageProfiling()
{
    if (!m_page->corePage())
        return;

    m_page->corePage()->inspectorController().show();

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::StopPageProfiling(), 0);
    });
}

void WebInspector::startElementSelection()
{
    if (!m_page->corePage())
        return;

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::StartElementSelection(), 0);
    });
}

void WebInspector::stopElementSelection()
{
    if (!m_page->corePage())
        return;

    whenFrontendConnectionEstablished([=] {
        m_frontendConnection->send(Messages::WebInspectorUI::StopElementSelection(), 0);
    });
}

void WebInspector::elementSelectionChanged(bool active)
{
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::ElementSelectionChanged(active), m_page->identifier());
}

void WebInspector::timelineRecordingChanged(bool active)
{
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::TimelineRecordingChanged(active), m_page->identifier());
}

void WebInspector::setMockCaptureDevicesEnabledOverride(Optional<bool> enabled)
{
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetMockCaptureDevicesEnabledOverride(enabled), m_page->identifier());
}

bool WebInspector::canAttachWindow()
{
    if (!m_page->corePage())
        return false;

    // Don't allow attaching to another inspector -- two inspectors in one window is too much!
    if (m_page->isInspectorPage())
        return false;

    // If we are already attached, allow attaching again to allow switching sides.
    if (m_attached)
        return true;

    // Don't allow the attach if the window would be too small to accommodate the minimum inspector size.
    unsigned inspectedPageHeight = m_page->corePage()->mainFrame().view()->visibleHeight();
    unsigned inspectedPageWidth = m_page->corePage()->mainFrame().view()->visibleWidth();
    unsigned maximumAttachedHeight = inspectedPageHeight * maximumAttachedHeightRatio;
    return minimumAttachedHeight <= maximumAttachedHeight && minimumAttachedWidth <= inspectedPageWidth;
}

void WebInspector::updateDockingAvailability()
{
    if (m_attached)
        return;

    bool canAttachWindow = this->canAttachWindow();
    if (m_previousCanAttach == canAttachWindow)
        return;

    m_previousCanAttach = canAttachWindow;

    WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachAvailabilityChanged(canAttachWindow), m_page->identifier());
}

} // namespace WebKit
