Add error code to CefResponse (issue #1845)

This commit is contained in:
Marshall Greenblatt 2016-05-11 14:20:07 -04:00
parent 543178ce67
commit 958618359c
11 changed files with 156 additions and 3 deletions

View File

@ -78,7 +78,8 @@ typedef struct _cef_resource_handler_t {
// (0) or the specified number of bytes have been read. Use the |response|
// object to set the mime type, http status code and other optional header
// values. To redirect the request to a new URL set |redirectUrl| to the new
// URL.
// URL. If an error occured while setting up the request you can call
// set_error() on |response| to indicate the error condition.
///
void (CEF_CALLBACK *get_response_headers)(
struct _cef_resource_handler_t* self, struct _cef_response_t* response,

View File

@ -60,6 +60,18 @@ typedef struct _cef_response_t {
///
int (CEF_CALLBACK *is_read_only)(struct _cef_response_t* self);
///
// Get the response error code. Returns ERR_NONE if there was no error.
///
cef_errorcode_t (CEF_CALLBACK *get_error)(struct _cef_response_t* self);
///
// Set the response error code. This can be used by custom scheme handlers to
// return errors during initial request processing.
///
void (CEF_CALLBACK *set_error)(struct _cef_response_t* self,
cef_errorcode_t error);
///
// Get the response status code.
///

View File

@ -71,7 +71,8 @@ class CefResourceHandler : public virtual CefBase {
// false or the specified number of bytes have been read. Use the |response|
// object to set the mime type, http status code and other optional header
// values. To redirect the request to a new URL set |redirectUrl| to the new
// URL.
// URL. If an error occured while setting up the request you can call
// SetError() on |response| to indicate the error condition.
///
/*--cef()--*/
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,

View File

@ -62,6 +62,19 @@ class CefResponse : public virtual CefBase {
/*--cef()--*/
virtual bool IsReadOnly() =0;
///
// Get the response error code. Returns ERR_NONE if there was no error.
///
/*--cef(default_retval=ERR_NONE)--*/
virtual cef_errorcode_t GetError() = 0;
///
// Set the response error code. This can be used by custom scheme handlers
// to return errors during initial request processing.
///
/*--cef()--*/
virtual void SetError(cef_errorcode_t error) = 0;
///
// Get the response status code.
///

View File

@ -366,6 +366,17 @@ void CefResourceRequestJob::SendHeaders() {
// Get header information from the handler.
handler_->GetResponseHeaders(response_, remaining_bytes_, redirectUrl);
receive_headers_end_ = base::TimeTicks::Now();
if (response_->GetError() != ERR_NONE) {
const URLRequestStatus& status =
URLRequestStatus::FromError(response_->GetError());
if (status.status() == URLRequestStatus::CANCELED ||
status.status() == URLRequestStatus::FAILED) {
NotifyStartError(status);
return;
}
}
if (!redirectUrl.empty()) {
std::string redirectUrlStr = redirectUrl;
redirect_url_ = GURL(redirectUrlStr);

View File

@ -35,7 +35,8 @@ CefRefPtr<CefResponse> CefResponse::Create() {
// CefResponseImpl ------------------------------------------------------------
CefResponseImpl::CefResponseImpl()
: status_code_(0),
: error_code_(ERR_NONE),
status_code_(0),
read_only_(false) {
}
@ -44,6 +45,17 @@ bool CefResponseImpl::IsReadOnly() {
return read_only_;
}
cef_errorcode_t CefResponseImpl::GetError() {
base::AutoLock lock_scope(lock_);
return error_code_;
}
void CefResponseImpl::SetError(cef_errorcode_t error) {
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
error_code_ = error;
}
int CefResponseImpl::GetStatus() {
base::AutoLock lock_scope(lock_);
return status_code_;

View File

@ -26,6 +26,8 @@ class CefResponseImpl : public CefResponse {
// CefResponse methods.
bool IsReadOnly() override;
cef_errorcode_t GetError() override;
void SetError(cef_errorcode_t error) override;
int GetStatus() override;
void SetStatus(int status) override;
CefString GetStatusText() override;
@ -45,6 +47,7 @@ class CefResponseImpl : public CefResponse {
void SetReadOnly(bool read_only);
protected:
cef_errorcode_t error_code_;
int status_code_;
CefString status_text_;
CefString mime_type_;

View File

@ -45,6 +45,33 @@ int CEF_CALLBACK response_is_read_only(struct _cef_response_t* self) {
return _retval;
}
cef_errorcode_t CEF_CALLBACK response_get_error(struct _cef_response_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return ERR_NONE;
// Execute
cef_errorcode_t _retval = CefResponseCppToC::Get(self)->GetError();
// Return type: simple
return _retval;
}
void CEF_CALLBACK response_set_error(struct _cef_response_t* self,
cef_errorcode_t error) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefResponseCppToC::Get(self)->SetError(
error);
}
int CEF_CALLBACK response_get_status(struct _cef_response_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -209,6 +236,8 @@ void CEF_CALLBACK response_set_header_map(struct _cef_response_t* self,
CefResponseCppToC::CefResponseCppToC() {
GetStruct()->is_read_only = response_is_read_only;
GetStruct()->get_error = response_get_error;
GetStruct()->set_error = response_set_error;
GetStruct()->get_status = response_get_status;
GetStruct()->set_status = response_set_status;
GetStruct()->get_status_text = response_get_status_text;

View File

@ -43,6 +43,32 @@ bool CefResponseCToCpp::IsReadOnly() {
return _retval?true:false;
}
cef_errorcode_t CefResponseCToCpp::GetError() {
cef_response_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_error))
return ERR_NONE;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_errorcode_t _retval = _struct->get_error(_struct);
// Return type: simple
return _retval;
}
void CefResponseCToCpp::SetError(cef_errorcode_t error) {
cef_response_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, set_error))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->set_error(_struct,
error);
}
int CefResponseCToCpp::GetStatus() {
cef_response_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_status))

View File

@ -31,6 +31,8 @@ class CefResponseCToCpp
// CefResponse methods.
bool IsReadOnly() OVERRIDE;
cef_errorcode_t GetError() OVERRIDE;
void SetError(cef_errorcode_t error) OVERRIDE;
int GetStatus() OVERRIDE;
void SetStatus(int status) OVERRIDE;
CefString GetStatusText() OVERRIDE;

View File

@ -26,6 +26,8 @@ class TestResults {
url.clear();
html.clear();
status_code = 0;
response_error_code = ERR_NONE;
expected_error_code = ERR_NONE;
redirect_url.clear();
sub_url.clear();
sub_html.clear();
@ -48,6 +50,11 @@ class TestResults {
std::string html;
int status_code;
// Error code set on the response.
cef_errorcode_t response_error_code;
// Error code expected in OnLoadError.
cef_errorcode_t expected_error_code;
// Used for testing redirects
std::string redirect_url;
@ -165,6 +172,8 @@ class TestSchemeHandler : public TestHandler {
const CefString& errorText,
const CefString& failedUrl) override {
test_results_->got_error.yes();
// Check that the error code matches the expectation.
EXPECT_EQ(errorCode, test_results_->expected_error_code);
DestroyTest();
}
@ -239,6 +248,10 @@ class ClientSchemeHandler : public CefResourceHandler {
callback->Continue();
}
return true;
} else if (test_results_->response_error_code != ERR_NONE) {
// Propagate the error code.
callback->Continue();
return true;
}
// Response was canceled.
@ -268,6 +281,8 @@ class ClientSchemeHandler : public CefResourceHandler {
}
} else if (!test_results_->redirect_url.empty()) {
redirectUrl = test_results_->redirect_url;
} else if (test_results_->response_error_code != ERR_NONE) {
response->SetError(test_results_->response_error_code);
} else {
response->SetStatus(test_results_->status_code);
@ -527,6 +542,7 @@ TEST(SchemeHandlerTest, Registration) {
g_TestResults.got_request.reset();
g_TestResults.got_read.reset();
g_TestResults.got_output.reset();
g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
handler->ExecuteTest();
EXPECT_TRUE(g_TestResults.got_error);
@ -540,10 +556,12 @@ TEST(SchemeHandlerTest, Registration) {
WaitForIOThread();
g_TestResults.got_error.reset();
g_TestResults.expected_error_code = ERR_NONE;
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(g_TestResults.got_error);
EXPECT_TRUE(g_TestResults.got_request);
EXPECT_TRUE(g_TestResults.got_read);
EXPECT_TRUE(g_TestResults.got_output);
@ -629,6 +647,25 @@ TEST(SchemeHandlerTest, CustomStandardErrorResponse) {
ClearTestSchemes();
}
// Test that a custom standard scheme can return a CEF error code in the response.
TEST(SchemeHandlerTest, CustomStandardErrorCodeResponse) {
RegisterTestScheme("customstd", "test");
g_TestResults.url = "customstd://test/run.html";
g_TestResults.response_error_code = ERR_FILE_TOO_BIG;
g_TestResults.expected_error_code = ERR_FILE_TOO_BIG;
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
EXPECT_TRUE(g_TestResults.got_error);
ClearTestSchemes();
}
// Test that a custom nonstandard scheme can return an error code.
TEST(SchemeHandlerTest, CustomNonStandardErrorResponse) {
RegisterTestScheme("customnonstd", std::string());
@ -653,6 +690,7 @@ TEST(SchemeHandlerTest, CustomNonStandardErrorResponse) {
TEST(SchemeHandlerTest, CustomStandardNameNotHandled) {
RegisterTestScheme("customstd", "test");
g_TestResults.url = "customstd2://test/run.html";
g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
@ -661,6 +699,7 @@ TEST(SchemeHandlerTest, CustomStandardNameNotHandled) {
EXPECT_FALSE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
EXPECT_TRUE(g_TestResults.got_error);
ClearTestSchemes();
}
@ -670,6 +709,7 @@ TEST(SchemeHandlerTest, CustomStandardNameNotHandled) {
TEST(SchemeHandlerTest, CustomNonStandardNameNotHandled) {
RegisterTestScheme("customnonstd", std::string());
g_TestResults.url = "customnonstd2:some%20value";
g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
@ -678,6 +718,7 @@ TEST(SchemeHandlerTest, CustomNonStandardNameNotHandled) {
EXPECT_FALSE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
EXPECT_TRUE(g_TestResults.got_error);
ClearTestSchemes();
}
@ -687,6 +728,7 @@ TEST(SchemeHandlerTest, CustomNonStandardNameNotHandled) {
TEST(SchemeHandlerTest, CustomStandardDomainNotHandled) {
RegisterTestScheme("customstd", "test");
g_TestResults.url = "customstd://noexist/run.html";
g_TestResults.expected_error_code = ERR_FAILED;
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
@ -695,6 +737,7 @@ TEST(SchemeHandlerTest, CustomStandardDomainNotHandled) {
EXPECT_FALSE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
EXPECT_TRUE(g_TestResults.got_error);
ClearTestSchemes();
}