- Add support for returning an HTTP status code from HandleBeforeResourceLoad and custom scheme handlers via the CefResponse class (issue #202).

- Add unit tests for custom scheme handlers (issue #221).
- Fix reversed enable/disable of stop and reload buttons in cefclient.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@222 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-04-21 16:46:16 +00:00
parent f9c9c9318c
commit f18083e5df
25 changed files with 654 additions and 69 deletions

View File

@ -191,6 +191,7 @@
'tests/unittests/dom_unittest.cc',
'tests/unittests/request_unittest.cc',
'tests/unittests/run_all_unittests.cc',
'tests/unittests/scheme_handler_unittest.cc',
'tests/unittests/stream_unittest.cc',
'tests/unittests/string_unittest.cc',
'tests/unittests/test_handler.h',

View File

@ -818,7 +818,7 @@ public:
CefRefPtr<CefRequest> request,
CefString& redirectUrl,
CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType,
CefRefPtr<CefResponse> response,
int loadFlags) =0;
// Called on the IO thread to handle requests for URLs with an unknown
@ -1235,21 +1235,33 @@ class CefResponse : public CefBase
public:
typedef std::map<CefString,CefString> HeaderMap;
// Returns the response status code.
// Returns/sets the response status code.
/*--cef()--*/
virtual int GetStatus() =0;
/*--cef()--*/
virtual void SetStatus(int status) = 0;
// Returns the response status text.
// Returns/sets the response status text.
/*--cef()--*/
virtual CefString GetStatusText() =0;
/*--cef()--*/
virtual void SetStatusText(const CefString& statusText) = 0;
// Returns/sets the response mime type.
/*--cef()--*/
virtual CefString GetMimeType() = 0;
/*--cef()--*/
virtual void SetMimeType(const CefString& mimeType) = 0;
// Returns the value for the specified response header field.
/*--cef()--*/
virtual CefString GetHeader(const CefString& name) =0;
// Retrieves a map of all response header fields.
// Retrieves/sets a map of all response header fields.
/*--cef()--*/
virtual void GetHeaderMap(HeaderMap& headerMap) =0;
/*--cef()--*/
virtual void SetHeaderMap(const HeaderMap& headerMap) =0;
};
@ -1635,7 +1647,8 @@ public:
// |mime_type| to the mime type for the response.
/*--cef()--*/
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
CefString& mime_type, int* response_length) =0;
CefRefPtr<CefResponse> response,
int* response_length) =0;
// Cancel processing of the request.
/*--cef()--*/

View File

@ -652,8 +652,8 @@ typedef struct _cef_handler_t
enum cef_retval_t (CEF_CALLBACK *handle_before_resource_load)(
struct _cef_handler_t* self, struct _cef_browser_t* browser,
struct _cef_request_t* request, cef_string_t* redirectUrl,
struct _cef_stream_reader_t** resourceStream, cef_string_t* mimeType,
int loadFlags);
struct _cef_stream_reader_t** resourceStream,
struct _cef_response_t* response, int loadFlags);
// Called on the IO thread to handle requests for URLs with an unknown
// protocol component. Return RV_HANDLED to indicate that the request should
@ -1020,22 +1020,34 @@ typedef struct _cef_response_t
// Base structure.
cef_base_t base;
// Returns the response status code.
// Returns/sets the response status code.
int (CEF_CALLBACK *get_status)(struct _cef_response_t* self);
void (CEF_CALLBACK *set_status)(struct _cef_response_t* self, int status);
// Returns the response status text.
// Returns/sets the response status text.
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_status_text)(
struct _cef_response_t* self);
void (CEF_CALLBACK *set_status_text)(struct _cef_response_t* self,
const cef_string_t* statusText);
// Returns/sets the response mime type.
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_mime_type)(
struct _cef_response_t* self);
void (CEF_CALLBACK *set_mime_type)(struct _cef_response_t* self,
const cef_string_t* mimeType);
// Returns the value for the specified response header field.
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_header)(struct _cef_response_t* self,
const cef_string_t* name);
// Retrieves a map of all response header fields.
// Retrieves/sets a map of all response header fields.
void (CEF_CALLBACK *get_header_map)(struct _cef_response_t* self,
cef_string_map_t headerMap);
void (CEF_CALLBACK *set_header_map)(struct _cef_response_t* self,
cef_string_map_t headerMap);
} cef_response_t;
@ -1396,7 +1408,7 @@ typedef struct _cef_scheme_handler_t
// to 0 or the specified number of bytes have been read. If there is a
// response set |mime_type| to the mime type for the response.
int (CEF_CALLBACK *process_request)(struct _cef_scheme_handler_t* self,
struct _cef_request_t* request, cef_string_t* mime_type,
struct _cef_request_t* request, struct _cef_response_t* response,
int* response_length);
// Cancel processing of the request.

