mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Allow custom schemes to cause redirects (issue #98).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@223 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
@ -808,11 +808,12 @@ public:
|
|||||||
// Called on the IO thread before a resource is loaded. To allow the resource
|
// Called on the IO thread before a resource is loaded. To allow the resource
|
||||||
// to load normally return RV_CONTINUE. To redirect the resource to a new url
|
// to load normally return RV_CONTINUE. To redirect the resource to a new url
|
||||||
// populate the |redirectUrl| value and return RV_CONTINUE. To specify data
|
// populate the |redirectUrl| value and return RV_CONTINUE. To specify data
|
||||||
// for the resource return a CefStream object in |resourceStream|, set
|
// for the resource return a CefStream object in |resourceStream|, use the
|
||||||
// |mimeType| to the resource stream's mime type, and return RV_CONTINUE. To
|
// |response| object to set mime type, HTTP status code and optional header
|
||||||
// cancel loading of the resource return RV_HANDLED. Any modifications to
|
// values, and return RV_CONTINUE. To cancel loading of the resource return
|
||||||
// |request| will be observed. If the URL in |request| is changed and
|
// RV_HANDLED. Any modifications to |request| will be observed. If the URL in
|
||||||
// |redirectUrl| is also set, the URL in |request| will be used.
|
// |request| is changed and |redirectUrl| is also set, the URL in |request|
|
||||||
|
// will be used.
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
virtual RetVal HandleBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
virtual RetVal HandleBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefRequest> request,
|
CefRefPtr<CefRequest> request,
|
||||||
@ -1637,16 +1638,19 @@ class CefSchemeHandler : public CefBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Process the request. All response generation should take place in this
|
// Process the request. All response generation should take place in this
|
||||||
// method. If there is no response set |response_length| to zero and
|
// method. If there is no response set |response_length| to zero or return
|
||||||
// ReadResponse() will not be called. If the response length is not known then
|
// false and ReadResponse() will not be called. If the response length is not
|
||||||
// set |response_length| to -1 and ReadResponse() will be called until it
|
// known set |response_length| to -1 and ReadResponse() will be called until
|
||||||
// returns false or until the value of |bytes_read| is set to 0. Otherwise,
|
// it returns false or until the value of |bytes_read| is set to 0. If the
|
||||||
// set |response_length| to a positive value and ReadResponse() will be called
|
// response length is known set |response_length| to a positive value and
|
||||||
// until it returns false, the value of |bytes_read| is set to 0 or the
|
// ReadResponse() will be called until it returns false, the value of
|
||||||
// specified number of bytes have been read. If there is a response set
|
// |bytes_read| is set to 0 or the specified number of bytes have been read.
|
||||||
// |mime_type| to the mime type for the response.
|
// 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,
|
||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefResponse> response,
|
||||||
int* response_length) =0;
|
int* response_length) =0;
|
||||||
|
|
||||||
|
@ -644,11 +644,12 @@ typedef struct _cef_handler_t
|
|||||||
// Called on the IO thread before a resource is loaded. To allow the resource
|
// Called on the IO thread before a resource is loaded. To allow the resource
|
||||||
// to load normally return RV_CONTINUE. To redirect the resource to a new url
|
// to load normally return RV_CONTINUE. To redirect the resource to a new url
|
||||||
// populate the |redirectUrl| value and return RV_CONTINUE. To specify data
|
// populate the |redirectUrl| value and return RV_CONTINUE. To specify data
|
||||||
// for the resource return a CefStream object in |resourceStream|, set
|
// for the resource return a CefStream object in |resourceStream|, use the
|
||||||
// |mimeType| to the resource stream's mime type, and return RV_CONTINUE. To
|
// |response| object to set mime type, HTTP status code and optional header
|
||||||
// cancel loading of the resource return RV_HANDLED. Any modifications to
|
// values, and return RV_CONTINUE. To cancel loading of the resource return
|
||||||
// |request| will be observed. If the URL in |request| is changed and
|
// RV_HANDLED. Any modifications to |request| will be observed. If the URL in
|
||||||
// |redirectUrl| is also set, the URL in |request| will be used.
|
// |request| is changed and |redirectUrl| is also set, the URL in |request|
|
||||||
|
// will be used.
|
||||||
enum cef_retval_t (CEF_CALLBACK *handle_before_resource_load)(
|
enum cef_retval_t (CEF_CALLBACK *handle_before_resource_load)(
|
||||||
struct _cef_handler_t* self, struct _cef_browser_t* browser,
|
struct _cef_handler_t* self, struct _cef_browser_t* browser,
|
||||||
struct _cef_request_t* request, cef_string_t* redirectUrl,
|
struct _cef_request_t* request, cef_string_t* redirectUrl,
|
||||||
@ -1399,17 +1400,20 @@ 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
|
// Process the request. All response generation should take place in this
|
||||||
// function. If there is no response set |response_length| to zero and
|
// function. If there is no response set |response_length| to zero or return
|
||||||
// read_response() will not be called. If the response length is not known
|
// false (0) and read_response() will not be called. If the response length is
|
||||||
// then set |response_length| to -1 and read_response() will be called until
|
// not known set |response_length| to -1 and read_response() will be called
|
||||||
// it returns false (0) or until the value of |bytes_read| is set to 0.
|
// until it returns false (0) or until the value of |bytes_read| is set to 0.
|
||||||
// Otherwise, set |response_length| to a positive value and read_response()
|
// If the response length is known set |response_length| to a positive value
|
||||||
// will be called until it returns false (0), the value of |bytes_read| is set
|
// and read_response() will be called until it returns false (0), the value of
|
||||||
// to 0 or the specified number of bytes have been read. If there is a
|
// |bytes_read| is set to 0 or the specified number of bytes have been read.
|
||||||
// response set |mime_type| to the mime type for the response.
|
// 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, struct _cef_response_t* response,
|
struct _cef_request_t* request, cef_string_t* redirectUrl,
|
||||||
int* response_length);
|
struct _cef_response_t* response, int* response_length);
|
||||||
|
|
||||||
// Cancel processing of the request.
|
// Cancel processing of the request.
|
||||||
void (CEF_CALLBACK *cancel)(struct _cef_scheme_handler_t* self);
|
void (CEF_CALLBACK *cancel)(struct _cef_scheme_handler_t* self);
|
||||||
|
@ -129,6 +129,12 @@ public:
|
|||||||
|
|
||||||
virtual bool IsRedirectResponse(GURL* location, int* http_status_code)
|
virtual bool IsRedirectResponse(GURL* location, int* http_status_code)
|
||||||
{
|
{
|
||||||
|
if (redirect_url_.is_valid()) {
|
||||||
|
// Redirect to the new URL.
|
||||||
|
*http_status_code = 303;
|
||||||
|
location->Swap(&redirect_url_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +156,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
GURL url_;
|
GURL url_;
|
||||||
|
GURL redirect_url_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DidResolve(const GURL& url)
|
void DidResolve(const GURL& url)
|
||||||
@ -189,12 +196,23 @@ private:
|
|||||||
static_cast<CefRequestImpl*>(req.get())->Set(owner_->request());
|
static_cast<CefRequestImpl*>(req.get())->Set(owner_->request());
|
||||||
|
|
||||||
owner_->handler_->Cancel();
|
owner_->handler_->Cancel();
|
||||||
|
|
||||||
int response_length = 0;
|
int response_length = 0;
|
||||||
|
CefString redirectUrl;
|
||||||
|
|
||||||
// handler should complete content generation in ProcessRequest
|
// handler should complete content generation in ProcessRequest
|
||||||
bool res = owner_->handler_->ProcessRequest(req, owner_->response_,
|
bool res = owner_->handler_->ProcessRequest(req, redirectUrl,
|
||||||
&response_length);
|
owner_->response_, &response_length);
|
||||||
if (res)
|
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;
|
owner_->response_length_ = response_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
if (owner_loop_) {
|
if (owner_loop_) {
|
||||||
|
@ -19,18 +19,20 @@
|
|||||||
|
|
||||||
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_response_t* response, int* response_length)
|
cef_string_t* redirectUrl, cef_response_t* response, int* response_length)
|
||||||
{
|
{
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
DCHECK(request);
|
DCHECK(request);
|
||||||
|
DCHECK(redirectUrl);
|
||||||
DCHECK(response);
|
DCHECK(response);
|
||||||
DCHECK(response_length);
|
DCHECK(response_length);
|
||||||
if(!self || !request || !response || !response_length)
|
if(!self || !request || !redirectUrl || !response || !response_length)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
CefString redirectUrlStr(redirectUrl);
|
||||||
return CefSchemeHandlerCppToC::Get(self)->ProcessRequest(
|
return CefSchemeHandlerCppToC::Get(self)->ProcessRequest(
|
||||||
CefRequestCToCpp::Wrap(request), CefResponseCToCpp::Wrap(response),
|
CefRequestCToCpp::Wrap(request), redirectUrlStr,
|
||||||
response_length);
|
CefResponseCToCpp::Wrap(response), response_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)
|
void CEF_CALLBACK scheme_handler_cancel(struct _cef_scheme_handler_t* self)
|
||||||
|
@ -18,13 +18,15 @@
|
|||||||
// 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,
|
||||||
CefRefPtr<CefResponse> response, int* response_length)
|
CefString& redirectUrl, CefRefPtr<CefResponse> response,
|
||||||
|
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),
|
||||||
CefResponseCppToC::Wrap(response), response_length) ? true : false;
|
redirectUrl.GetWritableStruct(), CefResponseCppToC::Wrap(response),
|
||||||
|
response_length) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefSchemeHandlerCToCpp::Cancel()
|
void CefSchemeHandlerCToCpp::Cancel()
|
||||||
|
@ -34,7 +34,8 @@ public:
|
|||||||
|
|
||||||
// CefSchemeHandler methods
|
// CefSchemeHandler methods
|
||||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefRefPtr<CefResponse> response, int* response_length);
|
CefString& redirectUrl, CefRefPtr<CefResponse> response,
|
||||||
|
int* response_length);
|
||||||
virtual void Cancel();
|
virtual void Cancel();
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
@ -20,15 +20,18 @@ public:
|
|||||||
ClientSchemeHandler() : offset_(0) {}
|
ClientSchemeHandler() : offset_(0) {}
|
||||||
|
|
||||||
// Process the request. All response generation should take place in this
|
// Process the request. All response generation should take place in this
|
||||||
// method. If there is no response set |response_length| to zero and
|
// method. If there is no response set |response_length| to zero or return
|
||||||
// ReadResponse() will not be called. If the response length is not known then
|
// false and ReadResponse() will not be called. If the response length is not
|
||||||
// set |response_length| to -1 and ReadResponse() will be called until it
|
// known set |response_length| to -1 and ReadResponse() will be called until
|
||||||
// returns false or until the value of |bytes_read| is set to 0. Otherwise,
|
// it returns false or until the value of |bytes_read| is set to 0. If the
|
||||||
// set |response_length| to a positive value and ReadResponse() will be called
|
// response length is known set |response_length| to a positive value and
|
||||||
// until it returns false, the value of |bytes_read| is set to 0 or the
|
// ReadResponse() will be called until it returns false, the value of
|
||||||
// specified number of bytes have been read. If there is a response set
|
// |bytes_read| is set to 0 or the specified number of bytes have been read.
|
||||||
// |mime_type| to the mime type for the response.
|
// 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,
|
||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefResponse> response,
|
||||||
int* response_length)
|
int* response_length)
|
||||||
{
|
{
|
||||||
|
@ -21,16 +21,19 @@ public:
|
|||||||
got_request.reset();
|
got_request.reset();
|
||||||
got_read.reset();
|
got_read.reset();
|
||||||
got_output.reset();
|
got_output.reset();
|
||||||
|
got_redirect.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string html;
|
std::string html;
|
||||||
int status_code;
|
int status_code;
|
||||||
|
std::string redirect_url;
|
||||||
|
|
||||||
TrackCallback
|
TrackCallback
|
||||||
got_request,
|
got_request,
|
||||||
got_read,
|
got_read,
|
||||||
got_output;
|
got_output,
|
||||||
|
got_redirect;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestSchemeHandler : public TestHandler
|
class TestSchemeHandler : public TestHandler
|
||||||
@ -46,6 +49,28 @@ public:
|
|||||||
CreateBrowser(test_results_->url);
|
CreateBrowser(test_results_->url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual RetVal HandleBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
CefRefPtr<CefRequest> request,
|
||||||
|
NavType navType, bool isRedirect)
|
||||||
|
{
|
||||||
|
if (isRedirect) {
|
||||||
|
test_results_->got_redirect.yes();
|
||||||
|
std::string newUrl = request->GetURL();
|
||||||
|
EXPECT_EQ(newUrl, test_results_->redirect_url);
|
||||||
|
|
||||||
|
// No read should have occurred for the redirect.
|
||||||
|
EXPECT_TRUE(test_results_->got_request);
|
||||||
|
EXPECT_FALSE(test_results_->got_read);
|
||||||
|
|
||||||
|
// Now loading the redirect URL.
|
||||||
|
test_results_->url = test_results_->redirect_url;
|
||||||
|
test_results_->redirect_url.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return RV_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
virtual RetVal HandleLoadEnd(CefRefPtr<CefBrowser> browser,
|
virtual RetVal HandleLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefFrame> frame,
|
CefRefPtr<CefFrame> frame,
|
||||||
int httpStatusCode)
|
int httpStatusCode)
|
||||||
@ -74,6 +99,7 @@ public:
|
|||||||
: test_results_(tr), offset_(0) {}
|
: test_results_(tr), offset_(0) {}
|
||||||
|
|
||||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
|
CefString& redirectUrl,
|
||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefResponse> response,
|
||||||
int* response_length)
|
int* response_length)
|
||||||
{
|
{
|
||||||
@ -86,13 +112,16 @@ public:
|
|||||||
|
|
||||||
response->SetStatus(test_results_->status_code);
|
response->SetStatus(test_results_->status_code);
|
||||||
|
|
||||||
bool handled = !test_results_->html.empty();
|
if (!test_results_->redirect_url.empty()) {
|
||||||
if(handled) {
|
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();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Cancel()
|
virtual void Cancel()
|
||||||
@ -251,6 +280,24 @@ TEST(SchemeHandlerTest, StandardSchemeNoResponse)
|
|||||||
EXPECT_FALSE(g_TestResults.got_output);
|
EXPECT_FALSE(g_TestResults.got_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that a standard scheme can generate redirects.
|
||||||
|
TEST(SchemeHandlerTest, StandardSchemeRedirect)
|
||||||
|
{
|
||||||
|
CreateStandardTestScheme();
|
||||||
|
g_TestResults.url = "stdscheme://tests/run.html";
|
||||||
|
g_TestResults.redirect_url = "stdscheme://tests/redirect.html";
|
||||||
|
g_TestResults.html =
|
||||||
|
"<html><head></head><body><h1>Redirected</h1></body></html>";
|
||||||
|
|
||||||
|
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);
|
||||||
|
EXPECT_TRUE(g_TestResults.got_redirect);
|
||||||
|
}
|
||||||
|
|
||||||
// Test that a non-standard scheme can return normal results.
|
// Test that a non-standard scheme can return normal results.
|
||||||
TEST(SchemeHandlerTest, NonStandardSchemeNormalResponse)
|
TEST(SchemeHandlerTest, NonStandardSchemeNormalResponse)
|
||||||
{
|
{
|
||||||
@ -313,3 +360,21 @@ TEST(SchemeHandlerTest, NonStandardSchemeNoResponse)
|
|||||||
EXPECT_FALSE(g_TestResults.got_read);
|
EXPECT_FALSE(g_TestResults.got_read);
|
||||||
EXPECT_FALSE(g_TestResults.got_output);
|
EXPECT_FALSE(g_TestResults.got_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that a non-standard scheme can generate redirects.
|
||||||
|
TEST(SchemeHandlerTest, NonStandardSchemeRedirect)
|
||||||
|
{
|
||||||
|
CreateNonStandardTestScheme();
|
||||||
|
g_TestResults.url = "nonstdscheme:some%20value";
|
||||||
|
g_TestResults.redirect_url = "nonstdscheme:some%20other%20value";
|
||||||
|
g_TestResults.html =
|
||||||
|
"<html><head></head><body><h1>Redirected</h1></body></html>";
|
||||||
|
|
||||||
|
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);
|
||||||
|
EXPECT_TRUE(g_TestResults.got_redirect);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user