199 lines
6.5 KiB
C++
199 lines
6.5 KiB
C++
// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
|
|
// reserved. Use of this source code is governed by a BSD-style license that
|
|
// can be found in the LICENSE file.
|
|
|
|
#include "tests/ceftests/test_server_runner.h"
|
|
|
|
#include "include/cef_server.h"
|
|
#include "include/wrapper/cef_closure_task.h"
|
|
#include "include/wrapper/cef_helpers.h"
|
|
#include "tests/gtest/include/gtest/gtest.h"
|
|
|
|
namespace test_server {
|
|
|
|
namespace {
|
|
|
|
const int kHttpServerBacklog = 10;
|
|
|
|
// Created on the UI thread and called on the dedicated server thread.
|
|
class ServerHandler : public CefServerHandler {
|
|
public:
|
|
explicit ServerHandler(Runner::Delegate* delegate) : delegate_(delegate) {}
|
|
|
|
~ServerHandler() override {
|
|
CEF_REQUIRE_UI_THREAD();
|
|
EXPECT_FALSE(server_);
|
|
delegate_->OnServerHandlerDeleted();
|
|
}
|
|
|
|
void Shutdown() { server_->Shutdown(); }
|
|
|
|
// CefServerHandler methods:
|
|
void OnServerCreated(CefRefPtr<CefServer> server) override {
|
|
EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
|
|
server_ = server;
|
|
NotifyServerCreated("http://" + server->GetAddress().ToString());
|
|
}
|
|
|
|
void OnServerDestroyed(CefRefPtr<CefServer> server) override {
|
|
EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
|
|
server_ = nullptr;
|
|
NotifyServerDestroyed();
|
|
}
|
|
|
|
void OnClientConnected(CefRefPtr<CefServer> server,
|
|
int connection_id) override {
|
|
EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
|
|
EXPECT_TRUE(server->HasConnection());
|
|
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
|
}
|
|
|
|
void OnClientDisconnected(CefRefPtr<CefServer> server,
|
|
int connection_id) override {
|
|
EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
|
|
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
|
}
|
|
|
|
void OnHttpRequest(CefRefPtr<CefServer> server,
|
|
int connection_id,
|
|
const CefString& client_address,
|
|
CefRefPtr<CefRequest> request) override {
|
|
EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
|
|
NotifyTestServerRequest(server, connection_id, client_address, request);
|
|
}
|
|
|
|
void OnWebSocketRequest(CefRefPtr<CefServer> server,
|
|
int connection_id,
|
|
const CefString& client_address,
|
|
CefRefPtr<CefRequest> request,
|
|
CefRefPtr<CefCallback> callback) override {}
|
|
void OnWebSocketConnected(CefRefPtr<CefServer> server,
|
|
int connection_id) override {}
|
|
void OnWebSocketMessage(CefRefPtr<CefServer> server,
|
|
int connection_id,
|
|
const void* data,
|
|
size_t data_size) override {}
|
|
|
|
private:
|
|
void NotifyServerCreated(const std::string& server_origin) {
|
|
if (!CefCurrentlyOn(TID_UI)) {
|
|
CefPostTask(TID_UI, base::BindOnce(&ServerHandler::NotifyServerCreated,
|
|
this, server_origin));
|
|
return;
|
|
}
|
|
|
|
delegate_->OnServerCreated(server_origin);
|
|
}
|
|
|
|
void NotifyServerDestroyed() {
|
|
if (!CefCurrentlyOn(TID_UI)) {
|
|
CefPostTask(TID_UI,
|
|
base::BindOnce(&ServerHandler::NotifyServerDestroyed, this));
|
|
return;
|
|
}
|
|
|
|
delegate_->OnServerDestroyed();
|
|
}
|
|
|
|
void NotifyTestServerRequest(CefRefPtr<CefServer> server,
|
|
int connection_id,
|
|
const CefString& client_address,
|
|
CefRefPtr<CefRequest> request) {
|
|
if (!CefCurrentlyOn(TID_UI)) {
|
|
CefPostTask(TID_UI, base::BindOnce(
|
|
&ServerHandler::NotifyTestServerRequest, this,
|
|
server, connection_id, client_address, request));
|
|
return;
|
|
}
|
|
|
|
auto response_callback = base::BindRepeating(&ServerHandler::SendResponse,
|
|
server, connection_id);
|
|
delegate_->OnTestServerRequest(request, response_callback);
|
|
}
|
|
|
|
static void SendResponse(CefRefPtr<CefServer> server,
|
|
int connection_id,
|
|
CefRefPtr<CefResponse> response,
|
|
const std::string& response_data) {
|
|
// Execute on the server thread because some methods require it.
|
|
CefRefPtr<CefTaskRunner> task_runner = server->GetTaskRunner();
|
|
if (!task_runner->BelongsToCurrentThread()) {
|
|
task_runner->PostTask(CefCreateClosureTask(
|
|
base::BindOnce(ServerHandler::SendResponse, server, connection_id,
|
|
response, response_data)));
|
|
return;
|
|
}
|
|
|
|
if (!server->IsValidConnection(connection_id)) {
|
|
// This can occur if the connected browser has already closed.
|
|
return;
|
|
}
|
|
|
|
const int response_code = response->GetStatus();
|
|
if (response_code <= 0) {
|
|
// Intentionally not responding for incomplete request tests.
|
|
return;
|
|
}
|
|
|
|
const CefString& content_type = response->GetMimeType();
|
|
int64_t content_length = static_cast<int64_t>(response_data.size());
|
|
|
|
CefResponse::HeaderMap extra_headers;
|
|
response->GetHeaderMap(extra_headers);
|
|
|
|
server->SendHttpResponse(connection_id, response_code, content_type,
|
|
content_length, extra_headers);
|
|
|
|
if (response_data == kIncompleteDoNotSendData) {
|
|
// Intentionally not sending data for incomplete request tests.
|
|
return;
|
|
}
|
|
|
|
if (content_length != 0) {
|
|
server->SendRawData(connection_id, response_data.data(),
|
|
response_data.size());
|
|
server->CloseConnection(connection_id);
|
|
}
|
|
|
|
// The connection should be closed.
|
|
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
|
}
|
|
|
|
Runner::Delegate* const delegate_;
|
|
CefRefPtr<CefServer> server_;
|
|
|
|
IMPLEMENT_REFCOUNTING(ServerHandler);
|
|
DISALLOW_COPY_AND_ASSIGN(ServerHandler);
|
|
};
|
|
|
|
class ServerRunner : public Runner {
|
|
public:
|
|
explicit ServerRunner(Delegate* delegate) : Runner(delegate) {}
|
|
|
|
void StartServer() override {
|
|
CEF_REQUIRE_UI_THREAD();
|
|
DCHECK(!handler_);
|
|
handler_ = new ServerHandler(delegate_);
|
|
CefServer::CreateServer(kHttpServerAddress, kHttpServerPort,
|
|
kHttpServerBacklog, handler_);
|
|
}
|
|
|
|
void ShutdownServer() override {
|
|
CEF_REQUIRE_UI_THREAD();
|
|
DCHECK(handler_);
|
|
handler_->Shutdown();
|
|
handler_ = nullptr;
|
|
}
|
|
|
|
private:
|
|
CefRefPtr<ServerHandler> handler_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
std::unique_ptr<Runner> Runner::CreateNormal(Delegate* delegate) {
|
|
return std::make_unique<ServerRunner>(delegate);
|
|
}
|
|
|
|
} // namespace test_server
|