#ifndef COMPONENTS_CRONET_NATIVE_TEST_TEST_URL_REQUEST_CALLBACK_H_
#define COMPONENTS_CRONET_NATIVE_TEST_TEST_URL_REQUEST_CALLBACK_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "cronet_c.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
namespace cronet {
namespace test {
class TestUrlRequestCallback {
public:
enum ResponseStep {
NOTHING,
ON_RECEIVED_REDIRECT,
ON_RESPONSE_STARTED,
ON_READ_COMPLETED,
ON_SUCCEEDED,
ON_FAILED,
ON_CANCELED,
};
enum FailureType {
NONE,
CANCEL_SYNC,
CANCEL_ASYNC,
CANCEL_ASYNC_WITHOUT_PAUSE,
};
struct UrlResponseInfo {
explicit UrlResponseInfo(Cronet_UrlResponseInfoPtr response_info);
UrlResponseInfo(const std::vector<std::string>& urls,
const std::string& message,
int32_t status_code,
int64_t received_bytes,
std::vector<std::string> headers);
~UrlResponseInfo();
std::string url;
std::vector<std::string> url_chain;
int32_t http_status_code = 0;
std::string http_status_text;
std::vector<std::pair<std::string, std::string>> all_headers;
bool was_cached = false;
std::string negotiated_protocol;
std::string proxy_server;
int64_t received_byte_count = 0;
};
explicit TestUrlRequestCallback(bool direct_executor);
virtual ~TestUrlRequestCallback();
Cronet_ExecutorPtr GetExecutor();
Cronet_UrlRequestCallbackPtr CreateUrlRequestCallback();
void set_auto_advance(bool auto_advance) { auto_advance_ = auto_advance; }
void set_accumulate_response_data(bool accuumulate) {
accumulate_response_data_ = accuumulate;
}
void set_failure(FailureType failure_type, ResponseStep failure_step) {
failure_step_ = failure_step;
failure_type_ = failure_type;
}
void WaitForDone() { done_.Wait(); }
void WaitForNextStep() {
step_block_.Wait();
step_block_.Reset();
}
void ShutdownExecutor();
bool IsDone() { return done_.IsSignaled(); }
std::vector<std::unique_ptr<UrlResponseInfo>>& redirect_response_info_list() {
return redirect_response_info_list_;
}
std::vector<std::string>& redirect_url_list() { return redirect_url_list_; }
Cronet_UrlResponseInfoPtr original_response_info() const {
return original_response_info_;
}
UrlResponseInfo* response_info() { return response_info_.get(); }
Cronet_ErrorPtr last_error() const { return last_error_; }
Cronet_Error_ERROR_CODE last_error_code() const { return last_error_code_; }
std::string_view last_error_message() const { return last_error_message_; }
ResponseStep response_step() const { return response_step_; }
int redirect_count() const { return redirect_count_; }
bool on_error_called() const { return on_error_called_; }
bool on_canceled_called() const { return on_canceled_called_; }
int response_data_length() const { return response_data_length_; }
std::string_view response_as_string() const { return response_as_string_; }
Cronet_ExecutorPtr GetExecutorRaw() { return executor_; }
void set_executor(Cronet_ExecutorPtr executor) { executor_ = executor; }
void set_response_step(ResponseStep response_step) {
response_step_ = response_step;
}
protected:
virtual void OnSucceeded(Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info);
void StartNextRead(Cronet_UrlRequestPtr request, Cronet_BufferPtr buffer) {
Cronet_UrlRequest_Read(request, buffer);
}
private:
class Executor;
virtual void OnRedirectReceived(Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info,
Cronet_String newLocationUrl);
virtual void OnResponseStarted(Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info);
virtual void OnReadCompleted(Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info,
Cronet_BufferPtr buffer,
uint64_t bytes_read);
virtual void OnFailed(Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info,
Cronet_ErrorPtr error);
virtual void OnCanceled(Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info);
void StartNextRead(Cronet_UrlRequestPtr request) {
Cronet_BufferPtr buffer = Cronet_Buffer_Create();
Cronet_Buffer_InitWithAlloc(buffer, READ_BUFFER_SIZE);
StartNextRead(request, buffer);
}
void SignalDone() { done_.Signal(); }
void CheckExecutorThread();
* Returns false if the callback should continue to advance the
* request.
*/
bool MaybeCancelOrPause(Cronet_UrlRequestPtr request);
static TestUrlRequestCallback* GetThis(Cronet_UrlRequestCallbackPtr self);
static void OnRedirectReceived(Cronet_UrlRequestCallbackPtr self,
Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info,
Cronet_String newLocationUrl);
static void OnResponseStarted(Cronet_UrlRequestCallbackPtr self,
Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info);
static void OnReadCompleted(Cronet_UrlRequestCallbackPtr self,
Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info,
Cronet_BufferPtr buffer,
uint64_t bytesRead);
static void OnSucceeded(Cronet_UrlRequestCallbackPtr self,
Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info);
static void OnFailed(Cronet_UrlRequestCallbackPtr self,
Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info,
Cronet_ErrorPtr error);
static void OnCanceled(Cronet_UrlRequestCallbackPtr self,
Cronet_UrlRequestPtr request,
Cronet_UrlResponseInfoPtr info);
static void Execute(Cronet_ExecutorPtr self, Cronet_RunnablePtr runnable);
static void ExecuteDirect(Cronet_ExecutorPtr self,
Cronet_RunnablePtr runnable);
const int READ_BUFFER_SIZE = 32 * 1024;
bool auto_advance_ = true;
bool accumulate_response_data_ = true;
const bool direct_executor_;
FailureType failure_type_ = NONE;
ResponseStep failure_step_ = NOTHING;
base::WaitableEvent done_;
base::WaitableEvent step_block_;
base::Lock executor_lock_;
Cronet_ExecutorPtr executor_ = nullptr;
std::unique_ptr<base::Thread> executor_thread_;
std::vector<std::unique_ptr<UrlResponseInfo>> redirect_response_info_list_;
std::vector<std::string> redirect_url_list_;
Cronet_UrlResponseInfoPtr original_response_info_ = nullptr;
std::unique_ptr<UrlResponseInfo> response_info_;
Cronet_ErrorPtr last_error_ = nullptr;
Cronet_Error_ERROR_CODE last_error_code_ =
Cronet_Error_ERROR_CODE_ERROR_OTHER;
std::string last_error_message_;
ResponseStep response_step_ = NOTHING;
int redirect_count_ = 0;
bool on_error_called_ = false;
bool on_canceled_called_ = false;
int response_data_length_ = 0;
std::string response_as_string_;
};
}
}
#endif