View File

@ -42,6 +42,7 @@
#include "cef_process_io_thread.h"
#include "external_protocol_handler.h"
#include "request_impl.h"
#include "response_impl.h"
#include "http_header_utils.h"
#include "base/file_path.h"
@ -313,10 +314,10 @@ class RequestProxy : public net::URLRequest::Delegate,
// Handler output will be returned in these variables
CefString redirectUrl;
CefRefPtr<CefStreamReader> resourceStream;
CefString mimeType;
CefRefPtr<CefResponse> response(new CefResponseImpl());
CefHandler::RetVal rv = handler->HandleBeforeResourceLoad(
browser_, request, redirectUrl, resourceStream, mimeType,
browser_, request, redirectUrl, resourceStream, response,
loadFlags);
// Observe URL from request.
@ -371,10 +372,32 @@ class RequestProxy : public net::URLRequest::Delegate,
resource_stream_ = resourceStream;
CefResponseImpl* responseImpl =
static_cast<CefResponseImpl*>(response.get());
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders(
responseImpl->GenerateResponseLine()));
ResourceResponseInfo info;
info.content_length = static_cast<int64>(offset);
if(!mimeType.empty())
info.mime_type = mimeType;
info.mime_type = response->GetMimeType();
info.headers = headers;
OnReceivedResponse(info);
AsyncReadData();
} else if (response->GetStatus() != 0) {
// status set, but no resource stream
handled = true;
CefResponseImpl* responseImpl =
static_cast<CefResponseImpl*>(response.get());
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders(
responseImpl->GenerateResponseLine()));
ResourceResponseInfo info;
info.content_length = 0;
info.mime_type = response->GetMimeType();
info.headers = headers;
OnReceivedResponse(info);
AsyncReadData();
}

View File

