WebInspectorServer.cpp [plain text]
#include "config.h"
#if ENABLE(INSPECTOR_SERVER)
#include "WebInspectorServer.h"
#include "HTTPRequest.h"
#include "WebInspectorProxy.h"
#include "WebSocketServerConnection.h"
using namespace WebCore;
namespace WebKit {
static unsigned pageIdFromRequestPath(const String& path)
{
size_t start = path.reverseFind('/');
String numberString = path.substring(start + 1, path.length() - start - 1);
bool ok = false;
unsigned number = numberString.toUIntStrict(&ok);
if (!ok)
return 0;
return number;
}
WebInspectorServer& WebInspectorServer::shared()
{
static WebInspectorServer& server = *new WebInspectorServer;
return server;
}
WebInspectorServer::WebInspectorServer()
: WebSocketServer(this)
, m_nextAvailablePageId(1)
{
}
WebInspectorServer::~WebInspectorServer()
{
HashMap<unsigned, WebSocketServerConnection*>::iterator end = m_connectionMap.end();
for (HashMap<unsigned, WebSocketServerConnection*>::iterator it = m_connectionMap.begin(); it != end; ++it) {
WebSocketServerConnection* connection = it->value;
WebInspectorProxy* client = m_clientMap.get(connection->identifier());
closeConnection(client, connection);
}
}
int WebInspectorServer::registerPage(WebInspectorProxy* client)
{
#ifndef ASSERT_DISABLED
ClientMap::iterator end = m_clientMap.end();
for (ClientMap::iterator it = m_clientMap.begin(); it != end; ++it)
ASSERT(it->value != client);
#endif
int pageId = m_nextAvailablePageId++;
m_clientMap.set(pageId, client);
return pageId;
}
void WebInspectorServer::unregisterPage(int pageId)
{
m_clientMap.remove(pageId);
WebSocketServerConnection* connection = m_connectionMap.get(pageId);
if (connection)
closeConnection(0, connection);
}
#if !PLATFORM(QT)
String WebInspectorServer::inspectorUrlForPageID(int)
{
return String();
}
#endif
void WebInspectorServer::sendMessageOverConnection(unsigned pageIdForConnection, const String& message)
{
WebSocketServerConnection* connection = m_connectionMap.get(pageIdForConnection);
if (connection)
connection->sendWebSocketMessage(message);
}
void WebInspectorServer::didReceiveUnrecognizedHTTPRequest(WebSocketServerConnection* connection, PassRefPtr<HTTPRequest> request)
{
String path = request->url();
size_t pathEnd = path.find('?');
if (pathEnd == notFound)
pathEnd = path.find('#');
if (pathEnd != notFound)
path.truncate(pathEnd);
Vector<char> body;
String contentType;
bool found = platformResourceForPath(path, body, contentType);
HTTPHeaderMap headerFields;
headerFields.set("Connection", "close");
headerFields.set("Content-Length", String::number(body.size()));
if (found)
headerFields.set("Content-Type", contentType);
connection->sendHTTPResponseHeader(found ? 200 : 404, found ? "OK" : "Not Found", headerFields);
connection->sendRawData(body.data(), body.size());
connection->shutdownAfterSendOrNow();
}
bool WebInspectorServer::didReceiveWebSocketUpgradeHTTPRequest(WebSocketServerConnection*, PassRefPtr<HTTPRequest> request)
{
String path = request->url();
DEFINE_STATIC_LOCAL(const String, inspectorWebSocketConnectionPathPrefix, (ASCIILiteral("/devtools/page/")));
if (!path.startsWith(inspectorWebSocketConnectionPathPrefix))
return false;
int pageId = pageIdFromRequestPath(path);
if (!pageId)
return false;
WebInspectorProxy* client = m_clientMap.get(pageId);
if (!client)
return false;
return true;
}
void WebInspectorServer::didEstablishWebSocketConnection(WebSocketServerConnection* connection, PassRefPtr<HTTPRequest> request)
{
String path = request->url();
unsigned pageId = pageIdFromRequestPath(path);
ASSERT(pageId);
if (m_connectionMap.contains(pageId)) {
LOG_ERROR("A remote inspector connection already exist for page ID %d. Ignoring.", pageId);
connection->shutdownNow();
return;
}
connection->setIdentifier(pageId);
m_connectionMap.set(pageId, connection);
WebInspectorProxy* client = m_clientMap.get(pageId);
client->remoteFrontendConnected();
}
void WebInspectorServer::didReceiveWebSocketMessage(WebSocketServerConnection* connection, const String& message)
{
unsigned pageId = connection->identifier();
ASSERT(pageId);
WebInspectorProxy* client = m_clientMap.get(pageId);
client->dispatchMessageFromRemoteFrontend(message);
}
void WebInspectorServer::didCloseWebSocketConnection(WebSocketServerConnection* connection)
{
unsigned pageId = connection->identifier();
if (!pageId)
return;
WebInspectorProxy* client = m_clientMap.get(pageId);
closeConnection(client, connection);
}
void WebInspectorServer::closeConnection(WebInspectorProxy* client, WebSocketServerConnection* connection)
{
if (client)
client->remoteFrontendDisconnected();
m_connectionMap.remove(connection->identifier());
connection->setIdentifier(0);
connection->shutdownNow();
}
}
#endif // ENABLE(INSPECTOR_SERVER)