mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Support asynchronous continuation of custom scheme handler responses (issue #269).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@278 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
4
cef.gyp
4
cef.gyp
@ -340,6 +340,8 @@
|
|||||||
'libcef_dll/cpptoc/request_cpptoc.h',
|
'libcef_dll/cpptoc/request_cpptoc.h',
|
||||||
'libcef_dll/cpptoc/response_cpptoc.cc',
|
'libcef_dll/cpptoc/response_cpptoc.cc',
|
||||||
'libcef_dll/cpptoc/response_cpptoc.h',
|
'libcef_dll/cpptoc/response_cpptoc.h',
|
||||||
|
'libcef_dll/cpptoc/scheme_handler_callback_cpptoc.cc',
|
||||||
|
'libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h',
|
||||||
'libcef_dll/cpptoc/stream_reader_cpptoc.cc',
|
'libcef_dll/cpptoc/stream_reader_cpptoc.cc',
|
||||||
'libcef_dll/cpptoc/stream_reader_cpptoc.h',
|
'libcef_dll/cpptoc/stream_reader_cpptoc.h',
|
||||||
'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
|
'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
|
||||||
@ -538,6 +540,8 @@
|
|||||||
'libcef_dll/ctocpp/request_ctocpp.h',
|
'libcef_dll/ctocpp/request_ctocpp.h',
|
||||||
'libcef_dll/ctocpp/response_ctocpp.cc',
|
'libcef_dll/ctocpp/response_ctocpp.cc',
|
||||||
'libcef_dll/ctocpp/response_ctocpp.h',
|
'libcef_dll/ctocpp/response_ctocpp.h',
|
||||||
|
'libcef_dll/ctocpp/scheme_handler_callback_ctocpp.cc',
|
||||||
|
'libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h',
|
||||||
'libcef_dll/ctocpp/stream_reader_ctocpp.cc',
|
'libcef_dll/ctocpp/stream_reader_ctocpp.cc',
|
||||||
'libcef_dll/ctocpp/stream_reader_ctocpp.h',
|
'libcef_dll/ctocpp/stream_reader_ctocpp.h',
|
||||||
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
|
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
|
||||||
|
@ -2468,9 +2468,35 @@ public:
|
|||||||
CefRefPtr<CefRequest> request) =0;
|
CefRefPtr<CefRequest> request) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
// Class used to facilitate asynchronous responses to custom scheme handler
|
||||||
|
// requests. The methods of this class may be called on any thread.
|
||||||
|
///
|
||||||
|
/*--cef(source=library)--*/
|
||||||
|
class CefSchemeHandlerCallback : public virtual CefBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
// Notify that header information is now available for retrieval.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
virtual void HeadersAvailable() =0;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Class used to represent a custom scheme handler interface. The methods of
|
// Notify that response data is now available for reading.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
virtual void BytesAvailable() =0;
|
||||||
|
|
||||||
|
///
|
||||||
|
// Cancel processing of the request.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
virtual void Cancel() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
// Class used to implement a custom scheme handler interface. The methods of
|
||||||
// this class will always be called on the IO thread.
|
// this class will always be called on the IO thread.
|
||||||
///
|
///
|
||||||
/*--cef(source=client)--*/
|
/*--cef(source=client)--*/
|
||||||
@ -2478,38 +2504,49 @@ class CefSchemeHandler : public virtual CefBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
// Process the request. All response generation should take place in this
|
// Begin processing the request. To handle the request return true and call
|
||||||
// method. If there is no response set |response_length| to zero or return
|
// HeadersAvailable() once the response header information is available
|
||||||
// false and ReadResponse() will not be called. If the response length is not
|
// (HeadersAvailable() can also be called from inside this method if header
|
||||||
// known set |response_length| to -1 and ReadResponse() will be called until
|
// information is available immediately). To redirect the request to a new
|
||||||
// it returns false or until the value of |bytes_read| is set to 0. If the
|
// URL set |redirectUrl| to the new URL and return true. To cancel the request
|
||||||
// response length is known set |response_length| to a positive value and
|
// return false.
|
||||||
// ReadResponse() will be called until it returns false, the value of
|
|
||||||
// |bytes_read| is set to 0 or the specified number of bytes have been read.
|
|
||||||
// Use the |response| object to set the mime type, http status code and
|
|
||||||
// optional header values for the response and return true. To redirect the
|
|
||||||
// request to a new URL set |redirectUrl| to the new URL and return true.
|
|
||||||
///
|
///
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefString& redirectUrl,
|
CefString& redirectUrl,
|
||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefSchemeHandlerCallback> callback) =0;
|
||||||
int* response_length) =0;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
// Cancel processing of the request.
|
// Retrieve response header information. If the response length is not known
|
||||||
|
// set |response_length| to -1 and ReadResponse() will be called until it
|
||||||
|
// returns false. If the response length is known set |response_length|
|
||||||
|
// to a positive value and ReadResponse() will be called until it returns
|
||||||
|
// 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.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||||
|
int64& response_length) =0;
|
||||||
|
|
||||||
|
///
|
||||||
|
// Read response data. If data is available immediately copy up to
|
||||||
|
// |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
|
||||||
|
// bytes copied, and return true. To read the data at a later time set
|
||||||
|
// |bytes_read| to 0, return true and call BytesAvailable() when the data is
|
||||||
|
// available. To indicate response completion return false.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
virtual bool ReadResponse(void* data_out,
|
||||||
|
int bytes_to_read,
|
||||||
|
int& bytes_read,
|
||||||
|
CefRefPtr<CefSchemeHandlerCallback> callback) =0;
|
||||||
|
|
||||||
|
///
|
||||||
|
// Request processing has been canceled.
|
||||||
///
|
///
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
virtual void Cancel() =0;
|
virtual void Cancel() =0;
|
||||||
|
|
||||||
///
|
|
||||||
// Copy up to |bytes_to_read| bytes into |data_out|. If the copy succeeds
|
|
||||||
// set |bytes_read| to the number of bytes copied and return true. If the
|
|
||||||
// copy fails return false and ReadResponse() will not be called again.
|
|
||||||
///
|
|
||||||
/*--cef()--*/
|
|
||||||
virtual bool ReadResponse(void* data_out, int bytes_to_read,
|
|
||||||
int* bytes_read) =0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2270,7 +2270,36 @@ typedef struct _cef_scheme_handler_factory_t
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
// Structure used to represent a custom scheme handler structure. The functions
|
// Structure used to facilitate asynchronous responses to custom scheme handler
|
||||||
|
// requests. The functions of this structure may be called on any thread.
|
||||||
|
///
|
||||||
|
typedef struct _cef_scheme_handler_callback_t
|
||||||
|
{
|
||||||
|
// Base structure.
|
||||||
|
cef_base_t base;
|
||||||
|
|
||||||
|
///
|
||||||
|
// Notify that header information is now available for retrieval.
|
||||||
|
///
|
||||||
|
void (CEF_CALLBACK *headers_available)(
|
||||||
|
struct _cef_scheme_handler_callback_t* self);
|
||||||
|
|
||||||
|
///
|
||||||
|
// Notify that response data is now available for reading.
|
||||||
|
///
|
||||||
|
void (CEF_CALLBACK *bytes_available)(
|
||||||
|
struct _cef_scheme_handler_callback_t* self);
|
||||||
|
|
||||||
|
///
|
||||||
|
// Cancel processing of the request.
|
||||||
|
///
|
||||||
|
void (CEF_CALLBACK *cancel)(struct _cef_scheme_handler_callback_t* self);
|
||||||
|
|
||||||
|
} cef_scheme_handler_callback_t;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
// Structure used to implement a custom scheme handler structure. The functions
|
||||||
// of this structure will always be called on the IO thread.
|
// of this structure will always be called on the IO thread.
|
||||||
///
|
///
|
||||||
typedef struct _cef_scheme_handler_t
|
typedef struct _cef_scheme_handler_t
|
||||||
@ -2279,35 +2308,44 @@ typedef struct _cef_scheme_handler_t
|
|||||||
cef_base_t base;
|
cef_base_t base;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Process the request. All response generation should take place in this
|
// Begin processing the request. To handle the request return true (1) and
|
||||||
// function. If there is no response set |response_length| to zero or return
|
// call headers_available() once the response header information is available
|
||||||
// false (0) and read_response() will not be called. If the response length is
|
// (headers_available() can also be called from inside this function if header
|
||||||
// not known set |response_length| to -1 and read_response() will be called
|
// information is available immediately). To redirect the request to a new URL
|
||||||
// until it returns false (0) or until the value of |bytes_read| is set to 0.
|
// set |redirectUrl| to the new URL and return true (1). To cancel the request
|
||||||
// If the response length is known set |response_length| to a positive value
|
// return false (0).
|
||||||
// and read_response() will be called until it returns false (0), the value of
|
|
||||||
// |bytes_read| is set to 0 or the specified number of bytes have been read.
|
|
||||||
// Use the |response| object to set the mime type, http status code and
|
|
||||||
// optional header values for the response and return true (1). To redirect
|
|
||||||
// the request to a new URL set |redirectUrl| to the new URL and return true
|
|
||||||
// (1).
|
|
||||||
///
|
///
|
||||||
int (CEF_CALLBACK *process_request)(struct _cef_scheme_handler_t* self,
|
int (CEF_CALLBACK *process_request)(struct _cef_scheme_handler_t* self,
|
||||||
struct _cef_request_t* request, cef_string_t* redirectUrl,
|
struct _cef_request_t* request, cef_string_t* redirectUrl,
|
||||||
struct _cef_response_t* response, int* response_length);
|
struct _cef_scheme_handler_callback_t* callback);
|
||||||
|
|
||||||
///
|
///
|
||||||
// Cancel processing of the request.
|
// Retrieve response header information. If the response length is not known
|
||||||
|
// set |response_length| to -1 and read_response() will be called until it
|
||||||
|
// returns false (0). If the response length is known set |response_length| to
|
||||||
|
// a positive value and read_response() will be called until it returns false
|
||||||
|
// (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.
|
||||||
///
|
///
|
||||||
void (CEF_CALLBACK *cancel)(struct _cef_scheme_handler_t* self);
|
void (CEF_CALLBACK *get_response_headers)(struct _cef_scheme_handler_t* self,
|
||||||
|
struct _cef_response_t* response, int64* response_length);
|
||||||
|
|
||||||
///
|
///
|
||||||
// Copy up to |bytes_to_read| bytes into |data_out|. If the copy succeeds set
|
// Read response data. If data is available immediately copy up to
|
||||||
// |bytes_read| to the number of bytes copied and return true (1). If the copy
|
// |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
|
||||||
// fails return false (0) and read_response() will not be called again.
|
// bytes copied, and return true (1). To read the data at a later time set
|
||||||
|
// |bytes_read| to 0, return true (1) and call bytes_available() when the data
|
||||||
|
// is available. To indicate response completion return false (0).
|
||||||
///
|
///
|
||||||
int (CEF_CALLBACK *read_response)(struct _cef_scheme_handler_t* self,
|
int (CEF_CALLBACK *read_response)(struct _cef_scheme_handler_t* self,
|
||||||
void* data_out, int bytes_to_read, int* bytes_read);
|
void* data_out, int bytes_to_read, int* bytes_read,
|
||||||
|
struct _cef_scheme_handler_callback_t* callback);
|
||||||
|
|
||||||
|
///
|
||||||
|
// Request processing has been canceled.
|
||||||
|
///
|
||||||
|
void (CEF_CALLBACK *cancel)(struct _cef_scheme_handler_t* self);
|
||||||
|
|
||||||
} cef_scheme_handler_t;
|
} cef_scheme_handler_t;
|
||||||
|
|
||||||
|
@ -529,7 +529,7 @@ class RequestProxy : public net::URLRequest::Delegate,
|
|||||||
|
|
||||||
request_->Start();
|
request_->Start();
|
||||||
|
|
||||||
if (request_->has_upload() &&
|
if (request_.get() && request_->has_upload() &&
|
||||||
params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
|
params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
|
||||||
upload_progress_timer_.Start(
|
upload_progress_timer_.Start(
|
||||||
base::TimeDelta::FromMilliseconds(
|
base::TimeDelta::FromMilliseconds(
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
using net::URLRequestStatus;
|
||||||
using WebKit::WebSecurityPolicy;
|
using WebKit::WebSecurityPolicy;
|
||||||
using WebKit::WebString;
|
using WebKit::WebString;
|
||||||
|
|
||||||
@ -105,29 +106,52 @@ public:
|
|||||||
CefRefPtr<CefSchemeHandler> handler)
|
CefRefPtr<CefSchemeHandler> handler)
|
||||||
: net::URLRequestJob(request),
|
: net::URLRequestJob(request),
|
||||||
handler_(handler),
|
handler_(handler),
|
||||||
response_length_(0),
|
remaining_bytes_(0)
|
||||||
url_(request->url()),
|
{
|
||||||
remaining_bytes_(0) { }
|
}
|
||||||
|
|
||||||
virtual ~CefUrlRequestJob(){}
|
virtual ~CefUrlRequestJob()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Start() OVERRIDE
|
virtual void Start() OVERRIDE
|
||||||
{
|
{
|
||||||
handler_->Cancel();
|
REQUIRE_IOT();
|
||||||
// Continue asynchronously.
|
|
||||||
DCHECK(!async_resolver_);
|
if (!callback_)
|
||||||
response_ = new CefResponseImpl();
|
callback_ = new Callback(this);
|
||||||
async_resolver_ = new AsyncResolver(this);
|
|
||||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
CefRefPtr<CefRequest> req(CefRequest::CreateRequest());
|
||||||
async_resolver_.get(), &AsyncResolver::Resolve, url_));
|
CefString redirectUrl;
|
||||||
|
|
||||||
|
// Populate the request data.
|
||||||
|
static_cast<CefRequestImpl*>(req.get())->Set(request());
|
||||||
|
|
||||||
|
// Handler can decide whether to process the request.
|
||||||
|
bool rv = handler_->ProcessRequest(req, redirectUrl, callback_.get());
|
||||||
|
if (!rv) {
|
||||||
|
// Cancel the request.
|
||||||
|
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, ERR_ABORTED));
|
||||||
|
} else if (!redirectUrl.empty()) {
|
||||||
|
// Treat the request as a redirect.
|
||||||
|
std::string redirectUrlStr = redirectUrl;
|
||||||
|
redirect_url_ = GURL(redirectUrlStr);
|
||||||
|
NotifyHeadersComplete();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Kill() OVERRIDE
|
virtual void Kill() OVERRIDE
|
||||||
{
|
{
|
||||||
if (async_resolver_) {
|
REQUIRE_IOT();
|
||||||
async_resolver_->Cancel();
|
|
||||||
async_resolver_ = NULL;
|
// Notify the handler that the request has been canceled.
|
||||||
|
handler_->Cancel();
|
||||||
|
|
||||||
|
if (callback_) {
|
||||||
|
callback_->Detach();
|
||||||
|
callback_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
net::URLRequestJob::Kill();
|
net::URLRequestJob::Kill();
|
||||||
@ -136,52 +160,62 @@ public:
|
|||||||
virtual bool ReadRawData(net::IOBuffer* dest, int dest_size, int *bytes_read)
|
virtual bool ReadRawData(net::IOBuffer* dest, int dest_size, int *bytes_read)
|
||||||
OVERRIDE
|
OVERRIDE
|
||||||
{
|
{
|
||||||
|
REQUIRE_IOT();
|
||||||
|
|
||||||
DCHECK_NE(dest_size, 0);
|
DCHECK_NE(dest_size, 0);
|
||||||
DCHECK(bytes_read);
|
DCHECK(bytes_read);
|
||||||
|
|
||||||
// When remaining_bytes_>=0, it means the handler knows the content size
|
if (remaining_bytes_ == 0) {
|
||||||
// before hand. We continue to read until
|
// No more data to read.
|
||||||
if (remaining_bytes_>=0) {
|
*bytes_read = 0;
|
||||||
if (remaining_bytes_ < dest_size)
|
return true;
|
||||||
|
} else if (remaining_bytes_ > 0 && remaining_bytes_ < dest_size) {
|
||||||
|
// The handler knows the content size beforehand.
|
||||||
dest_size = static_cast<int>(remaining_bytes_);
|
dest_size = static_cast<int>(remaining_bytes_);
|
||||||
|
|
||||||
// If we should copy zero bytes because |remaining_bytes_| is zero, short
|
|
||||||
// circuit here.
|
|
||||||
if (!dest_size) {
|
|
||||||
*bytes_read = 0;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remaining_bytes > 0
|
// Read response data from the handler.
|
||||||
bool rv = handler_->ReadResponse(dest->data(), dest_size, bytes_read);
|
bool rv = handler_->ReadResponse(dest->data(), dest_size, *bytes_read,
|
||||||
remaining_bytes_ -= *bytes_read;
|
callback_.get());
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
// handler indicated no further data to read
|
// The handler has indicated completion of the request.
|
||||||
*bytes_read = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// The handler returns -1 for GetResponseLength, this means the handler
|
|
||||||
// doesn't know the content size before hand. We do basically the same
|
|
||||||
// thing, except for checking the return value for handler_->ReadResponse,
|
|
||||||
// which is an indicator for no further data to be read.
|
|
||||||
bool rv = handler_->ReadResponse(dest->data(), dest_size, bytes_read);
|
|
||||||
if (!rv)
|
|
||||||
// handler indicated no further data to read
|
|
||||||
*bytes_read = 0;
|
*bytes_read = 0;
|
||||||
return true;
|
return true;
|
||||||
|
} else if(*bytes_read == 0) {
|
||||||
|
if (!GetStatus().is_io_pending()) {
|
||||||
|
// Report our status as IO pending.
|
||||||
|
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
|
||||||
|
callback_->SetDestination(dest, dest_size);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
} else if(*bytes_read > dest_size) {
|
||||||
|
// Normalize the return value.
|
||||||
|
*bytes_read = dest_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE {
|
if(remaining_bytes_ > 0)
|
||||||
|
remaining_bytes_ -= *bytes_read;
|
||||||
|
|
||||||
|
// Continue calling this method.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE
|
||||||
|
{
|
||||||
|
REQUIRE_IOT();
|
||||||
|
|
||||||
|
if (response_.get()) {
|
||||||
CefResponseImpl* responseImpl =
|
CefResponseImpl* responseImpl =
|
||||||
static_cast<CefResponseImpl*>(response_.get());
|
static_cast<CefResponseImpl*>(response_.get());
|
||||||
info->headers = responseImpl->GetResponseHeaders();
|
info->headers = responseImpl->GetResponseHeaders();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool IsRedirectResponse(GURL* location, int* http_status_code)
|
virtual bool IsRedirectResponse(GURL* location, int* http_status_code)
|
||||||
OVERRIDE
|
OVERRIDE
|
||||||
{
|
{
|
||||||
|
REQUIRE_IOT();
|
||||||
|
|
||||||
if (redirect_url_.is_valid()) {
|
if (redirect_url_.is_valid()) {
|
||||||
// Redirect to the new URL.
|
// Redirect to the new URL.
|
||||||
*http_status_code = 303;
|
*http_status_code = 303;
|
||||||
@ -193,105 +227,132 @@ public:
|
|||||||
|
|
||||||
virtual bool GetMimeType(std::string* mime_type) const OVERRIDE
|
virtual bool GetMimeType(std::string* mime_type) const OVERRIDE
|
||||||
{
|
{
|
||||||
DCHECK(request_);
|
REQUIRE_IOT();
|
||||||
// call handler to get mime type
|
|
||||||
|
if (response_.get())
|
||||||
*mime_type = response_->GetMimeType();
|
*mime_type = response_->GetMimeType();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefSchemeHandler> handler_;
|
CefRefPtr<CefSchemeHandler> handler_;
|
||||||
CefRefPtr<CefResponse> response_;
|
CefRefPtr<CefResponse> response_;
|
||||||
int response_length_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
GURL url_;
|
|
||||||
GURL redirect_url_;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DidResolve(const GURL& url)
|
void SendHeaders()
|
||||||
{
|
{
|
||||||
async_resolver_ = NULL;
|
REQUIRE_IOT();
|
||||||
|
|
||||||
// We may have been orphaned...
|
// We may have been orphaned...
|
||||||
if (!request_)
|
if (!request())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
remaining_bytes_ = response_length_;
|
response_ = new CefResponseImpl();
|
||||||
|
remaining_bytes_ = 0;
|
||||||
|
|
||||||
|
// Get header information from the handler.
|
||||||
|
handler_->GetResponseHeaders(response_, remaining_bytes_);
|
||||||
|
|
||||||
if (remaining_bytes_ > 0)
|
if (remaining_bytes_ > 0)
|
||||||
set_expected_content_size(remaining_bytes_);
|
set_expected_content_size(remaining_bytes_);
|
||||||
|
|
||||||
|
// Continue processing the request.
|
||||||
NotifyHeadersComplete();
|
NotifyHeadersComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 remaining_bytes_;
|
// Client callback for asynchronous response continuation.
|
||||||
std::string m_response;
|
class Callback : public CefSchemeHandlerCallback
|
||||||
|
{
|
||||||
class AsyncResolver :
|
|
||||||
public base::RefCountedThreadSafe<AsyncResolver> {
|
|
||||||
public:
|
public:
|
||||||
explicit AsyncResolver(CefUrlRequestJob* owner)
|
Callback(CefUrlRequestJob* job)
|
||||||
: owner_(owner), owner_loop_(MessageLoop::current()) {
|
: job_(job),
|
||||||
|
dest_(NULL),
|
||||||
|
dest_size_() {}
|
||||||
|
|
||||||
|
virtual void HeadersAvailable() OVERRIDE
|
||||||
|
{
|
||||||
|
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||||
|
// Currently on IO thread.
|
||||||
|
if (job_ && !job_->has_response_started()) {
|
||||||
|
// Send header information.
|
||||||
|
job_->SendHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resolve(const GURL& url) {
|
|
||||||
base::AutoLock locked(lock_);
|
|
||||||
if (!owner_ || !owner_loop_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// safe to perform long operation here
|
|
||||||
CefRefPtr<CefRequest> req(CefRequest::CreateRequest());
|
|
||||||
|
|
||||||
// populate the request data
|
|
||||||
static_cast<CefRequestImpl*>(req.get())->Set(owner_->request());
|
|
||||||
|
|
||||||
owner_->handler_->Cancel();
|
|
||||||
|
|
||||||
int response_length = 0;
|
|
||||||
CefString redirectUrl;
|
|
||||||
|
|
||||||
// handler should complete content generation in ProcessRequest
|
|
||||||
bool res = owner_->handler_->ProcessRequest(req, redirectUrl,
|
|
||||||
owner_->response_, &response_length);
|
|
||||||
if (res) {
|
|
||||||
if (!redirectUrl.empty()) {
|
|
||||||
// Treat the request as a redirect.
|
|
||||||
std::string redirectUrlStr = redirectUrl;
|
|
||||||
owner_->redirect_url_ = GURL(redirectUrlStr);
|
|
||||||
owner_->response_length_ = 0;
|
|
||||||
} else {
|
} else {
|
||||||
owner_->response_length_ = response_length;
|
// Execute this method on the IO thread.
|
||||||
|
CefThread::PostTask(CefThread::IO, FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &Callback::HeadersAvailable));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
virtual void BytesAvailable() OVERRIDE
|
||||||
if (owner_loop_) {
|
{
|
||||||
owner_loop_->PostTask(FROM_HERE, NewRunnableMethod(
|
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||||
this, &AsyncResolver::ReturnResults, url));
|
// Currently on IO thread.
|
||||||
|
if (job_ && job_->has_response_started() &&
|
||||||
|
job_->GetStatus().is_io_pending()) {
|
||||||
|
// Read the bytes. They should be available but, if not, wait again.
|
||||||
|
int bytes_read = 0;
|
||||||
|
if (job_->ReadRawData(dest_, dest_size_, &bytes_read)) {
|
||||||
|
if (bytes_read > 0) {
|
||||||
|
// Clear the IO_PENDING status.
|
||||||
|
job_->SetStatus(URLRequestStatus());
|
||||||
|
|
||||||
|
// Notify about the available bytes.
|
||||||
|
job_->NotifyReadComplete(bytes_read);
|
||||||
|
|
||||||
|
dest_ = NULL;
|
||||||
|
dest_size_ = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// All done.
|
||||||
|
job_->NotifyDone(URLRequestStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Execute this method on the IO thread.
|
||||||
|
CefThread::PostTask(CefThread::IO, FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &Callback::BytesAvailable));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cancel() {
|
virtual void Cancel() OVERRIDE
|
||||||
owner_->handler_->Cancel();
|
{
|
||||||
|
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||||
base::AutoLock locked(lock_);
|
// Currently on IO thread.
|
||||||
owner_ = NULL;
|
if (job_)
|
||||||
owner_loop_ = NULL;
|
job_->Kill();
|
||||||
|
} else {
|
||||||
|
// Execute this method on the IO thread.
|
||||||
|
CefThread::PostTask(CefThread::IO, FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &Callback::Cancel));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Detach()
|
||||||
|
{
|
||||||
|
REQUIRE_IOT();
|
||||||
|
job_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDestination(net::IOBuffer* dest, int dest_size)
|
||||||
|
{
|
||||||
|
dest_ = dest;
|
||||||
|
dest_size_ = dest_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImplementsThreadSafeReferenceCounting() { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReturnResults(const GURL& url) {
|
CefUrlRequestJob* job_;
|
||||||
if (owner_)
|
|
||||||
owner_->DidResolve(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
CefUrlRequestJob* owner_;
|
net::IOBuffer* dest_;
|
||||||
|
int dest_size_;
|
||||||
|
|
||||||
base::Lock lock_;
|
IMPLEMENT_REFCOUNTING(Callback);
|
||||||
MessageLoop* owner_loop_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class AsyncResolver;
|
GURL redirect_url_;
|
||||||
scoped_refptr<AsyncResolver> async_resolver_;
|
int64 remaining_bytes_;
|
||||||
|
CefRefPtr<Callback> callback_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefUrlRequestJob);
|
DISALLOW_COPY_AND_ASSIGN(CefUrlRequestJob);
|
||||||
};
|
};
|
||||||
|
65
libcef_dll/cpptoc/scheme_handler_callback_cpptoc.cc
Normal file
65
libcef_dll/cpptoc/scheme_handler_callback_cpptoc.cc
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// A portion of this file was generated by the CEF translator tool. When
|
||||||
|
// making changes by hand only do so within the body of existing function
|
||||||
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
|
// for more information.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h"
|
||||||
|
|
||||||
|
|
||||||
|
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||||
|
|
||||||
|
void CEF_CALLBACK scheme_handler_callback_headers_available(
|
||||||
|
struct _cef_scheme_handler_callback_t* self)
|
||||||
|
{
|
||||||
|
DCHECK(self);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefSchemeHandlerCallbackCppToC::Get(self)->HeadersAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEF_CALLBACK scheme_handler_callback_bytes_available(
|
||||||
|
struct _cef_scheme_handler_callback_t* self)
|
||||||
|
{
|
||||||
|
DCHECK(self);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefSchemeHandlerCallbackCppToC::Get(self)->BytesAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEF_CALLBACK scheme_handler_callback_cancel(
|
||||||
|
struct _cef_scheme_handler_callback_t* self)
|
||||||
|
{
|
||||||
|
DCHECK(self);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefSchemeHandlerCallbackCppToC::Get(self)->Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// CONSTRUCTOR - Do not edit by hand.
|
||||||
|
|
||||||
|
CefSchemeHandlerCallbackCppToC::CefSchemeHandlerCallbackCppToC(
|
||||||
|
CefSchemeHandlerCallback* cls)
|
||||||
|
: CefCppToC<CefSchemeHandlerCallbackCppToC, CefSchemeHandlerCallback,
|
||||||
|
cef_scheme_handler_callback_t>(cls)
|
||||||
|
{
|
||||||
|
struct_.struct_.headers_available = scheme_handler_callback_headers_available;
|
||||||
|
struct_.struct_.bytes_available = scheme_handler_callback_bytes_available;
|
||||||
|
struct_.struct_.cancel = scheme_handler_callback_cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
template<> long CefCppToC<CefSchemeHandlerCallbackCppToC,
|
||||||
|
CefSchemeHandlerCallback, cef_scheme_handler_callback_t>::DebugObjCt = 0;
|
||||||
|
#endif
|
||||||
|
|
35
libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h
Normal file
35
libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file was generated by the CEF translator tool and should not edited
|
||||||
|
// by hand. See the translator.README.txt file in the tools directory for
|
||||||
|
// more information.
|
||||||
|
//
|
||||||
|
#ifndef _SCHEMEHANDLERCALLBACK_CPPTOC_H
|
||||||
|
#define _SCHEMEHANDLERCALLBACK_CPPTOC_H
|
||||||
|
|
||||||
|
#ifndef BUILDING_CEF_SHARED
|
||||||
|
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
|
||||||
|
#else // BUILDING_CEF_SHARED
|
||||||
|
|
||||||
|
#include "include/cef.h"
|
||||||
|
#include "include/cef_capi.h"
|
||||||
|
#include "libcef_dll/cpptoc/cpptoc.h"
|
||||||
|
|
||||||
|
// Wrap a C++ class with a C structure.
|
||||||
|
// This class may be instantiated and accessed DLL-side only.
|
||||||
|
class CefSchemeHandlerCallbackCppToC
|
||||||
|
: public CefCppToC<CefSchemeHandlerCallbackCppToC, CefSchemeHandlerCallback,
|
||||||
|
cef_scheme_handler_callback_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CefSchemeHandlerCallbackCppToC(CefSchemeHandlerCallback* cls);
|
||||||
|
virtual ~CefSchemeHandlerCallbackCppToC() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BUILDING_CEF_SHARED
|
||||||
|
#endif // _SCHEMEHANDLERCALLBACK_CPPTOC_H
|
||||||
|
|
@ -13,26 +13,54 @@
|
|||||||
#include "libcef_dll/cpptoc/scheme_handler_cpptoc.h"
|
#include "libcef_dll/cpptoc/scheme_handler_cpptoc.h"
|
||||||
#include "libcef_dll/ctocpp/request_ctocpp.h"
|
#include "libcef_dll/ctocpp/request_ctocpp.h"
|
||||||
#include "libcef_dll/ctocpp/response_ctocpp.h"
|
#include "libcef_dll/ctocpp/response_ctocpp.h"
|
||||||
|
#include "libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h"
|
||||||
|
|
||||||
|
|
||||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||||
|
|
||||||
int CEF_CALLBACK scheme_handler_process_request(
|
int CEF_CALLBACK scheme_handler_process_request(
|
||||||
struct _cef_scheme_handler_t* self, cef_request_t* request,
|
struct _cef_scheme_handler_t* self, cef_request_t* request,
|
||||||
cef_string_t* redirectUrl, cef_response_t* response, int* response_length)
|
cef_string_t* redirectUrl, cef_scheme_handler_callback_t* callback)
|
||||||
{
|
{
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
DCHECK(request);
|
DCHECK(request);
|
||||||
DCHECK(redirectUrl);
|
DCHECK(redirectUrl);
|
||||||
DCHECK(response);
|
if(!self || !request || !redirectUrl)
|
||||||
DCHECK(response_length);
|
|
||||||
if(!self || !request || !redirectUrl || !response || !response_length)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CefString redirectUrlStr(redirectUrl);
|
CefString redirectUrlStr(redirectUrl);
|
||||||
return CefSchemeHandlerCppToC::Get(self)->ProcessRequest(
|
return CefSchemeHandlerCppToC::Get(self)->ProcessRequest(
|
||||||
CefRequestCToCpp::Wrap(request), redirectUrlStr,
|
CefRequestCToCpp::Wrap(request), redirectUrlStr,
|
||||||
CefResponseCToCpp::Wrap(response), response_length);
|
CefSchemeHandlerCallbackCToCpp::Wrap(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEF_CALLBACK scheme_handler_get_response_headers(
|
||||||
|
struct _cef_scheme_handler_t* self, cef_response_t* response,
|
||||||
|
int64* response_length)
|
||||||
|
{
|
||||||
|
DCHECK(self);
|
||||||
|
DCHECK(response);
|
||||||
|
DCHECK(response_length);
|
||||||
|
if (!self || !response || !response_length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefSchemeHandlerCppToC::Get(self)->GetResponseHeaders(
|
||||||
|
CefResponseCToCpp::Wrap(response), *response_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CEF_CALLBACK scheme_handler_read_response(
|
||||||
|
struct _cef_scheme_handler_t* self, void* data_out, int bytes_to_read,
|
||||||
|
int* bytes_read, cef_scheme_handler_callback_t* callback)
|
||||||
|
{
|
||||||
|
DCHECK(self);
|
||||||
|
DCHECK(data_out);
|
||||||
|
DCHECK(bytes_read);
|
||||||
|
if(!self || !data_out || !bytes_read)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return CefSchemeHandlerCppToC::Get(self)->ReadResponse(
|
||||||
|
data_out, bytes_to_read, *bytes_read,
|
||||||
|
CefSchemeHandlerCallbackCToCpp::Wrap(callback)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)
|
void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)
|
||||||
@ -44,22 +72,6 @@ void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)
|
|||||||
CefSchemeHandlerCppToC::Get(self)->Cancel();
|
CefSchemeHandlerCppToC::Get(self)->Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CEF_CALLBACK scheme_handler_read_response(
|
|
||||||
struct _cef_scheme_handler_t* self, void* data_out, int bytes_to_read,
|
|
||||||
int* bytes_read)
|
|
||||||
{
|
|
||||||
DCHECK(self);
|
|
||||||
DCHECK(data_out);
|
|
||||||
DCHECK(bytes_read);
|
|
||||||
if(!self || !data_out || !bytes_read)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
bool rv = CefSchemeHandlerCppToC::Get(self)->ReadResponse(
|
|
||||||
data_out, bytes_to_read, bytes_read);
|
|
||||||
|
|
||||||
return rv?1:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// CONSTRUCTOR - Do not edit by hand.
|
// CONSTRUCTOR - Do not edit by hand.
|
||||||
|
|
||||||
@ -68,8 +80,9 @@ CefSchemeHandlerCppToC::CefSchemeHandlerCppToC(CefSchemeHandler* cls)
|
|||||||
cls)
|
cls)
|
||||||
{
|
{
|
||||||
struct_.struct_.process_request = scheme_handler_process_request;
|
struct_.struct_.process_request = scheme_handler_process_request;
|
||||||
struct_.struct_.cancel = scheme_handler_cancel;
|
struct_.struct_.get_response_headers = scheme_handler_get_response_headers;
|
||||||
struct_.struct_.read_response = scheme_handler_read_response;
|
struct_.struct_.read_response = scheme_handler_read_response;
|
||||||
|
struct_.struct_.cancel = scheme_handler_cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
47
libcef_dll/ctocpp/scheme_handler_callback_ctocpp.cc
Normal file
47
libcef_dll/ctocpp/scheme_handler_callback_ctocpp.cc
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// A portion of this file was generated by the CEF translator tool. When
|
||||||
|
// making changes by hand only do so within the body of existing static and
|
||||||
|
// virtual method implementations. See the translator.README.txt file in the
|
||||||
|
// tools directory for more information.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h"
|
||||||
|
|
||||||
|
|
||||||
|
// VIRTUAL METHODS - Body may be edited by hand.
|
||||||
|
|
||||||
|
void CefSchemeHandlerCallbackCToCpp::HeadersAvailable()
|
||||||
|
{
|
||||||
|
if (CEF_MEMBER_MISSING(struct_, headers_available))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct_->headers_available(struct_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefSchemeHandlerCallbackCToCpp::BytesAvailable()
|
||||||
|
{
|
||||||
|
if (CEF_MEMBER_MISSING(struct_, bytes_available))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct_->bytes_available(struct_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefSchemeHandlerCallbackCToCpp::Cancel()
|
||||||
|
{
|
||||||
|
if (CEF_MEMBER_MISSING(struct_, cancel))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct_->cancel(struct_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
template<> long CefCToCpp<CefSchemeHandlerCallbackCToCpp,
|
||||||
|
CefSchemeHandlerCallback, cef_scheme_handler_callback_t>::DebugObjCt = 0;
|
||||||
|
#endif
|
||||||
|
|
43
libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h
Normal file
43
libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
//
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file was generated by the CEF translator tool and should not edited
|
||||||
|
// by hand. See the translator.README.txt file in the tools directory for
|
||||||
|
// more information.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _SCHEMEHANDLERCALLBACK_CTOCPP_H
|
||||||
|
#define _SCHEMEHANDLERCALLBACK_CTOCPP_H
|
||||||
|
|
||||||
|
#ifndef USING_CEF_SHARED
|
||||||
|
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
|
||||||
|
#else // USING_CEF_SHARED
|
||||||
|
|
||||||
|
#include "include/cef.h"
|
||||||
|
#include "include/cef_capi.h"
|
||||||
|
#include "libcef_dll/ctocpp/ctocpp.h"
|
||||||
|
|
||||||
|
// Wrap a C structure with a C++ class.
|
||||||
|
// This class may be instantiated and accessed wrapper-side only.
|
||||||
|
class CefSchemeHandlerCallbackCToCpp
|
||||||
|
: public CefCToCpp<CefSchemeHandlerCallbackCToCpp, CefSchemeHandlerCallback,
|
||||||
|
cef_scheme_handler_callback_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CefSchemeHandlerCallbackCToCpp(cef_scheme_handler_callback_t* str)
|
||||||
|
: CefCToCpp<CefSchemeHandlerCallbackCToCpp, CefSchemeHandlerCallback,
|
||||||
|
cef_scheme_handler_callback_t>(str) {}
|
||||||
|
virtual ~CefSchemeHandlerCallbackCToCpp() {}
|
||||||
|
|
||||||
|
// CefSchemeHandlerCallback methods
|
||||||
|
virtual void HeadersAvailable() OVERRIDE;
|
||||||
|
virtual void BytesAvailable() OVERRIDE;
|
||||||
|
virtual void Cancel() OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USING_CEF_SHARED
|
||||||
|
#endif // _SCHEMEHANDLERCALLBACK_CTOCPP_H
|
||||||
|
|
@ -12,21 +12,41 @@
|
|||||||
|
|
||||||
#include "libcef_dll/cpptoc/request_cpptoc.h"
|
#include "libcef_dll/cpptoc/request_cpptoc.h"
|
||||||
#include "libcef_dll/cpptoc/response_cpptoc.h"
|
#include "libcef_dll/cpptoc/response_cpptoc.h"
|
||||||
|
#include "libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h"
|
||||||
#include "libcef_dll/ctocpp/scheme_handler_ctocpp.h"
|
#include "libcef_dll/ctocpp/scheme_handler_ctocpp.h"
|
||||||
|
|
||||||
|
|
||||||
// VIRTUAL METHODS - Body may be edited by hand.
|
// VIRTUAL METHODS - Body may be edited by hand.
|
||||||
|
|
||||||
bool CefSchemeHandlerCToCpp::ProcessRequest(CefRefPtr<CefRequest> request,
|
bool CefSchemeHandlerCToCpp::ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefString& redirectUrl, CefRefPtr<CefResponse> response,
|
CefString& redirectUrl, CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
int* response_length)
|
|
||||||
{
|
{
|
||||||
if(CEF_MEMBER_MISSING(struct_, process_request))
|
if(CEF_MEMBER_MISSING(struct_, process_request))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return struct_->process_request(struct_, CefRequestCppToC::Wrap(request),
|
return struct_->process_request(struct_, CefRequestCppToC::Wrap(request),
|
||||||
redirectUrl.GetWritableStruct(), CefResponseCppToC::Wrap(response),
|
redirectUrl.GetWritableStruct(),
|
||||||
response_length) ? true : false;
|
CefSchemeHandlerCallbackCppToC::Wrap(callback)) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefSchemeHandlerCToCpp::GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||||
|
int64& response_length)
|
||||||
|
{
|
||||||
|
if (CEF_MEMBER_MISSING(struct_, get_response_headers))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct_->get_response_headers(struct_, CefResponseCppToC::Wrap(response),
|
||||||
|
&response_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefSchemeHandlerCToCpp::ReadResponse(void* data_out, int bytes_to_read,
|
||||||
|
int& bytes_read, CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
|
{
|
||||||
|
if(CEF_MEMBER_MISSING(struct_, read_response))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return struct_->read_response(struct_, data_out, bytes_to_read, &bytes_read,
|
||||||
|
CefSchemeHandlerCallbackCppToC::Wrap(callback)) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefSchemeHandlerCToCpp::Cancel()
|
void CefSchemeHandlerCToCpp::Cancel()
|
||||||
@ -37,16 +57,6 @@ void CefSchemeHandlerCToCpp::Cancel()
|
|||||||
struct_->cancel(struct_);
|
struct_->cancel(struct_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefSchemeHandlerCToCpp::ReadResponse(void* data_out, int bytes_to_read,
|
|
||||||
int* bytes_read)
|
|
||||||
{
|
|
||||||
if(CEF_MEMBER_MISSING(struct_, read_response))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return struct_->read_response(struct_, data_out, bytes_to_read, bytes_read) ?
|
|
||||||
true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
template<> long CefCToCpp<CefSchemeHandlerCToCpp, CefSchemeHandler,
|
template<> long CefCToCpp<CefSchemeHandlerCToCpp, CefSchemeHandler,
|
||||||
|
@ -34,11 +34,13 @@ public:
|
|||||||
|
|
||||||
// CefSchemeHandler methods
|
// CefSchemeHandler methods
|
||||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefString& redirectUrl, CefRefPtr<CefResponse> response,
|
CefString& redirectUrl,
|
||||||
int* response_length) OVERRIDE;
|
CefRefPtr<CefSchemeHandlerCallback> callback) OVERRIDE;
|
||||||
|
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||||
|
int64& response_length) OVERRIDE;
|
||||||
|
virtual bool ReadResponse(void* data_out, int bytes_to_read, int& bytes_read,
|
||||||
|
CefRefPtr<CefSchemeHandlerCallback> callback) OVERRIDE;
|
||||||
virtual void Cancel() OVERRIDE;
|
virtual void Cancel() OVERRIDE;
|
||||||
virtual bool ReadResponse(void* data_out, int bytes_to_read,
|
|
||||||
int* bytes_read) OVERRIDE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BUILDING_CEF_SHARED
|
#endif // BUILDING_CEF_SHARED
|
||||||
|
@ -19,21 +19,10 @@ class ClientSchemeHandler : public CefSchemeHandler
|
|||||||
public:
|
public:
|
||||||
ClientSchemeHandler() : offset_(0) {}
|
ClientSchemeHandler() : offset_(0) {}
|
||||||
|
|
||||||
// Process the request. All response generation should take place in this
|
|
||||||
// method. If there is no response set |response_length| to zero or return
|
|
||||||
// false and ReadResponse() will not be called. If the response length is not
|
|
||||||
// known set |response_length| to -1 and ReadResponse() will be called until
|
|
||||||
// it returns false or until the value of |bytes_read| is set to 0. If the
|
|
||||||
// response length is known set |response_length| to a positive value and
|
|
||||||
// ReadResponse() will be called until it returns false, the value of
|
|
||||||
// |bytes_read| is set to 0 or the specified number of bytes have been read.
|
|
||||||
// Use the |response| object to set the mime type, http status code and
|
|
||||||
// optional header values for the response and return true. To redirect the
|
|
||||||
// request to a new URL set |redirectUrl| to the new URL and return true.
|
|
||||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefString& redirectUrl,
|
CefString& redirectUrl,
|
||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
int* response_length)
|
OVERRIDE
|
||||||
{
|
{
|
||||||
REQUIRE_IO_THREAD();
|
REQUIRE_IO_THREAD();
|
||||||
|
|
||||||
@ -65,8 +54,7 @@ public:
|
|||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
// Set the resulting mime type
|
// Set the resulting mime type
|
||||||
response->SetMimeType("text/html");
|
mime_type_ = "text/html";
|
||||||
response->SetStatus(200);
|
|
||||||
}
|
}
|
||||||
else if(strstr(url.c_str(), "client.png") != NULL) {
|
else if(strstr(url.c_str(), "client.png") != NULL) {
|
||||||
// Load the response image
|
// Load the response image
|
||||||
@ -77,40 +65,55 @@ public:
|
|||||||
data_ = std::string(reinterpret_cast<const char*>(pBytes), dwSize);
|
data_ = std::string(reinterpret_cast<const char*>(pBytes), dwSize);
|
||||||
handled = true;
|
handled = true;
|
||||||
// Set the resulting mime type
|
// Set the resulting mime type
|
||||||
response->SetMimeType("image/jpg");
|
mime_type_ = "image/jpg";
|
||||||
response->SetStatus(200);
|
|
||||||
}
|
}
|
||||||
#elif defined(OS_MACOSX)
|
#elif defined(OS_MACOSX)
|
||||||
if(LoadBinaryResource("logo.png", data_)) {
|
if(LoadBinaryResource("logo.png", data_)) {
|
||||||
handled = true;
|
handled = true;
|
||||||
response->SetMimeType("image/png");
|
// Set the resulting mime type
|
||||||
response->SetStatus(200);
|
mime_type_ = "image/png";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the resulting response length
|
if (handled) {
|
||||||
*response_length = data_.length();
|
// Indicate the headers are available.
|
||||||
|
callback->HeadersAvailable();
|
||||||
return handled;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel processing of the request.
|
return false;
|
||||||
virtual void Cancel()
|
}
|
||||||
|
|
||||||
|
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||||
|
int64& response_length) OVERRIDE
|
||||||
|
{
|
||||||
|
REQUIRE_IO_THREAD();
|
||||||
|
|
||||||
|
ASSERT(!data_.empty());
|
||||||
|
|
||||||
|
response->SetMimeType(mime_type_);
|
||||||
|
response->SetStatus(200);
|
||||||
|
|
||||||
|
// Set the resulting response length
|
||||||
|
response_length = data_.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Cancel() OVERRIDE
|
||||||
{
|
{
|
||||||
REQUIRE_IO_THREAD();
|
REQUIRE_IO_THREAD();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy up to |bytes_to_read| bytes into |data_out|. If the copy succeeds
|
virtual bool ReadResponse(void* data_out,
|
||||||
// set |bytes_read| to the number of bytes copied and return true. If the
|
int bytes_to_read,
|
||||||
// copy fails return false and ReadResponse() will not be called again.
|
int& bytes_read,
|
||||||
virtual bool ReadResponse(void* data_out, int bytes_to_read,
|
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
int* bytes_read)
|
OVERRIDE
|
||||||
{
|
{
|
||||||
REQUIRE_IO_THREAD();
|
REQUIRE_IO_THREAD();
|
||||||
|
|
||||||
bool has_data = false;
|
bool has_data = false;
|
||||||
*bytes_read = 0;
|
bytes_read = 0;
|
||||||
|
|
||||||
AutoLock lock_scope(this);
|
AutoLock lock_scope(this);
|
||||||
|
|
||||||
@ -121,7 +124,7 @@ public:
|
|||||||
memcpy(data_out, data_.c_str() + offset_, transfer_size);
|
memcpy(data_out, data_.c_str() + offset_, transfer_size);
|
||||||
offset_ += transfer_size;
|
offset_ += transfer_size;
|
||||||
|
|
||||||
*bytes_read = transfer_size;
|
bytes_read = transfer_size;
|
||||||
has_data = true;
|
has_data = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +133,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string data_;
|
std::string data_;
|
||||||
|
std::string mime_type_;
|
||||||
size_t offset_;
|
size_t offset_;
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
||||||
|
@ -12,7 +12,8 @@ class TestResults
|
|||||||
public:
|
public:
|
||||||
TestResults()
|
TestResults()
|
||||||
: status_code(0),
|
: status_code(0),
|
||||||
sub_status_code(0)
|
sub_status_code(0),
|
||||||
|
delay(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ public:
|
|||||||
sub_status_code = 0;
|
sub_status_code = 0;
|
||||||
sub_allow_origin.clear();
|
sub_allow_origin.clear();
|
||||||
exit_url.clear();
|
exit_url.clear();
|
||||||
|
delay = 0;
|
||||||
got_request.reset();
|
got_request.reset();
|
||||||
got_read.reset();
|
got_read.reset();
|
||||||
got_output.reset();
|
got_output.reset();
|
||||||
@ -51,6 +53,9 @@ public:
|
|||||||
std::string sub_allow_origin;
|
std::string sub_allow_origin;
|
||||||
std::string exit_url;
|
std::string exit_url;
|
||||||
|
|
||||||
|
// Delay for returning scheme handler results.
|
||||||
|
int delay;
|
||||||
|
|
||||||
TrackCallback
|
TrackCallback
|
||||||
got_request,
|
got_request,
|
||||||
got_read,
|
got_read,
|
||||||
@ -149,21 +154,57 @@ class ClientSchemeHandler : public CefSchemeHandler
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClientSchemeHandler(TestResults* tr)
|
ClientSchemeHandler(TestResults* tr)
|
||||||
: test_results_(tr), offset_(0), is_sub_(false) {}
|
: test_results_(tr), offset_(0), is_sub_(false), has_delayed_(false) {}
|
||||||
|
|
||||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefString& redirectUrl,
|
CefString& redirectUrl,
|
||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
int* response_length)
|
OVERRIDE
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
std::string url = request->GetURL();
|
std::string url = request->GetURL();
|
||||||
is_sub_ = (!test_results_->sub_url.empty() &&
|
is_sub_ = (!test_results_->sub_url.empty() &&
|
||||||
test_results_->sub_url == url);
|
test_results_->sub_url == url);
|
||||||
|
|
||||||
if (is_sub_) {
|
if (is_sub_) {
|
||||||
test_results_->got_sub_request.yes();
|
test_results_->got_sub_request.yes();
|
||||||
|
|
||||||
|
if (!test_results_->sub_html.empty())
|
||||||
|
handled = true;
|
||||||
|
} else {
|
||||||
|
EXPECT_EQ(url, test_results_->url);
|
||||||
|
|
||||||
|
test_results_->got_request.yes();
|
||||||
|
|
||||||
|
if (!test_results_->redirect_url.empty()) {
|
||||||
|
redirectUrl = test_results_->redirect_url;
|
||||||
|
return true; // don't call Continue() for URL redirects.
|
||||||
|
} else if (!test_results_->html.empty()) {
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
if (test_results_->delay > 0) {
|
||||||
|
// Continue after the delay.
|
||||||
|
CefPostDelayedTask(TID_IO, NewCefRunnableMethod(callback.get(),
|
||||||
|
&CefSchemeHandlerCallback::HeadersAvailable), test_results_->delay);
|
||||||
|
} else {
|
||||||
|
// Continue immediately.
|
||||||
|
callback->HeadersAvailable();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||||
|
int64& response_length) OVERRIDE
|
||||||
|
{
|
||||||
|
if (is_sub_) {
|
||||||
response->SetStatus(test_results_->sub_status_code);
|
response->SetStatus(test_results_->sub_status_code);
|
||||||
|
|
||||||
if (!test_results_->sub_allow_origin.empty()) {
|
if (!test_results_->sub_allow_origin.empty()) {
|
||||||
@ -177,38 +218,45 @@ public:
|
|||||||
|
|
||||||
if (!test_results_->sub_html.empty()) {
|
if (!test_results_->sub_html.empty()) {
|
||||||
response->SetMimeType("text/html");
|
response->SetMimeType("text/html");
|
||||||
*response_length = test_results_->sub_html.size();
|
response_length = test_results_->sub_html.size();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EXPECT_EQ(url, test_results_->url);
|
|
||||||
|
|
||||||
test_results_->got_request.yes();
|
|
||||||
|
|
||||||
response->SetStatus(test_results_->status_code);
|
response->SetStatus(test_results_->status_code);
|
||||||
|
|
||||||
if (!test_results_->redirect_url.empty()) {
|
if (!test_results_->html.empty()) {
|
||||||
redirectUrl = test_results_->redirect_url;
|
|
||||||
return true;
|
|
||||||
} else if (!test_results_->html.empty()) {
|
|
||||||
response->SetMimeType("text/html");
|
response->SetMimeType("text/html");
|
||||||
*response_length = test_results_->html.size();
|
response_length = test_results_->html.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Cancel() OVERRIDE
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool ReadResponse(void* data_out,
|
||||||
|
int bytes_to_read,
|
||||||
|
int& bytes_read,
|
||||||
|
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
|
OVERRIDE
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||||
|
|
||||||
|
if (test_results_->delay > 0) {
|
||||||
|
if (!has_delayed_) {
|
||||||
|
// Continue after a delay.
|
||||||
|
CefPostDelayedTask(TID_IO,
|
||||||
|
NewCefRunnableMethod(this,
|
||||||
|
&ClientSchemeHandler::ContinueAfterDelay, callback),
|
||||||
|
test_results_->delay);
|
||||||
|
bytes_read = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
has_delayed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Cancel()
|
|
||||||
{
|
|
||||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool ReadResponse(void* data_out, int bytes_to_read, int* bytes_read)
|
|
||||||
{
|
|
||||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
|
||||||
|
|
||||||
std::string* data;
|
std::string* data;
|
||||||
|
|
||||||
if (is_sub_) {
|
if (is_sub_) {
|
||||||
@ -220,7 +268,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool has_data = false;
|
bool has_data = false;
|
||||||
*bytes_read = 0;
|
bytes_read = 0;
|
||||||
|
|
||||||
AutoLock lock_scope(this);
|
AutoLock lock_scope(this);
|
||||||
|
|
||||||
@ -231,7 +279,7 @@ public:
|
|||||||
memcpy(data_out, data->c_str() + offset_, transfer_size);
|
memcpy(data_out, data->c_str() + offset_, transfer_size);
|
||||||
offset_ += transfer_size;
|
offset_ += transfer_size;
|
||||||
|
|
||||||
*bytes_read = transfer_size;
|
bytes_read = transfer_size;
|
||||||
has_data = true;
|
has_data = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,9 +287,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ContinueAfterDelay(CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||||
|
{
|
||||||
|
has_delayed_ = true;
|
||||||
|
callback->BytesAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
TestResults* test_results_;
|
TestResults* test_results_;
|
||||||
size_t offset_;
|
size_t offset_;
|
||||||
bool is_sub_;
|
bool is_sub_;
|
||||||
|
bool has_delayed_;
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
||||||
IMPLEMENT_LOCKING(ClientSchemeHandler);
|
IMPLEMENT_LOCKING(ClientSchemeHandler);
|
||||||
@ -466,6 +521,27 @@ TEST(SchemeHandlerTest, CustomStandardNormalResponse)
|
|||||||
ClearTestSchemes();
|
ClearTestSchemes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that a custom standard scheme can return normal results with delayed
|
||||||
|
// responses.
|
||||||
|
TEST(SchemeHandlerTest, CustomStandardNormalResponseDelayed)
|
||||||
|
{
|
||||||
|
RegisterTestScheme("customstd", "test");
|
||||||
|
g_TestResults.url = "customstd://test/run.html";
|
||||||
|
g_TestResults.html =
|
||||||
|
"<html><head></head><body><h1>Success!</h1></body></html>";
|
||||||
|
g_TestResults.status_code = 200;
|
||||||
|
g_TestResults.delay = 100;
|
||||||
|
|
||||||
|
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
|
||||||
|
EXPECT_TRUE(g_TestResults.got_request);
|
||||||
|
EXPECT_TRUE(g_TestResults.got_read);
|
||||||
|
EXPECT_TRUE(g_TestResults.got_output);
|
||||||
|
|
||||||
|
ClearTestSchemes();
|
||||||
|
}
|
||||||
|
|
||||||
// Test that a custom nonstandard scheme can return normal results.
|
// Test that a custom nonstandard scheme can return normal results.
|
||||||
TEST(SchemeHandlerTest, CustomNonStandardNormalResponse)
|
TEST(SchemeHandlerTest, CustomNonStandardNormalResponse)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user