@ -6,10 +6,16 @@
#include "response_impl.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "http_header_utils.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
CefResponseImpl::CefResponseImpl()
: status_code_(0)
{
}
CefResponseImpl::CefResponseImpl(const WebKit::WebURLResponse &response)
{
DCHECK(!response.isNull());
@ -18,6 +24,8 @@ CefResponseImpl::CefResponseImpl(const WebKit::WebURLResponse &response)
status_code_ = response.httpStatusCode();
str = response.httpStatusText();
status_text_ = CefString(str);
str = response.mimeType();
mime_type_ = CefString(str);
HttpHeaderUtils::HeaderVisitor visitor(&header_map_);
response.visitHTTPHeaderFields(&visitor);
@ -25,16 +33,44 @@ CefResponseImpl::CefResponseImpl(const WebKit::WebURLResponse &response)
int CefResponseImpl::GetStatus()
{
AutoLock lock_scope(this);
return status_code_;
}
void CefResponseImpl::SetStatus(int status)
{
AutoLock lock_scope(this);
status_code_ = status;
}
CefString CefResponseImpl::GetStatusText()
{
AutoLock lock_scope(this);
return status_text_;
}
void CefResponseImpl::SetStatusText(const CefString& statusText)
{
AutoLock lock_scope(this);
status_text_ = statusText;
}
CefString CefResponseImpl::GetMimeType()
{
AutoLock lock_scope(this);
return mime_type_;
}
void CefResponseImpl::SetMimeType(const CefString& mimeType)
{
AutoLock lock_scope(this);
mime_type_ = mimeType;
}
CefString CefResponseImpl::GetHeader(const CefString& name)
{
AutoLock lock_scope(this);
CefString value;
HeaderMap::const_iterator it = header_map_.find(name);
@ -46,5 +82,32 @@ CefString CefResponseImpl::GetHeader(const CefString& name)
void CefResponseImpl::GetHeaderMap(HeaderMap& map)
{
AutoLock lock_scope(this);
map = header_map_;
}
void CefResponseImpl::SetHeaderMap(const HeaderMap& headerMap)
{
AutoLock lock_scope(this);
header_map_ = headerMap;
}
CefString CefResponseImpl::GenerateResponseLine()
{
AutoLock lock_scope(this);
std::string response_line;
std::string status_text;
if(status_text_.empty())
status_text = (status_code_ == 200)?"OK":"ERROR";
else
status_text = status_text_;
base::SStringPrintf(&response_line, "HTTP/1.1 %d %s", status_code_,
status_text.c_str());
CefString value(response_line);
return value;
}

View File

@ -15,18 +15,27 @@ class WebURLResponse;
class CefResponseImpl : public CefThreadSafeBase<CefResponse>
{
public:
CefResponseImpl();
CefResponseImpl(const WebKit::WebURLResponse& response);
~CefResponseImpl() {}
// CefResponse API
virtual int GetStatus();
virtual void SetStatus(int status);
virtual CefString GetStatusText();
virtual void SetStatusText(const CefString& statusText);
virtual CefString GetMimeType();
virtual void SetMimeType(const CefString& mimeType);
virtual CefString GetHeader(const CefString& name);
virtual void GetHeaderMap(HeaderMap& headerMap);
virtual void SetHeaderMap(const HeaderMap& headerMap);
CefString GenerateResponseLine();
protected:
int status_code_;
CefString status_text_;
CefString mime_type_;
HeaderMap header_map_;
};

View File

@ -10,6 +10,7 @@
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/upload_data.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_filter.h"
@ -19,6 +20,7 @@
#include "tracker.h"
#include "cef_context.h"
#include "request_impl.h"
#include "response_impl.h"
#include <map>
@ -61,6 +63,7 @@ public:
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_));
@ -116,6 +119,14 @@ public:
}
}
virtual void GetResponseInfo(net::HttpResponseInfo* info) {
CefResponseImpl* responseImpl =
static_cast<CefResponseImpl*>(response_.get());
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders(responseImpl->GenerateResponseLine()));
info->headers = headers;
}
virtual bool IsRedirectResponse(GURL* location, int* http_status_code)
{
return false;
@ -125,7 +136,7 @@ public:
{
DCHECK(request_);
// call handler to get mime type
*mime_type = mime_type_;
*mime_type = response_->GetMimeType();
return true;
}
@ -134,7 +145,7 @@ public:
}
CefRefPtr<CefSchemeHandler> handler_;
std::string mime_type_;
CefRefPtr<CefResponse> response_;
int response_length_;
protected:
@ -178,15 +189,13 @@ private:
static_cast<CefRequestImpl*>(req.get())->Set(owner_->request());
owner_->handler_->Cancel();
CefString mime_type;
int response_length = 0;
// handler should complete content generation in ProcessRequest
bool res = owner_->handler_->ProcessRequest(req, mime_type,
bool res = owner_->handler_->ProcessRequest(req, owner_->response_,
&response_length);
if (res) {
owner_->mime_type_ = mime_type;
if (res)
owner_->response_length_ = response_length;
}
//////////////////////////////////////////////////////////////////////////
if (owner_loop_) {
owner_loop_->PostTask(FROM_HERE, NewRunnableMethod(

View File

@ -15,6 +15,7 @@
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/request_ctocpp.h"
#include "libcef_dll/ctocpp/response_ctocpp.h"
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
@ -197,25 +198,24 @@ enum cef_retval_t CEF_CALLBACK handler_handle_load_error(
enum cef_retval_t CEF_CALLBACK handler_handle_before_resource_load(
struct _cef_handler_t* self, cef_browser_t* browser,
struct _cef_request_t* request, cef_string_t* redirectUrl,
struct _cef_stream_reader_t** resourceStream, cef_string_t* mimeType,
int loadFlags)
struct _cef_stream_reader_t** resourceStream,
struct _cef_response_t* response, int loadFlags)
{
DCHECK(self);
DCHECK(browser);
DCHECK(redirectUrl);
DCHECK(resourceStream);
DCHECK(mimeType);
if(!self || !browser || !redirectUrl || !resourceStream || !mimeType)
DCHECK(response);
if(!self || !browser || !redirectUrl || !resourceStream || !response)
return RV_CONTINUE;
CefRefPtr<CefStreamReader> streamPtr;
CefString redirectUrlStr(redirectUrl);
CefString mimeTypeStr(mimeType);
enum cef_retval_t rv = CefHandlerCppToC::Get(self)->
HandleBeforeResourceLoad(CefBrowserCToCpp::Wrap(browser),
CefRequestCToCpp::Wrap(request), redirectUrlStr, streamPtr, mimeTypeStr,
loadFlags);
CefRequestCToCpp::Wrap(request), redirectUrlStr, streamPtr,
CefResponseCToCpp::Wrap(response), loadFlags);
if(streamPtr.get())
*resourceStream = CefStreamReaderCToCpp::Unwrap(streamPtr);

View File

@ -25,6 +25,15 @@ int CEF_CALLBACK response_get_status(struct _cef_response_t* self)
return CefResponseCppToC::Get(self)->GetStatus();
}
void CEF_CALLBACK response_set_status(struct _cef_response_t* self, int status)
{
DCHECK(self);
if(!self)
return;
CefResponseCppToC::Get(self)->SetStatus(status);
}
cef_string_userfree_t CEF_CALLBACK response_get_status_text(
struct _cef_response_t* self)
{
@ -36,6 +45,37 @@ cef_string_userfree_t CEF_CALLBACK response_get_status_text(
return text.DetachToUserFree();
}
void CEF_CALLBACK response_set_status_text(struct _cef_response_t* self,
const cef_string_t* statusText)
{
DCHECK(self);
if(!self)
return;
CefResponseCppToC::Get(self)->SetStatusText(CefString(statusText));
}
cef_string_userfree_t CEF_CALLBACK response_get_mime_type(
struct _cef_response_t* self)
{
DCHECK(self);
if(!self)
return NULL;
CefString text = CefResponseCppToC::Get(self)->GetMimeType();
return text.DetachToUserFree();
}
void CEF_CALLBACK response_set_mime_type(struct _cef_response_t* self,
const cef_string_t* mimeType)
{
DCHECK(self);
if(!self)
return;
CefResponseCppToC::Get(self)->SetMimeType(CefString(mimeType));
}
cef_string_userfree_t CEF_CALLBACK response_get_header(
struct _cef_response_t* self, const cef_string_t* name)
{
@ -59,6 +99,20 @@ void CEF_CALLBACK response_get_header_map(struct _cef_response_t* self,
transfer_string_map_contents(map, headerMap);
}
void CEF_CALLBACK response_set_header_map(struct _cef_response_t* self,
cef_string_map_t headerMap)
{
DCHECK(self);
if(!self)
return;
CefResponse::HeaderMap map;
if(headerMap)
transfer_string_map_contents(headerMap, map);
CefResponseCppToC::Get(self)->SetHeaderMap(map);
}
// CONSTRUCTOR - Do not edit by hand.
@ -66,9 +120,14 @@ CefResponseCppToC::CefResponseCppToC(CefResponse* cls)
: CefCppToC<CefResponseCppToC, CefResponse, cef_response_t>(cls)
{
struct_.struct_.get_status = response_get_status;
struct_.struct_.set_status = response_set_status;
struct_.struct_.get_status_text = response_get_status_text;
struct_.struct_.set_status_text = response_set_status_text;
struct_.struct_.get_mime_type = response_get_mime_type;
struct_.struct_.set_mime_type = response_set_mime_type;
struct_.struct_.get_header = response_get_header;
struct_.struct_.get_header_map = response_get_header_map;
struct_.struct_.set_header_map = response_set_header_map;
}
#ifdef _DEBUG

View File

@ -12,24 +12,25 @@
#include "libcef_dll/cpptoc/scheme_handler_cpptoc.h"
#include "libcef_dll/ctocpp/request_ctocpp.h"
#include "libcef_dll/ctocpp/response_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* mime_type, int* response_length)
cef_response_t* response, int* response_length)
{
DCHECK(self);
DCHECK(request);
DCHECK(mime_type);
DCHECK(response);
DCHECK(response_length);
if(!self || !request || !mime_type || !response_length)
if(!self || !request || !response || !response_length)
return 0;
CefString mimeTypeStr(mime_type);
return CefSchemeHandlerCppToC::Get(self)->ProcessRequest(
CefRequestCToCpp::Wrap(request), mimeTypeStr, response_length);
CefRequestCToCpp::Wrap(request), CefResponseCToCpp::Wrap(response),
response_length);
}
void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)

View File

@ -13,6 +13,7 @@
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/request_cpptoc.h"
#include "libcef_dll/cpptoc/response_cpptoc.h"
#include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
@ -151,7 +152,7 @@ CefHandler::RetVal CefHandlerCToCpp::HandleLoadError(
CefHandler::RetVal CefHandlerCToCpp::HandleBeforeResourceLoad(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefRequest> request,
CefString& redirectUrl, CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType, int loadFlags)
CefRefPtr<CefResponse> response, int loadFlags)
{
if(CEF_MEMBER_MISSING(struct_, handle_before_resource_load))
return RV_CONTINUE;
@ -160,8 +161,8 @@ CefHandler::RetVal CefHandlerCToCpp::HandleBeforeResourceLoad(
cef_retval_t rv = struct_->handle_before_resource_load(struct_,
CefBrowserCppToC::Wrap(browser), CefRequestCppToC::Wrap(request),
redirectUrl.GetWritableStruct(), &streamRet, mimeType.GetWritableStruct(),
loadFlags);
redirectUrl.GetWritableStruct(), &streamRet,
CefResponseCppToC::Wrap(response), loadFlags);
if(streamRet)
resourceStream = CefStreamReaderCppToC::Unwrap(streamRet);

View File

@ -54,8 +54,8 @@ public:
const CefString& failedUrl, CefString& errorText);
virtual RetVal HandleBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefRequest> request, CefString& redirectUrl,
CefRefPtr<CefStreamReader>& resourceStream, CefString& mimeType,
int loadFlags);
CefRefPtr<CefStreamReader>& resourceStream,
CefRefPtr<CefResponse> response, int loadFlags);
virtual RetVal HandleProtocolExecution(CefRefPtr<CefBrowser> browser,
const CefString& url, bool& allow_os_execution);
virtual RetVal HandleDownloadResponse(CefRefPtr<CefBrowser> browser,

View File

@ -24,6 +24,14 @@ int CefResponseCToCpp::GetStatus()
return struct_->get_status(struct_);
}
void CefResponseCToCpp::SetStatus(int status)
{
if(CEF_MEMBER_MISSING(struct_, set_status))
return;
struct_->set_status(struct_, status);
}
CefString CefResponseCToCpp::GetStatusText()
{
CefString str;
@ -35,6 +43,33 @@ CefString CefResponseCToCpp::GetStatusText()
return str;
}
void CefResponseCToCpp::SetStatusText(const CefString& statusText)
{
if(CEF_MEMBER_MISSING(struct_, set_status_text))
return;
struct_->set_status_text(struct_, statusText.GetStruct());
}
CefString CefResponseCToCpp::GetMimeType()
{
CefString str;
if(CEF_MEMBER_MISSING(struct_, get_mime_type))
return str;
cef_string_userfree_t strPtr = struct_->get_mime_type(struct_);
str.AttachToUserFree(strPtr);
return str;
}
void CefResponseCToCpp::SetMimeType(const CefString& mimeType)
{
if(CEF_MEMBER_MISSING(struct_, set_mime_type))
return;
struct_->set_mime_type(struct_, mimeType.GetStruct());
}
CefString CefResponseCToCpp::GetHeader(const CefString& name)
{
CefString str;
@ -60,6 +95,25 @@ void CefResponseCToCpp::GetHeaderMap(HeaderMap& headerMap)
cef_string_map_free(map);
}
void CefResponseCToCpp::SetHeaderMap(const HeaderMap& headerMap)
{
if(CEF_MEMBER_MISSING(struct_, set_header_map))
return;
cef_string_map_t map = NULL;
if(!headerMap.empty()) {
map = cef_string_map_alloc();
if(!map)
return;
transfer_string_map_contents(headerMap, map);
}
struct_->set_header_map(struct_, map);
if(map)
cef_string_map_free(map);
}
#ifdef _DEBUG
template<> long CefCToCpp<CefResponseCToCpp, CefResponse,

