mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-23 07:27:42 +01: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:
parent
ad66d3774c
commit
88a46e0b44
4
cef.gyp
4
cef.gyp
@ -340,6 +340,8 @@
|
||||
'libcef_dll/cpptoc/request_cpptoc.h',
|
||||
'libcef_dll/cpptoc/response_cpptoc.cc',
|
||||
'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.h',
|
||||
'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
|
||||
@ -538,6 +540,8 @@
|
||||
'libcef_dll/ctocpp/request_ctocpp.h',
|
||||
'libcef_dll/ctocpp/response_ctocpp.cc',
|
||||
'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.h',
|
||||
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
|
||||
|
@ -2468,9 +2468,35 @@ public:
|
||||
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;
|
||||
|
||||
///
|
||||
// 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 represent a custom scheme handler interface. The methods of
|
||||
// Class used to implement a custom scheme handler interface. The methods of
|
||||
// this class will always be called on the IO thread.
|
||||
///
|
||||
/*--cef(source=client)--*/
|
||||
@ -2478,38 +2504,49 @@ class CefSchemeHandler : public virtual CefBase
|
||||
{
|
||||
public:
|
||||
///
|
||||
// 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.
|
||||
// Begin processing the request. To handle the request return true and call
|
||||
// HeadersAvailable() once the response header information is available
|
||||
// (HeadersAvailable() can also be called from inside this method if header
|
||||
// information is available immediately). To redirect the request to a new
|
||||
// URL set |redirectUrl| to the new URL and return true. To cancel the request
|
||||
// return false.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefString& redirectUrl,
|
||||
CefRefPtr<CefResponse> response,
|
||||
int* response_length) =0;
|
||||
CefRefPtr<CefSchemeHandlerCallback> callback) =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()--*/
|
||||
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.
|
||||
///
|
||||
typedef struct _cef_scheme_handler_t
|
||||
@ -2279,35 +2308,44 @@ typedef struct _cef_scheme_handler_t
|
||||
cef_base_t base;
|
||||
|
||||
///
|
||||
// Process the request. All response generation should take place in this
|
||||
// function. If there is no response set |response_length| to zero or return
|
||||
// false (0) and read_response() will not be called. If the response length is
|
||||
// not known set |response_length| to -1 and read_response() will be called
|
||||
// until it returns false (0) 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 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).
|
||||
// Begin processing the request. To handle the request return true (1) and
|
||||
// call headers_available() once the response header information is available
|
||||
// (headers_available() can also be called from inside this function if header
|
||||
// information is available immediately). To redirect the request to a new URL
|
||||
// set |redirectUrl| to the new URL and return true (1). To cancel the request
|
||||
// return false (0).
|
||||
///
|
||||
int (CEF_CALLBACK *process_request)(struct _cef_scheme_handler_t* self,
|
||||
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
|
||||
// |bytes_read| to the number of bytes copied and return true (1). If the copy
|
||||
// fails return false (0) and read_response() will not be called again.
|
||||
// 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 (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,
|
||||
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;
|
||||
|
||||
|
@ -529,7 +529,7 @@ class RequestProxy : public net::URLRequest::Delegate,
|
||||
|
||||
request_->Start();
|
||||
|
||||
if (request_->has_upload() &&
|
||||
if (request_.get() && request_->has_upload() &&
|
||||
params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
|
||||
upload_progress_timer_.Start(
|
||||
base::TimeDelta::FromMilliseconds(
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
using net::URLRequestStatus;
|
||||
using WebKit::WebSecurityPolicy;
|
||||
using WebKit::WebString;
|
||||
|
||||
@ -104,30 +105,53 @@ public:
|
||||
CefUrlRequestJob(net::URLRequest* request,
|
||||
CefRefPtr<CefSchemeHandler> handler)
|
||||
: net::URLRequestJob(request),
|
||||
handler_(handler),
|
||||
response_length_(0),
|
||||
url_(request->url()),
|
||||
remaining_bytes_(0) { }
|
||||
handler_(handler),
|
||||
remaining_bytes_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CefUrlRequestJob(){}
|
||||
virtual ~CefUrlRequestJob()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Start() OVERRIDE
|
||||
{
|
||||
handler_->Cancel();
|
||||
// Continue asynchronously.
|
||||
DCHECK(!async_resolver_);
|
||||
response_ = new CefResponseImpl();
|
||||
async_resolver_ = new AsyncResolver(this);
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
async_resolver_.get(), &AsyncResolver::Resolve, url_));
|
||||
REQUIRE_IOT();
|
||||
|
||||
if (!callback_)
|
||||
callback_ = new Callback(this);
|
||||
|
||||
CefRefPtr<CefRequest> req(CefRequest::CreateRequest());
|
||||
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;
|
||||
}
|
||||
|
||||
virtual void Kill() OVERRIDE
|
||||
{
|
||||
if (async_resolver_) {
|
||||
async_resolver_->Cancel();
|
||||
async_resolver_ = NULL;
|
||||
REQUIRE_IOT();
|
||||
|
||||
// Notify the handler that the request has been canceled.
|
||||
handler_->Cancel();
|
||||
|
||||
if (callback_) {
|
||||
callback_->Detach();
|
||||
callback_ = NULL;
|
||||
}
|
||||
|
||||
net::URLRequestJob::Kill();
|
||||
@ -136,52 +160,62 @@ public:
|
||||
virtual bool ReadRawData(net::IOBuffer* dest, int dest_size, int *bytes_read)
|
||||
OVERRIDE
|
||||
{
|
||||
REQUIRE_IOT();
|
||||
|
||||
DCHECK_NE(dest_size, 0);
|
||||
DCHECK(bytes_read);
|
||||
|
||||
// When remaining_bytes_>=0, it means the handler knows the content size
|
||||
// before hand. We continue to read until
|
||||
if (remaining_bytes_>=0) {
|
||||
if (remaining_bytes_ < dest_size)
|
||||
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
|
||||
bool rv = handler_->ReadResponse(dest->data(), dest_size, bytes_read);
|
||||
remaining_bytes_ -= *bytes_read;
|
||||
if (!rv) {
|
||||
// handler indicated no further data to read
|
||||
*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;
|
||||
if (remaining_bytes_ == 0) {
|
||||
// No more data to read.
|
||||
*bytes_read = 0;
|
||||
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_);
|
||||
}
|
||||
|
||||
// Read response data from the handler.
|
||||
bool rv = handler_->ReadResponse(dest->data(), dest_size, *bytes_read,
|
||||
callback_.get());
|
||||
if (!rv) {
|
||||
// The handler has indicated completion of the request.
|
||||
*bytes_read = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
if(remaining_bytes_ > 0)
|
||||
remaining_bytes_ -= *bytes_read;
|
||||
|
||||
// Continue calling this method.
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE {
|
||||
CefResponseImpl* responseImpl =
|
||||
static_cast<CefResponseImpl*>(response_.get());
|
||||
info->headers = responseImpl->GetResponseHeaders();
|
||||
virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE
|
||||
{
|
||||
REQUIRE_IOT();
|
||||
|
||||
if (response_.get()) {
|
||||
CefResponseImpl* responseImpl =
|
||||
static_cast<CefResponseImpl*>(response_.get());
|
||||
info->headers = responseImpl->GetResponseHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool IsRedirectResponse(GURL* location, int* http_status_code)
|
||||
OVERRIDE
|
||||
{
|
||||
REQUIRE_IOT();
|
||||
|
||||
if (redirect_url_.is_valid()) {
|
||||
// Redirect to the new URL.
|
||||
*http_status_code = 303;
|
||||
@ -193,105 +227,132 @@ public:
|
||||
|
||||
virtual bool GetMimeType(std::string* mime_type) const OVERRIDE
|
||||
{
|
||||
DCHECK(request_);
|
||||
// call handler to get mime type
|
||||
*mime_type = response_->GetMimeType();
|
||||
REQUIRE_IOT();
|
||||
|
||||
if (response_.get())
|
||||
*mime_type = response_->GetMimeType();
|
||||
return true;
|
||||
}
|
||||
|
||||
CefRefPtr<CefSchemeHandler> handler_;
|
||||
CefRefPtr<CefResponse> response_;
|
||||
int response_length_;
|
||||
|
||||
protected:
|
||||
GURL url_;
|
||||
GURL redirect_url_;
|
||||
|
||||
private:
|
||||
void DidResolve(const GURL& url)
|
||||
void SendHeaders()
|
||||
{
|
||||
async_resolver_ = NULL;
|
||||
REQUIRE_IOT();
|
||||
|
||||
// We may have been orphaned...
|
||||
if (!request_)
|
||||
if (!request())
|
||||
return;
|
||||
|
||||
remaining_bytes_ = response_length_;
|
||||
if (remaining_bytes_>0)
|
||||
response_ = new CefResponseImpl();
|
||||
remaining_bytes_ = 0;
|
||||
|
||||
// Get header information from the handler.
|
||||
handler_->GetResponseHeaders(response_, remaining_bytes_);
|
||||
|
||||
if (remaining_bytes_ > 0)
|
||||
set_expected_content_size(remaining_bytes_);
|
||||
|
||||
// Continue processing the request.
|
||||
NotifyHeadersComplete();
|
||||
}
|
||||
|
||||
int64 remaining_bytes_;
|
||||
std::string m_response;
|
||||
|
||||
class AsyncResolver :
|
||||
public base::RefCountedThreadSafe<AsyncResolver> {
|
||||
// Client callback for asynchronous response continuation.
|
||||
class Callback : public CefSchemeHandlerCallback
|
||||
{
|
||||
public:
|
||||
explicit AsyncResolver(CefUrlRequestJob* owner)
|
||||
: owner_(owner), owner_loop_(MessageLoop::current()) {
|
||||
}
|
||||
Callback(CefUrlRequestJob* job)
|
||||
: job_(job),
|
||||
dest_(NULL),
|
||||
dest_size_() {}
|
||||
|
||||
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 {
|
||||
owner_->response_length_ = response_length;
|
||||
virtual void HeadersAvailable() OVERRIDE
|
||||
{
|
||||
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||
// Currently on IO thread.
|
||||
if (job_ && !job_->has_response_started()) {
|
||||
// Send header information.
|
||||
job_->SendHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (owner_loop_) {
|
||||
owner_loop_->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
this, &AsyncResolver::ReturnResults, url));
|
||||
} else {
|
||||
// Execute this method on the IO thread.
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE,
|
||||
NewRunnableMethod(this, &Callback::HeadersAvailable));
|
||||
}
|
||||
}
|
||||
|
||||
void Cancel() {
|
||||
owner_->handler_->Cancel();
|
||||
virtual void BytesAvailable() OVERRIDE
|
||||
{
|
||||
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||
// 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());
|
||||
|
||||
base::AutoLock locked(lock_);
|
||||
owner_ = NULL;
|
||||
owner_loop_ = NULL;
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Cancel() OVERRIDE
|
||||
{
|
||||
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||
// Currently on IO thread.
|
||||
if (job_)
|
||||
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:
|
||||
void ReturnResults(const GURL& url) {
|
||||
if (owner_)
|
||||
owner_->DidResolve(url);
|
||||
}
|
||||
CefUrlRequestJob* job_;
|
||||
|
||||
CefUrlRequestJob* owner_;
|
||||
net::IOBuffer* dest_;
|
||||
int dest_size_;
|
||||
|
||||
base::Lock lock_;
|
||||
MessageLoop* owner_loop_;
|
||||
IMPLEMENT_REFCOUNTING(Callback);
|
||||
};
|
||||
|
||||
friend class AsyncResolver;
|
||||
scoped_refptr<AsyncResolver> async_resolver_;
|
||||
GURL redirect_url_;
|
||||
int64 remaining_bytes_;
|
||||
CefRefPtr<Callback> callback_;
|
||||
|
||||
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/ctocpp/request_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.
|
||||
|
||||
int CEF_CALLBACK scheme_handler_process_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(request);
|
||||
DCHECK(redirectUrl);
|
||||
DCHECK(response);
|
||||
DCHECK(response_length);
|
||||
if(!self || !request || !redirectUrl || !response || !response_length)
|
||||
if(!self || !request || !redirectUrl)
|
||||
return 0;
|
||||
|
||||
CefString redirectUrlStr(redirectUrl);
|
||||
return CefSchemeHandlerCppToC::Get(self)->ProcessRequest(
|
||||
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)
|
||||
@ -44,22 +72,6 @@ void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)
|
||||
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.
|
||||
|
||||
@ -68,8 +80,9 @@ CefSchemeHandlerCppToC::CefSchemeHandlerCppToC(CefSchemeHandler* cls)
|
||||
cls)
|
||||
{
|
||||
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_.cancel = scheme_handler_cancel;
|
||||
}
|
||||
|
||||
#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/response_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h"
|
||||
#include "libcef_dll/ctocpp/scheme_handler_ctocpp.h"
|
||||
|
||||
|
||||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
bool CefSchemeHandlerCToCpp::ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefString& redirectUrl, CefRefPtr<CefResponse> response,
|
||||
int* response_length)
|
||||
CefString& redirectUrl, CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||
{
|
||||
if(CEF_MEMBER_MISSING(struct_, process_request))
|
||||
return false;
|
||||
|
||||
return struct_->process_request(struct_, CefRequestCppToC::Wrap(request),
|
||||
redirectUrl.GetWritableStruct(), CefResponseCppToC::Wrap(response),
|
||||
response_length) ? true : false;
|
||||
redirectUrl.GetWritableStruct(),
|
||||
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()
|
||||
@ -37,16 +57,6 @@ void CefSchemeHandlerCToCpp::Cancel()
|
||||
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
|
||||
template<> long CefCToCpp<CefSchemeHandlerCToCpp, CefSchemeHandler,
|
||||
|
@ -34,11 +34,13 @@ public:
|
||||
|
||||
// CefSchemeHandler methods
|
||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefString& redirectUrl, CefRefPtr<CefResponse> response,
|
||||
int* response_length) OVERRIDE;
|
||||
CefString& redirectUrl,
|
||||
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 bool ReadResponse(void* data_out, int bytes_to_read,
|
||||
int* bytes_read) OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // BUILDING_CEF_SHARED
|
||||
|
@ -19,21 +19,10 @@ class ClientSchemeHandler : public CefSchemeHandler
|
||||
public:
|
||||
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,
|
||||
CefString& redirectUrl,
|
||||
CefRefPtr<CefResponse> response,
|
||||
int* response_length)
|
||||
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||
OVERRIDE
|
||||
{
|
||||
REQUIRE_IO_THREAD();
|
||||
|
||||
@ -65,8 +54,7 @@ public:
|
||||
handled = true;
|
||||
|
||||
// Set the resulting mime type
|
||||
response->SetMimeType("text/html");
|
||||
response->SetStatus(200);
|
||||
mime_type_ = "text/html";
|
||||
}
|
||||
else if(strstr(url.c_str(), "client.png") != NULL) {
|
||||
// Load the response image
|
||||
@ -77,40 +65,55 @@ public:
|
||||
data_ = std::string(reinterpret_cast<const char*>(pBytes), dwSize);
|
||||
handled = true;
|
||||
// Set the resulting mime type
|
||||
response->SetMimeType("image/jpg");
|
||||
response->SetStatus(200);
|
||||
mime_type_ = "image/jpg";
|
||||
}
|
||||
#elif defined(OS_MACOSX)
|
||||
if(LoadBinaryResource("logo.png", data_)) {
|
||||
handled = true;
|
||||
response->SetMimeType("image/png");
|
||||
response->SetStatus(200);
|
||||
// Set the resulting mime type
|
||||
mime_type_ = "image/png";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set the resulting response length
|
||||
*response_length = data_.length();
|
||||
if (handled) {
|
||||
// Indicate the headers are available.
|
||||
callback->HeadersAvailable();
|
||||
return true;
|
||||
}
|
||||
|
||||
return handled;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cancel processing of the request.
|
||||
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();
|
||||
}
|
||||
|
||||
// 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.
|
||||
virtual bool ReadResponse(void* data_out, int bytes_to_read,
|
||||
int* bytes_read)
|
||||
virtual bool ReadResponse(void* data_out,
|
||||
int bytes_to_read,
|
||||
int& bytes_read,
|
||||
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||
OVERRIDE
|
||||
{
|
||||
REQUIRE_IO_THREAD();
|
||||
|
||||
bool has_data = false;
|
||||
*bytes_read = 0;
|
||||
bytes_read = 0;
|
||||
|
||||
AutoLock lock_scope(this);
|
||||
|
||||
@ -121,7 +124,7 @@ public:
|
||||
memcpy(data_out, data_.c_str() + offset_, transfer_size);
|
||||
offset_ += transfer_size;
|
||||
|
||||
*bytes_read = transfer_size;
|
||||
bytes_read = transfer_size;
|
||||
has_data = true;
|
||||
}
|
||||
|
||||
@ -130,6 +133,7 @@ public:
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
std::string mime_type_;
|
||||
size_t offset_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
||||
|
@ -12,7 +12,8 @@ class TestResults
|
||||
public:
|
||||
TestResults()
|
||||
: status_code(0),
|
||||
sub_status_code(0)
|
||||
sub_status_code(0),
|
||||
delay(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -27,6 +28,7 @@ public:
|
||||
sub_status_code = 0;
|
||||
sub_allow_origin.clear();
|
||||
exit_url.clear();
|
||||
delay = 0;
|
||||
got_request.reset();
|
||||
got_read.reset();
|
||||
got_output.reset();
|
||||
@ -51,6 +53,9 @@ public:
|
||||
std::string sub_allow_origin;
|
||||
std::string exit_url;
|
||||
|
||||
// Delay for returning scheme handler results.
|
||||
int delay;
|
||||
|
||||
TrackCallback
|
||||
got_request,
|
||||
got_read,
|
||||
@ -149,21 +154,57 @@ class ClientSchemeHandler : public CefSchemeHandler
|
||||
{
|
||||
public:
|
||||
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,
|
||||
CefString& redirectUrl,
|
||||
CefRefPtr<CefResponse> response,
|
||||
int* response_length)
|
||||
CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||
OVERRIDE
|
||||
{
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
bool handled = false;
|
||||
|
||||
std::string url = request->GetURL();
|
||||
is_sub_ = (!test_results_->sub_url.empty() &&
|
||||
test_results_->sub_url == url);
|
||||
|
||||
if (is_sub_) {
|
||||
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);
|
||||
|
||||
if (!test_results_->sub_allow_origin.empty()) {
|
||||
@ -177,38 +218,45 @@ public:
|
||||
|
||||
if (!test_results_->sub_html.empty()) {
|
||||
response->SetMimeType("text/html");
|
||||
*response_length = test_results_->sub_html.size();
|
||||
return true;
|
||||
response_length = test_results_->sub_html.size();
|
||||
}
|
||||
} else {
|
||||
EXPECT_EQ(url, test_results_->url);
|
||||
|
||||
test_results_->got_request.yes();
|
||||
|
||||
response->SetStatus(test_results_->status_code);
|
||||
|
||||
if (!test_results_->redirect_url.empty()) {
|
||||
redirectUrl = test_results_->redirect_url;
|
||||
return true;
|
||||
} else if (!test_results_->html.empty()) {
|
||||
if (!test_results_->html.empty()) {
|
||||
response->SetMimeType("text/html");
|
||||
*response_length = test_results_->html.size();
|
||||
return true;
|
||||
response_length = test_results_->html.size();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void Cancel()
|
||||
virtual void Cancel() OVERRIDE
|
||||
{
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
}
|
||||
|
||||
virtual bool ReadResponse(void* data_out, int bytes_to_read, int* bytes_read)
|
||||
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;
|
||||
}
|
||||
|
||||
has_delayed_ = false;
|
||||
}
|
||||
|
||||
std::string* data;
|
||||
|
||||
if (is_sub_) {
|
||||
@ -220,7 +268,7 @@ public:
|
||||
}
|
||||
|
||||
bool has_data = false;
|
||||
*bytes_read = 0;
|
||||
bytes_read = 0;
|
||||
|
||||
AutoLock lock_scope(this);
|
||||
|
||||
@ -231,7 +279,7 @@ public:
|
||||
memcpy(data_out, data->c_str() + offset_, transfer_size);
|
||||
offset_ += transfer_size;
|
||||
|
||||
*bytes_read = transfer_size;
|
||||
bytes_read = transfer_size;
|
||||
has_data = true;
|
||||
}
|
||||
|
||||
@ -239,9 +287,16 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void ContinueAfterDelay(CefRefPtr<CefSchemeHandlerCallback> callback)
|
||||
{
|
||||
has_delayed_ = true;
|
||||
callback->BytesAvailable();
|
||||
}
|
||||
|
||||
TestResults* test_results_;
|
||||
size_t offset_;
|
||||
bool is_sub_;
|
||||
bool has_delayed_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
||||
IMPLEMENT_LOCKING(ClientSchemeHandler);
|
||||
@ -466,6 +521,27 @@ TEST(SchemeHandlerTest, CustomStandardNormalResponse)
|
||||
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(SchemeHandlerTest, CustomNonStandardNormalResponse)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user