ceftests: Add shared test_request and test_server implementations
To reduce text execution time and flakyness this change also introduces a global test server that is initialized when needed and torn down after all tests have completed.
This commit is contained in:
parent
d63e5bbd8a
commit
b09cd1a197
|
@ -520,6 +520,11 @@
|
|||
'tests/ceftests/task_unittest.cc',
|
||||
'tests/ceftests/test_handler.cc',
|
||||
'tests/ceftests/test_handler.h',
|
||||
'tests/ceftests/test_request.cc',
|
||||
'tests/ceftests/test_request.h',
|
||||
'tests/ceftests/test_server.cc',
|
||||
'tests/ceftests/test_server.h',
|
||||
'tests/ceftests/test_server_unittest.cc',
|
||||
'tests/ceftests/test_suite.cc',
|
||||
'tests/ceftests/test_suite.h',
|
||||
'tests/ceftests/test_util.cc',
|
||||
|
@ -588,6 +593,10 @@
|
|||
'tests/ceftests/urlrequest_unittest.cc',
|
||||
'tests/ceftests/test_handler.cc',
|
||||
'tests/ceftests/test_handler.h',
|
||||
'tests/ceftests/test_request.cc',
|
||||
'tests/ceftests/test_request.h',
|
||||
'tests/ceftests/test_server.cc',
|
||||
'tests/ceftests/test_server.h',
|
||||
'tests/ceftests/test_suite.cc',
|
||||
'tests/ceftests/test_suite.h',
|
||||
'tests/ceftests/test_util.cc',
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "tests/ceftests/routing_test_handler.h"
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
#include "tests/ceftests/test_server.h"
|
||||
#include "tests/ceftests/test_suite.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
@ -1050,30 +1051,29 @@ namespace {
|
|||
|
||||
const char kCookieAccessScheme[] = "http";
|
||||
const char kCookieAccessDomain[] = "test-cookies.com";
|
||||
const char kCookieAccessServerIP[] = "127.0.0.1";
|
||||
const uint16 kCookieAccessServerPort = 8099;
|
||||
const char* kCookieAccessServerAddress = test_server::kServerAddress;
|
||||
const uint16 kCookieAccessServerPort = test_server::kServerPort;
|
||||
|
||||
std::string GetCookieAccessOrigin(const std::string& scheme,
|
||||
bool server_backend) {
|
||||
std::stringstream ss;
|
||||
if (server_backend) {
|
||||
ss << scheme << "://" << kCookieAccessServerIP << ":"
|
||||
ss << scheme << "://" << kCookieAccessServerAddress << ":"
|
||||
<< kCookieAccessServerPort;
|
||||
} else {
|
||||
ss << scheme << "://" << kCookieAccessDomain;
|
||||
}
|
||||
ss << "/";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GetCookieAccessUrl1(const std::string& scheme,
|
||||
bool server_backend) {
|
||||
return GetCookieAccessOrigin(scheme, server_backend) + "cookie1.html";
|
||||
return GetCookieAccessOrigin(scheme, server_backend) + "/cookie1.html";
|
||||
}
|
||||
|
||||
std::string GetCookieAccessUrl2(const std::string& scheme,
|
||||
bool server_backend) {
|
||||
return GetCookieAccessOrigin(scheme, server_backend) + "cookie2.html";
|
||||
return GetCookieAccessOrigin(scheme, server_backend) + "/cookie2.html";
|
||||
}
|
||||
|
||||
void TestCookieString(const std::string& cookie_str,
|
||||
|
@ -1248,7 +1248,7 @@ class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory,
|
|||
};
|
||||
|
||||
// HTTP server handler.
|
||||
class CookieAccessServerHandler : public CefServerHandler,
|
||||
class CookieAccessServerHandler : public test_server::ObserverHelper,
|
||||
public CookieAccessResponseHandler {
|
||||
public:
|
||||
CookieAccessServerHandler()
|
||||
|
@ -1288,8 +1288,7 @@ class CookieAccessServerHandler : public CefServerHandler,
|
|||
EXPECT_TRUE(complete_callback_.is_null());
|
||||
complete_callback_ = complete_callback;
|
||||
|
||||
CefServer::CreateServer(kCookieAccessServerIP, kCookieAccessServerPort, 10,
|
||||
this);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Results in a call to VerifyResults() and eventual execution of the
|
||||
|
@ -1301,73 +1300,60 @@ class CookieAccessServerHandler : public CefServerHandler,
|
|||
EXPECT_TRUE(complete_callback_.is_null());
|
||||
complete_callback_ = complete_callback;
|
||||
|
||||
EXPECT_TRUE(server_);
|
||||
if (server_)
|
||||
server_->Shutdown();
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void OnServerCreated(CefRefPtr<CefServer> server) override {
|
||||
EXPECT_TRUE(server);
|
||||
EXPECT_TRUE(server->IsRunning());
|
||||
EXPECT_FALSE(server->HasConnection());
|
||||
void OnInitialized(const std::string& server_origin) override {
|
||||
EXPECT_UI_THREAD();
|
||||
EXPECT_STREQ(server_origin.c_str(),
|
||||
GetCookieAccessOrigin(kCookieAccessScheme, true).c_str());
|
||||
|
||||
EXPECT_FALSE(got_server_created_);
|
||||
got_server_created_.yes();
|
||||
|
||||
EXPECT_FALSE(server_);
|
||||
server_ = server;
|
||||
|
||||
EXPECT_FALSE(server_runner_);
|
||||
server_runner_ = server_->GetTaskRunner();
|
||||
EXPECT_TRUE(server_runner_);
|
||||
EXPECT_TRUE(server_runner_->BelongsToCurrentThread());
|
||||
|
||||
CefPostTask(
|
||||
TID_UI,
|
||||
base::Bind(&CookieAccessServerHandler::RunCompleteCallback, this));
|
||||
RunCompleteCallback();
|
||||
}
|
||||
|
||||
void OnServerDestroyed(CefRefPtr<CefServer> server) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_FALSE(server->IsRunning());
|
||||
EXPECT_FALSE(server->HasConnection());
|
||||
void OnShutdown() override {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
EXPECT_FALSE(got_server_destroyed_);
|
||||
got_server_destroyed_.yes();
|
||||
|
||||
server_ = nullptr;
|
||||
|
||||
VerifyResults();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnClientConnected(CefRefPtr<CefServer> server,
|
||||
bool OnClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_TRUE(server->HasConnection());
|
||||
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
EXPECT_TRUE(connection_id_set_.find(connection_id) ==
|
||||
connection_id_set_.end());
|
||||
connection_id_set_.insert(connection_id);
|
||||
|
||||
actual_connection_ct_++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
bool OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
|
||||
EXPECT_TRUE(it != connection_id_set_.end());
|
||||
connection_id_set_.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnHttpRequest(CefRefPtr<CefServer> server,
|
||||
bool OnHttpRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_UI_THREAD();
|
||||
EXPECT_TRUE(VerifyConnection(connection_id));
|
||||
EXPECT_FALSE(client_address.empty());
|
||||
|
||||
|
@ -1378,50 +1364,16 @@ class CookieAccessServerHandler : public CefServerHandler,
|
|||
HandleRequest(server, connection_id, request);
|
||||
|
||||
actual_http_request_ct_++;
|
||||
}
|
||||
|
||||
void OnWebSocketRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OnWebSocketConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OnWebSocketMessage(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const void* data,
|
||||
size_t data_size) override {
|
||||
NOTREACHED();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool RunningOnServerThread() {
|
||||
return server_runner_ && server_runner_->BelongsToCurrentThread();
|
||||
}
|
||||
|
||||
bool VerifyServer(CefRefPtr<CefServer> server) {
|
||||
V_DECLARE();
|
||||
V_EXPECT_TRUE(RunningOnServerThread());
|
||||
V_EXPECT_TRUE(server);
|
||||
V_EXPECT_TRUE(server_);
|
||||
V_EXPECT_TRUE(server->GetAddress().ToString() ==
|
||||
server_->GetAddress().ToString());
|
||||
V_RETURN();
|
||||
}
|
||||
|
||||
bool VerifyConnection(int connection_id) {
|
||||
return connection_id_set_.find(connection_id) != connection_id_set_.end();
|
||||
}
|
||||
|
||||
void VerifyResults() {
|
||||
EXPECT_TRUE(RunningOnServerThread());
|
||||
|
||||
EXPECT_TRUE(got_server_created_);
|
||||
EXPECT_TRUE(got_server_destroyed_);
|
||||
EXPECT_TRUE(connection_id_set_.empty());
|
||||
|
@ -1453,10 +1405,19 @@ class CookieAccessServerHandler : public CefServerHandler,
|
|||
}
|
||||
}
|
||||
|
||||
void SendResponse(CefRefPtr<CefServer> server,
|
||||
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::Bind(CookieAccessServerHandler::SendResponse, server,
|
||||
connection_id, response, response_data)));
|
||||
return;
|
||||
}
|
||||
|
||||
int response_code = response->GetStatus();
|
||||
const CefString& content_type = response->GetMimeType();
|
||||
int64 content_length = static_cast<int64>(response_data.size());
|
||||
|
@ -1489,8 +1450,6 @@ class CookieAccessServerHandler : public CefServerHandler,
|
|||
typedef std::map<std::string, CookieAccessData*> ResponseDataMap;
|
||||
ResponseDataMap data_map_;
|
||||
|
||||
CefRefPtr<CefServer> server_;
|
||||
CefRefPtr<CefTaskRunner> server_runner_;
|
||||
bool initialized_;
|
||||
|
||||
// Only accessed on the UI thread.
|
||||
|
@ -1512,7 +1471,6 @@ class CookieAccessServerHandler : public CefServerHandler,
|
|||
|
||||
std::string request_log_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CookieAccessServerHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(CookieAccessServerHandler);
|
||||
};
|
||||
|
||||
|
@ -1833,7 +1791,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
|
|||
EXPECT_FALSE(server_handler_);
|
||||
|
||||
server_handler_ = new CookieAccessServerHandler();
|
||||
AddResponses(server_handler_.get());
|
||||
AddResponses(server_handler_);
|
||||
server_handler_->CreateServer(complete_callback);
|
||||
}
|
||||
|
||||
|
@ -1911,6 +1869,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
|
|||
void ShutdownServer(const base::Closure& complete_callback) {
|
||||
EXPECT_TRUE(server_handler_);
|
||||
|
||||
// |server_handler_| will delete itself after shutdown.
|
||||
server_handler_->ShutdownServer(complete_callback);
|
||||
server_handler_ = nullptr;
|
||||
}
|
||||
|
@ -1933,7 +1892,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
|
|||
CefRefPtr<CefRequestContext> context_;
|
||||
CefRefPtr<CefCookieManager> cookie_manager_;
|
||||
|
||||
CefRefPtr<CookieAccessServerHandler> server_handler_;
|
||||
CookieAccessServerHandler* server_handler_ = nullptr;
|
||||
CefRefPtr<CookieAccessSchemeHandlerFactory> scheme_factory_;
|
||||
|
||||
CookieAccessData data1_;
|
||||
|
@ -2292,7 +2251,7 @@ class CookieRestartTestHandler : public RoutingTestHandler,
|
|||
EXPECT_FALSE(server_handler_);
|
||||
|
||||
server_handler_ = new CookieAccessServerHandler();
|
||||
AddResponses(server_handler_.get());
|
||||
AddResponses(server_handler_);
|
||||
// 2 requests for each URL.
|
||||
server_handler_->SetExpectedRequestCount(4);
|
||||
server_handler_->CreateServer(complete_callback);
|
||||
|
@ -2351,6 +2310,7 @@ class CookieRestartTestHandler : public RoutingTestHandler,
|
|||
void ShutdownServer(const base::Closure& complete_callback) {
|
||||
EXPECT_TRUE(server_handler_);
|
||||
|
||||
// |server_handler_| will delete itself after shutdown.
|
||||
server_handler_->ShutdownServer(complete_callback);
|
||||
server_handler_ = nullptr;
|
||||
}
|
||||
|
@ -2360,7 +2320,7 @@ class CookieRestartTestHandler : public RoutingTestHandler,
|
|||
CefRefPtr<CefRequestContext> context_;
|
||||
CefRefPtr<CefCookieManager> cookie_manager_;
|
||||
|
||||
CefRefPtr<CookieAccessServerHandler> server_handler_;
|
||||
CookieAccessServerHandler* server_handler_ = nullptr;
|
||||
|
||||
CookieAccessData data1_;
|
||||
CookieAccessData data2_;
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
#include "include/cef_app.h"
|
||||
#include "include/cef_task.h"
|
||||
#include "include/cef_thread.h"
|
||||
#include "include/cef_waitable_event.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
#include "tests/ceftests/test_server.h"
|
||||
#include "tests/ceftests/test_suite.h"
|
||||
#include "tests/shared/browser/client_app_browser.h"
|
||||
#include "tests/shared/browser/main_message_loop_external_pump.h"
|
||||
|
@ -48,6 +50,7 @@
|
|||
namespace {
|
||||
|
||||
void QuitMessageLoop() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
client::MainMessageLoop* message_loop = client::MainMessageLoop::Get();
|
||||
if (message_loop)
|
||||
message_loop->Quit();
|
||||
|
@ -74,8 +77,8 @@ void RunTestsOnTestThread() {
|
|||
while (TestHandler::HasBrowser())
|
||||
sleep(100);
|
||||
|
||||
// Quit the CEF message loop.
|
||||
CefPostTask(TID_UI, base::Bind(&QuitMessageLoop));
|
||||
// Wait for the test server to stop, and then quit the CEF message loop.
|
||||
test_server::Stop(base::Bind(QuitMessageLoop));
|
||||
}
|
||||
|
||||
// Called on the UI thread.
|
||||
|
@ -201,6 +204,12 @@ int main(int argc, char* argv[]) {
|
|||
if (settings.multi_threaded_message_loop) {
|
||||
// Run the test suite on the main thread.
|
||||
retval = test_suite.Run();
|
||||
|
||||
// Wait for the test server to stop.
|
||||
CefRefPtr<CefWaitableEvent> event =
|
||||
CefWaitableEvent::CreateWaitableEvent(true, false);
|
||||
test_server::Stop(base::Bind(&CefWaitableEvent::Signal, event));
|
||||
event->Wait();
|
||||
} else {
|
||||
// Create and start the test thread.
|
||||
CefRefPtr<CefThread> thread = CefThread::CreateThread("test_thread");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
namespace {
|
||||
|
||||
// Must use a different port than test_server.cc.
|
||||
const char kTestServerAddress[] = "127.0.0.1";
|
||||
const uint16 kTestServerPort = 8099;
|
||||
const int kTestTimeout = 5000;
|
||||
|
@ -27,7 +28,7 @@ const int kTestTimeout = 5000;
|
|||
std::string GetTestServerOrigin(bool is_websocket) {
|
||||
std::stringstream ss;
|
||||
ss << (is_websocket ? "ws://" : "http://") << kTestServerAddress << ":"
|
||||
<< kTestServerPort << "/";
|
||||
<< kTestServerPort;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
@ -793,7 +794,7 @@ CefRefPtr<CefRequest> CreateTestServerRequest(
|
|||
const std::string& content_type = std::string(),
|
||||
const CefRequest::HeaderMap& extra_headers = CefRequest::HeaderMap()) {
|
||||
CefRefPtr<CefRequest> request = CefRequest::Create();
|
||||
request->SetURL(GetTestServerOrigin(false) + path);
|
||||
request->SetURL(GetTestServerOrigin(false) + "/" + path);
|
||||
request->SetMethod(method);
|
||||
|
||||
CefRequest::HeaderMap header_map;
|
||||
|
@ -1277,7 +1278,7 @@ class EchoWebSocketRequestHandler : public TestServerHandler::WsRequestHandler {
|
|||
explicit EchoWebSocketRequestHandler(int expected_message_ct)
|
||||
: expected_message_ct_(expected_message_ct), actual_message_ct_(0) {}
|
||||
|
||||
std::string GetWebSocketUrl() { return GetTestServerOrigin(true) + "echo"; }
|
||||
std::string GetWebSocketUrl() { return GetTestServerOrigin(true) + "/echo"; }
|
||||
|
||||
bool HandleRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
// 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_request.h"
|
||||
|
||||
#include "include/cef_urlrequest.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace test_request {
|
||||
|
||||
namespace {
|
||||
|
||||
// Implementation of CefURLRequestClient that stores response information.
|
||||
class RequestClient : public CefURLRequestClient, public State {
|
||||
public:
|
||||
RequestClient(const bool has_credentials,
|
||||
const std::string& username,
|
||||
const std::string& password,
|
||||
const RequestDoneCallback& done_callback)
|
||||
: has_credentials_(has_credentials),
|
||||
username_(username),
|
||||
password_(password),
|
||||
done_callback_(done_callback) {
|
||||
DCHECK(!done_callback_.is_null());
|
||||
}
|
||||
|
||||
void OnUploadProgress(CefRefPtr<CefURLRequest> request,
|
||||
int64 current,
|
||||
int64 total) override {
|
||||
upload_progress_ct_++;
|
||||
upload_total_ = total;
|
||||
}
|
||||
|
||||
void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
|
||||
int64 current,
|
||||
int64 total) override {
|
||||
response_ = request->GetResponse();
|
||||
DCHECK(response_.get());
|
||||
DCHECK(response_->IsReadOnly());
|
||||
download_progress_ct_++;
|
||||
download_total_ = total;
|
||||
}
|
||||
|
||||
void OnDownloadData(CefRefPtr<CefURLRequest> request,
|
||||
const void* data,
|
||||
size_t data_length) override {
|
||||
response_ = request->GetResponse();
|
||||
DCHECK(response_.get());
|
||||
DCHECK(response_->IsReadOnly());
|
||||
download_data_ct_++;
|
||||
download_data_ += std::string(static_cast<const char*>(data), data_length);
|
||||
}
|
||||
|
||||
bool GetAuthCredentials(bool isProxy,
|
||||
const CefString& host,
|
||||
int port,
|
||||
const CefString& realm,
|
||||
const CefString& scheme,
|
||||
CefRefPtr<CefAuthCallback> callback) override {
|
||||
auth_credentials_ct_++;
|
||||
if (has_credentials_) {
|
||||
callback->Continue(username_, password_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
|
||||
request_complete_ct_++;
|
||||
|
||||
request_ = request->GetRequest();
|
||||
DCHECK(request_->IsReadOnly());
|
||||
status_ = request->GetRequestStatus();
|
||||
error_code_ = request->GetRequestError();
|
||||
response_was_cached_ = request->ResponseWasCached();
|
||||
response_ = request->GetResponse();
|
||||
if (response_) {
|
||||
DCHECK(response_->IsReadOnly());
|
||||
}
|
||||
|
||||
done_callback_.Run(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
const bool has_credentials_;
|
||||
const std::string username_;
|
||||
const std::string password_;
|
||||
const RequestDoneCallback done_callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(RequestClient);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void Send(const SendConfig& config, const RequestDoneCallback& callback) {
|
||||
DCHECK(config.request_);
|
||||
CefRefPtr<RequestClient> client = new RequestClient(
|
||||
config.has_credentials_, config.username_, config.password_, callback);
|
||||
if (config.frame_) {
|
||||
config.frame_->CreateURLRequest(config.request_, client.get());
|
||||
} else {
|
||||
CefURLRequest::Create(config.request_, client.get(),
|
||||
config.request_context_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace test_request
|
|
@ -0,0 +1,69 @@
|
|||
// 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_REQUEST_H_
|
||||
#define CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/cef_frame.h"
|
||||
#include "include/cef_request.h"
|
||||
#include "include/cef_request_context.h"
|
||||
#include "include/cef_response.h"
|
||||
|
||||
namespace test_request {
|
||||
|
||||
// Stores all state passed to CefURLRequestClient.
|
||||
struct State {
|
||||
public:
|
||||
// Number of times each callback is executed.
|
||||
int upload_progress_ct_ = 0;
|
||||
int download_progress_ct_ = 0;
|
||||
int download_data_ct_ = 0;
|
||||
int auth_credentials_ct_ = 0;
|
||||
int request_complete_ct_ = 0;
|
||||
|
||||
// From OnUploadProgress.
|
||||
int64 upload_total_ = 0;
|
||||
|
||||
// From OnDownloadProgress.
|
||||
int64 download_total_ = 0;
|
||||
|
||||
// From OnDownloadData.
|
||||
std::string download_data_;
|
||||
|
||||
// From OnRequestComplete.
|
||||
CefRefPtr<CefRequest> request_;
|
||||
cef_urlrequest_status_t status_ = UR_UNKNOWN;
|
||||
cef_errorcode_t error_code_ = ERR_NONE;
|
||||
CefRefPtr<CefResponse> response_;
|
||||
bool response_was_cached_ = false;
|
||||
};
|
||||
|
||||
typedef base::Callback<void(const State& state)> RequestDoneCallback;
|
||||
|
||||
struct SendConfig {
|
||||
// Send using |frame_| or |request_context_| if non-nullptr.
|
||||
// Sends using the global request context if both are nullptr.
|
||||
CefRefPtr<CefFrame> frame_;
|
||||
CefRefPtr<CefRequestContext> request_context_;
|
||||
|
||||
// The request to send.
|
||||
CefRefPtr<CefRequest> request_;
|
||||
|
||||
// Returned via GetAuthCredentials if |has_credentials_| is true.
|
||||
bool has_credentials_ = false;
|
||||
std::string username_;
|
||||
std::string password_;
|
||||
};
|
||||
|
||||
// Send a request. |callback| will be executed on the calling thread after the
|
||||
// request completes.
|
||||
void Send(const SendConfig& config, const RequestDoneCallback& callback);
|
||||
|
||||
} // namespace test_request
|
||||
|
||||
#endif // CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
|
|
@ -0,0 +1,492 @@
|
|||
// 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 <vector>
|
||||
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace test_server {
|
||||
|
||||
// Must use a different port than server_unittest.cc.
|
||||
const char kServerAddress[] = "127.0.0.1";
|
||||
const uint16 kServerPort = 8098;
|
||||
const char kServerScheme[] = "http";
|
||||
const char kServerOrigin[] = "http://127.0.0.1:8098";
|
||||
|
||||
namespace {
|
||||
|
||||
class ServerManager;
|
||||
ServerManager* g_manager = nullptr;
|
||||
|
||||
// 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 {
|
||||
DCHECK(!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 {
|
||||
DCHECK(server->HasConnection());
|
||||
DCHECK(server->IsValidConnection(connection_id));
|
||||
NotifyClientConnected(server, connection_id);
|
||||
}
|
||||
|
||||
void OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
DCHECK(!server->IsValidConnection(connection_id));
|
||||
NotifyClientDisconnected(server, 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 NotifyClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id);
|
||||
static void NotifyClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id);
|
||||
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();
|
||||
DCHECK(!g_manager);
|
||||
g_manager = this;
|
||||
}
|
||||
|
||||
~ServerManager() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(observer_list_.empty());
|
||||
DCHECK(start_callback_list_.empty());
|
||||
DCHECK(stop_callback_.is_null());
|
||||
|
||||
g_manager = nullptr;
|
||||
}
|
||||
|
||||
void Start(const StartDoneCallback& callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!origin_.empty()) {
|
||||
// The server is already running.
|
||||
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(callback);
|
||||
|
||||
// Only create the handler a single time.
|
||||
if (!handler_) {
|
||||
handler_ = new ServerHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void Stop(const DoneCallback& callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!handler_) {
|
||||
// The server is not currently running.
|
||||
callback.Run();
|
||||
return;
|
||||
}
|
||||
|
||||
// Only 1 stop callback supported.
|
||||
DCHECK(stop_callback_.is_null());
|
||||
stop_callback_ = 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;
|
||||
}
|
||||
}
|
||||
DCHECK(found);
|
||||
}
|
||||
|
||||
void NotifyServerCreated(const std::string& server_origin) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
DCHECK(origin_.empty());
|
||||
origin_ = server_origin;
|
||||
|
||||
StartDoneCallbackList::const_iterator it = start_callback_list_.begin();
|
||||
for (; it != start_callback_list_.end(); ++it) {
|
||||
(*it).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();
|
||||
|
||||
DCHECK(!stop_callback_.is_null());
|
||||
stop_callback_.Run();
|
||||
stop_callback_.Reset();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void NotifyClientConnected(CefRefPtr<CefServer> server, int connection_id) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
DCHECK(!observer_list_.empty());
|
||||
|
||||
// Use a copy in case |observer_list_| is modified during iteration.
|
||||
ObserverList list = observer_list_;
|
||||
|
||||
ObserverList::const_iterator it = list.begin();
|
||||
for (; it != list.end(); ++it) {
|
||||
if ((*it)->OnClientConnected(server, connection_id)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
DCHECK(!observer_list_.empty());
|
||||
|
||||
// Use a copy in case |observer_list_| is modified during iteration.
|
||||
ObserverList list = observer_list_;
|
||||
|
||||
ObserverList::const_iterator it = list.begin();
|
||||
for (; it != list.end(); ++it) {
|
||||
if ((*it)->OnClientDisconnected(server, connection_id)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyHttpRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
DCHECK(!observer_list_.empty());
|
||||
|
||||
// Use a copy in case |observer_list_| is modified during iteration.
|
||||
ObserverList list = observer_list_;
|
||||
|
||||
ObserverList::const_iterator it = list.begin();
|
||||
for (; it != list.end(); ++it) {
|
||||
if ((*it)->OnHttpRequest(server, connection_id, client_address,
|
||||
request)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CefRefPtr<ServerHandler> handler_;
|
||||
std::string origin_;
|
||||
|
||||
typedef std::vector<StartDoneCallback> StartDoneCallbackList;
|
||||
StartDoneCallbackList start_callback_list_;
|
||||
|
||||
DoneCallback stop_callback_;
|
||||
|
||||
typedef std::vector<Observer*> ObserverList;
|
||||
ObserverList observer_list_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ServerManager);
|
||||
};
|
||||
|
||||
ServerManager* GetServerManager() {
|
||||
return g_manager;
|
||||
}
|
||||
|
||||
ServerManager* GetOrCreateServerManager() {
|
||||
if (!g_manager) {
|
||||
new ServerManager();
|
||||
DCHECK(g_manager);
|
||||
}
|
||||
return g_manager;
|
||||
}
|
||||
|
||||
// static
|
||||
void ServerHandler::NotifyServerCreated(const std::string& server_origin) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(ServerHandler::NotifyServerCreated, server_origin));
|
||||
return;
|
||||
}
|
||||
|
||||
GetServerManager()->NotifyServerCreated(server_origin);
|
||||
}
|
||||
|
||||
// static
|
||||
void ServerHandler::NotifyServerDestroyed() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(ServerHandler::NotifyServerDestroyed));
|
||||
return;
|
||||
}
|
||||
|
||||
GetServerManager()->NotifyServerDestroyed();
|
||||
}
|
||||
|
||||
// static
|
||||
void ServerHandler::NotifyServerHandlerDeleted() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(ServerHandler::NotifyServerHandlerDeleted));
|
||||
return;
|
||||
}
|
||||
|
||||
GetServerManager()->NotifyServerHandlerDeleted();
|
||||
}
|
||||
|
||||
// static
|
||||
void ServerHandler::NotifyClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(ServerHandler::NotifyClientConnected, server,
|
||||
connection_id));
|
||||
return;
|
||||
}
|
||||
|
||||
GetServerManager()->NotifyClientConnected(server, connection_id);
|
||||
}
|
||||
|
||||
// static
|
||||
void ServerHandler::NotifyClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(ServerHandler::NotifyClientDisconnected,
|
||||
server, connection_id));
|
||||
return;
|
||||
}
|
||||
|
||||
GetServerManager()->NotifyClientDisconnected(server, connection_id);
|
||||
}
|
||||
|
||||
// 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::Bind(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) {
|
||||
DCHECK(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,
|
||||
const DoneCallback& callback) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(InitializeRegistration, registration, callback));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(!g_stopping);
|
||||
|
||||
registration->Initialize();
|
||||
if (!callback.is_null())
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Start(const StartDoneCallback& callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(Start, callback));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(!g_stopping);
|
||||
|
||||
GetOrCreateServerManager()->Start(callback);
|
||||
}
|
||||
|
||||
void Stop(const DoneCallback& callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(Stop, callback));
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop will be called one time on test framework shutdown.
|
||||
DCHECK(!g_stopping);
|
||||
g_stopping = true;
|
||||
|
||||
ServerManager* manager = GetServerManager();
|
||||
if (manager) {
|
||||
manager->Stop(callback);
|
||||
} else {
|
||||
callback.Run();
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration> AddObserver(Observer* observer,
|
||||
const DoneCallback& callback) {
|
||||
DCHECK(observer);
|
||||
CefRefPtr<ObserverRegistration> registration =
|
||||
new ObserverRegistration(observer);
|
||||
InitializeRegistration(registration, callback);
|
||||
return registration.get();
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration> AddObserverAndStart(
|
||||
Observer* observer,
|
||||
const StartDoneCallback& callback) {
|
||||
return AddObserver(observer, base::Bind(Start, callback));
|
||||
}
|
||||
|
||||
// ObserverHelper
|
||||
|
||||
ObserverHelper::ObserverHelper() : weak_ptr_factory_(this) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
}
|
||||
|
||||
ObserverHelper::~ObserverHelper() {
|
||||
DCHECK(state_ == State::NONE);
|
||||
}
|
||||
|
||||
void ObserverHelper::Initialize() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(state_ == State::NONE);
|
||||
state_ = State::INITIALIZING;
|
||||
registration_ = AddObserverAndStart(
|
||||
this,
|
||||
base::Bind(&ObserverHelper::OnStartDone, weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void ObserverHelper::Shutdown() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(state_ == State::INITIALIZED);
|
||||
state_ = State::SHUTTINGDOWN;
|
||||
registration_ = nullptr;
|
||||
}
|
||||
|
||||
void ObserverHelper::OnStartDone(const std::string& server_origin) {
|
||||
DCHECK(state_ == State::INITIALIZING);
|
||||
state_ = State::INITIALIZED;
|
||||
OnInitialized(server_origin);
|
||||
}
|
||||
|
||||
void ObserverHelper::OnRegistered() {
|
||||
DCHECK(state_ == State::INITIALIZING);
|
||||
}
|
||||
|
||||
void ObserverHelper::OnUnregistered() {
|
||||
DCHECK(state_ == State::SHUTTINGDOWN);
|
||||
state_ = State::NONE;
|
||||
OnShutdown();
|
||||
}
|
||||
|
||||
} // namespace test_server
|
|
@ -0,0 +1,119 @@
|
|||
// 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_H_
|
||||
#define CEF_TESTS_CEFTESTS_TEST_SERVER_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/cef_registration.h"
|
||||
#include "include/cef_request.h"
|
||||
#include "include/cef_server.h"
|
||||
|
||||
namespace test_server {
|
||||
|
||||
extern const char kServerAddress[];
|
||||
extern const uint16 kServerPort;
|
||||
extern const char kServerScheme[];
|
||||
extern const char kServerOrigin[];
|
||||
|
||||
typedef base::Closure DoneCallback;
|
||||
|
||||
typedef base::Callback<void(const std::string& server_origin)>
|
||||
StartDoneCallback;
|
||||
|
||||
// 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(const 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(const DoneCallback& callback);
|
||||
|
||||
// Observer for CefServerHandler 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;
|
||||
|
||||
// See CefServerHandler documentation for usage. Return true if the callback
|
||||
// was handled.
|
||||
virtual bool OnClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) {
|
||||
return false;
|
||||
}
|
||||
virtual bool OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) {
|
||||
return false;
|
||||
}
|
||||
virtual bool OnHttpRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Observer() {}
|
||||
};
|
||||
|
||||
// Add an observer for CefServerHandler 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,
|
||||
const DoneCallback& callback);
|
||||
|
||||
// Combination of AddObserver() followed by Start().
|
||||
CefRefPtr<CefRegistration> AddObserverAndStart(
|
||||
Observer* observer,
|
||||
const StartDoneCallback& callback);
|
||||
|
||||
// Helper for managing Observer registration and callbacks. Only used on the UI
|
||||
// thread.
|
||||
class ObserverHelper : 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
|
||||
|
||||
#endif // CEF_TESTS_CEFTESTS_TEST_SERVER_H_
|
|
@ -0,0 +1,257 @@
|
|||
// 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 <sstream>
|
||||
|
||||
#include "include/cef_task.h"
|
||||
#include "include/cef_waitable_event.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/ceftests/test_request.h"
|
||||
#include "tests/ceftests/test_server.h"
|
||||
#include "tests/ceftests/track_callback.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct TestState {
|
||||
TrackCallback got_initialized_;
|
||||
TrackCallback got_connected_;
|
||||
TrackCallback got_request_;
|
||||
TrackCallback got_response_;
|
||||
TrackCallback got_disconnected_;
|
||||
TrackCallback got_shutdown_;
|
||||
|
||||
bool ExpectAll() {
|
||||
EXPECT_TRUE(got_initialized_);
|
||||
EXPECT_TRUE(got_connected_);
|
||||
EXPECT_TRUE(got_request_);
|
||||
EXPECT_TRUE(got_response_);
|
||||
EXPECT_TRUE(got_disconnected_);
|
||||
EXPECT_TRUE(got_shutdown_);
|
||||
return got_initialized_ && got_connected_ && got_request_ &&
|
||||
got_response_ && got_disconnected_ && got_shutdown_;
|
||||
}
|
||||
};
|
||||
|
||||
const char kResponseData[] = "Test data";
|
||||
|
||||
class TestServerObserver : public test_server::ObserverHelper {
|
||||
public:
|
||||
TestServerObserver(TestState* state,
|
||||
const std::string& path,
|
||||
const base::Closure& done_callback)
|
||||
: state_(state),
|
||||
path_(path),
|
||||
done_callback_(done_callback),
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(state);
|
||||
DCHECK(!path.empty());
|
||||
DCHECK(!done_callback_.is_null());
|
||||
Initialize();
|
||||
}
|
||||
|
||||
~TestServerObserver() override { done_callback_.Run(); }
|
||||
|
||||
void OnInitialized(const std::string& server_origin) override {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
EXPECT_FALSE(state_->got_initialized_);
|
||||
EXPECT_FALSE(state_->got_connected_);
|
||||
EXPECT_FALSE(state_->got_request_);
|
||||
EXPECT_FALSE(state_->got_response_);
|
||||
EXPECT_FALSE(state_->got_disconnected_);
|
||||
EXPECT_FALSE(state_->got_shutdown_);
|
||||
|
||||
state_->got_initialized_.yes();
|
||||
|
||||
url_ = server_origin + path_;
|
||||
|
||||
// Send a request to the server.
|
||||
test_request::SendConfig config;
|
||||
config.request_ = CefRequest::Create();
|
||||
config.request_->SetURL(url_);
|
||||
test_request::Send(config,
|
||||
base::Bind(&TestServerObserver::OnRequestResponse,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
bool OnClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) 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();
|
||||
const std::string& url = request->GetURL();
|
||||
if (url != url_)
|
||||
return false;
|
||||
|
||||
EXPECT_TRUE(state_->got_initialized_);
|
||||
EXPECT_TRUE(state_->got_connected_);
|
||||
EXPECT_FALSE(state_->got_request_);
|
||||
EXPECT_FALSE(state_->got_response_);
|
||||
EXPECT_FALSE(state_->got_disconnected_);
|
||||
EXPECT_FALSE(state_->got_shutdown_);
|
||||
|
||||
state_->got_request_.yes();
|
||||
connection_id_ = connection_id;
|
||||
|
||||
server->SendHttp200Response(connection_id, "text/plain", kResponseData,
|
||||
sizeof(kResponseData) - 1);
|
||||
|
||||
// Stop propagating the callback.
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnRequestResponse(const test_request::State& state) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
// Don't test for disconnected, which may race response.
|
||||
EXPECT_TRUE(state_->got_initialized_);
|
||||
EXPECT_TRUE(state_->got_connected_);
|
||||
EXPECT_TRUE(state_->got_request_);
|
||||
EXPECT_FALSE(state_->got_response_);
|
||||
EXPECT_FALSE(state_->got_shutdown_);
|
||||
|
||||
state_->got_response_.yes();
|
||||
|
||||
EXPECT_STREQ(url_.c_str(), state.request_->GetURL().ToString().c_str());
|
||||
EXPECT_EQ(UR_SUCCESS, state.status_);
|
||||
EXPECT_EQ(ERR_NONE, state.error_code_);
|
||||
EXPECT_EQ(200, state.response_->GetStatus());
|
||||
EXPECT_STREQ(kResponseData, state.download_data_.c_str());
|
||||
|
||||
// Trigger shutdown asynchronously.
|
||||
CefPostTask(TID_UI, base::Bind(&TestServerObserver::Shutdown,
|
||||
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 {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
EXPECT_TRUE(state_->got_initialized_);
|
||||
EXPECT_TRUE(state_->got_connected_);
|
||||
EXPECT_TRUE(state_->got_request_);
|
||||
EXPECT_TRUE(state_->got_response_);
|
||||
EXPECT_TRUE(state_->got_disconnected_);
|
||||
EXPECT_FALSE(state_->got_shutdown_);
|
||||
|
||||
state_->got_shutdown_.yes();
|
||||
|
||||
// End the test.
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
TestState* const state_;
|
||||
const std::string path_;
|
||||
const base::Closure done_callback_;
|
||||
|
||||
std::string url_;
|
||||
int connection_id_ = -1;
|
||||
|
||||
base::WeakPtrFactory<TestServerObserver> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TestServerObserver);
|
||||
};
|
||||
|
||||
void CreateObserverOnUIThread(TestState* state,
|
||||
const std::string& path,
|
||||
const base::Closure& done_callback) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(CreateObserverOnUIThread, base::Unretained(state),
|
||||
path, done_callback));
|
||||
return;
|
||||
}
|
||||
|
||||
new TestServerObserver(state, path, done_callback);
|
||||
}
|
||||
|
||||
void SignalIfDone(CefRefPtr<CefWaitableEvent> event,
|
||||
size_t* count,
|
||||
size_t total) {
|
||||
if (++(*count) == total) {
|
||||
event->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(TestServerTest, ObserverHelperSingle) {
|
||||
CefRefPtr<CefWaitableEvent> event =
|
||||
CefWaitableEvent::CreateWaitableEvent(true, false);
|
||||
|
||||
TestState state;
|
||||
CreateObserverOnUIThread(&state, "/TestServerTest.ObserverHelperSingle",
|
||||
base::Bind(&CefWaitableEvent::Signal, event));
|
||||
event->TimedWait(2000);
|
||||
|
||||
EXPECT_TRUE(state.ExpectAll());
|
||||
}
|
||||
|
||||
TEST(TestServerTest, ObserverHelperMultiple) {
|
||||
CefRefPtr<CefWaitableEvent> event =
|
||||
CefWaitableEvent::CreateWaitableEvent(true, false);
|
||||
|
||||
TestState states[3];
|
||||
size_t count = 0;
|
||||
const size_t size = arraysize(states);
|
||||
|
||||
const base::Closure& done_callback =
|
||||
base::Bind(SignalIfDone, event, base::Unretained(&count), size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << "/TestServerTest.ObserverHelperMultiple" << i;
|
||||
CreateObserverOnUIThread(&states[i], ss.str(), done_callback);
|
||||
}
|
||||
|
||||
event->TimedWait(2000);
|
||||
|
||||
EXPECT_EQ(size, count);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
EXPECT_TRUE(states[i].ExpectAll()) << i;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_scoped_temp_dir.h"
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
#include "tests/ceftests/test_request.h"
|
||||
#include "tests/ceftests/test_server.h"
|
||||
#include "tests/ceftests/test_suite.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
@ -45,9 +47,9 @@ const char kRequestSchemeCustom[] = "urcustom";
|
|||
const char kRequestHostCustom[] = "test";
|
||||
|
||||
// Server backend.
|
||||
const char kRequestAddressServer[] = "127.0.0.1";
|
||||
const uint16 kRequestPortServer = 8099;
|
||||
const char kRequestSchemeServer[] = "http";
|
||||
const char* kRequestAddressServer = test_server::kServerAddress;
|
||||
const uint16 kRequestPortServer = test_server::kServerPort;
|
||||
const char* kRequestSchemeServer = test_server::kServerScheme;
|
||||
|
||||
const char kRequestSendCookieName[] = "urcookie_send";
|
||||
const char kRequestSaveCookieName[] = "urcookie_save";
|
||||
|
@ -1205,7 +1207,7 @@ class RequestSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
|||
// SERVER BACKEND
|
||||
|
||||
// HTTP server handler.
|
||||
class RequestServerHandler : public CefServerHandler {
|
||||
class RequestServerHandler : public test_server::ObserverHelper {
|
||||
public:
|
||||
RequestServerHandler()
|
||||
: initialized_(false),
|
||||
|
@ -1244,8 +1246,7 @@ class RequestServerHandler : public CefServerHandler {
|
|||
EXPECT_TRUE(complete_callback_.is_null());
|
||||
complete_callback_ = complete_callback;
|
||||
|
||||
CefServer::CreateServer(kRequestAddressServer, kRequestPortServer, 10,
|
||||
this);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Results in a call to VerifyResults() and eventual execution of the
|
||||
|
@ -1256,73 +1257,59 @@ class RequestServerHandler : public CefServerHandler {
|
|||
EXPECT_TRUE(complete_callback_.is_null());
|
||||
complete_callback_ = complete_callback;
|
||||
|
||||
EXPECT_TRUE(server_);
|
||||
if (server_)
|
||||
server_->Shutdown();
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void OnServerCreated(CefRefPtr<CefServer> server) override {
|
||||
EXPECT_TRUE(server);
|
||||
EXPECT_TRUE(server->IsRunning());
|
||||
EXPECT_FALSE(server->HasConnection());
|
||||
void OnInitialized(const std::string& server_origin) override {
|
||||
EXPECT_UI_THREAD();
|
||||
EXPECT_STREQ(server_origin.c_str(), GetRequestOrigin(true).c_str());
|
||||
EXPECT_FALSE(got_initialized_);
|
||||
got_initialized_.yes();
|
||||
|
||||
EXPECT_FALSE(got_server_created_);
|
||||
got_server_created_.yes();
|
||||
|
||||
EXPECT_FALSE(server_);
|
||||
server_ = server;
|
||||
|
||||
EXPECT_FALSE(server_runner_);
|
||||
server_runner_ = server_->GetTaskRunner();
|
||||
EXPECT_TRUE(server_runner_);
|
||||
EXPECT_TRUE(server_runner_->BelongsToCurrentThread());
|
||||
|
||||
CefPostTask(TID_UI, base::Bind(&RequestServerHandler::RunCompleteCallback,
|
||||
this, true));
|
||||
RunCompleteCallback(true);
|
||||
}
|
||||
|
||||
void OnServerDestroyed(CefRefPtr<CefServer> server) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_FALSE(server->IsRunning());
|
||||
EXPECT_FALSE(server->HasConnection());
|
||||
|
||||
EXPECT_FALSE(got_server_destroyed_);
|
||||
got_server_destroyed_.yes();
|
||||
void OnShutdown() override {
|
||||
EXPECT_UI_THREAD();
|
||||
EXPECT_FALSE(got_shutdown_);
|
||||
got_shutdown_.yes();
|
||||
|
||||
data_map_.SetOwnerTaskRunner(nullptr);
|
||||
server_ = nullptr;
|
||||
|
||||
VerifyResults();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnClientConnected(CefRefPtr<CefServer> server,
|
||||
bool OnClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_TRUE(server->HasConnection());
|
||||
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
EXPECT_TRUE(connection_id_set_.find(connection_id) ==
|
||||
connection_id_set_.end());
|
||||
connection_id_set_.insert(connection_id);
|
||||
|
||||
actual_connection_ct_++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
bool OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
|
||||
EXPECT_TRUE(it != connection_id_set_.end());
|
||||
connection_id_set_.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnHttpRequest(CefRefPtr<CefServer> server,
|
||||
bool OnHttpRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_UI_THREAD();
|
||||
EXPECT_TRUE(VerifyConnection(connection_id));
|
||||
EXPECT_FALSE(client_address.empty());
|
||||
|
||||
|
@ -1333,52 +1320,18 @@ class RequestServerHandler : public CefServerHandler {
|
|||
HandleRequest(server, connection_id, request);
|
||||
|
||||
actual_http_request_ct_++;
|
||||
}
|
||||
|
||||
void OnWebSocketRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OnWebSocketConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OnWebSocketMessage(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const void* data,
|
||||
size_t data_size) override {
|
||||
NOTREACHED();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool RunningOnServerThread() {
|
||||
return server_runner_ && server_runner_->BelongsToCurrentThread();
|
||||
}
|
||||
|
||||
bool VerifyServer(CefRefPtr<CefServer> server) {
|
||||
V_DECLARE();
|
||||
V_EXPECT_TRUE(RunningOnServerThread());
|
||||
V_EXPECT_TRUE(server);
|
||||
V_EXPECT_TRUE(server_);
|
||||
V_EXPECT_TRUE(server->GetAddress().ToString() ==
|
||||
server_->GetAddress().ToString());
|
||||
V_RETURN();
|
||||
}
|
||||
|
||||
bool VerifyConnection(int connection_id) {
|
||||
return connection_id_set_.find(connection_id) != connection_id_set_.end();
|
||||
}
|
||||
|
||||
void VerifyResults() {
|
||||
EXPECT_TRUE(RunningOnServerThread());
|
||||
|
||||
EXPECT_TRUE(got_server_created_);
|
||||
EXPECT_TRUE(got_server_destroyed_);
|
||||
EXPECT_TRUE(got_initialized_);
|
||||
EXPECT_TRUE(got_shutdown_);
|
||||
EXPECT_TRUE(connection_id_set_.empty());
|
||||
EXPECT_EQ(expected_connection_ct_, actual_connection_ct_) << request_log_;
|
||||
EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
|
||||
|
@ -1409,7 +1362,7 @@ class RequestServerHandler : public CefServerHandler {
|
|||
}
|
||||
}
|
||||
|
||||
void HandleAuthRequest(CefRefPtr<CefServer> server,
|
||||
static void HandleAuthRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
CefRefPtr<CefResponse> response = CefResponse::Create();
|
||||
|
@ -1417,7 +1370,7 @@ class RequestServerHandler : public CefServerHandler {
|
|||
SendResponse(server, connection_id, response, std::string());
|
||||
}
|
||||
|
||||
void HandleNormalRequest(CefRefPtr<CefServer> server,
|
||||
static void HandleNormalRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
CefRefPtr<CefRequest> request,
|
||||
RequestRunSettings* settings) {
|
||||
|
@ -1437,7 +1390,7 @@ class RequestServerHandler : public CefServerHandler {
|
|||
SendResponse(server, connection_id, response, response_data);
|
||||
}
|
||||
|
||||
void HandleRedirectRequest(CefRefPtr<CefServer> server,
|
||||
static void HandleRedirectRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefRequest> redirect_request,
|
||||
|
@ -1460,10 +1413,19 @@ class RequestServerHandler : public CefServerHandler {
|
|||
SendResponse(server, connection_id, redirect_response, std::string());
|
||||
}
|
||||
|
||||
void SendResponse(CefRefPtr<CefServer> server,
|
||||
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::Bind(RequestServerHandler::SendResponse, server, connection_id,
|
||||
response, response_data)));
|
||||
return;
|
||||
}
|
||||
|
||||
const int response_code = response->GetStatus();
|
||||
if (response_code <= 0) {
|
||||
// Intentionally not responding for incomplete request tests.
|
||||
|
@ -1498,8 +1460,8 @@ class RequestServerHandler : public CefServerHandler {
|
|||
EXPECT_UI_THREAD();
|
||||
|
||||
if (startup) {
|
||||
// Transfer DataMap ownership to the server thread.
|
||||
data_map_.SetOwnerTaskRunner(server_->GetTaskRunner());
|
||||
// Transfer DataMap ownership to the UI thread.
|
||||
data_map_.SetOwnerTaskRunner(CefTaskRunner::GetForCurrentThread());
|
||||
}
|
||||
|
||||
EXPECT_FALSE(complete_callback_.is_null());
|
||||
|
@ -1509,8 +1471,6 @@ class RequestServerHandler : public CefServerHandler {
|
|||
|
||||
RequestDataMap data_map_;
|
||||
|
||||
CefRefPtr<CefServer> server_;
|
||||
CefRefPtr<CefTaskRunner> server_runner_;
|
||||
bool initialized_;
|
||||
|
||||
// Only accessed on the UI thread.
|
||||
|
@ -1519,8 +1479,8 @@ class RequestServerHandler : public CefServerHandler {
|
|||
// After initialization the below members are only accessed on the server
|
||||
// thread.
|
||||
|
||||
TrackCallback got_server_created_;
|
||||
TrackCallback got_server_destroyed_;
|
||||
TrackCallback got_initialized_;
|
||||
TrackCallback got_shutdown_;
|
||||
|
||||
typedef std::set<int> ConnectionIdSet;
|
||||
ConnectionIdSet connection_id_set_;
|
||||
|
@ -1531,106 +1491,6 @@ class RequestServerHandler : public CefServerHandler {
|
|||
int actual_http_request_ct_;
|
||||
|
||||
std::string request_log_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(RequestServerHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(RequestServerHandler);
|
||||
};
|
||||
|
||||
// URLREQUEST CLIENT
|
||||
|
||||
// Implementation of CefURLRequestClient that stores response information.
|
||||
class RequestClient : public CefURLRequestClient {
|
||||
public:
|
||||
typedef base::Callback<void(CefRefPtr<RequestClient>)>
|
||||
RequestCompleteCallback;
|
||||
|
||||
explicit RequestClient(const RequestCompleteCallback& complete_callback)
|
||||
: complete_callback_(complete_callback) {
|
||||
EXPECT_FALSE(complete_callback_.is_null());
|
||||
}
|
||||
|
||||
void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
|
||||
request_complete_ct_++;
|
||||
|
||||
request_ = request->GetRequest();
|
||||
EXPECT_TRUE(request_->IsReadOnly());
|
||||
status_ = request->GetRequestStatus();
|
||||
error_code_ = request->GetRequestError();
|
||||
response_was_cached_ = request->ResponseWasCached();
|
||||
response_ = request->GetResponse();
|
||||
if (response_) {
|
||||
EXPECT_TRUE(response_->IsReadOnly());
|
||||
}
|
||||
|
||||
complete_callback_.Run(this);
|
||||
}
|
||||
|
||||
void OnUploadProgress(CefRefPtr<CefURLRequest> request,
|
||||
int64 current,
|
||||
int64 total) override {
|
||||
upload_progress_ct_++;
|
||||
upload_total_ = total;
|
||||
}
|
||||
|
||||
void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
|
||||
int64 current,
|
||||
int64 total) override {
|
||||
response_ = request->GetResponse();
|
||||
EXPECT_TRUE(response_.get());
|
||||
EXPECT_TRUE(response_->IsReadOnly());
|
||||
download_progress_ct_++;
|
||||
download_total_ = total;
|
||||
}
|
||||
|
||||
void OnDownloadData(CefRefPtr<CefURLRequest> request,
|
||||
const void* data,
|
||||
size_t data_length) override {
|
||||
response_ = request->GetResponse();
|
||||
EXPECT_TRUE(response_.get());
|
||||
EXPECT_TRUE(response_->IsReadOnly());
|
||||
download_data_ct_++;
|
||||
download_data_ += std::string(static_cast<const char*>(data), data_length);
|
||||
}
|
||||
|
||||
bool GetAuthCredentials(bool isProxy,
|
||||
const CefString& host,
|
||||
int port,
|
||||
const CefString& realm,
|
||||
const CefString& scheme,
|
||||
CefRefPtr<CefAuthCallback> callback) override {
|
||||
auth_credentials_ct_++;
|
||||
if (has_authentication_) {
|
||||
callback->Continue(username_, password_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const RequestCompleteCallback complete_callback_;
|
||||
|
||||
public:
|
||||
bool has_authentication_ = false;
|
||||
std::string username_;
|
||||
std::string password_;
|
||||
|
||||
int request_complete_ct_ = 0;
|
||||
int upload_progress_ct_ = 0;
|
||||
int download_progress_ct_ = 0;
|
||||
int download_data_ct_ = 0;
|
||||
int auth_credentials_ct_ = 0;
|
||||
|
||||
int64 upload_total_ = 0;
|
||||
int64 download_total_ = 0;
|
||||
std::string download_data_;
|
||||
CefRefPtr<CefRequest> request_;
|
||||
CefURLRequest::Status status_ = UR_UNKNOWN;
|
||||
CefURLRequest::ErrorCode error_code_ = ERR_NONE;
|
||||
CefRefPtr<CefResponse> response_;
|
||||
bool response_was_cached_ = false;
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(RequestClient);
|
||||
};
|
||||
|
||||
// SHARED TEST RUNNER
|
||||
|
@ -2501,31 +2361,31 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
|
|||
}
|
||||
|
||||
// Send a request. |complete_callback| will be executed on request completion.
|
||||
void SendRequest(
|
||||
const RequestClient::RequestCompleteCallback& complete_callback) {
|
||||
CefRefPtr<CefRequest> request;
|
||||
if (settings_.redirect_request)
|
||||
request = settings_.redirect_request;
|
||||
else
|
||||
request = settings_.request;
|
||||
EXPECT_TRUE(request.get());
|
||||
void SendRequest(const test_request::RequestDoneCallback& done_callback) {
|
||||
test_request::SendConfig config;
|
||||
|
||||
CefRefPtr<RequestClient> client = new RequestClient(complete_callback);
|
||||
if (settings_.redirect_request)
|
||||
config.request_ = settings_.redirect_request;
|
||||
else
|
||||
config.request_ = settings_.request;
|
||||
EXPECT_TRUE(config.request_.get());
|
||||
|
||||
// Not delegating to CefRequestHandler::GetAuthCredentials.
|
||||
if (!use_frame_method_ && settings_.expect_authentication) {
|
||||
client->has_authentication_ = true;
|
||||
client->username_ = settings_.username;
|
||||
client->password_ = settings_.password;
|
||||
config.has_credentials_ = true;
|
||||
config.username_ = settings_.username;
|
||||
config.password_ = settings_.password;
|
||||
}
|
||||
|
||||
if (use_frame_method_) {
|
||||
EXPECT_TRUE(frame_);
|
||||
frame_->CreateURLRequest(request, client.get());
|
||||
config.frame_ = frame_;
|
||||
} else {
|
||||
CefURLRequest::Create(request, client.get(), request_context_);
|
||||
config.request_context_ = request_context_;
|
||||
}
|
||||
|
||||
test_request::Send(config, done_callback);
|
||||
|
||||
if (settings_.incomplete_type != RequestRunSettings::INCOMPLETE_NONE) {
|
||||
incomplete_request_callback_.Run();
|
||||
incomplete_request_callback_.Reset();
|
||||
|
@ -2533,7 +2393,7 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
|
|||
}
|
||||
|
||||
// Verify a response.
|
||||
void VerifyResponse(CefRefPtr<RequestClient> client) {
|
||||
void VerifyResponse(const test_request::State* const client) {
|
||||
CefRefPtr<CefRequest> expected_request;
|
||||
CefRefPtr<CefResponse> expected_response;
|
||||
|
||||
|
@ -2607,8 +2467,8 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
|
|||
}
|
||||
|
||||
void SingleRunTestComplete(const base::Closure& complete_callback,
|
||||
CefRefPtr<RequestClient> completed_client) {
|
||||
VerifyResponse(completed_client);
|
||||
const test_request::State& completed_client) {
|
||||
VerifyResponse(&completed_client);
|
||||
complete_callback.Run();
|
||||
}
|
||||
|
||||
|
@ -2628,9 +2488,9 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
|
|||
|
||||
void MultipleRunTestNext(const base::Closure& complete_callback,
|
||||
int send_count,
|
||||
CefRefPtr<RequestClient> completed_client) {
|
||||
const test_request::State& completed_client) {
|
||||
// Verify the completed request.
|
||||
VerifyResponse(completed_client);
|
||||
VerifyResponse(&completed_client);
|
||||
|
||||
if (send_count == settings_.expected_send_count) {
|
||||
// All requests complete.
|
||||
|
@ -2757,6 +2617,7 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
|
|||
void ShutdownServer(const base::Closure& complete_callback) {
|
||||
EXPECT_TRUE(server_handler_);
|
||||
|
||||
// |server_handler_| will delete itself after shutdown.
|
||||
server_handler_->ShutdownServer(complete_callback);
|
||||
server_handler_ = nullptr;
|
||||
}
|
||||
|
@ -2797,7 +2658,7 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
|
|||
TestMap test_map_;
|
||||
|
||||
// Server backend.
|
||||
CefRefPtr<RequestServerHandler> server_handler_;
|
||||
RequestServerHandler* server_handler_ = nullptr;
|
||||
|
||||
// Scheme handler backend.
|
||||
std::string scheme_name_;
|
||||
|
|
Loading…
Reference in New Issue