View File

@ -32,9 +32,14 @@ public:
// CefResponse methods
virtual int GetStatus();
virtual void SetStatus(int status);
virtual CefString GetStatusText();
virtual void SetStatusText(const CefString& statusText);
virtual CefString GetMimeType();
virtual void SetMimeType(const CefString& mimeType);
virtual CefString GetHeader(const CefString& name);
virtual void GetHeaderMap(HeaderMap& headerMap);
virtual void SetHeaderMap(const HeaderMap& headerMap);
};
#endif // USING_CEF_SHARED

View File

@ -11,19 +11,20 @@
//
#include "libcef_dll/cpptoc/request_cpptoc.h"
#include "libcef_dll/cpptoc/response_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& mime_type, int* response_length)
CefRefPtr<CefResponse> response, int* response_length)
{
if(CEF_MEMBER_MISSING(struct_, process_request))
return false;
return struct_->process_request(struct_, CefRequestCppToC::Wrap(request),
mime_type.GetWritableStruct(), response_length) ? true : false;
CefResponseCppToC::Wrap(response), response_length) ? true : false;
}
void CefSchemeHandlerCToCpp::Cancel()

View File

@ -34,7 +34,7 @@ public:
// CefSchemeHandler methods
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
CefString& mime_type, int* response_length);
CefRefPtr<CefResponse> response, int* response_length);
virtual void Cancel();
virtual bool ReadResponse(void* data_out, int bytes_to_read, int* bytes_read);
};

