#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)
{
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 (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));
}
void WebInspector::show()
{
if (!m_page->corePage())
return;
m_page->corePage()->inspectorController().show();
}
void WebInspector::close()
{
if (!m_page->corePage())
return;
if (!m_frontendConnection)
return;
closeFrontendConnection();
}
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::setDeveloperPreferenceOverride(InspectorClient::DeveloperPreference developerPreference, Optional<bool> overrideValue)
{
WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetDeveloperPreferenceOverride(developerPreference, overrideValue), m_page->identifier());
}
bool WebInspector::canAttachWindow()
{
if (!m_page->corePage())
return false;
if (m_page->isInspectorPage())
return false;
if (m_attached)
return true;
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());
}
}