ceftests: Refactor test_server to support both HTTP and HTTPS servers (see issue #3348)
This commit is contained in:
parent
68be2b8938
commit
a4d63010c9
|
@ -524,7 +524,15 @@
|
||||||
'tests/ceftests/test_request.h',
|
'tests/ceftests/test_request.h',
|
||||||
'tests/ceftests/test_server.cc',
|
'tests/ceftests/test_server.cc',
|
||||||
'tests/ceftests/test_server.h',
|
'tests/ceftests/test_server.h',
|
||||||
'tests/ceftests/test_server_unittest.cc',
|
'tests/ceftests/test_server_observer.h',
|
||||||
|
'tests/ceftests/test_server_observer.cc',
|
||||||
|
'tests/ceftests/test_server_observer_unittest.cc',
|
||||||
|
'tests/ceftests/test_server_manager.h',
|
||||||
|
'tests/ceftests/test_server_manager.cc',
|
||||||
|
'tests/ceftests/test_server_runner.h',
|
||||||
|
'tests/ceftests/test_server_runner.cc',
|
||||||
|
'tests/ceftests/test_server_runner_normal.cc',
|
||||||
|
'tests/ceftests/test_server_runner_test.cc',
|
||||||
'tests/ceftests/test_suite.cc',
|
'tests/ceftests/test_suite.cc',
|
||||||
'tests/ceftests/test_suite.h',
|
'tests/ceftests/test_suite.h',
|
||||||
'tests/ceftests/test_util.cc',
|
'tests/ceftests/test_util.cc',
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "tests/ceftests/routing_test_handler.h"
|
#include "tests/ceftests/routing_test_handler.h"
|
||||||
#include "tests/ceftests/test_handler.h"
|
#include "tests/ceftests/test_handler.h"
|
||||||
#include "tests/ceftests/test_server.h"
|
#include "tests/ceftests/test_server_observer.h"
|
||||||
#include "tests/ceftests/test_suite.h"
|
#include "tests/ceftests/test_suite.h"
|
||||||
#include "tests/ceftests/test_util.h"
|
#include "tests/ceftests/test_util.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "tests/ceftests/routing_test_handler.h"
|
#include "tests/ceftests/routing_test_handler.h"
|
||||||
#include "tests/ceftests/test_request.h"
|
#include "tests/ceftests/test_request.h"
|
||||||
#include "tests/ceftests/test_server.h"
|
#include "tests/ceftests/test_server_observer.h"
|
||||||
#include "tests/ceftests/test_util.h"
|
#include "tests/ceftests/test_util.h"
|
||||||
#include "tests/shared/browser/client_app_browser.h"
|
#include "tests/shared/browser/client_app_browser.h"
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,9 @@
|
||||||
|
|
||||||
#include "tests/ceftests/test_server.h"
|
#include "tests/ceftests/test_server.h"
|
||||||
|
|
||||||
#include <vector>
|
#include "tests/ceftests/test_server_manager.h"
|
||||||
|
|
||||||
#include "include/cef_server.h"
|
#include <vector>
|
||||||
#include "include/wrapper/cef_closure_task.h"
|
|
||||||
#include "include/wrapper/cef_helpers.h"
|
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
|
||||||
|
|
||||||
namespace test_server {
|
namespace test_server {
|
||||||
|
|
||||||
|
@ -20,476 +17,22 @@ const char kServerScheme[] = "http";
|
||||||
const char kServerOrigin[] = "http://127.0.0.1:8098";
|
const char kServerOrigin[] = "http://127.0.0.1:8098";
|
||||||
const char kIncompleteDoNotSendData[] = "DO NOT SEND";
|
const char kIncompleteDoNotSendData[] = "DO NOT SEND";
|
||||||
|
|
||||||
namespace {
|
CefRefPtr<CefResponse> Create404Response() {
|
||||||
|
auto response = CefResponse::Create();
|
||||||
class ServerManager;
|
response->SetStatus(404);
|
||||||
ServerManager* g_manager = nullptr;
|
response->SetMimeType("text/html");
|
||||||
|
return response;
|
||||||
// True if Stop() has been called.
|
|
||||||
bool g_stopping = false;
|
|
||||||
|
|
||||||
// Created on the UI thread and called on the dedicated server thread.
|
|
||||||
class ServerHandler : public CefServerHandler {
|
|
||||||
public:
|
|
||||||
ServerHandler() {
|
|
||||||
CefServer::CreateServer(kServerAddress, kServerPort, 10, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ServerHandler() override {
|
|
||||||
EXPECT_FALSE(server_);
|
|
||||||
NotifyServerHandlerDeleted();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown() { server_->Shutdown(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// CefServerHandler methods:
|
|
||||||
void OnServerCreated(CefRefPtr<CefServer> server) override {
|
|
||||||
server_ = server;
|
|
||||||
NotifyServerCreated(kServerOrigin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnServerDestroyed(CefRefPtr<CefServer> server) override {
|
|
||||||
server_ = nullptr;
|
|
||||||
NotifyServerDestroyed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnClientConnected(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id) override {
|
|
||||||
EXPECT_TRUE(server->HasConnection());
|
|
||||||
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnClientDisconnected(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id) override {
|
|
||||||
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnHttpRequest(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id,
|
|
||||||
const CefString& client_address,
|
|
||||||
CefRefPtr<CefRequest> request) override {
|
|
||||||
NotifyHttpRequest(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:
|
|
||||||
static void NotifyServerCreated(const std::string& server_origin);
|
|
||||||
static void NotifyServerDestroyed();
|
|
||||||
static void NotifyServerHandlerDeleted();
|
|
||||||
static void NotifyHttpRequest(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id,
|
|
||||||
const CefString& client_address,
|
|
||||||
CefRefPtr<CefRequest> request);
|
|
||||||
|
|
||||||
CefRefPtr<CefServer> server_;
|
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(ServerHandler);
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ServerHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only accessed on the UI thread. Deletes itself after the server is stopped.
|
|
||||||
class ServerManager {
|
|
||||||
public:
|
|
||||||
ServerManager() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
EXPECT_FALSE(g_manager);
|
|
||||||
g_manager = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~ServerManager() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
EXPECT_TRUE(observer_list_.empty());
|
|
||||||
EXPECT_TRUE(start_callback_list_.empty());
|
|
||||||
EXPECT_TRUE(stop_callback_.is_null());
|
|
||||||
|
|
||||||
g_manager = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start(StartDoneCallback callback) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
if (!origin_.empty()) {
|
|
||||||
// The server is already running.
|
|
||||||
std::move(callback).Run(origin_);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If tests run in parallel, and the server is starting, then there may be
|
|
||||||
// multiple pending callbacks.
|
|
||||||
start_callback_list_.push_back(std::move(callback));
|
|
||||||
|
|
||||||
// Only create the handler a single time.
|
|
||||||
if (!handler_) {
|
|
||||||
handler_ = new ServerHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Stop(DoneCallback callback) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
if (!handler_) {
|
|
||||||
// The server is not currently running.
|
|
||||||
std::move(callback).Run();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only 1 stop callback supported.
|
|
||||||
EXPECT_TRUE(stop_callback_.is_null());
|
|
||||||
stop_callback_ = std::move(callback);
|
|
||||||
|
|
||||||
handler_->Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddObserver(Observer* observer) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
observer_list_.push_back(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveObserver(Observer* observer) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
bool found = false;
|
|
||||||
ObserverList::iterator it = observer_list_.begin();
|
|
||||||
for (; it != observer_list_.end(); ++it) {
|
|
||||||
if (*it == observer) {
|
|
||||||
observer_list_.erase(it);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(found);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyServerCreated(const std::string& server_origin) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
|
|
||||||
EXPECT_TRUE(origin_.empty());
|
|
||||||
origin_ = server_origin;
|
|
||||||
|
|
||||||
for (auto& callback : start_callback_list_) {
|
|
||||||
std::move(callback).Run(origin_);
|
|
||||||
}
|
|
||||||
start_callback_list_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyServerDestroyed() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
|
|
||||||
origin_.clear();
|
|
||||||
handler_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All server-related objects have been torn down.
|
|
||||||
void NotifyServerHandlerDeleted() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
|
|
||||||
EXPECT_FALSE(stop_callback_.is_null());
|
|
||||||
std::move(stop_callback_).Run();
|
|
||||||
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyHttpRequest(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id,
|
|
||||||
const CefString& client_address,
|
|
||||||
CefRefPtr<CefRequest> request) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
|
|
||||||
// TODO(chrome-runtime): Debug why favicon requests don't always have the
|
|
||||||
// correct resource type.
|
|
||||||
const std::string& url = request->GetURL();
|
|
||||||
if (request->GetResourceType() == RT_FAVICON ||
|
|
||||||
url.find("/favicon.ico") != std::string::npos) {
|
|
||||||
// We don't currently handle favicon requests.
|
|
||||||
server->SendHttp404Response(connection_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_FALSE(observer_list_.empty()) << url;
|
|
||||||
|
|
||||||
// Use a copy in case |observer_list_| is modified during iteration.
|
|
||||||
ObserverList list = observer_list_;
|
|
||||||
|
|
||||||
bool handled = false;
|
|
||||||
|
|
||||||
auto response_callback = base::BindRepeating(&ServerManager::SendResponse,
|
|
||||||
server, connection_id);
|
|
||||||
|
|
||||||
ObserverList::const_iterator it = list.begin();
|
|
||||||
for (; it != list.end(); ++it) {
|
|
||||||
if ((*it)->OnHttpRequest(request, response_callback)) {
|
|
||||||
handled = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!handled) {
|
|
||||||
server->SendHttp500Response(connection_id, "Unhandled request.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
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(ServerManager::SendResponse, server, connection_id,
|
|
||||||
response, response_data)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No response should be sent yet.
|
|
||||||
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
|
||||||
|
|
||||||
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 content_length = static_cast<int64>(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));
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<ServerHandler> handler_;
|
|
||||||
std::string origin_;
|
|
||||||
|
|
||||||
using StartDoneCallbackList = std::vector<StartDoneCallback>;
|
|
||||||
StartDoneCallbackList start_callback_list_;
|
|
||||||
|
|
||||||
DoneCallback stop_callback_;
|
|
||||||
|
|
||||||
using ObserverList = std::vector<Observer*>;
|
|
||||||
ObserverList observer_list_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ServerManager);
|
|
||||||
};
|
|
||||||
|
|
||||||
ServerManager* GetServerManager() {
|
|
||||||
return g_manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerManager* GetOrCreateServerManager() {
|
void Stop(base::OnceClosure callback) {
|
||||||
if (!g_manager) {
|
// Stop both HTTPS and HTTP servers in a chain.
|
||||||
new ServerManager();
|
Manager::Stop(base::BindOnce(
|
||||||
EXPECT_TRUE(g_manager);
|
[](base::OnceClosure callback) {
|
||||||
}
|
Manager::Stop(std::move(callback),
|
||||||
return g_manager;
|
/*https_server=*/false);
|
||||||
}
|
},
|
||||||
|
std::move(callback)),
|
||||||
// static
|
/*https_server=*/true);
|
||||||
void ServerHandler::NotifyServerCreated(const std::string& server_origin) {
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI, base::BindOnce(ServerHandler::NotifyServerCreated,
|
|
||||||
server_origin));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetServerManager()->NotifyServerCreated(server_origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void ServerHandler::NotifyServerDestroyed() {
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI, base::BindOnce(ServerHandler::NotifyServerDestroyed));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetServerManager()->NotifyServerDestroyed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void ServerHandler::NotifyServerHandlerDeleted() {
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI,
|
|
||||||
base::BindOnce(ServerHandler::NotifyServerHandlerDeleted));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetServerManager()->NotifyServerHandlerDeleted();
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void ServerHandler::NotifyHttpRequest(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id,
|
|
||||||
const CefString& client_address,
|
|
||||||
CefRefPtr<CefRequest> request) {
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI, base::BindOnce(ServerHandler::NotifyHttpRequest, server,
|
|
||||||
connection_id, client_address, request));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetServerManager()->NotifyHttpRequest(server, connection_id, client_address,
|
|
||||||
request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// May be created on any thread but will be destroyed on the UI thread.
|
|
||||||
class ObserverRegistration : public CefRegistration {
|
|
||||||
public:
|
|
||||||
explicit ObserverRegistration(Observer* const observer)
|
|
||||||
: observer_(observer) {
|
|
||||||
EXPECT_TRUE(observer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ObserverRegistration() override {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
|
|
||||||
ServerManager* manager = GetServerManager();
|
|
||||||
if (manager) {
|
|
||||||
manager->RemoveObserver(observer_);
|
|
||||||
observer_->OnUnregistered();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Initialize() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
GetOrCreateServerManager()->AddObserver(observer_);
|
|
||||||
observer_->OnRegistered();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Observer* const observer_;
|
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ObserverRegistration);
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ObserverRegistration);
|
|
||||||
};
|
|
||||||
|
|
||||||
void InitializeRegistration(CefRefPtr<ObserverRegistration> registration,
|
|
||||||
DoneCallback callback) {
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI, base::BindOnce(InitializeRegistration, registration,
|
|
||||||
std::move(callback)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_FALSE(g_stopping);
|
|
||||||
|
|
||||||
registration->Initialize();
|
|
||||||
if (!callback.is_null())
|
|
||||||
std::move(callback).Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void Start(StartDoneCallback callback) {
|
|
||||||
EXPECT_FALSE(callback.is_null());
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI, base::BindOnce(Start, std::move(callback)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_FALSE(g_stopping);
|
|
||||||
|
|
||||||
GetOrCreateServerManager()->Start(std::move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Stop(DoneCallback callback) {
|
|
||||||
EXPECT_FALSE(callback.is_null());
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
|
||||||
CefPostTask(TID_UI, base::BindOnce(Stop, std::move(callback)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop will be called one time on test framework shutdown.
|
|
||||||
EXPECT_FALSE(g_stopping);
|
|
||||||
g_stopping = true;
|
|
||||||
|
|
||||||
ServerManager* manager = GetServerManager();
|
|
||||||
if (manager) {
|
|
||||||
manager->Stop(std::move(callback));
|
|
||||||
} else {
|
|
||||||
std::move(callback).Run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefRegistration> AddObserver(Observer* observer,
|
|
||||||
DoneCallback callback) {
|
|
||||||
EXPECT_TRUE(observer);
|
|
||||||
CefRefPtr<ObserverRegistration> registration =
|
|
||||||
new ObserverRegistration(observer);
|
|
||||||
InitializeRegistration(registration, std::move(callback));
|
|
||||||
return registration.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefRegistration> AddObserverAndStart(Observer* observer,
|
|
||||||
StartDoneCallback callback) {
|
|
||||||
return AddObserver(observer, base::BindOnce(Start, std::move(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObserverHelper
|
|
||||||
|
|
||||||
ObserverHelper::ObserverHelper() : weak_ptr_factory_(this) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
}
|
|
||||||
|
|
||||||
ObserverHelper::~ObserverHelper() {
|
|
||||||
EXPECT_TRUE(state_ == State::NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObserverHelper::Initialize() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
EXPECT_TRUE(state_ == State::NONE);
|
|
||||||
state_ = State::INITIALIZING;
|
|
||||||
registration_ =
|
|
||||||
AddObserverAndStart(this, base::BindOnce(&ObserverHelper::OnStartDone,
|
|
||||||
weak_ptr_factory_.GetWeakPtr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObserverHelper::Shutdown() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
EXPECT_TRUE(state_ == State::INITIALIZED);
|
|
||||||
state_ = State::SHUTTINGDOWN;
|
|
||||||
registration_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObserverHelper::OnStartDone(const std::string& server_origin) {
|
|
||||||
EXPECT_TRUE(state_ == State::INITIALIZING);
|
|
||||||
state_ = State::INITIALIZED;
|
|
||||||
OnInitialized(server_origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObserverHelper::OnRegistered() {
|
|
||||||
EXPECT_TRUE(state_ == State::INITIALIZING);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObserverHelper::OnUnregistered() {
|
|
||||||
EXPECT_TRUE(state_ == State::SHUTTINGDOWN);
|
|
||||||
state_ = State::NONE;
|
|
||||||
OnShutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace test_server
|
} // namespace test_server
|
||||||
|
|
|
@ -23,92 +23,16 @@ extern const char kServerOrigin[];
|
||||||
// Used with incomplete tests for data that should not be sent.
|
// Used with incomplete tests for data that should not be sent.
|
||||||
extern const char kIncompleteDoNotSendData[];
|
extern const char kIncompleteDoNotSendData[];
|
||||||
|
|
||||||
using DoneCallback = base::OnceClosure;
|
// Create a 404 response for passing to ResponseCallback.
|
||||||
|
CefRefPtr<CefResponse> Create404Response();
|
||||||
|
|
||||||
using StartDoneCallback =
|
using ResponseCallback =
|
||||||
base::OnceCallback<void(const std::string& server_origin)>;
|
|
||||||
|
|
||||||
// Starts the server if it is not currently running, and executes |callback| on
|
|
||||||
// the UI thread. This method should be called by each test case that relies on
|
|
||||||
// the server.
|
|
||||||
void Start(StartDoneCallback callback);
|
|
||||||
|
|
||||||
// Stops the server if it is currently running, and executes |callback| on the
|
|
||||||
// UI thread. This method will be called by the test framework on shutdown.
|
|
||||||
void Stop(DoneCallback callback);
|
|
||||||
|
|
||||||
// Observer for server callbacks. Methods will be called on the UI thread.
|
|
||||||
class Observer {
|
|
||||||
public:
|
|
||||||
// Called when this Observer is registered.
|
|
||||||
virtual void OnRegistered() = 0;
|
|
||||||
|
|
||||||
// Called when this Observer is unregistered.
|
|
||||||
virtual void OnUnregistered() = 0;
|
|
||||||
|
|
||||||
using ResponseCallback =
|
|
||||||
base::RepeatingCallback<void(CefRefPtr<CefResponse> response,
|
base::RepeatingCallback<void(CefRefPtr<CefResponse> response,
|
||||||
const std::string& response_data)>;
|
const std::string& response_data)>;
|
||||||
|
|
||||||
// Return true and execute |response_callback| either synchronously or
|
// Stops all servers that are currently running and executes |callback| on the
|
||||||
// asynchronously if the request was handled. Do not execute
|
// UI thread. This method will be called by the test framework on shutdown.
|
||||||
// |response_callback| when returning false.
|
void Stop(base::OnceClosure callback);
|
||||||
virtual bool OnHttpRequest(CefRefPtr<CefRequest> request,
|
|
||||||
const ResponseCallback& response_callback) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~Observer() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add an observer for server callbacks. Remains registered until the returned
|
|
||||||
// CefRegistration object is destroyed. Registered observers will be executed in
|
|
||||||
// the order of registration until one returns true to indicate that it handled
|
|
||||||
// the callback. |callback| will be executed on the UI thread after registration
|
|
||||||
// is complete.
|
|
||||||
CefRefPtr<CefRegistration> AddObserver(Observer* observer,
|
|
||||||
DoneCallback callback);
|
|
||||||
|
|
||||||
// Combination of AddObserver() followed by Start().
|
|
||||||
CefRefPtr<CefRegistration> AddObserverAndStart(Observer* observer,
|
|
||||||
StartDoneCallback callback);
|
|
||||||
|
|
||||||
// Helper for managing Observer registration and callbacks. Only used on the UI
|
|
||||||
// thread.
|
|
||||||
class ObserverHelper : public Observer {
|
|
||||||
public:
|
|
||||||
ObserverHelper();
|
|
||||||
~ObserverHelper() override;
|
|
||||||
|
|
||||||
// Initialize the registration. Results in a call to OnInitialized().
|
|
||||||
void Initialize();
|
|
||||||
|
|
||||||
// Shut down the registration. Results in a call to OnShutdown().
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// Implement this method to start sending server requests after Initialize().
|
|
||||||
virtual void OnInitialized(const std::string& server_origin) = 0;
|
|
||||||
|
|
||||||
// Implement this method to continue the test after Shutdown().
|
|
||||||
virtual void OnShutdown() = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OnStartDone(const std::string& server_origin);
|
|
||||||
void OnRegistered() override;
|
|
||||||
void OnUnregistered() override;
|
|
||||||
|
|
||||||
CefRefPtr<CefRegistration> registration_;
|
|
||||||
|
|
||||||
enum class State {
|
|
||||||
NONE,
|
|
||||||
INITIALIZING,
|
|
||||||
INITIALIZED,
|
|
||||||
SHUTTINGDOWN,
|
|
||||||
} state_ = State::NONE;
|
|
||||||
|
|
||||||
base::WeakPtrFactory<ObserverHelper> weak_ptr_factory_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ObserverHelper);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test_server
|
} // namespace test_server
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,282 @@
|
||||||
|
// 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_manager.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 {
|
||||||
|
|
||||||
|
Manager* g_http_manager = nullptr;
|
||||||
|
Manager* g_https_manager = nullptr;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// May be created on any thread but will be destroyed on the UI thread.
|
||||||
|
class ObserverRegistration : public CefRegistration {
|
||||||
|
public:
|
||||||
|
ObserverRegistration(Observer* observer, bool https_server)
|
||||||
|
: observer_(observer), https_server_(https_server) {
|
||||||
|
EXPECT_TRUE(observer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ObserverRegistration() override {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
if (auto manager = Manager::GetInstance(https_server_)) {
|
||||||
|
manager->RemoveObserver(observer_);
|
||||||
|
observer_->OnUnregistered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
Manager::GetOrCreateInstance(https_server_)->AddObserver(observer_);
|
||||||
|
observer_->OnRegistered();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitializeRegistration(
|
||||||
|
CefRefPtr<ObserverRegistration> registration,
|
||||||
|
Manager::DoneCallback callback) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(InitializeRegistration, registration,
|
||||||
|
std::move(callback)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
registration->Initialize();
|
||||||
|
if (!callback.is_null())
|
||||||
|
std::move(callback).Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Observer* const observer_;
|
||||||
|
const bool https_server_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ObserverRegistration);
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ObserverRegistration);
|
||||||
|
};
|
||||||
|
|
||||||
|
Manager::Manager(bool https_server) : https_server_(https_server) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
if (https_server) {
|
||||||
|
DCHECK(!g_https_manager);
|
||||||
|
g_https_manager = this;
|
||||||
|
} else {
|
||||||
|
DCHECK(!g_http_manager);
|
||||||
|
g_http_manager = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Manager::~Manager() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
EXPECT_TRUE(observer_list_.empty());
|
||||||
|
EXPECT_TRUE(start_callback_list_.empty());
|
||||||
|
EXPECT_TRUE(stop_callback_.is_null());
|
||||||
|
|
||||||
|
if (https_server_) {
|
||||||
|
g_https_manager = nullptr;
|
||||||
|
} else {
|
||||||
|
g_http_manager = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
Manager* Manager::GetInstance(bool https_server) {
|
||||||
|
return https_server ? g_https_manager : g_http_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
Manager* Manager::GetOrCreateInstance(bool https_server) {
|
||||||
|
if (auto manager = GetInstance(https_server)) {
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Manager(https_server);
|
||||||
|
auto manager = GetInstance(https_server);
|
||||||
|
DCHECK(manager);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Manager::Start(StartDoneCallback callback, bool https_server) {
|
||||||
|
EXPECT_FALSE(callback.is_null());
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(Manager::Start, std::move(callback),
|
||||||
|
https_server));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Manager::GetOrCreateInstance(https_server)->StartImpl(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Manager::Stop(DoneCallback callback, bool https_server) {
|
||||||
|
EXPECT_FALSE(callback.is_null());
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(Manager::Stop, std::move(callback),
|
||||||
|
https_server));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto manager = Manager::GetInstance(https_server)) {
|
||||||
|
manager->StopImpl(std::move(callback));
|
||||||
|
} else {
|
||||||
|
std::move(callback).Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
CefRefPtr<CefRegistration> Manager::AddObserver(Observer* observer,
|
||||||
|
DoneCallback callback,
|
||||||
|
bool https_server) {
|
||||||
|
EXPECT_TRUE(observer);
|
||||||
|
CefRefPtr<ObserverRegistration> registration =
|
||||||
|
new ObserverRegistration(observer, https_server);
|
||||||
|
ObserverRegistration::InitializeRegistration(registration,
|
||||||
|
std::move(callback));
|
||||||
|
return registration.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
CefRefPtr<CefRegistration> Manager::AddObserverAndStart(
|
||||||
|
Observer* observer,
|
||||||
|
StartDoneCallback callback,
|
||||||
|
bool https_server) {
|
||||||
|
return AddObserver(
|
||||||
|
observer,
|
||||||
|
base::BindOnce(Manager::Start, std::move(callback), https_server),
|
||||||
|
https_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::StartImpl(StartDoneCallback callback) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
EXPECT_FALSE(stopping_);
|
||||||
|
|
||||||
|
if (!origin_.empty()) {
|
||||||
|
// The server is already running.
|
||||||
|
std::move(callback).Run(origin_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tests run in parallel, and the server is starting, then there may be
|
||||||
|
// multiple pending callbacks.
|
||||||
|
start_callback_list_.push_back(std::move(callback));
|
||||||
|
|
||||||
|
// Only create the runner a single time.
|
||||||
|
if (!runner_) {
|
||||||
|
runner_ = Runner::Create(this, https_server_);
|
||||||
|
runner_->StartServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::StopImpl(DoneCallback callback) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
if (!runner_) {
|
||||||
|
// The server is not currently running.
|
||||||
|
std::move(callback).Run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop will be called one time on test framework shutdown.
|
||||||
|
EXPECT_FALSE(stopping_);
|
||||||
|
stopping_ = true;
|
||||||
|
|
||||||
|
// Only 1 stop callback supported.
|
||||||
|
EXPECT_TRUE(stop_callback_.is_null());
|
||||||
|
stop_callback_ = std::move(callback);
|
||||||
|
|
||||||
|
runner_->ShutdownServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::AddObserver(Observer* observer) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
EXPECT_FALSE(stopping_);
|
||||||
|
observer_list_.push_back(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::RemoveObserver(Observer* observer) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
bool found = false;
|
||||||
|
ObserverList::iterator it = observer_list_.begin();
|
||||||
|
for (; it != observer_list_.end(); ++it) {
|
||||||
|
if (*it == observer) {
|
||||||
|
observer_list_.erase(it);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::OnServerCreated(const std::string& server_origin) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
EXPECT_TRUE(origin_.empty());
|
||||||
|
origin_ = server_origin;
|
||||||
|
|
||||||
|
for (auto& callback : start_callback_list_) {
|
||||||
|
std::move(callback).Run(origin_);
|
||||||
|
}
|
||||||
|
start_callback_list_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::OnServerDestroyed() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
origin_.clear();
|
||||||
|
runner_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// All server-related objects have been torn down.
|
||||||
|
void Manager::OnServerHandlerDeleted() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
EXPECT_FALSE(stop_callback_.is_null());
|
||||||
|
std::move(stop_callback_).Run();
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::OnHttpRequest(CefRefPtr<CefRequest> request,
|
||||||
|
const ResponseCallback& response_callback) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
// TODO(chrome-runtime): Debug why favicon requests don't always have the
|
||||||
|
// correct resource type.
|
||||||
|
const std::string& url = request->GetURL();
|
||||||
|
if (request->GetResourceType() == RT_FAVICON ||
|
||||||
|
url.find("/favicon.ico") != std::string::npos) {
|
||||||
|
// We don't currently handle favicon requests.
|
||||||
|
response_callback.Run(Create404Response(), std::string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_FALSE(observer_list_.empty()) << url;
|
||||||
|
|
||||||
|
// Use a copy in case |observer_list_| is modified during iteration.
|
||||||
|
ObserverList list = observer_list_;
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
ObserverList::const_iterator it = list.begin();
|
||||||
|
for (; it != list.end(); ++it) {
|
||||||
|
if ((*it)->OnHttpRequest(request, response_callback)) {
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
LOG(WARNING) << "Unhandled request for: " << url;
|
||||||
|
response_callback.Run(Create404Response(), std::string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace test_server
|
|
@ -0,0 +1,98 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef CEF_TESTS_CEFTESTS_TEST_SERVER_MANAGER_H_
|
||||||
|
#define CEF_TESTS_CEFTESTS_TEST_SERVER_MANAGER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "include/base/cef_callback.h"
|
||||||
|
#include "include/cef_registration.h"
|
||||||
|
#include "include/cef_request.h"
|
||||||
|
#include "include/cef_response.h"
|
||||||
|
#include "tests/ceftests/test_server_observer.h"
|
||||||
|
#include "tests/ceftests/test_server_runner.h"
|
||||||
|
|
||||||
|
namespace test_server {
|
||||||
|
|
||||||
|
class ObserverRegistration;
|
||||||
|
|
||||||
|
// Static methods are safe to call on any thread. Non-static methods are only
|
||||||
|
// called on the UI thread. Deletes itself after the server is stopped. Use
|
||||||
|
// ObserverHelper instead of calling these methods directly.
|
||||||
|
class Manager : public Runner::Delegate {
|
||||||
|
public:
|
||||||
|
using StartDoneCallback =
|
||||||
|
base::OnceCallback<void(const std::string& server_origin)>;
|
||||||
|
using DoneCallback = base::OnceClosure;
|
||||||
|
|
||||||
|
// Starts the server if it is not currently running, and executes |callback|
|
||||||
|
// on the UI thread.
|
||||||
|
static void Start(StartDoneCallback callback, bool https_server);
|
||||||
|
|
||||||
|
// Stops the server if it is currently running, and executes |callback| on the
|
||||||
|
// UI thread. This method will be called by the test framework on shutdown.
|
||||||
|
static void Stop(DoneCallback callback, bool https_server);
|
||||||
|
|
||||||
|
// Add an observer for server callbacks. Remains registered until the returned
|
||||||
|
// CefRegistration object is destroyed. Registered observers will be executed
|
||||||
|
// in the order of registration until one returns true to indicate that it
|
||||||
|
// handled the callback. |callback| will be executed on the UI thread after
|
||||||
|
// registration is complete.
|
||||||
|
static CefRefPtr<CefRegistration> AddObserver(Observer* observer,
|
||||||
|
DoneCallback callback,
|
||||||
|
bool https_server);
|
||||||
|
|
||||||
|
// Combination of AddObserver() followed by Start().
|
||||||
|
static CefRefPtr<CefRegistration> AddObserverAndStart(
|
||||||
|
Observer* observer,
|
||||||
|
StartDoneCallback callback,
|
||||||
|
bool https_server);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ObserverRegistration;
|
||||||
|
|
||||||
|
explicit Manager(bool https_server);
|
||||||
|
~Manager();
|
||||||
|
|
||||||
|
static Manager* GetInstance(bool https_server);
|
||||||
|
static Manager* GetOrCreateInstance(bool https_server);
|
||||||
|
|
||||||
|
void StartImpl(StartDoneCallback callback);
|
||||||
|
void StopImpl(DoneCallback callback);
|
||||||
|
|
||||||
|
void AddObserver(Observer* observer);
|
||||||
|
void RemoveObserver(Observer* observer);
|
||||||
|
|
||||||
|
// Runner::Delegate methods:
|
||||||
|
void OnServerCreated(const std::string& server_origin) override;
|
||||||
|
void OnServerDestroyed() override;
|
||||||
|
void OnServerHandlerDeleted() override;
|
||||||
|
void OnHttpRequest(CefRefPtr<CefRequest> request,
|
||||||
|
const ResponseCallback& response_callback) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool https_server_;
|
||||||
|
|
||||||
|
std::unique_ptr<Runner> runner_;
|
||||||
|
std::string origin_;
|
||||||
|
|
||||||
|
using StartDoneCallbackList = std::vector<StartDoneCallback>;
|
||||||
|
StartDoneCallbackList start_callback_list_;
|
||||||
|
|
||||||
|
DoneCallback stop_callback_;
|
||||||
|
|
||||||
|
using ObserverList = std::vector<Observer*>;
|
||||||
|
ObserverList observer_list_;
|
||||||
|
|
||||||
|
bool stopping_ = false;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Manager);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace test_server
|
||||||
|
|
||||||
|
#endif // CEF_TESTS_CEFTESTS_TEST_SERVER_MANAGER_H_
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 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.h"
|
||||||
|
|
||||||
|
#include "include/wrapper/cef_helpers.h"
|
||||||
|
#include "tests/ceftests/test_server_manager.h"
|
||||||
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace test_server {
|
||||||
|
|
||||||
|
ObserverHelper::ObserverHelper() : weak_ptr_factory_(this) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
}
|
||||||
|
|
||||||
|
ObserverHelper::~ObserverHelper() {
|
||||||
|
EXPECT_TRUE(state_ == State::NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObserverHelper::Initialize(bool https_server) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
EXPECT_TRUE(state_ == State::NONE);
|
||||||
|
state_ = State::INITIALIZING;
|
||||||
|
registration_ = Manager::AddObserverAndStart(
|
||||||
|
this,
|
||||||
|
base::BindOnce(&ObserverHelper::OnStartDone,
|
||||||
|
weak_ptr_factory_.GetWeakPtr()),
|
||||||
|
https_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObserverHelper::Shutdown() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
EXPECT_TRUE(state_ == State::INITIALIZED);
|
||||||
|
state_ = State::SHUTTINGDOWN;
|
||||||
|
registration_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObserverHelper::OnStartDone(const std::string& server_origin) {
|
||||||
|
EXPECT_TRUE(state_ == State::INITIALIZING);
|
||||||
|
state_ = State::INITIALIZED;
|
||||||
|
OnInitialized(server_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObserverHelper::OnRegistered() {
|
||||||
|
EXPECT_TRUE(state_ == State::INITIALIZING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObserverHelper::OnUnregistered() {
|
||||||
|
EXPECT_TRUE(state_ == State::SHUTTINGDOWN);
|
||||||
|
state_ = State::NONE;
|
||||||
|
OnShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace test_server
|
|
@ -0,0 +1,82 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef CEF_TESTS_CEFTESTS_TEST_SERVER_OBSERVER_H_
|
||||||
|
#define CEF_TESTS_CEFTESTS_TEST_SERVER_OBSERVER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "include/base/cef_callback.h"
|
||||||
|
#include "include/base/cef_weak_ptr.h"
|
||||||
|
#include "include/cef_registration.h"
|
||||||
|
#include "include/cef_request.h"
|
||||||
|
#include "tests/ceftests/test_server.h"
|
||||||
|
|
||||||
|
namespace test_server {
|
||||||
|
|
||||||
|
// Observer for server callbacks. Methods will be called on the UI thread.
|
||||||
|
class Observer {
|
||||||
|
public:
|
||||||
|
using ResponseCallback = test_server::ResponseCallback;
|
||||||
|
|
||||||
|
// Called when this Observer is registered.
|
||||||
|
virtual void OnRegistered() = 0;
|
||||||
|
|
||||||
|
// Called when this Observer is unregistered.
|
||||||
|
virtual void OnUnregistered() = 0;
|
||||||
|
|
||||||
|
// Return true and execute |response_callback| either synchronously or
|
||||||
|
// asynchronously if the request was handled. Do not execute
|
||||||
|
// |response_callback| when returning false.
|
||||||
|
virtual bool OnHttpRequest(CefRefPtr<CefRequest> request,
|
||||||
|
const ResponseCallback& response_callback) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~Observer() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper for managing Observer registration and callbacks. Only used on the UI
|
||||||
|
// thread.
|
||||||
|
class ObserverHelper : public Observer {
|
||||||
|
public:
|
||||||
|
ObserverHelper();
|
||||||
|
~ObserverHelper() override;
|
||||||
|
|
||||||
|
// Initialize the registration. If |https_server| is true an HTTPS server will
|
||||||
|
// be used, otherwise an HTTP server will be used. Results in a call to
|
||||||
|
// OnInitialized().
|
||||||
|
void Initialize(bool https_server = false);
|
||||||
|
|
||||||
|
// Shut down the registration. Results in a call to OnShutdown().
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
// Implement this method to start sending server requests after Initialize().
|
||||||
|
virtual void OnInitialized(const std::string& server_origin) = 0;
|
||||||
|
|
||||||
|
// Implement this method to continue the test after Shutdown().
|
||||||
|
virtual void OnShutdown() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnStartDone(const std::string& server_origin);
|
||||||
|
void OnRegistered() override;
|
||||||
|
void OnUnregistered() override;
|
||||||
|
|
||||||
|
CefRefPtr<CefRegistration> registration_;
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
NONE,
|
||||||
|
INITIALIZING,
|
||||||
|
INITIALIZED,
|
||||||
|
SHUTTINGDOWN,
|
||||||
|
} state_ = State::NONE;
|
||||||
|
|
||||||
|
base::WeakPtrFactory<ObserverHelper> weak_ptr_factory_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ObserverHelper);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace test_server
|
||||||
|
|
||||||
|
#endif // CEF_TESTS_CEFTESTS_TEST_SERVER_OBSERVER_H_
|
|
@ -10,7 +10,7 @@
|
||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "include/wrapper/cef_helpers.h"
|
#include "include/wrapper/cef_helpers.h"
|
||||||
#include "tests/ceftests/test_request.h"
|
#include "tests/ceftests/test_request.h"
|
||||||
#include "tests/ceftests/test_server.h"
|
#include "tests/ceftests/test_server_observer.h"
|
||||||
#include "tests/ceftests/track_callback.h"
|
#include "tests/ceftests/track_callback.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
|
@ -18,21 +18,16 @@ namespace {
|
||||||
|
|
||||||
struct TestState {
|
struct TestState {
|
||||||
TrackCallback got_initialized_;
|
TrackCallback got_initialized_;
|
||||||
TrackCallback got_connected_;
|
|
||||||
TrackCallback got_request_;
|
TrackCallback got_request_;
|
||||||
TrackCallback got_response_;
|
TrackCallback got_response_;
|
||||||
TrackCallback got_disconnected_;
|
|
||||||
TrackCallback got_shutdown_;
|
TrackCallback got_shutdown_;
|
||||||
|
|
||||||
bool ExpectAll() {
|
bool ExpectAll() {
|
||||||
EXPECT_TRUE(got_initialized_);
|
EXPECT_TRUE(got_initialized_);
|
||||||
EXPECT_TRUE(got_connected_);
|
|
||||||
EXPECT_TRUE(got_request_);
|
EXPECT_TRUE(got_request_);
|
||||||
EXPECT_TRUE(got_response_);
|
EXPECT_TRUE(got_response_);
|
||||||
EXPECT_TRUE(got_disconnected_);
|
|
||||||
EXPECT_TRUE(got_shutdown_);
|
EXPECT_TRUE(got_shutdown_);
|
||||||
return got_initialized_ && got_connected_ && got_request_ &&
|
return got_initialized_ && got_request_ && got_response_ && got_shutdown_;
|
||||||
got_response_ && got_disconnected_ && got_shutdown_;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,10 +53,8 @@ class TestServerObserver : public test_server::ObserverHelper {
|
||||||
void OnInitialized(const std::string& server_origin) override {
|
void OnInitialized(const std::string& server_origin) override {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
EXPECT_FALSE(state_->got_initialized_);
|
EXPECT_FALSE(state_->got_initialized_);
|
||||||
EXPECT_FALSE(state_->got_connected_);
|
|
||||||
EXPECT_FALSE(state_->got_request_);
|
EXPECT_FALSE(state_->got_request_);
|
||||||
EXPECT_FALSE(state_->got_response_);
|
EXPECT_FALSE(state_->got_response_);
|
||||||
EXPECT_FALSE(state_->got_disconnected_);
|
|
||||||
EXPECT_FALSE(state_->got_shutdown_);
|
EXPECT_FALSE(state_->got_shutdown_);
|
||||||
|
|
||||||
state_->got_initialized_.yes();
|
state_->got_initialized_.yes();
|
||||||
|
@ -77,49 +70,25 @@ class TestServerObserver : public test_server::ObserverHelper {
|
||||||
weak_ptr_factory_.GetWeakPtr()));
|
weak_ptr_factory_.GetWeakPtr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnClientConnected(CefRefPtr<CefServer> server,
|
bool OnHttpRequest(CefRefPtr<CefRequest> request,
|
||||||
int connection_id) override {
|
const ResponseCallback& response_callback) override {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
if (state_->got_connected_) {
|
|
||||||
// We already got the callback once. Let the next observer get the
|
|
||||||
// callback.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_TRUE(state_->got_initialized_);
|
|
||||||
EXPECT_FALSE(state_->got_request_);
|
|
||||||
EXPECT_FALSE(state_->got_response_);
|
|
||||||
EXPECT_FALSE(state_->got_disconnected_);
|
|
||||||
EXPECT_FALSE(state_->got_shutdown_);
|
|
||||||
|
|
||||||
state_->got_connected_.yes();
|
|
||||||
|
|
||||||
// We don't know if this connection is the one that we're going to
|
|
||||||
// handle, so continue propagating the callback.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnHttpRequest(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id,
|
|
||||||
const CefString& client_address,
|
|
||||||
CefRefPtr<CefRequest> request) override {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
const std::string& url = request->GetURL();
|
const std::string& url = request->GetURL();
|
||||||
if (url != url_)
|
if (url != url_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
EXPECT_TRUE(state_->got_initialized_);
|
EXPECT_TRUE(state_->got_initialized_);
|
||||||
EXPECT_TRUE(state_->got_connected_);
|
|
||||||
EXPECT_FALSE(state_->got_request_);
|
EXPECT_FALSE(state_->got_request_);
|
||||||
EXPECT_FALSE(state_->got_response_);
|
EXPECT_FALSE(state_->got_response_);
|
||||||
EXPECT_FALSE(state_->got_disconnected_);
|
|
||||||
EXPECT_FALSE(state_->got_shutdown_);
|
EXPECT_FALSE(state_->got_shutdown_);
|
||||||
|
|
||||||
state_->got_request_.yes();
|
state_->got_request_.yes();
|
||||||
connection_id_ = connection_id;
|
|
||||||
|
|
||||||
server->SendHttp200Response(connection_id, "text/plain", kResponseData,
|
auto response = CefResponse::Create();
|
||||||
sizeof(kResponseData) - 1);
|
response->SetStatus(200);
|
||||||
|
response->SetMimeType("text/plain");
|
||||||
|
|
||||||
|
response_callback.Run(response, kResponseData);
|
||||||
|
|
||||||
// Stop propagating the callback.
|
// Stop propagating the callback.
|
||||||
return true;
|
return true;
|
||||||
|
@ -129,7 +98,6 @@ class TestServerObserver : public test_server::ObserverHelper {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
// Don't test for disconnected, which may race response.
|
// Don't test for disconnected, which may race response.
|
||||||
EXPECT_TRUE(state_->got_initialized_);
|
EXPECT_TRUE(state_->got_initialized_);
|
||||||
EXPECT_TRUE(state_->got_connected_);
|
|
||||||
EXPECT_TRUE(state_->got_request_);
|
EXPECT_TRUE(state_->got_request_);
|
||||||
EXPECT_FALSE(state_->got_response_);
|
EXPECT_FALSE(state_->got_response_);
|
||||||
EXPECT_FALSE(state_->got_shutdown_);
|
EXPECT_FALSE(state_->got_shutdown_);
|
||||||
|
@ -147,35 +115,11 @@ class TestServerObserver : public test_server::ObserverHelper {
|
||||||
weak_ptr_factory_.GetWeakPtr()));
|
weak_ptr_factory_.GetWeakPtr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnClientDisconnected(CefRefPtr<CefServer> server,
|
|
||||||
int connection_id) override {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
if (connection_id != connection_id_) {
|
|
||||||
// Not the connection that we handled. Let the next observer get the
|
|
||||||
// callback.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't test for response, which may race disconnected.
|
|
||||||
EXPECT_TRUE(state_->got_initialized_);
|
|
||||||
EXPECT_TRUE(state_->got_connected_);
|
|
||||||
EXPECT_TRUE(state_->got_request_);
|
|
||||||
EXPECT_FALSE(state_->got_disconnected_);
|
|
||||||
EXPECT_FALSE(state_->got_shutdown_);
|
|
||||||
|
|
||||||
state_->got_disconnected_.yes();
|
|
||||||
|
|
||||||
// Stop propagating the callback.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnShutdown() override {
|
void OnShutdown() override {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
EXPECT_TRUE(state_->got_initialized_);
|
EXPECT_TRUE(state_->got_initialized_);
|
||||||
EXPECT_TRUE(state_->got_connected_);
|
|
||||||
EXPECT_TRUE(state_->got_request_);
|
EXPECT_TRUE(state_->got_request_);
|
||||||
EXPECT_TRUE(state_->got_response_);
|
EXPECT_TRUE(state_->got_response_);
|
||||||
EXPECT_TRUE(state_->got_disconnected_);
|
|
||||||
EXPECT_FALSE(state_->got_shutdown_);
|
EXPECT_FALSE(state_->got_shutdown_);
|
||||||
|
|
||||||
state_->got_shutdown_.yes();
|
state_->got_shutdown_.yes();
|
||||||
|
@ -190,7 +134,6 @@ class TestServerObserver : public test_server::ObserverHelper {
|
||||||
base::OnceClosure done_callback_;
|
base::OnceClosure done_callback_;
|
||||||
|
|
||||||
std::string url_;
|
std::string url_;
|
||||||
int connection_id_ = -1;
|
|
||||||
|
|
||||||
base::WeakPtrFactory<TestServerObserver> weak_ptr_factory_;
|
base::WeakPtrFactory<TestServerObserver> weak_ptr_factory_;
|
||||||
|
|
||||||
|
@ -220,7 +163,7 @@ void SignalIfDone(CefRefPtr<CefWaitableEvent> event,
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(TestServerTest, ObserverHelperSingle) {
|
TEST(TestServerObserverTest, HelperSingle) {
|
||||||
CefRefPtr<CefWaitableEvent> event =
|
CefRefPtr<CefWaitableEvent> event =
|
||||||
CefWaitableEvent::CreateWaitableEvent(true, false);
|
CefWaitableEvent::CreateWaitableEvent(true, false);
|
||||||
|
|
||||||
|
@ -232,7 +175,7 @@ TEST(TestServerTest, ObserverHelperSingle) {
|
||||||
EXPECT_TRUE(state.ExpectAll());
|
EXPECT_TRUE(state.ExpectAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestServerTest, ObserverHelperMultiple) {
|
TEST(TestServerObserverTest, HelperMultiple) {
|
||||||
CefRefPtr<CefWaitableEvent> event =
|
CefRefPtr<CefWaitableEvent> event =
|
||||||
CefWaitableEvent::CreateWaitableEvent(true, false);
|
CefWaitableEvent::CreateWaitableEvent(true, false);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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 "tests/shared/common/client_switches.h"
|
||||||
|
|
||||||
|
#include "include/base/cef_logging.h"
|
||||||
|
#include "include/cef_command_line.h"
|
||||||
|
|
||||||
|
namespace test_server {
|
||||||
|
|
||||||
|
Runner::Runner(Delegate* delegate) : delegate_(delegate) {
|
||||||
|
DCHECK(delegate_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::unique_ptr<Runner> Runner::Create(Runner::Delegate* delegate,
|
||||||
|
bool https_server) {
|
||||||
|
static bool use_test_http_server = [] {
|
||||||
|
auto command_line = CefCommandLine::GetGlobalCommandLine();
|
||||||
|
return command_line->HasSwitch(client::switches::kUseTestHttpServer);
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (https_server || use_test_http_server) {
|
||||||
|
return CreateTest(delegate, https_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateNormal(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace test_server
|
|
@ -0,0 +1,68 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef CEF_TESTS_CEFTESTS_TEST_SERVER_RUNNER_H_
|
||||||
|
#define CEF_TESTS_CEFTESTS_TEST_SERVER_RUNNER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "include/cef_request.h"
|
||||||
|
#include "include/internal/cef_types.h"
|
||||||
|
#include "tests/ceftests/test_server.h"
|
||||||
|
|
||||||
|
namespace test_server {
|
||||||
|
|
||||||
|
// Runs the server. All methods will be called on the UI thread.
|
||||||
|
class Runner {
|
||||||
|
public:
|
||||||
|
// Interface implemented by the Manager that creates/owns the Runner.
|
||||||
|
class Delegate {
|
||||||
|
public:
|
||||||
|
// Server created notification.
|
||||||
|
virtual void OnServerCreated(const std::string& server_origin) = 0;
|
||||||
|
|
||||||
|
// Server destroyed notification. May delete the Runner.
|
||||||
|
virtual void OnServerDestroyed() = 0;
|
||||||
|
|
||||||
|
// Server handler deleted notification. May delete the Manager.
|
||||||
|
virtual void OnServerHandlerDeleted() = 0;
|
||||||
|
|
||||||
|
// Server request notification.
|
||||||
|
virtual void OnHttpRequest(CefRefPtr<CefRequest> request,
|
||||||
|
const ResponseCallback& response_callback) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~Delegate() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// |delegate| will outlive this object.
|
||||||
|
explicit Runner(Delegate* delegate);
|
||||||
|
virtual ~Runner() = default;
|
||||||
|
|
||||||
|
// Called by the Manager to create the Runner.
|
||||||
|
static std::unique_ptr<Runner> Create(Delegate* delegate, bool https_server);
|
||||||
|
|
||||||
|
// Called by the Manager to create/destroy the server handler.
|
||||||
|
virtual void StartServer() = 0;
|
||||||
|
virtual void ShutdownServer() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Create a Runner based on CefServer.
|
||||||
|
static std::unique_ptr<Runner> CreateNormal(Delegate* delegate);
|
||||||
|
|
||||||
|
// Create a Runner based on CefTestServer.
|
||||||
|
static std::unique_ptr<Runner> CreateTest(Delegate* delegate,
|
||||||
|
bool https_server);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Delegate* const delegate_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Runner);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace test_server
|
||||||
|
|
||||||
|
#endif // CEF_TESTS_CEFTESTS_TEST_SERVER_RUNNER_H_
|
|
@ -0,0 +1,196 @@
|
||||||
|
// 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 kServerBacklog = 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(kServerOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
NotifyHttpRequest(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 NotifyHttpRequest(CefRefPtr<CefServer> server,
|
||||||
|
int connection_id,
|
||||||
|
const CefString& client_address,
|
||||||
|
CefRefPtr<CefRequest> request) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&ServerHandler::NotifyHttpRequest,
|
||||||
|
this, server, connection_id,
|
||||||
|
client_address, request));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto response_callback = base::BindRepeating(&ServerHandler::SendResponse,
|
||||||
|
server, connection_id);
|
||||||
|
delegate_->OnHttpRequest(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No response should be sent yet.
|
||||||
|
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
||||||
|
|
||||||
|
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 content_length = static_cast<int64>(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(kServerAddress, kServerPort, kServerBacklog,
|
||||||
|
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
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright (c) 2022 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/base/cef_logging.h"
|
||||||
|
|
||||||
|
namespace test_server {
|
||||||
|
|
||||||
|
std::unique_ptr<Runner> Runner::CreateTest(Delegate* delegate,
|
||||||
|
bool https_server) {
|
||||||
|
NOTREACHED();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace test_server
|
|
@ -19,7 +19,7 @@
|
||||||
#include "include/wrapper/cef_scoped_temp_dir.h"
|
#include "include/wrapper/cef_scoped_temp_dir.h"
|
||||||
#include "tests/ceftests/test_handler.h"
|
#include "tests/ceftests/test_handler.h"
|
||||||
#include "tests/ceftests/test_request.h"
|
#include "tests/ceftests/test_request.h"
|
||||||
#include "tests/ceftests/test_server.h"
|
#include "tests/ceftests/test_server_observer.h"
|
||||||
#include "tests/ceftests/test_suite.h"
|
#include "tests/ceftests/test_suite.h"
|
||||||
#include "tests/ceftests/test_util.h"
|
#include "tests/ceftests/test_util.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
|
|
@ -51,6 +51,7 @@ const char kInitialShowState[] = "initial-show-state";
|
||||||
const char kHideChromeStatusBubble[] = "hide-chrome-status-bubble";
|
const char kHideChromeStatusBubble[] = "hide-chrome-status-bubble";
|
||||||
const char kUseDefaultPopup[] = "use-default-popup";
|
const char kUseDefaultPopup[] = "use-default-popup";
|
||||||
const char kUseClientDialogs[] = "use-client-dialogs";
|
const char kUseClientDialogs[] = "use-client-dialogs";
|
||||||
|
const char kUseTestHttpServer[] = "use-test-http-server";
|
||||||
|
|
||||||
} // namespace switches
|
} // namespace switches
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -45,6 +45,7 @@ extern const char kInitialShowState[];
|
||||||
extern const char kHideChromeStatusBubble[];
|
extern const char kHideChromeStatusBubble[];
|
||||||
extern const char kUseDefaultPopup[];
|
extern const char kUseDefaultPopup[];
|
||||||
extern const char kUseClientDialogs[];
|
extern const char kUseClientDialogs[];
|
||||||
|
extern const char kUseTestHttpServer[];
|
||||||
|
|
||||||
} // namespace switches
|
} // namespace switches
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
Loading…
Reference in New Issue