View File

@ -251,14 +251,14 @@ void ClientHandler::SetEditHwnd(CefWindowHandle hwnd)
void ClientHandler::SetButtonHwnds(CefWindowHandle backHwnd,
CefWindowHandle forwardHwnd,
CefWindowHandle stopHwnd,
CefWindowHandle reloadHwnd)
CefWindowHandle reloadHwnd,
CefWindowHandle stopHwnd)
{
Lock();
m_BackHwnd = backHwnd;
m_ForwardHwnd = forwardHwnd;
m_StopHwnd = stopHwnd;
m_ReloadHwnd = reloadHwnd;
m_StopHwnd = stopHwnd;
Unlock();
}

View File

@ -128,7 +128,7 @@ public:
CefRefPtr<CefRequest> request,
CefString& redirectUrl,
CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType,
CefRefPtr<CefResponse> response,
int loadFlags);
// Called on the IO thread to handle requests for URLs with an unknown

View File

@ -536,7 +536,7 @@ CefHandler::RetVal ClientHandler::HandleTitleChange(
CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefRequest> request,
CefString& redirectUrl, CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType, int loadFlags)
CefRefPtr<CefResponse> response, int loadFlags)
{
REQUIRE_IO_THREAD();
@ -547,23 +547,28 @@ CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad(
DumpRequestContents(request, dump);
resourceStream = CefStreamReader::CreateForData(
(void*)dump.c_str(), dump.size());
mimeType = "text/plain";
response->SetMimeType("text/plain");
response->SetStatus(200);
} else if (strstr(url.c_str(), "/ps_logo2.png") != NULL) {
// Any time we find "ps_logo2.png" in the URL substitute in our own image
resourceStream = GetBinaryResourceReader("logo.png");
mimeType = "image/png";
response->SetMimeType("image/png");
response->SetStatus(200);
} else if(url == "http://tests/localstorage") {
// Show the localstorage contents
resourceStream = GetBinaryResourceReader("localstorage.html");
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(url == "http://tests/xmlhttprequest") {
// Show the xmlhttprequest HTML contents
resourceStream = GetBinaryResourceReader("xmlhttprequest.html");
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(url == "http://tests/domaccess") {
// Show the domaccess HTML contents
resourceStream = GetBinaryResourceReader("domaccess.html");
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
}
return RV_CONTINUE;

View File

@ -695,7 +695,7 @@ CefHandler::RetVal ClientHandler::HandleTitleChange(
CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefRequest> request,
CefString& redirectUrl, CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType, int loadFlags)
CefRefPtr<CefResponse> response, int loadFlags)
{
REQUIRE_IO_THREAD();
@ -706,35 +706,43 @@ CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad(
DumpRequestContents(request, dump);
resourceStream =
CefStreamReader::CreateForData((void*)dump.c_str(), dump.size());
mimeType = "text/plain";
response->SetMimeType("text/plain");
response->SetStatus(200);
} else if(strstr(url.c_str(), "/ps_logo2.png") != NULL) {
// Any time we find "ps_logo2.png" in the URL substitute in our own image
resourceStream = GetBinaryResourceReader(IDS_LOGO);
mimeType = "image/png";
response->SetMimeType("image/png");
response->SetStatus(200);
} else if(url == "http://tests/uiapp") {
// Show the uiapp contents
resourceStream = GetBinaryResourceReader(IDS_UIPLUGIN);
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(url == "http://tests/osrapp") {
// Show the osrapp contents
resourceStream = GetBinaryResourceReader(IDS_OSRPLUGIN);
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(url == "http://tests/localstorage") {
// Show the localstorage contents
resourceStream = GetBinaryResourceReader(IDS_LOCALSTORAGE);
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(url == "http://tests/xmlhttprequest") {
// Show the xmlhttprequest HTML contents
resourceStream = GetBinaryResourceReader(IDS_XMLHTTPREQUEST);
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(url == "http://tests/domaccess") {
// Show the domaccess HTML contents
resourceStream = GetBinaryResourceReader(IDS_DOMACCESS);
mimeType = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
} else if(strstr(url.c_str(), "/logoball.png") != NULL) {
// Load the "logoball.png" image resource.
resourceStream = GetBinaryResourceReader(IDS_LOGOBALL);
mimeType = "image/png";
response->SetMimeType("image/png");
response->SetStatus(200);
}
return RV_CONTINUE;
}

View File

@ -7,7 +7,7 @@ function execXMLHttpRequest()
xhr.open("GET",document.getElementById("url").value,false);
xhr.setRequestHeader('My-Custom-Header', 'Some Value');
xhr.send();
document.getElementById('ta').value = "Request\n\n"+xhr.responseText;
document.getElementById('ta').value = "Status Code: "+xhr.status+"\n\n"+xhr.responseText;
}
</script>
<form>

View File

@ -29,7 +29,8 @@ public:
// specified number of bytes have been read. If there is a response set
// |mime_type| to the mime type for the response.
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
CefString& mime_type, int* response_length)
CefRefPtr<CefResponse> response,
int* response_length)
{
REQUIRE_IO_THREAD();
@ -60,7 +61,8 @@ public:
handled = true;
// Set the resulting mime type
mime_type = "text/html";
response->SetMimeType("text/html");
response->SetStatus(200);
}
else if(strstr(url.c_str(), "client.png") != NULL) {
// Load the response image
@ -70,7 +72,9 @@ public:
if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) {
data_ = std::string(reinterpret_cast<const char*>(pBytes), dwSize);
handled = true;
mime_type = "image/png";
// Set the resulting mime type
response->SetMimeType("image/jpg");
response->SetStatus(200);
}
#elif defined(__APPLE__)
if(LoadBinaryResource("logo.png", data_)) {

View File

@ -259,7 +259,7 @@ public:
CefRefPtr<CefRequest> request,
CefString& redirectUrl,
CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType,
CefRefPtr<CefResponse> response,
int loadFlags)
{
g_RequestSendRecvTestHandlerHandleBeforeResourceLoadCalled = true;

View File

@ -0,0 +1,315 @@
// 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.
#include "test_handler.h"
namespace {
class TestResults
{
public:
TestResults()
{
}
void reset()
{
url.clear();
html.clear();
status_code = 0;
got_request.reset();
got_read.reset();
got_output.reset();
}
std::string url;
std::string html;
int status_code;
TrackCallback
got_request,
got_read,
got_output;
};
class TestSchemeHandler : public TestHandler
{
public:
TestSchemeHandler(TestResults* tr)
: test_results_(tr)
{
}
virtual void RunTest()
{
CreateBrowser(test_results_->url);
}
virtual RetVal HandleLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode)
{
// Test that the output is correct.
std::string output = frame->GetSource();
if (output == test_results_->html)
test_results_->got_output.yes();
// Test that the status code is correct.
EXPECT_EQ(httpStatusCode, test_results_->status_code);
DestroyTest();
return RV_CONTINUE;
}
protected:
TestResults* test_results_;
};
class ClientSchemeHandler : public CefThreadSafeBase<CefSchemeHandler>
{
public:
ClientSchemeHandler(TestResults* tr)
: test_results_(tr), offset_(0) {}
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response,
int* response_length)
{
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
test_results_->got_request.yes();
std::string url = request->GetURL();
EXPECT_EQ(url, test_results_->url);
response->SetStatus(test_results_->status_code);
bool handled = !test_results_->html.empty();
if(handled) {
response->SetMimeType("text/html");
*response_length = test_results_->html.size();
}
return handled;
}
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));
test_results_->got_read.yes();
bool has_data = false;
*bytes_read = 0;
Lock();
size_t size = test_results_->html.size();
if(offset_ < size) {
int transfer_size =
std::min(bytes_to_read, static_cast<int>(size - offset_));
memcpy(data_out, test_results_->html.c_str() + offset_, transfer_size);
offset_ += transfer_size;
*bytes_read = transfer_size;
has_data = true;
}
Unlock();
return has_data;
}
private:
TestResults* test_results_;
size_t offset_;
};
class ClientSchemeHandlerFactory :
public CefThreadSafeBase<CefSchemeHandlerFactory>
{
public:
ClientSchemeHandlerFactory(TestResults* tr)
: test_results_(tr){}
virtual CefRefPtr<CefSchemeHandler> Create()
{
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
return new ClientSchemeHandler(test_results_);
}
TestResults* test_results_;
};
// Global test results object.
TestResults g_TestResults;
void CreateStandardTestScheme()
{
g_TestResults.reset();
static bool registered = false;
if (!registered) {
CefRegisterScheme("stdscheme", "tests", true,
new ClientSchemeHandlerFactory(&g_TestResults));
registered = true;
}
}
void CreateNonStandardTestScheme()
{
g_TestResults.reset();
static bool registered = false;
if (!registered) {
CefRegisterScheme("nonstdscheme", CefString(), false,
new ClientSchemeHandlerFactory(&g_TestResults));
registered = true;
}
}
} // anonymous
// Test that a standard scheme can return normal results.
TEST(SchemeHandlerTest, StandardSchemeNormalResponse)
{
CreateStandardTestScheme();
g_TestResults.url = "stdscheme://tests/run.html";
g_TestResults.html =
"<html><head></head><body><h1>Success!</h1></body></html>";
g_TestResults.status_code = 200;
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);
}
// Test that a standard scheme can return an error code.
TEST(SchemeHandlerTest, StandardSchemeErrorResponse)
{
CreateStandardTestScheme();
g_TestResults.url = "stdscheme://tests/run.html";
g_TestResults.html =
"<html><head></head><body><h1>404</h1></body></html>";
g_TestResults.status_code = 404;
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);
}
// Test that standard scheme handling fails when the scheme name is incorrect.
TEST(SchemeHandlerTest, StandardSchemeNameNotHandled)
{
CreateStandardTestScheme();
g_TestResults.url = "stdscheme2://tests/run.html";
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
EXPECT_FALSE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
}
// Test that standard scheme handling fails when the domain name is incorrect.
TEST(SchemeHandlerTest, StandardSchemeDomainNotHandled)
{
CreateStandardTestScheme();
g_TestResults.url = "stdscheme://tests2/run.html";
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
EXPECT_FALSE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
}
// Test that a standard scheme can return no response.
TEST(SchemeHandlerTest, StandardSchemeNoResponse)
{
CreateStandardTestScheme();
g_TestResults.url = "stdscheme://tests/run.html";
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
EXPECT_TRUE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
}
// Test that a non-standard scheme can return normal results.
TEST(SchemeHandlerTest, NonStandardSchemeNormalResponse)
{
CreateNonStandardTestScheme();
g_TestResults.url = "nonstdscheme:some%20value";
g_TestResults.html =
"<html><head></head><body><h1>Success!</h1></body></html>";
g_TestResults.status_code = 200;
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);
}
// Test that a non-standard scheme can return an error code.
TEST(SchemeHandlerTest, NonStandardSchemeErrorResponse)
{
CreateNonStandardTestScheme();
g_TestResults.url = "nonstdscheme:some%20value";
g_TestResults.html =
"<html><head></head><body><h1>404</h1></body></html>";
g_TestResults.status_code = 404;
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);
}
// Test that non-standard scheme handling fails when the scheme name is
// incorrect.
TEST(SchemeHandlerTest, NonStandardSchemeNameNotHandled)
{
CreateNonStandardTestScheme();
g_TestResults.url = "nonstdscheme2:some%20value";
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
EXPECT_FALSE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
}
// Test that a non-standard scheme can return no response.
TEST(SchemeHandlerTest, NonStandardSchemeNoResponse)
{
CreateNonStandardTestScheme();
g_TestResults.url = "nonstdscheme:some%20value";
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
handler->ExecuteTest();
EXPECT_TRUE(g_TestResults.got_request);
EXPECT_FALSE(g_TestResults.got_read);
EXPECT_FALSE(g_TestResults.got_output);
}

View File

@ -15,6 +15,7 @@ public:
TrackCallback(): gotit_(false) {}
void yes() { gotit_ = true; }
bool isSet() { return gotit_; }
void reset() { gotit_ = false; }
operator bool() const { return gotit_; }
protected:
bool gotit_;
@ -111,7 +112,7 @@ public:
CefRefPtr<CefRequest> request,
CefString& redirectUrl,
CefRefPtr<CefStreamReader>& resourceStream,
CefString& mimeType,
CefRefPtr<CefResponse> response,
int loadFlags)
{
Lock();
@ -122,7 +123,8 @@ public:
// Return the previously mapped resource
resourceStream = CefStreamReader::CreateForData(
(void*)it->second.first.c_str(), it->second.first.length());
mimeType = it->second.second;
response->SetMimeType(it->second.second);
response->SetStatus(200);
}
}
Unlock();