NetworkSocketChannel.cpp [plain text]
#include "config.h"
#include "NetworkSocketChannel.h"
#include "DataReference.h"
#include "NetworkConnectionToWebProcess.h"
#include "NetworkProcess.h"
#include "NetworkSession.h"
#include "WebCoreArgumentCoders.h"
#include "WebSocketChannelMessages.h"
#include "WebSocketTask.h"
namespace WebKit {
using namespace WebCore;
std::unique_ptr<NetworkSocketChannel> NetworkSocketChannel::create(NetworkConnectionToWebProcess& connection, PAL::SessionID sessionID, const ResourceRequest& request, const String& protocol, WebSocketIdentifier identifier)
{
auto result = makeUnique<NetworkSocketChannel>(connection, connection.networkProcess().networkSession(sessionID), request, protocol, identifier);
if (!result->m_socket) {
result->didClose(0, "Cannot create a web socket task"_s);
return nullptr;
}
return result;
}
NetworkSocketChannel::NetworkSocketChannel(NetworkConnectionToWebProcess& connection, NetworkSession* session, const ResourceRequest& request, const String& protocol, WebSocketIdentifier identifier)
: m_connectionToWebProcess(connection)
, m_identifier(identifier)
, m_session(makeWeakPtr(session))
, m_errorTimer(*this, &NetworkSocketChannel::sendDelayedError)
{
if (!m_session)
return;
m_socket = m_session->createWebSocketTask(*this, request, protocol);
if (m_socket) {
m_session->addWebSocketTask(*m_socket);
m_socket->resume();
}
}
NetworkSocketChannel::~NetworkSocketChannel()
{
if (m_session)
m_session->removeWebSocketTask(*m_socket);
if (m_socket)
m_socket->cancel();
}
void NetworkSocketChannel::sendString(const IPC::DataReference& message, CompletionHandler<void()>&& callback)
{
m_socket->sendString(message, WTFMove(callback));
}
void NetworkSocketChannel::sendData(const IPC::DataReference& data, CompletionHandler<void()>&& callback)
{
m_socket->sendData(data, WTFMove(callback));
}
void NetworkSocketChannel::finishClosingIfPossible()
{
if (m_state == State::Open) {
m_state = State::Closing;
return;
}
ASSERT(m_state == State::Closing);
m_state = State::Closed;
m_connectionToWebProcess.removeSocketChannel(m_identifier);
}
void NetworkSocketChannel::close(int32_t code, const String& reason)
{
m_socket->close(code, reason);
finishClosingIfPossible();
}
void NetworkSocketChannel::didConnect(const String& subprotocol, const String& extensions)
{
send(Messages::WebSocketChannel::DidConnect { subprotocol, extensions });
}
void NetworkSocketChannel::didReceiveText(const String& text)
{
send(Messages::WebSocketChannel::DidReceiveText { text });
}
void NetworkSocketChannel::didReceiveBinaryData(const uint8_t* data, size_t length)
{
send(Messages::WebSocketChannel::DidReceiveBinaryData { { data, length } });
}
void NetworkSocketChannel::didClose(unsigned short code, const String& reason)
{
if (m_errorTimer.isActive()) {
m_closeInfo = std::make_pair(code, reason);
return;
}
send(Messages::WebSocketChannel::DidClose { code, reason });
finishClosingIfPossible();
}
void NetworkSocketChannel::didReceiveMessageError(const String& errorMessage)
{
m_errorMessage = errorMessage;
m_errorTimer.startOneShot(NetworkProcess::randomClosedPortDelay());
}
void NetworkSocketChannel::sendDelayedError()
{
send(Messages::WebSocketChannel::DidReceiveMessageError { m_errorMessage });
if (m_closeInfo) {
send(Messages::WebSocketChannel::DidClose { m_closeInfo->first, m_closeInfo->second });
finishClosingIfPossible();
}
}
void NetworkSocketChannel::didSendHandshakeRequest(ResourceRequest&& request)
{
send(Messages::WebSocketChannel::DidSendHandshakeRequest { request });
}
void NetworkSocketChannel::didReceiveHandshakeResponse(ResourceResponse&& response)
{
response.sanitizeHTTPHeaderFields(ResourceResponse::SanitizationType::CrossOriginSafe);
send(Messages::WebSocketChannel::DidReceiveHandshakeResponse { response });
}
IPC::Connection* NetworkSocketChannel::messageSenderConnection() const
{
return &m_connectionToWebProcess.connection();
}
NetworkSession* NetworkSocketChannel::session()
{
return m_session.get();
}
}