Convert usage and tests to the new CefResourceHandler API (see issue #2622)

Limited test coverage for the old API is still available by passing the
`--test-old-resource-api` command-line flag to ceftests.
This commit is contained in:
Marshall Greenblatt
2019-12-31 14:24:10 +02:00
parent dfcfb51bef
commit 1c88c74f86
12 changed files with 1293 additions and 409 deletions

View File

@ -37,14 +37,10 @@
#define CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_ #define CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_
#pragma once #pragma once
#include "include/base/cef_logging.h"
#include "include/base/cef_macros.h" #include "include/base/cef_macros.h"
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_base.h"
#include "include/cef_resource_handler.h" #include "include/cef_resource_handler.h"
#include "include/cef_response.h" #include "include/cef_response.h"
#include "include/cef_stream.h"
class CefStreamReader;
/// ///
// Implementation of the CefResourceHandler class for reading from a CefStream. // Implementation of the CefResourceHandler class for reading from a CefStream.
@ -65,37 +61,25 @@ class CefStreamResourceHandler : public CefResourceHandler {
CefResponse::HeaderMap header_map, CefResponse::HeaderMap header_map,
CefRefPtr<CefStreamReader> stream); CefRefPtr<CefStreamReader> stream);
virtual ~CefStreamResourceHandler();
// CefResourceHandler methods. // CefResourceHandler methods.
virtual bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) OVERRIDE; CefRefPtr<CefCallback> callback) OVERRIDE;
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response, void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length, int64& response_length,
CefString& redirectUrl) OVERRIDE; CefString& redirectUrl) OVERRIDE;
virtual bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) OVERRIDE; CefRefPtr<CefResourceReadCallback> callback) OVERRIDE;
virtual void Cancel() OVERRIDE; void Cancel() OVERRIDE;
private: private:
void ReadOnFileThread(int bytes_to_read, CefRefPtr<CefCallback> callback);
const int status_code_; const int status_code_;
const CefString status_text_; const CefString status_text_;
const CefString mime_type_; const CefString mime_type_;
const CefResponse::HeaderMap header_map_; const CefResponse::HeaderMap header_map_;
const CefRefPtr<CefStreamReader> stream_; const CefRefPtr<CefStreamReader> stream_;
bool read_on_file_thread_;
class Buffer;
scoped_ptr<Buffer> buffer_;
#if DCHECK_IS_ON()
// Used in debug builds to verify that |buffer_| isn't being accessed on
// multiple threads at the same time.
bool buffer_owned_by_file_thread_;
#endif
IMPLEMENT_REFCOUNTING(CefStreamResourceHandler); IMPLEMENT_REFCOUNTING(CefStreamResourceHandler);
DISALLOW_COPY_AND_ASSIGN(CefStreamResourceHandler); DISALLOW_COPY_AND_ASSIGN(CefStreamResourceHandler);

View File

@ -52,9 +52,11 @@ class RedirectHandler : public CefResourceHandler {
public: public:
explicit RedirectHandler(const GURL& url) : url_(url) {} explicit RedirectHandler(const GURL& url) : url_(url) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
callback->Continue(); // Continue immediately.
handle_request = true;
return true; return true;
} }
@ -65,10 +67,11 @@ class RedirectHandler : public CefResourceHandler {
redirectUrl = url_.spec(); redirectUrl = url_.spec();
} }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
NOTREACHED();
return false; return false;
} }
@ -78,6 +81,7 @@ class RedirectHandler : public CefResourceHandler {
GURL url_; GURL url_;
IMPLEMENT_REFCOUNTING(RedirectHandler); IMPLEMENT_REFCOUNTING(RedirectHandler);
DISALLOW_COPY_AND_ASSIGN(RedirectHandler);
}; };
class InternalHandler : public CefResourceHandler { class InternalHandler : public CefResourceHandler {
@ -87,9 +91,11 @@ class InternalHandler : public CefResourceHandler {
int size) int size)
: mime_type_(mime_type), reader_(reader), size_(size) {} : mime_type_(mime_type), reader_(reader), size_(size) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
callback->Continue(); // Continue immediately.
handle_request = true;
return true; return true;
} }
@ -102,11 +108,21 @@ class InternalHandler : public CefResourceHandler {
response->SetStatus(200); response->SetStatus(200);
} }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
bytes_read = reader_->Read(data_out, 1, bytes_to_read); // Read until the buffer is full or until Read() returns 0 to indicate no
// more data.
bytes_read = 0;
int read = 0;
do {
read = static_cast<int>(
reader_->Read(static_cast<char*>(data_out) + bytes_read, 1,
bytes_to_read - bytes_read));
bytes_read += read;
} while (read != 0 && bytes_read < bytes_to_read);
return (bytes_read > 0); return (bytes_read > 0);
} }
@ -118,6 +134,7 @@ class InternalHandler : public CefResourceHandler {
int size_; int size_;
IMPLEMENT_REFCOUNTING(InternalHandler); IMPLEMENT_REFCOUNTING(InternalHandler);
DISALLOW_COPY_AND_ASSIGN(InternalHandler);
}; };
class InternalHandlerFactory : public CefSchemeHandlerFactory { class InternalHandlerFactory : public CefSchemeHandlerFactory {
@ -170,6 +187,7 @@ class InternalHandlerFactory : public CefSchemeHandlerFactory {
std::unique_ptr<InternalHandlerDelegate> delegate_; std::unique_ptr<InternalHandlerDelegate> delegate_;
IMPLEMENT_REFCOUNTING(InternalHandlerFactory); IMPLEMENT_REFCOUNTING(InternalHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(InternalHandlerFactory);
}; };
} // namespace } // namespace

View File

@ -6,84 +6,19 @@
#include <algorithm> #include <algorithm>
#include "include/base/cef_bind.h"
#include "include/base/cef_logging.h" #include "include/base/cef_logging.h"
#include "include/base/cef_macros.h" #include "include/cef_task.h"
#include "include/cef_callback.h"
#include "include/cef_request.h"
#include "include/cef_stream.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h" #include "include/wrapper/cef_helpers.h"
// Class that represents a readable/writable character buffer.
class CefStreamResourceHandler::Buffer {
public:
Buffer() : size_(0), bytes_requested_(0), bytes_written_(0), bytes_read_(0) {}
void Reset(int new_size) {
if (size_ < new_size) {
size_ = new_size;
buffer_.reset(new char[size_]);
DCHECK(buffer_);
}
bytes_requested_ = new_size;
bytes_written_ = 0;
bytes_read_ = 0;
}
bool IsEmpty() const { return (bytes_written_ == 0); }
bool CanRead() const { return (bytes_read_ < bytes_written_); }
int WriteTo(void* data_out, int bytes_to_read) {
const int write_size =
std::min(bytes_to_read, bytes_written_ - bytes_read_);
if (write_size > 0) {
memcpy(data_out, buffer_.get() + bytes_read_, write_size);
bytes_read_ += write_size;
}
return write_size;
}
int ReadFrom(CefRefPtr<CefStreamReader> reader) {
// Read until the buffer is full or until Read() returns 0 to indicate no
// more data.
int bytes_read;
do {
bytes_read =
static_cast<int>(reader->Read(buffer_.get() + bytes_written_, 1,
bytes_requested_ - bytes_written_));
bytes_written_ += bytes_read;
} while (bytes_read != 0 && bytes_written_ < bytes_requested_);
return bytes_written_;
}
private:
scoped_ptr<char[]> buffer_;
int size_;
int bytes_requested_;
int bytes_written_;
int bytes_read_;
DISALLOW_COPY_AND_ASSIGN(Buffer);
};
CefStreamResourceHandler::CefStreamResourceHandler( CefStreamResourceHandler::CefStreamResourceHandler(
const CefString& mime_type, const CefString& mime_type,
CefRefPtr<CefStreamReader> stream) CefRefPtr<CefStreamReader> stream)
: status_code_(200), : status_code_(200),
status_text_("OK"), status_text_("OK"),
mime_type_(mime_type), mime_type_(mime_type),
stream_(stream) stream_(stream) {
#if DCHECK_IS_ON()
,
buffer_owned_by_file_thread_(false)
#endif
{
DCHECK(!mime_type_.empty()); DCHECK(!mime_type_.empty());
DCHECK(stream_.get()); DCHECK(stream_.get());
read_on_file_thread_ = stream_->MayBlock();
} }
CefStreamResourceHandler::CefStreamResourceHandler( CefStreamResourceHandler::CefStreamResourceHandler(
@ -96,22 +31,18 @@ CefStreamResourceHandler::CefStreamResourceHandler(
status_text_(status_text), status_text_(status_text),
mime_type_(mime_type), mime_type_(mime_type),
header_map_(header_map), header_map_(header_map),
stream_(stream) stream_(stream) {
#if DCHECK_IS_ON()
,
buffer_owned_by_file_thread_(false)
#endif
{
DCHECK(!mime_type_.empty()); DCHECK(!mime_type_.empty());
DCHECK(stream_.get()); DCHECK(stream_.get());
read_on_file_thread_ = stream_->MayBlock();
} }
CefStreamResourceHandler::~CefStreamResourceHandler() {} bool CefStreamResourceHandler::Open(CefRefPtr<CefRequest> request,
bool& handle_request,
bool CefStreamResourceHandler::ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) { CefRefPtr<CefCallback> callback) {
callback->Continue(); DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
// Continue the request immediately.
handle_request = true;
return true; return true;
} }
@ -119,6 +50,8 @@ void CefStreamResourceHandler::GetResponseHeaders(
CefRefPtr<CefResponse> response, CefRefPtr<CefResponse> response,
int64& response_length, int64& response_length,
CefString& redirectUrl) { CefString& redirectUrl) {
CEF_REQUIRE_IO_THREAD();
response->SetStatus(status_code_); response->SetStatus(status_code_);
response->SetStatusText(status_text_); response->SetStatusText(status_text_);
response->SetMimeType(mime_type_); response->SetMimeType(mime_type_);
@ -129,38 +62,14 @@ void CefStreamResourceHandler::GetResponseHeaders(
response_length = -1; response_length = -1;
} }
bool CefStreamResourceHandler::ReadResponse(void* data_out, bool CefStreamResourceHandler::Read(
void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) { CefRefPtr<CefResourceReadCallback> callback) {
DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
DCHECK_GT(bytes_to_read, 0); DCHECK_GT(bytes_to_read, 0);
if (read_on_file_thread_) {
#if DCHECK_IS_ON()
DCHECK(!buffer_owned_by_file_thread_);
#endif
if (buffer_ && (buffer_->CanRead() || buffer_->IsEmpty())) {
if (buffer_->CanRead()) {
// Provide data from the buffer.
bytes_read = buffer_->WriteTo(data_out, bytes_to_read);
return (bytes_read > 0);
} else {
// End of the steam.
bytes_read = 0;
return false;
}
} else {
// Perform another read on the file thread.
bytes_read = 0;
#if DCHECK_IS_ON()
buffer_owned_by_file_thread_ = true;
#endif
CefPostTask(TID_FILE,
base::Bind(&CefStreamResourceHandler::ReadOnFileThread, this,
bytes_to_read, callback));
return true;
}
} else {
// Read until the buffer is full or until Read() returns 0 to indicate no // Read until the buffer is full or until Read() returns 0 to indicate no
// more data. // more data.
bytes_read = 0; bytes_read = 0;
@ -174,25 +83,5 @@ bool CefStreamResourceHandler::ReadResponse(void* data_out,
return (bytes_read > 0); return (bytes_read > 0);
} }
}
void CefStreamResourceHandler::Cancel() {} void CefStreamResourceHandler::Cancel() {}
void CefStreamResourceHandler::ReadOnFileThread(
int bytes_to_read,
CefRefPtr<CefCallback> callback) {
CEF_REQUIRE_FILE_THREAD();
#if DCHECK_IS_ON()
DCHECK(buffer_owned_by_file_thread_);
#endif
if (!buffer_)
buffer_.reset(new Buffer());
buffer_->Reset(bytes_to_read);
buffer_->ReadFrom(stream_);
#if DCHECK_IS_ON()
buffer_owned_by_file_thread_ = false;
#endif
callback->Continue();
}

View File

@ -28,9 +28,13 @@ class ClientSchemeHandler : public CefResourceHandler {
public: public:
ClientSchemeHandler() : offset_(0) {} ClientSchemeHandler() : offset_(0) {}
virtual bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) OVERRIDE { CefRefPtr<CefCallback> callback) OVERRIDE {
CEF_REQUIRE_IO_THREAD(); DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
// The request will be continued or canceled based on the return value.
handle_request = true;
bool handled = false; bool handled = false;
@ -70,16 +74,10 @@ class ClientSchemeHandler : public CefResourceHandler {
} }
} }
if (handled) { return handled;
// Indicate the headers are available.
callback->Continue();
return true;
} }
return false; void GetResponseHeaders(CefRefPtr<CefResponse> response,
}
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length, int64& response_length,
CefString& redirectUrl) OVERRIDE { CefString& redirectUrl) OVERRIDE {
CEF_REQUIRE_IO_THREAD(); CEF_REQUIRE_IO_THREAD();
@ -93,13 +91,13 @@ class ClientSchemeHandler : public CefResourceHandler {
response_length = data_.length(); response_length = data_.length();
} }
virtual void Cancel() OVERRIDE { CEF_REQUIRE_IO_THREAD(); } void Cancel() OVERRIDE { CEF_REQUIRE_IO_THREAD(); }
virtual bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) OVERRIDE { CefRefPtr<CefResourceReadCallback> callback) OVERRIDE {
CEF_REQUIRE_IO_THREAD(); DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
bool has_data = false; bool has_data = false;
bytes_read = 0; bytes_read = 0;
@ -124,14 +122,16 @@ class ClientSchemeHandler : public CefResourceHandler {
size_t offset_; size_t offset_;
IMPLEMENT_REFCOUNTING(ClientSchemeHandler); IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandler);
}; };
// Implementation of the factory for for creating schema handlers. // Implementation of the factory for for creating schema handlers.
class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory { class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
public: public:
ClientSchemeHandlerFactory() {}
// Return a new scheme handler instance to handle the request. // Return a new scheme handler instance to handle the request.
virtual CefRefPtr<CefResourceHandler> Create( CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
const CefString& scheme_name, const CefString& scheme_name,
CefRefPtr<CefRequest> request) OVERRIDE { CefRefPtr<CefRequest> request) OVERRIDE {
@ -140,6 +140,7 @@ class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
} }
IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerFactory);
}; };
} // namespace } // namespace

View File

@ -709,8 +709,11 @@ class CookieTestSchemeHandler : public TestHandler {
explicit SchemeHandler(CookieTestSchemeHandler* handler) explicit SchemeHandler(CookieTestSchemeHandler* handler)
: handler_(handler), offset_(0) {} : handler_(handler), offset_(0) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
std::string url = request->GetURL(); std::string url = request->GetURL();
if (url == handler_->url1_) { if (url == handler_->url1_) {
content_ = "<html><body>COOKIE TEST1</body></html>"; content_ = "<html><body>COOKIE TEST1</body></html>";
@ -731,7 +734,9 @@ class CookieTestSchemeHandler : public TestHandler {
if (it != headerMap.end() && it->second == "name2=value2") if (it != headerMap.end() && it->second == "name2=value2")
handler_->got_process_request_cookie_.yes(); handler_->got_process_request_cookie_.yes();
} }
callback->Continue();
// Continue immediately.
handle_request = true;
return true; return true;
} }
@ -751,10 +756,12 @@ class CookieTestSchemeHandler : public TestHandler {
} }
} }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
bool has_data = false; bool has_data = false;
bytes_read = 0; bytes_read = 0;
@ -781,6 +788,7 @@ class CookieTestSchemeHandler : public TestHandler {
std::string cookie_; std::string cookie_;
IMPLEMENT_REFCOUNTING(SchemeHandler); IMPLEMENT_REFCOUNTING(SchemeHandler);
DISALLOW_COPY_AND_ASSIGN(SchemeHandler);
}; };
class SchemeHandlerFactory : public CefSchemeHandlerFactory { class SchemeHandlerFactory : public CefSchemeHandlerFactory {
@ -810,6 +818,7 @@ class CookieTestSchemeHandler : public TestHandler {
CookieTestSchemeHandler* handler_; CookieTestSchemeHandler* handler_;
IMPLEMENT_REFCOUNTING(SchemeHandlerFactory); IMPLEMENT_REFCOUNTING(SchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(SchemeHandlerFactory);
}; };
CookieTestSchemeHandler(const std::string& scheme, CookieTestSchemeHandler(const std::string& scheme,
@ -1106,9 +1115,10 @@ class CookieAccessSchemeHandler : public CefResourceHandler {
explicit CookieAccessSchemeHandler(CookieAccessData* data) explicit CookieAccessSchemeHandler(CookieAccessData* data)
: data_(data), offset_(0) {} : data_(data), offset_(0) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
EXPECT_IO_THREAD(); EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
CefRequest::HeaderMap headerMap; CefRequest::HeaderMap headerMap;
request->GetHeaderMap(headerMap); request->GetHeaderMap(headerMap);
@ -1116,7 +1126,7 @@ class CookieAccessSchemeHandler : public CefResourceHandler {
TestCookieString(cookie_str, data_->cookie_js_ct_, data_->cookie_net_ct_); TestCookieString(cookie_str, data_->cookie_js_ct_, data_->cookie_net_ct_);
// Continue immediately. // Continue immediately.
callback->Continue(); handle_request = true;
return true; return true;
} }
@ -1136,11 +1146,11 @@ class CookieAccessSchemeHandler : public CefResourceHandler {
response_length = data_->response_data.length(); response_length = data_->response_data.length();
} }
bool ReadResponse(void* response_data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_IO_THREAD(); EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
bool has_data = false; bool has_data = false;
bytes_read = 0; bytes_read = 0;
@ -1149,8 +1159,7 @@ class CookieAccessSchemeHandler : public CefResourceHandler {
if (offset_ < size) { if (offset_ < size) {
int transfer_size = int transfer_size =
std::min(bytes_to_read, static_cast<int>(size - offset_)); std::min(bytes_to_read, static_cast<int>(size - offset_));
memcpy(response_data_out, data_->response_data.c_str() + offset_, memcpy(data_out, data_->response_data.c_str() + offset_, transfer_size);
transfer_size);
offset_ += transfer_size; offset_ += transfer_size;
bytes_read = transfer_size; bytes_read = transfer_size;
@ -1185,6 +1194,7 @@ class CookieAccessSchemeHandler : public CefResourceHandler {
size_t offset_; size_t offset_;
IMPLEMENT_REFCOUNTING(CookieAccessSchemeHandler); IMPLEMENT_REFCOUNTING(CookieAccessSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(CookieAccessSchemeHandler);
}; };
class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory, class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory,

View File

@ -22,7 +22,7 @@ const char kTestContentDisposition[] =
const char kTestMimeType[] = "text/plain"; const char kTestMimeType[] = "text/plain";
const char kTestContent[] = "Download test text"; const char kTestContent[] = "Download test text";
typedef base::Callback<void(CefRefPtr<CefCallback> /*callback*/)> DelayCallback; typedef base::Callback<void(const base::Closure& /*callback*/)> DelayCallback;
class DownloadSchemeHandler : public CefResourceHandler { class DownloadSchemeHandler : public CefResourceHandler {
public: public:
@ -33,8 +33,11 @@ class DownloadSchemeHandler : public CefResourceHandler {
should_delay_(false), should_delay_(false),
offset_(0) {} offset_(0) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
std::string url = request->GetURL(); std::string url = request->GetURL();
if (url == kTestDownloadUrl) { if (url == kTestDownloadUrl) {
got_download_request_->yes(); got_download_request_->yes();
@ -44,10 +47,14 @@ class DownloadSchemeHandler : public CefResourceHandler {
should_delay_ = true; should_delay_ = true;
} else { } else {
EXPECT_TRUE(false); // Not reached. EXPECT_TRUE(false); // Not reached.
// Cancel immediately.
handle_request = true;
return false; return false;
} }
callback->Continue(); // Continue immediately.
handle_request = true;
return true; return true;
} }
@ -68,19 +75,37 @@ class DownloadSchemeHandler : public CefResourceHandler {
} }
} }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
bytes_read = 0; bytes_read = 0;
if (should_delay_ && !delay_callback_.is_null()) { if (should_delay_ && !delay_callback_.is_null()) {
// Delay the download response a single time. // Delay the download response a single time.
delay_callback_.Run(callback); delay_callback_.Run(base::Bind(&DownloadSchemeHandler::ContinueRead, this,
data_out, bytes_to_read, callback));
delay_callback_.Reset(); delay_callback_.Reset();
return true; return true;
} }
return DoRead(data_out, bytes_to_read, bytes_read);
}
void Cancel() override {}
private:
void ContinueRead(void* data_out,
int bytes_to_read,
CefRefPtr<CefResourceReadCallback> callback) {
int bytes_read = 0;
DoRead(data_out, bytes_to_read, bytes_read);
callback->Continue(bytes_read);
}
bool DoRead(void* data_out, int bytes_to_read, int& bytes_read) {
bool has_data = false; bool has_data = false;
size_t size = content_.size(); size_t size = content_.size();
if (offset_ < size) { if (offset_ < size) {
@ -96,9 +121,6 @@ class DownloadSchemeHandler : public CefResourceHandler {
return has_data; return has_data;
} }
void Cancel() override {}
private:
DelayCallback delay_callback_; DelayCallback delay_callback_;
TrackCallback* got_download_request_; TrackCallback* got_download_request_;
bool should_delay_; bool should_delay_;
@ -106,8 +128,10 @@ class DownloadSchemeHandler : public CefResourceHandler {
std::string mime_type_; std::string mime_type_;
std::string content_disposition_; std::string content_disposition_;
size_t offset_; size_t offset_;
CefRefPtr<CefResourceReadCallback> read_callback_;
IMPLEMENT_REFCOUNTING(DownloadSchemeHandler); IMPLEMENT_REFCOUNTING(DownloadSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(DownloadSchemeHandler);
}; };
class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory { class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
@ -129,6 +153,7 @@ class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
TrackCallback* got_download_request_; TrackCallback* got_download_request_;
IMPLEMENT_REFCOUNTING(DownloadSchemeHandlerFactory); IMPLEMENT_REFCOUNTING(DownloadSchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(DownloadSchemeHandlerFactory);
}; };
class DownloadTestHandler : public TestHandler { class DownloadTestHandler : public TestHandler {
@ -239,7 +264,7 @@ class DownloadTestHandler : public TestHandler {
} }
// Callback from the scheme handler when the download request is delayed. // Callback from the scheme handler when the download request is delayed.
void OnDelayCallback(CefRefPtr<CefCallback> callback) { void OnDelayCallback(const base::Closure& callback) {
if (!CefCurrentlyOn(TID_UI)) { if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI, base::Bind(&DownloadTestHandler::OnDelayCallback, CefPostTask(TID_UI, base::Bind(&DownloadTestHandler::OnDelayCallback,
this, callback)); this, callback));
@ -261,8 +286,9 @@ class DownloadTestHandler : public TestHandler {
void ContinueNavigatedIfReady() { void ContinueNavigatedIfReady() {
EXPECT_EQ(test_mode_, NAVIGATED); EXPECT_EQ(test_mode_, NAVIGATED);
if (got_delay_callback_ && got_nav_load_) { if (got_delay_callback_ && got_nav_load_) {
delay_callback_->Continue(); EXPECT_FALSE(delay_callback_.is_null());
delay_callback_ = nullptr; delay_callback_.Run();
delay_callback_.Reset();
} }
} }
@ -462,7 +488,7 @@ class DownloadTestHandler : public TestHandler {
CefRefPtr<CefRequestContext> request_context_; CefRefPtr<CefRequestContext> request_context_;
// Used with NAVIGATED and PENDING test modes. // Used with NAVIGATED and PENDING test modes.
CefRefPtr<CefCallback> delay_callback_; base::Closure delay_callback_;
// Used with PENDING test mode. // Used with PENDING test mode.
CefRefPtr<CefDownloadItemCallback> download_item_callback_; CefRefPtr<CefDownloadItemCallback> download_item_callback_;

View File

@ -688,9 +688,10 @@ class RedirectSchemeHandler : public CefResourceHandler {
public: public:
RedirectSchemeHandler() : offset_(0), status_(0) {} RedirectSchemeHandler() : offset_(0), status_(0) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(CefCurrentlyOn(TID_IO)); EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
std::string url = request->GetURL(); std::string url = request->GetURL();
if (url == kRNav1) { if (url == kRNav1) {
@ -711,14 +712,17 @@ class RedirectSchemeHandler : public CefResourceHandler {
content_ = "<html><body>Nav4</body></html>"; content_ = "<html><body>Nav4</body></html>";
} }
handle_request = true;
if (status_ != 0) { if (status_ != 0) {
callback->Continue(); // Continue request.
return true; return true;
} else { }
// Cancel request.
g_got_invalid_request = true; g_got_invalid_request = true;
return false; return false;
} }
}
void GetResponseHeaders(CefRefPtr<CefResponse> response, void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length, int64& response_length,
@ -748,11 +752,14 @@ class RedirectSchemeHandler : public CefResourceHandler {
void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); } void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_TRUE(CefCurrentlyOn(TID_IO)); EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
bytes_read = 0;
bool has_data = false;
size_t size = content_.size(); size_t size = content_.size();
if (offset_ < size) { if (offset_ < size) {
@ -762,10 +769,10 @@ class RedirectSchemeHandler : public CefResourceHandler {
offset_ += transfer_size; offset_ += transfer_size;
bytes_read = transfer_size; bytes_read = transfer_size;
return true; has_data = true;
} }
return false; return has_data;
} }
protected: protected:
@ -775,6 +782,7 @@ class RedirectSchemeHandler : public CefResourceHandler {
std::string location_; std::string location_;
IMPLEMENT_REFCOUNTING(RedirectSchemeHandler); IMPLEMENT_REFCOUNTING(RedirectSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(RedirectSchemeHandler);
}; };
class RedirectSchemeHandlerFactory : public CefSchemeHandlerFactory { class RedirectSchemeHandlerFactory : public CefSchemeHandlerFactory {
@ -795,6 +803,7 @@ class RedirectSchemeHandlerFactory : public CefSchemeHandlerFactory {
} }
IMPLEMENT_REFCOUNTING(RedirectSchemeHandlerFactory); IMPLEMENT_REFCOUNTING(RedirectSchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(RedirectSchemeHandlerFactory);
}; };
class RedirectTestHandler : public TestHandler { class RedirectTestHandler : public TestHandler {
@ -2843,9 +2852,13 @@ class UnstartedSchemeHandler : public CefResourceHandler {
public: public:
UnstartedSchemeHandler() {} UnstartedSchemeHandler() {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
callback->Continue(); EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
// Continue immediately.
handle_request = true;
return true; return true;
} }
@ -2859,10 +2872,12 @@ class UnstartedSchemeHandler : public CefResourceHandler {
void Cancel() override { callback_ = nullptr; } void Cancel() override { callback_ = nullptr; }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
callback_ = callback; callback_ = callback;
// Pretend that we'll provide the data later. // Pretend that we'll provide the data later.
@ -2871,9 +2886,10 @@ class UnstartedSchemeHandler : public CefResourceHandler {
} }
protected: protected:
CefRefPtr<CefCallback> callback_; CefRefPtr<CefResourceReadCallback> callback_;
IMPLEMENT_REFCOUNTING(UnstartedSchemeHandler); IMPLEMENT_REFCOUNTING(UnstartedSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(UnstartedSchemeHandler);
}; };
// Browser side. // Browser side.
@ -3055,9 +3071,13 @@ class StalledSchemeHandler : public CefResourceHandler {
public: public:
StalledSchemeHandler() : offset_(0), write_size_(0) {} StalledSchemeHandler() : offset_(0), write_size_(0) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
callback->Continue(); EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
// Continue immediately.
handle_request = true;
return true; return true;
} }
@ -3074,18 +3094,23 @@ class StalledSchemeHandler : public CefResourceHandler {
void Cancel() override { callback_ = nullptr; } void Cancel() override { callback_ = nullptr; }
bool ReadResponse(void* data_out, bool Read(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
bytes_read = 0;
size_t size = content_.size(); size_t size = content_.size();
if (offset_ >= write_size_) { if (offset_ >= write_size_) {
// Now stall. // Now stall.
bytes_read = 0;
callback_ = callback; callback_ = callback;
return true; return true;
} }
bool has_data = false;
if (offset_ < size) { if (offset_ < size) {
// Write up to |write_size_| bytes. // Write up to |write_size_| bytes.
int transfer_size = int transfer_size =
@ -3095,19 +3120,20 @@ class StalledSchemeHandler : public CefResourceHandler {
offset_ += transfer_size; offset_ += transfer_size;
bytes_read = transfer_size; bytes_read = transfer_size;
return true; has_data = true;
} }
return false; return has_data;
} }
protected: protected:
std::string content_; std::string content_;
size_t offset_; size_t offset_;
size_t write_size_; size_t write_size_;
CefRefPtr<CefCallback> callback_; CefRefPtr<CefResourceReadCallback> callback_;
IMPLEMENT_REFCOUNTING(StalledSchemeHandler); IMPLEMENT_REFCOUNTING(StalledSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(StalledSchemeHandler);
}; };
// Browser side. // Browser side.

View File

@ -22,6 +22,7 @@ namespace {
// Normal stream resource handler implementation that additionally verifies // Normal stream resource handler implementation that additionally verifies
// calls to Cancel. // calls to Cancel.
// This also tests the CefStreamResourceHandler implementation.
class NormalResourceHandler : public CefStreamResourceHandler { class NormalResourceHandler : public CefStreamResourceHandler {
public: public:
NormalResourceHandler(int status_code, NormalResourceHandler(int status_code,
@ -50,27 +51,186 @@ class NormalResourceHandler : public CefStreamResourceHandler {
private: private:
const base::Closure destroy_callback_; const base::Closure destroy_callback_;
int cancel_ct_ = 0; int cancel_ct_ = 0;
};
DISALLOW_COPY_AND_ASSIGN(NormalResourceHandler); // Normal stream resource handler implementation that additionally continues
// using the callback object and verifies calls to Cancel.
class CallbackResourceHandler : public CefResourceHandler {
public:
enum Mode {
DELAYED_OPEN,
DELAYED_READ,
IMMEDIATE_OPEN,
IMMEDIATE_READ,
DELAYED_ALL,
IMMEDIATE_ALL,
};
bool IsDelayedOpen() const {
return mode_ == DELAYED_OPEN || mode_ == DELAYED_ALL;
}
bool IsDelayedRead() const {
return mode_ == DELAYED_READ || mode_ == DELAYED_ALL;
}
bool IsImmediateOpen() const {
return mode_ == IMMEDIATE_OPEN || mode_ == IMMEDIATE_ALL;
}
bool IsImmediateRead() const {
return mode_ == IMMEDIATE_READ || mode_ == IMMEDIATE_ALL;
}
CallbackResourceHandler(Mode mode,
int status_code,
const CefString& status_text,
const CefString& mime_type,
CefResponse::HeaderMap header_map,
CefRefPtr<CefStreamReader> stream,
const base::Closure& destroy_callback)
: mode_(mode),
status_code_(status_code),
status_text_(status_text),
mime_type_(mime_type),
header_map_(header_map),
stream_(stream),
destroy_callback_(destroy_callback) {
DCHECK(!mime_type_.empty());
DCHECK(stream_.get());
}
~CallbackResourceHandler() override {
EXPECT_EQ(1, cancel_ct_);
destroy_callback_.Run();
}
bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
if (IsDelayedOpen()) {
// Continue the request asynchronously by executing the callback.
CefPostTask(TID_FILE_USER_VISIBLE,
base::Bind(&CefCallback::Continue, callback));
handle_request = false;
return true;
} else if (IsImmediateOpen()) {
// Continue the request immediately be executing the callback.
callback->Continue();
handle_request = false;
return true;
}
// Continue the request immediately in the default manner.
handle_request = true;
return true;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
response->SetStatus(status_code_);
response->SetStatusText(status_text_);
response->SetMimeType(mime_type_);
if (!header_map_.empty())
response->SetHeaderMap(header_map_);
response_length = -1;
}
bool Read(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
EXPECT_GT(bytes_to_read, 0);
bytes_read = 0;
if (IsDelayedRead()) {
// Continue the request asynchronously by executing the callback.
CefPostTask(TID_FILE_USER_VISIBLE,
base::Bind(&CallbackResourceHandler::ContinueRead, this,
data_out, bytes_to_read, callback));
return true;
} else if (IsImmediateRead()) {
// Continue the request immediately be executing the callback.
ContinueRead(data_out, bytes_to_read, callback);
return true;
}
// Continue the request immediately in the default manner.
return DoRead(data_out, bytes_to_read, bytes_read);
}
void Cancel() override {
EXPECT_IO_THREAD();
cancel_ct_++;
}
private:
void ContinueRead(void* data_out,
int bytes_to_read,
CefRefPtr<CefResourceReadCallback> callback) {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
int bytes_read = 0;
DoRead(data_out, bytes_to_read, bytes_read);
callback->Continue(bytes_read);
}
bool DoRead(void* data_out, int bytes_to_read, int& bytes_read) {
DCHECK_GT(bytes_to_read, 0);
// Read until the buffer is full or until Read() returns 0 to indicate no
// more data.
bytes_read = 0;
int read = 0;
do {
read = static_cast<int>(
stream_->Read(static_cast<char*>(data_out) + bytes_read, 1,
bytes_to_read - bytes_read));
bytes_read += read;
} while (read != 0 && bytes_read < bytes_to_read);
return (bytes_read > 0);
}
const Mode mode_;
const int status_code_;
const CefString status_text_;
const CefString mime_type_;
const CefResponse::HeaderMap header_map_;
const CefRefPtr<CefStreamReader> stream_;
const base::Closure destroy_callback_;
int cancel_ct_ = 0;
IMPLEMENT_REFCOUNTING(CallbackResourceHandler);
DISALLOW_COPY_AND_ASSIGN(CallbackResourceHandler);
}; };
// Resource handler implementation that never completes. Used to test // Resource handler implementation that never completes. Used to test
// destruction handling behavior for in-progress requests. // destruction handling behavior for in-progress requests.
class IncompleteResourceHandler : public CefResourceHandler { class IncompleteResourceHandlerOld : public CefResourceHandler {
public: public:
enum TestMode { enum TestMode {
BLOCK_PROCESS_REQUEST, BLOCK_PROCESS_REQUEST,
BLOCK_READ_RESPONSE, BLOCK_READ_RESPONSE,
}; };
IncompleteResourceHandler(TestMode test_mode, IncompleteResourceHandlerOld(TestMode test_mode,
const std::string& mime_type, const std::string& mime_type,
const base::Closure& destroy_callback) const base::Closure& destroy_callback)
: test_mode_(test_mode), : test_mode_(test_mode),
mime_type_(mime_type), mime_type_(mime_type),
destroy_callback_(destroy_callback) {} destroy_callback_(destroy_callback) {}
~IncompleteResourceHandler() override { ~IncompleteResourceHandlerOld() override {
EXPECT_EQ(1, process_request_ct_); EXPECT_EQ(1, process_request_ct_);
EXPECT_EQ(1, cancel_ct_); EXPECT_EQ(1, cancel_ct_);
@ -147,6 +307,119 @@ class IncompleteResourceHandler : public CefResourceHandler {
CefRefPtr<CefCallback> incomplete_callback_; CefRefPtr<CefCallback> incomplete_callback_;
IMPLEMENT_REFCOUNTING(IncompleteResourceHandlerOld);
DISALLOW_COPY_AND_ASSIGN(IncompleteResourceHandlerOld);
};
class IncompleteResourceHandler : public CefResourceHandler {
public:
enum TestMode {
BLOCK_OPEN,
BLOCK_READ,
};
IncompleteResourceHandler(TestMode test_mode,
const std::string& mime_type,
const base::Closure& destroy_callback)
: test_mode_(test_mode),
mime_type_(mime_type),
destroy_callback_(destroy_callback) {}
~IncompleteResourceHandler() override {
EXPECT_EQ(1, open_ct_);
EXPECT_EQ(1, cancel_ct_);
if (test_mode_ == BLOCK_READ) {
EXPECT_EQ(1, get_response_headers_ct_);
EXPECT_EQ(1, read_ct_);
} else {
EXPECT_EQ(0, get_response_headers_ct_);
EXPECT_EQ(0, read_ct_);
}
destroy_callback_.Run();
}
bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
open_ct_++;
if (test_mode_ == BLOCK_OPEN) {
// Never release or execute this callback.
incomplete_open_callback_ = callback;
} else {
// Continue immediately.
handle_request = true;
}
return true;
}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
return false;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
EXPECT_IO_THREAD();
EXPECT_EQ(test_mode_, BLOCK_READ);
get_response_headers_ct_++;
response->SetStatus(200);
response->SetStatusText("OK");
response->SetMimeType(mime_type_);
response_length = 100;
}
bool Read(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
EXPECT_EQ(test_mode_, BLOCK_READ);
read_ct_++;
// Never release or execute this callback.
incomplete_read_callback_ = callback;
bytes_read = 0;
return true;
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
bytes_read = -2;
return false;
}
void Cancel() override {
EXPECT_IO_THREAD();
cancel_ct_++;
}
private:
const TestMode test_mode_;
const std::string mime_type_;
const base::Closure destroy_callback_;
int open_ct_ = 0;
int get_response_headers_ct_ = 0;
int read_ct_ = 0;
int cancel_ct_ = 0;
CefRefPtr<CefCallback> incomplete_open_callback_;
CefRefPtr<CefResourceReadCallback> incomplete_read_callback_;
IMPLEMENT_REFCOUNTING(IncompleteResourceHandler); IMPLEMENT_REFCOUNTING(IncompleteResourceHandler);
DISALLOW_COPY_AND_ASSIGN(IncompleteResourceHandler); DISALLOW_COPY_AND_ASSIGN(IncompleteResourceHandler);
}; };
@ -175,11 +448,23 @@ class BasicResponseTest : public TestHandler {
// Redirect the request (change the URL) in OnBeforeResourceLoad. // Redirect the request (change the URL) in OnBeforeResourceLoad.
REDIRECT_BEFORE_RESOURCE_LOAD, REDIRECT_BEFORE_RESOURCE_LOAD,
// Return a CefResourceHandler from GetResourceHandler that continues
// immediately by using the callback object instead of the return value.
IMMEDIATE_REQUEST_HANDLER_OPEN,
IMMEDIATE_REQUEST_HANDLER_READ,
IMMEDIATE_REQUEST_HANDLER_ALL,
// Return a CefResourceHandler from GetResourceHandler that continues with
// a delay by using the callback object.
DELAYED_REQUEST_HANDLER_OPEN,
DELAYED_REQUEST_HANDLER_READ,
DELAYED_REQUEST_HANDLER_ALL,
// Return a CefResourceHandler from GetResourceHandler that never completes, // Return a CefResourceHandler from GetResourceHandler that never completes,
// then close the browser to verify destruction handling of in-progress // then close the browser to verify destruction handling of in-progress
// requests. // requests.
INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST, INCOMPLETE_REQUEST_HANDLER_OPEN,
INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE, INCOMPLETE_REQUEST_HANDLER_READ,
// Redirect the request using a CefResourceHandler returned from // Redirect the request using a CefResourceHandler returned from
// GetResourceHandler. // GetResourceHandler.
@ -552,24 +837,7 @@ class BasicResponseTest : public TestHandler {
} }
void DestroyTest() override { void DestroyTest() override {
if (mode_ == LOAD || mode_ == MODIFY_BEFORE_RESOURCE_LOAD) { if (mode_ == RESTART_RESOURCE_RESPONSE) {
EXPECT_EQ(1, on_before_browse_ct_);
EXPECT_EQ(1, get_resource_request_handler_ct_);
EXPECT_EQ(1, get_cookie_access_filter_ct_);
EXPECT_EQ(1, on_before_resource_load_ct_);
EXPECT_EQ(1, get_resource_handler_ct_);
EXPECT_EQ(0, on_resource_redirect_ct_);
// Unhandled requests won't see a call to GetResourceResponseFilter
// or OnResourceResponse.
if (unhandled_) {
EXPECT_EQ(0, get_resource_response_filter_ct_);
EXPECT_EQ(0, on_resource_response_ct_);
} else {
EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(1, on_resource_response_ct_);
}
} else if (mode_ == RESTART_RESOURCE_RESPONSE) {
EXPECT_EQ(1, on_before_browse_ct_); EXPECT_EQ(1, on_before_browse_ct_);
EXPECT_EQ(2, get_resource_request_handler_ct_); EXPECT_EQ(2, get_resource_request_handler_ct_);
EXPECT_EQ(2, get_cookie_access_filter_ct_); EXPECT_EQ(2, get_cookie_access_filter_ct_);
@ -586,6 +854,23 @@ class BasicResponseTest : public TestHandler {
EXPECT_EQ(1, get_resource_response_filter_ct_); EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(2, on_resource_response_ct_); EXPECT_EQ(2, on_resource_response_ct_);
} }
} else if (IsLoad()) {
EXPECT_EQ(1, on_before_browse_ct_);
EXPECT_EQ(1, get_resource_request_handler_ct_);
EXPECT_EQ(1, get_cookie_access_filter_ct_);
EXPECT_EQ(1, on_before_resource_load_ct_);
EXPECT_EQ(1, get_resource_handler_ct_);
EXPECT_EQ(0, on_resource_redirect_ct_);
// Unhandled requests won't see a call to GetResourceResponseFilter
// or OnResourceResponse.
if (unhandled_) {
EXPECT_EQ(0, get_resource_response_filter_ct_);
EXPECT_EQ(0, on_resource_response_ct_);
} else {
EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(1, on_resource_response_ct_);
}
} else if (IsRedirect()) { } else if (IsRedirect()) {
EXPECT_EQ(2, on_before_browse_ct_); EXPECT_EQ(2, on_before_browse_ct_);
EXPECT_EQ(2, get_resource_request_handler_ct_); EXPECT_EQ(2, get_resource_request_handler_ct_);
@ -634,7 +919,7 @@ class BasicResponseTest : public TestHandler {
EXPECT_EQ(0, on_resource_redirect_ct_); EXPECT_EQ(0, on_resource_redirect_ct_);
if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE) { if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ) {
EXPECT_EQ(1, get_resource_response_filter_ct_); EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(1, on_resource_response_ct_); EXPECT_EQ(1, on_resource_response_ct_);
} else { } else {
@ -739,46 +1024,96 @@ class BasicResponseTest : public TestHandler {
return base::Bind(&BasicResponseTest::MaybeDestroyTest, this, true); return base::Bind(&BasicResponseTest::MaybeDestroyTest, this, true);
} }
CefRefPtr<CefResourceHandler> GetOKResource() { bool GetCallbackResourceHandlerMode(CallbackResourceHandler::Mode& mode) {
const std::string& body = GetResponseBody(); switch (mode_) {
case IMMEDIATE_REQUEST_HANDLER_OPEN:
mode = CallbackResourceHandler::IMMEDIATE_OPEN;
return true;
case IMMEDIATE_REQUEST_HANDLER_READ:
mode = CallbackResourceHandler::IMMEDIATE_READ;
return true;
case IMMEDIATE_REQUEST_HANDLER_ALL:
mode = CallbackResourceHandler::IMMEDIATE_ALL;
return true;
case DELAYED_REQUEST_HANDLER_OPEN:
mode = CallbackResourceHandler::DELAYED_OPEN;
return true;
case DELAYED_REQUEST_HANDLER_READ:
mode = CallbackResourceHandler::DELAYED_READ;
return true;
case DELAYED_REQUEST_HANDLER_ALL:
mode = CallbackResourceHandler::DELAYED_ALL;
return true;
default:
break;
}
return false;
}
CefRefPtr<CefResourceHandler> GetResource(int status_code,
const CefString& status_text,
const CefString& mime_type,
CefResponse::HeaderMap header_map,
const std::string& body) {
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData( CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
const_cast<char*>(body.c_str()), body.size()); const_cast<char*>(body.c_str()), body.size());
return new NormalResourceHandler(200, "OK", "text/html", CallbackResourceHandler::Mode handler_mode;
CefResponse::HeaderMap(), stream, if (GetCallbackResourceHandlerMode(handler_mode)) {
return new CallbackResourceHandler(handler_mode, status_code, status_text,
mime_type, header_map, stream,
GetResourceDestroyCallback()); GetResourceDestroyCallback());
} }
return new NormalResourceHandler(status_code, status_text, mime_type,
header_map, stream,
GetResourceDestroyCallback());
}
CefRefPtr<CefResourceHandler> GetOKResource() {
return GetResource(200, "OK", "text/html", CefResponse::HeaderMap(),
GetResponseBody());
}
CefRefPtr<CefResourceHandler> GetRedirectResource( CefRefPtr<CefResourceHandler> GetRedirectResource(
const std::string& redirect_url) { const std::string& redirect_url) {
const std::string& body = GetRedirectBody();
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
const_cast<char*>(body.c_str()), body.size());
CefResponse::HeaderMap headerMap; CefResponse::HeaderMap headerMap;
headerMap.insert(std::make_pair("Location", redirect_url)); headerMap.insert(std::make_pair("Location", redirect_url));
return new NormalResourceHandler(307, "Temporary Redirect", "text/html", return GetResource(307, "Temporary Redirect", "text/html", headerMap,
headerMap, stream, GetRedirectBody());
GetResourceDestroyCallback());
} }
CefRefPtr<CefResourceHandler> GetIncompleteResource() { CefRefPtr<CefResourceHandler> GetIncompleteResource() {
if (TestOldResourceAPI()) {
return new IncompleteResourceHandlerOld(
mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN
? IncompleteResourceHandlerOld::BLOCK_PROCESS_REQUEST
: IncompleteResourceHandlerOld::BLOCK_READ_RESPONSE,
"text/html", GetResourceDestroyCallback());
}
return new IncompleteResourceHandler( return new IncompleteResourceHandler(
mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN
? IncompleteResourceHandler::BLOCK_PROCESS_REQUEST ? IncompleteResourceHandler::BLOCK_OPEN
: IncompleteResourceHandler::BLOCK_READ_RESPONSE, : IncompleteResourceHandler::BLOCK_READ,
"text/html", GetResourceDestroyCallback()); "text/html", GetResourceDestroyCallback());
} }
bool IsLoad() const { bool IsLoad() const {
return mode_ == LOAD || mode_ == MODIFY_BEFORE_RESOURCE_LOAD || return mode_ == LOAD || mode_ == MODIFY_BEFORE_RESOURCE_LOAD ||
mode_ == RESTART_RESOURCE_RESPONSE; mode_ == RESTART_RESOURCE_RESPONSE ||
mode_ == IMMEDIATE_REQUEST_HANDLER_OPEN ||
mode_ == IMMEDIATE_REQUEST_HANDLER_READ ||
mode_ == IMMEDIATE_REQUEST_HANDLER_ALL ||
mode_ == DELAYED_REQUEST_HANDLER_OPEN ||
mode_ == DELAYED_REQUEST_HANDLER_READ ||
mode_ == DELAYED_REQUEST_HANDLER_ALL;
} }
bool IsIncompleteRequestHandler() const { bool IsIncompleteRequestHandler() const {
return mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST || return mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN ||
mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE; mode_ == INCOMPLETE_REQUEST_HANDLER_READ;
} }
bool IsIncomplete() const { bool IsIncomplete() const {
@ -916,7 +1251,7 @@ class BasicResponseTest : public TestHandler {
// response. // response.
const bool incomplete_unhandled = const bool incomplete_unhandled =
(mode_ == INCOMPLETE_BEFORE_RESOURCE_LOAD || (mode_ == INCOMPLETE_BEFORE_RESOURCE_LOAD ||
mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST || mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN ||
(IsAborted() && !custom_scheme_)); (IsAborted() && !custom_scheme_));
if ((unhandled_ && !override_unhandled) || incomplete_unhandled) { if ((unhandled_ && !override_unhandled) || incomplete_unhandled) {
@ -932,7 +1267,7 @@ class BasicResponseTest : public TestHandler {
EXPECT_STREQ("", response->GetMimeType().ToString().c_str()) << callback; EXPECT_STREQ("", response->GetMimeType().ToString().c_str()) << callback;
EXPECT_STREQ("", response->GetCharset().ToString().c_str()) << callback; EXPECT_STREQ("", response->GetCharset().ToString().c_str()) << callback;
} else { } else {
if ((mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE || IsAborted()) && if ((mode_ == INCOMPLETE_REQUEST_HANDLER_READ || IsAborted()) &&
callback == kOnResourceLoadComplete) { callback == kOnResourceLoadComplete) {
// We got a response, but we also got aborted. // We got a response, but we also got aborted.
EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback; EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback;
@ -1060,12 +1395,24 @@ class BasicResponseTest : public TestHandler {
// Tests only supported in handled mode. // Tests only supported in handled mode.
#define BASIC_TEST_HANDLED_MODES(name, custom) \ #define BASIC_TEST_HANDLED_MODES(name, custom) \
BASIC_TEST(name##ImmediateRequestHandlerOpen, \
IMMEDIATE_REQUEST_HANDLER_OPEN, custom, false) \
BASIC_TEST(name##ImmediateRequestHandlerRead, \
IMMEDIATE_REQUEST_HANDLER_READ, custom, false) \
BASIC_TEST(name##ImmediateRequestHandlerAll, IMMEDIATE_REQUEST_HANDLER_ALL, \
custom, false) \
BASIC_TEST(name##DelayedRequestHandlerOpen, DELAYED_REQUEST_HANDLER_OPEN, \
custom, false) \
BASIC_TEST(name##DelayedRequestHandlerRead, DELAYED_REQUEST_HANDLER_READ, \
custom, false) \
BASIC_TEST(name##DelayedRequestHandlerAll, DELAYED_REQUEST_HANDLER_ALL, \
custom, false) \
BASIC_TEST(name##IncompleteBeforeResourceLoad, \ BASIC_TEST(name##IncompleteBeforeResourceLoad, \
INCOMPLETE_BEFORE_RESOURCE_LOAD, custom, false) \ INCOMPLETE_BEFORE_RESOURCE_LOAD, custom, false) \
BASIC_TEST(name##IncompleteRequestHandlerProcessRequest, \ BASIC_TEST(name##IncompleteRequestHandlerOpen, \
INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST, custom, false) \ INCOMPLETE_REQUEST_HANDLER_OPEN, custom, false) \
BASIC_TEST(name##IncompleteRequestHandlerReadResponse, \ BASIC_TEST(name##IncompleteRequestHandlerRead, \
INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE, custom, false) INCOMPLETE_REQUEST_HANDLER_READ, custom, false)
BASIC_TEST_ALL_MODES(StandardHandled, false, false) BASIC_TEST_ALL_MODES(StandardHandled, false, false)
BASIC_TEST_ALL_MODES(StandardUnhandled, false, true) BASIC_TEST_ALL_MODES(StandardUnhandled, false, true)
@ -1095,11 +1442,23 @@ class SubresourceResponseTest : public RoutingTestHandler {
// Redirect the request (change the URL) in OnBeforeResourceLoad. // Redirect the request (change the URL) in OnBeforeResourceLoad.
REDIRECT_BEFORE_RESOURCE_LOAD, REDIRECT_BEFORE_RESOURCE_LOAD,
// Return a CefResourceHandler from GetResourceHandler that continues
// immediately by using the callback object instead of the return value.
IMMEDIATE_REQUEST_HANDLER_OPEN,
IMMEDIATE_REQUEST_HANDLER_READ,
IMMEDIATE_REQUEST_HANDLER_ALL,
// Return a CefResourceHandler from GetResourceHandler that continues with
// a delay by using the callback object.
DELAYED_REQUEST_HANDLER_OPEN,
DELAYED_REQUEST_HANDLER_READ,
DELAYED_REQUEST_HANDLER_ALL,
// Return a CefResourceHandler from GetResourceHandler that never completes, // Return a CefResourceHandler from GetResourceHandler that never completes,
// then close the browser to verify destruction handling of in-progress // then close the browser to verify destruction handling of in-progress
// requests. // requests.
INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST, INCOMPLETE_REQUEST_HANDLER_OPEN,
INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE, INCOMPLETE_REQUEST_HANDLER_READ,
// Redirect the request using a CefResourceHandler returned from // Redirect the request using a CefResourceHandler returned from
// GetResourceHandler. // GetResourceHandler.
@ -1581,22 +1940,7 @@ class SubresourceResponseTest : public RoutingTestHandler {
EXPECT_EQ(1, on_before_browse_ct_); EXPECT_EQ(1, on_before_browse_ct_);
} }
if (mode_ == LOAD || mode_ == MODIFY_BEFORE_RESOURCE_LOAD) { if (mode_ == RESTART_RESOURCE_RESPONSE) {
EXPECT_EQ(1, get_resource_request_handler_ct_);
EXPECT_EQ(1, get_cookie_access_filter_ct_);
EXPECT_EQ(1, on_before_resource_load_ct_);
EXPECT_EQ(1, get_resource_handler_ct_);
EXPECT_EQ(0, on_resource_redirect_ct_);
// Unhandled requests won't see a call to GetResourceResponseFilter or
// OnResourceResponse.
if (unhandled_) {
EXPECT_EQ(0, get_resource_response_filter_ct_);
EXPECT_EQ(0, on_resource_response_ct_);
} else {
EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(1, on_resource_response_ct_);
}
} else if (mode_ == RESTART_RESOURCE_RESPONSE) {
EXPECT_EQ(2, get_resource_request_handler_ct_); EXPECT_EQ(2, get_resource_request_handler_ct_);
EXPECT_EQ(2, get_cookie_access_filter_ct_); EXPECT_EQ(2, get_cookie_access_filter_ct_);
EXPECT_EQ(2, on_before_resource_load_ct_); EXPECT_EQ(2, on_before_resource_load_ct_);
@ -1612,6 +1956,21 @@ class SubresourceResponseTest : public RoutingTestHandler {
EXPECT_EQ(1, get_resource_response_filter_ct_); EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(2, on_resource_response_ct_); EXPECT_EQ(2, on_resource_response_ct_);
} }
} else if (IsLoad()) {
EXPECT_EQ(1, get_resource_request_handler_ct_);
EXPECT_EQ(1, get_cookie_access_filter_ct_);
EXPECT_EQ(1, on_before_resource_load_ct_);
EXPECT_EQ(1, get_resource_handler_ct_);
EXPECT_EQ(0, on_resource_redirect_ct_);
// Unhandled requests won't see a call to GetResourceResponseFilter or
// OnResourceResponse.
if (unhandled_) {
EXPECT_EQ(0, get_resource_response_filter_ct_);
EXPECT_EQ(0, on_resource_response_ct_);
} else {
EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(1, on_resource_response_ct_);
}
} else if (IsRedirect()) { } else if (IsRedirect()) {
EXPECT_EQ(2, get_resource_request_handler_ct_); EXPECT_EQ(2, get_resource_request_handler_ct_);
EXPECT_EQ(2, get_cookie_access_filter_ct_); EXPECT_EQ(2, get_cookie_access_filter_ct_);
@ -1655,7 +2014,7 @@ class SubresourceResponseTest : public RoutingTestHandler {
EXPECT_EQ(0, on_resource_redirect_ct_); EXPECT_EQ(0, on_resource_redirect_ct_);
if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE) { if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ) {
EXPECT_EQ(1, get_resource_response_filter_ct_); EXPECT_EQ(1, get_resource_response_filter_ct_);
EXPECT_EQ(1, on_resource_response_ct_); EXPECT_EQ(1, on_resource_response_ct_);
} else { } else {
@ -1812,66 +2171,106 @@ class SubresourceResponseTest : public RoutingTestHandler {
return base::Bind(&SubresourceResponseTest::MaybeDestroyTest, this, true); return base::Bind(&SubresourceResponseTest::MaybeDestroyTest, this, true);
} }
CefRefPtr<CefResourceHandler> GetMainResource() { bool GetCallbackResourceHandlerMode(CallbackResourceHandler::Mode& mode) {
const std::string& body = GetMainResponseBody(); switch (mode_) {
case IMMEDIATE_REQUEST_HANDLER_OPEN:
mode = CallbackResourceHandler::IMMEDIATE_OPEN;
return true;
case IMMEDIATE_REQUEST_HANDLER_READ:
mode = CallbackResourceHandler::IMMEDIATE_READ;
return true;
case IMMEDIATE_REQUEST_HANDLER_ALL:
mode = CallbackResourceHandler::IMMEDIATE_ALL;
return true;
case DELAYED_REQUEST_HANDLER_OPEN:
mode = CallbackResourceHandler::DELAYED_OPEN;
return true;
case DELAYED_REQUEST_HANDLER_READ:
mode = CallbackResourceHandler::DELAYED_READ;
return true;
case DELAYED_REQUEST_HANDLER_ALL:
mode = CallbackResourceHandler::DELAYED_ALL;
return true;
default:
break;
}
return false;
}
CefRefPtr<CefResourceHandler> GetResource(int status_code,
const CefString& status_text,
const CefString& mime_type,
CefResponse::HeaderMap header_map,
const std::string& body) {
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData( CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
const_cast<char*>(body.c_str()), body.size()); const_cast<char*>(body.c_str()), body.size());
return new NormalResourceHandler(200, "OK", "text/html", CallbackResourceHandler::Mode handler_mode;
CefResponse::HeaderMap(), stream, if (GetCallbackResourceHandlerMode(handler_mode)) {
return new CallbackResourceHandler(handler_mode, status_code, status_text,
mime_type, header_map, stream,
GetResourceDestroyCallback()); GetResourceDestroyCallback());
} }
return new NormalResourceHandler(status_code, status_text, mime_type,
header_map, stream,
GetResourceDestroyCallback());
}
CefRefPtr<CefResourceHandler> GetMainResource() {
return GetResource(200, "OK", "text/html", CefResponse::HeaderMap(),
GetMainResponseBody());
}
CefRefPtr<CefResourceHandler> GetSubResource() { CefRefPtr<CefResourceHandler> GetSubResource() {
const std::string& body = GetSubResponseBody(); return GetResource(200, "OK", "text/html", CefResponse::HeaderMap(),
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData( GetSubResponseBody());
const_cast<char*>(body.c_str()), body.size());
return new NormalResourceHandler(200, "OK", "text/html",
CefResponse::HeaderMap(), stream,
GetResourceDestroyCallback());
} }
CefRefPtr<CefResourceHandler> GetOKResource() { CefRefPtr<CefResourceHandler> GetOKResource() {
const std::string& body = GetResponseBody(); return GetResource(200, "OK", "text/javascript", CefResponse::HeaderMap(),
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData( GetResponseBody());
const_cast<char*>(body.c_str()), body.size());
return new NormalResourceHandler(200, "OK", "text/javascript",
CefResponse::HeaderMap(), stream,
GetResourceDestroyCallback());
} }
CefRefPtr<CefResourceHandler> GetRedirectResource( CefRefPtr<CefResourceHandler> GetRedirectResource(
const std::string& redirect_url) { const std::string& redirect_url) {
const std::string& body = GetRedirectBody();
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
const_cast<char*>(body.c_str()), body.size());
CefResponse::HeaderMap headerMap; CefResponse::HeaderMap headerMap;
headerMap.insert(std::make_pair("Location", redirect_url)); headerMap.insert(std::make_pair("Location", redirect_url));
return new NormalResourceHandler(307, "Temporary Redirect", return GetResource(307, "Temporary Redirect", "text/javascript", headerMap,
"text/javascript", headerMap, stream, GetRedirectBody());
GetResourceDestroyCallback());
} }
CefRefPtr<CefResourceHandler> GetIncompleteResource() { CefRefPtr<CefResourceHandler> GetIncompleteResource() {
if (TestOldResourceAPI()) {
return new IncompleteResourceHandlerOld(
mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN
? IncompleteResourceHandlerOld::BLOCK_PROCESS_REQUEST
: IncompleteResourceHandlerOld::BLOCK_READ_RESPONSE,
"text/javascript", GetResourceDestroyCallback());
}
return new IncompleteResourceHandler( return new IncompleteResourceHandler(
mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN
? IncompleteResourceHandler::BLOCK_PROCESS_REQUEST ? IncompleteResourceHandler::BLOCK_OPEN
: IncompleteResourceHandler::BLOCK_READ_RESPONSE, : IncompleteResourceHandler::BLOCK_READ,
"text/javascript", GetResourceDestroyCallback()); "text/javascript", GetResourceDestroyCallback());
} }
bool IsLoad() const { bool IsLoad() const {
return mode_ == LOAD || mode_ == MODIFY_BEFORE_RESOURCE_LOAD || return mode_ == LOAD || mode_ == MODIFY_BEFORE_RESOURCE_LOAD ||
mode_ == RESTART_RESOURCE_RESPONSE; mode_ == RESTART_RESOURCE_RESPONSE ||
mode_ == IMMEDIATE_REQUEST_HANDLER_OPEN ||
mode_ == IMMEDIATE_REQUEST_HANDLER_READ ||
mode_ == IMMEDIATE_REQUEST_HANDLER_ALL ||
mode_ == DELAYED_REQUEST_HANDLER_OPEN ||
mode_ == DELAYED_REQUEST_HANDLER_READ ||
mode_ == DELAYED_REQUEST_HANDLER_ALL;
} }
bool IsIncompleteRequestHandler() const { bool IsIncompleteRequestHandler() const {
return mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST || return mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN ||
mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE; mode_ == INCOMPLETE_REQUEST_HANDLER_READ;
} }
bool IsIncomplete() const { bool IsIncomplete() const {
@ -2010,7 +2409,7 @@ class SubresourceResponseTest : public RoutingTestHandler {
// response. // response.
const bool incomplete_unhandled = const bool incomplete_unhandled =
(mode_ == INCOMPLETE_BEFORE_RESOURCE_LOAD || (mode_ == INCOMPLETE_BEFORE_RESOURCE_LOAD ||
mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST); mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN);
if ((unhandled_ && !override_unhandled) || incomplete_unhandled) { if ((unhandled_ && !override_unhandled) || incomplete_unhandled) {
if (incomplete_unhandled) { if (incomplete_unhandled) {
@ -2025,7 +2424,7 @@ class SubresourceResponseTest : public RoutingTestHandler {
EXPECT_STREQ("", response->GetMimeType().ToString().c_str()) << callback; EXPECT_STREQ("", response->GetMimeType().ToString().c_str()) << callback;
EXPECT_STREQ("", response->GetCharset().ToString().c_str()) << callback; EXPECT_STREQ("", response->GetCharset().ToString().c_str()) << callback;
} else { } else {
if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE && if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ &&
callback == kOnResourceLoadComplete) { callback == kOnResourceLoadComplete) {
// We got a response, but we also got aborted. // We got a response, but we also got aborted.
EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback; EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback;
@ -2157,14 +2556,24 @@ class SubresourceResponseTest : public RoutingTestHandler {
// Tests only supported in handled mode. // Tests only supported in handled mode.
#define SUBRESOURCE_TEST_HANDLED_MODES(name, custom, subframe) \ #define SUBRESOURCE_TEST_HANDLED_MODES(name, custom, subframe) \
SUBRESOURCE_TEST(name##ImmediateRequestHandlerOpen, \
IMMEDIATE_REQUEST_HANDLER_OPEN, custom, false, subframe) \
SUBRESOURCE_TEST(name##ImmediateRequestHandlerRead, \
IMMEDIATE_REQUEST_HANDLER_READ, custom, false, subframe) \
SUBRESOURCE_TEST(name##ImmediateRequestHandlerAll, \
IMMEDIATE_REQUEST_HANDLER_ALL, custom, false, subframe) \
SUBRESOURCE_TEST(name##DelayedRequestHandlerOpen, \
DELAYED_REQUEST_HANDLER_OPEN, custom, false, subframe) \
SUBRESOURCE_TEST(name##DelayedRequestHandlerRead, \
DELAYED_REQUEST_HANDLER_READ, custom, false, subframe) \
SUBRESOURCE_TEST(name##DelayedRequestHandlerAll, \
DELAYED_REQUEST_HANDLER_ALL, custom, false, subframe) \
SUBRESOURCE_TEST(name##IncompleteBeforeResourceLoad, \ SUBRESOURCE_TEST(name##IncompleteBeforeResourceLoad, \
INCOMPLETE_BEFORE_RESOURCE_LOAD, custom, false, subframe) \ INCOMPLETE_BEFORE_RESOURCE_LOAD, custom, false, subframe) \
SUBRESOURCE_TEST(name##IncompleteRequestHandlerProcessRequest, \ SUBRESOURCE_TEST(name##IncompleteRequestHandlerOpen, \
INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST, custom, false, \ INCOMPLETE_REQUEST_HANDLER_OPEN, custom, false, subframe) \
subframe) \ SUBRESOURCE_TEST(name##IncompleteRequestHandlerRead, \
SUBRESOURCE_TEST(name##IncompleteRequestHandlerReadResponse, \ INCOMPLETE_REQUEST_HANDLER_READ, custom, false, subframe)
INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE, custom, false, \
subframe)
SUBRESOURCE_TEST_ALL_MODES(StandardHandledMainFrame, false, false, false) SUBRESOURCE_TEST_ALL_MODES(StandardHandledMainFrame, false, false, false)
SUBRESOURCE_TEST_ALL_MODES(StandardUnhandledMainFrame, false, true, false) SUBRESOURCE_TEST_ALL_MODES(StandardUnhandledMainFrame, false, true, false)

View File

@ -212,9 +212,9 @@ class TestSchemeHandler : public TestHandler {
IMPLEMENT_REFCOUNTING(TestSchemeHandler); IMPLEMENT_REFCOUNTING(TestSchemeHandler);
}; };
class ClientSchemeHandler : public CefResourceHandler { class ClientSchemeHandlerOld : public CefResourceHandler {
public: public:
explicit ClientSchemeHandler(TestResults* tr) explicit ClientSchemeHandlerOld(TestResults* tr)
: test_results_(tr), offset_(0), is_sub_(false), has_delayed_(false) {} : test_results_(tr), offset_(0), is_sub_(false), has_delayed_(false) {}
bool ProcessRequest(CefRefPtr<CefRequest> request, bool ProcessRequest(CefRefPtr<CefRequest> request,
@ -329,9 +329,10 @@ class ClientSchemeHandler : public CefResourceHandler {
if (test_results_->delay > 0) { if (test_results_->delay > 0) {
if (!has_delayed_) { if (!has_delayed_) {
// Continue after a delay. // Continue after a delay.
CefPostDelayedTask(TID_IO, CefPostDelayedTask(
base::Bind(&ClientSchemeHandler::ContinueAfterDelay, TID_IO,
this, callback), base::Bind(&ClientSchemeHandlerOld::ContinueAfterDelay, this,
callback),
test_results_->delay); test_results_->delay);
bytes_read = 0; bytes_read = 0;
return true; return true;
@ -378,7 +379,206 @@ class ClientSchemeHandler : public CefResourceHandler {
bool is_sub_; bool is_sub_;
bool has_delayed_; bool has_delayed_;
IMPLEMENT_REFCOUNTING(ClientSchemeHandlerOld);
DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerOld);
};
class ClientSchemeHandler : public CefResourceHandler {
public:
explicit ClientSchemeHandler(TestResults* tr)
: test_results_(tr), offset_(0), is_sub_(false), has_delayed_(false) {}
bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || 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_->html.empty())
handled = true;
}
std::string accept_language;
CefRequest::HeaderMap headerMap;
CefRequest::HeaderMap::iterator headerIter;
request->GetHeaderMap(headerMap);
headerIter = headerMap.find("Accept-Language");
if (headerIter != headerMap.end())
accept_language = headerIter->second;
EXPECT_TRUE(!accept_language.empty());
if (!test_results_->accept_language.empty()) {
// Value from CefBrowserSettings.accept_language set in
// PopulateBrowserSettings().
EXPECT_STREQ(test_results_->accept_language.data(),
accept_language.data());
} else {
// CEF_SETTINGS_ACCEPT_LANGUAGE value from
// CefSettings.accept_language_list set in CefTestSuite::GetSettings()
// and expanded internally by ComputeAcceptLanguageFromPref.
EXPECT_STREQ("en-GB,en;q=0.9", accept_language.data());
}
// Continue or cancel the request immediately based on the return value.
handle_request = true;
if (handled) {
if (test_results_->delay > 0) {
// Continue after the delay.
handle_request = false;
CefPostDelayedTask(TID_FILE_USER_BLOCKING,
base::Bind(&CefCallback::Continue, callback.get()),
test_results_->delay);
}
return true;
} else if (test_results_->response_error_code != ERR_NONE) {
// Propagate the error code.
return true;
}
// Response was canceled.
if (g_current_handler)
g_current_handler->DestroyTest();
return false;
}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
return false;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
if (is_sub_) {
response->SetStatus(test_results_->sub_status_code);
if (!test_results_->sub_allow_origin.empty()) {
// Set the Access-Control-Allow-Origin header to allow cross-domain
// scripting.
CefResponse::HeaderMap headers;
headers.insert(std::make_pair("Access-Control-Allow-Origin",
test_results_->sub_allow_origin));
response->SetHeaderMap(headers);
}
if (!test_results_->sub_html.empty()) {
response->SetMimeType("text/html");
response_length = test_results_->sub_html.size();
}
} else if (!test_results_->redirect_url.empty()) {
redirectUrl = test_results_->redirect_url;
} else if (test_results_->response_error_code != ERR_NONE) {
response->SetError(test_results_->response_error_code);
} else {
response->SetStatus(test_results_->status_code);
if (!test_results_->html.empty()) {
response->SetMimeType("text/html");
response_length = test_results_->html.size();
}
}
}
void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
bool Read(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
if (test_results_->delay > 0) {
if (!has_delayed_) {
// Continue after a delay.
CefPostDelayedTask(TID_FILE_USER_BLOCKING,
base::Bind(&ClientSchemeHandler::ContinueAfterDelay,
this, data_out, bytes_to_read, callback),
test_results_->delay);
bytes_read = 0;
return true;
}
has_delayed_ = false;
}
return GetData(data_out, bytes_to_read, bytes_read);
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
bytes_read = -2;
return false;
}
private:
void ContinueAfterDelay(void* data_out,
int bytes_to_read,
CefRefPtr<CefResourceReadCallback> callback) {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
has_delayed_ = true;
int bytes_read = 0;
GetData(data_out, bytes_to_read, bytes_read);
callback->Continue(bytes_read);
}
bool GetData(void* data_out, int bytes_to_read, int& bytes_read) {
std::string* data;
if (is_sub_) {
test_results_->got_sub_read.yes();
data = &test_results_->sub_html;
} else {
test_results_->got_read.yes();
data = &test_results_->html;
}
// Default to response complete.
bool has_data = false;
bytes_read = 0;
size_t size = data->size();
if (offset_ < size) {
int transfer_size =
std::min(bytes_to_read, static_cast<int>(size - offset_));
memcpy(data_out, data->c_str() + offset_, transfer_size);
offset_ += transfer_size;
bytes_read = transfer_size;
has_data = true;
}
return has_data;
}
TestResults* test_results_;
size_t offset_;
bool is_sub_;
bool has_delayed_;
IMPLEMENT_REFCOUNTING(ClientSchemeHandler); IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandler);
}; };
class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory { class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
@ -390,12 +590,16 @@ class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
const CefString& scheme_name, const CefString& scheme_name,
CefRefPtr<CefRequest> request) override { CefRefPtr<CefRequest> request) override {
EXPECT_TRUE(CefCurrentlyOn(TID_IO)); EXPECT_TRUE(CefCurrentlyOn(TID_IO));
if (TestOldResourceAPI()) {
return new ClientSchemeHandlerOld(test_results_);
}
return new ClientSchemeHandler(test_results_); return new ClientSchemeHandler(test_results_);
} }
TestResults* test_results_; TestResults* test_results_;
IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerFactory);
}; };
// Global test results object. // Global test results object.

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file. // can be found in the LICENSE file.
#include "tests/ceftests/test_util.h" #include "tests/ceftests/test_util.h"
#include "include/cef_command_line.h"
#include "include/cef_request_context_handler.h" #include "include/cef_request_context_handler.h"
#include "tests/gtest/include/gtest/gtest.h" #include "tests/gtest/include/gtest/gtest.h"
@ -266,6 +267,16 @@ void TestStringVectorEqual(const std::vector<CefString>& val1,
EXPECT_STREQ(val1[i].ToString().c_str(), val2[i].ToString().c_str()); EXPECT_STREQ(val1[i].ToString().c_str(), val2[i].ToString().c_str());
} }
bool TestOldResourceAPI() {
static int state = -1;
if (state == -1) {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
state = command_line->HasSwitch("test-old-resource-api") ? 1 : 0;
}
return state ? true : false;
}
CefRefPtr<CefRequestContext> CreateTestRequestContext( CefRefPtr<CefRequestContext> CreateTestRequestContext(
TestRequestContextMode mode, TestRequestContextMode mode,
const std::string& cache_path) { const std::string& cache_path) {

View File

@ -78,6 +78,9 @@ inline bool IsTestRequestContextModeCustom(TestRequestContextMode mode) {
mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER; mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER;
} }
// Returns true if the old CefResourceHandler API should be tested.
bool TestOldResourceAPI();
// Return a RequestContext object matching the specified |mode|. // Return a RequestContext object matching the specified |mode|.
// |cache_path| may be specified for CUSTOM modes. // |cache_path| may be specified for CUSTOM modes.
// Use the RC_TEST_GROUP_BASE macro to test all valid combinations. // Use the RC_TEST_GROUP_BASE macro to test all valid combinations.

View File

@ -546,13 +546,13 @@ bool IsAuthorized(CefRefPtr<CefRequest> request,
// SCHEME HANDLER BACKEND // SCHEME HANDLER BACKEND
// Serves request responses. // Serves request responses.
class RequestSchemeHandler : public CefResourceHandler { class RequestSchemeHandlerOld : public CefResourceHandler {
public: public:
RequestSchemeHandler(RequestRunSettings* settings, RequestSchemeHandlerOld(RequestRunSettings* settings,
const base::Closure& destroy_callback) const base::Closure& destroy_callback)
: settings_(settings), destroy_callback_(destroy_callback) {} : settings_(settings), destroy_callback_(destroy_callback) {}
~RequestSchemeHandler() override { ~RequestSchemeHandlerOld() override {
EXPECT_EQ(1, cancel_ct_); EXPECT_EQ(1, cancel_ct_);
destroy_callback_.Run(); destroy_callback_.Run();
} }
@ -580,7 +580,7 @@ class RequestSchemeHandler : public CefResourceHandler {
response_length = response_data_.length(); response_length = response_data_.length();
} }
bool ReadResponse(void* response_data_out, bool ReadResponse(void* data_out,
int bytes_to_read, int bytes_to_read,
int& bytes_read, int& bytes_read,
CefRefPtr<CefCallback> callback) override { CefRefPtr<CefCallback> callback) override {
@ -593,8 +593,7 @@ class RequestSchemeHandler : public CefResourceHandler {
if (offset_ < size) { if (offset_ < size) {
int transfer_size = int transfer_size =
std::min(bytes_to_read, static_cast<int>(size - offset_)); std::min(bytes_to_read, static_cast<int>(size - offset_));
memcpy(response_data_out, response_data_.c_str() + offset_, memcpy(data_out, response_data_.c_str() + offset_, transfer_size);
transfer_size);
offset_ += transfer_size; offset_ += transfer_size;
bytes_read = transfer_size; bytes_read = transfer_size;
@ -609,6 +608,99 @@ class RequestSchemeHandler : public CefResourceHandler {
cancel_ct_++; cancel_ct_++;
} }
private:
// |settings_| is not owned by this object.
RequestRunSettings* settings_;
base::Closure destroy_callback_;
std::string response_data_;
size_t offset_ = 0;
int cancel_ct_ = 0;
IMPLEMENT_REFCOUNTING(RequestSchemeHandlerOld);
DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandlerOld);
};
class RequestSchemeHandler : public CefResourceHandler {
public:
RequestSchemeHandler(RequestRunSettings* settings,
const base::Closure& destroy_callback)
: settings_(settings), destroy_callback_(destroy_callback) {}
~RequestSchemeHandler() override {
EXPECT_EQ(1, cancel_ct_);
destroy_callback_.Run();
}
bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
VerifyNormalRequest(settings_, request, false);
// HEAD requests are identical to GET requests except no response data is
// sent.
if (request->GetMethod() != "HEAD")
response_data_ = settings_->response_data;
// Continue immediately.
handle_request = true;
return true;
}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
return false;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
EXPECT_IO_THREAD();
GetNormalResponse(settings_, response);
response_length = response_data_.length();
}
bool Read(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
// Default to response complete.
bool has_data = false;
bytes_read = 0;
size_t size = response_data_.length();
if (offset_ < size) {
int transfer_size =
std::min(bytes_to_read, static_cast<int>(size - offset_));
memcpy(data_out, response_data_.c_str() + offset_, transfer_size);
offset_ += transfer_size;
bytes_read = transfer_size;
has_data = true;
}
return has_data;
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
bytes_read = -2;
return false;
}
void Cancel() override {
EXPECT_IO_THREAD();
cancel_ct_++;
}
private: private:
// |settings_| is not owned by this object. // |settings_| is not owned by this object.
RequestRunSettings* settings_; RequestRunSettings* settings_;
@ -620,19 +712,20 @@ class RequestSchemeHandler : public CefResourceHandler {
int cancel_ct_ = 0; int cancel_ct_ = 0;
IMPLEMENT_REFCOUNTING(RequestSchemeHandler); IMPLEMENT_REFCOUNTING(RequestSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandler);
}; };
// Serves redirect request responses. // Serves redirect request responses.
class RequestRedirectSchemeHandler : public CefResourceHandler { class RequestRedirectSchemeHandlerOld : public CefResourceHandler {
public: public:
RequestRedirectSchemeHandler(CefRefPtr<CefRequest> request, RequestRedirectSchemeHandlerOld(CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response, CefRefPtr<CefResponse> response,
const base::Closure& destroy_callback) const base::Closure& destroy_callback)
: request_(request), : request_(request),
response_(response), response_(response),
destroy_callback_(destroy_callback) {} destroy_callback_(destroy_callback) {}
~RequestRedirectSchemeHandler() override { ~RequestRedirectSchemeHandlerOld() override {
EXPECT_EQ(1, cancel_ct_); EXPECT_EQ(1, cancel_ct_);
destroy_callback_.Run(); destroy_callback_.Run();
} }
@ -679,6 +772,89 @@ class RequestRedirectSchemeHandler : public CefResourceHandler {
cancel_ct_++; cancel_ct_++;
} }
private:
CefRefPtr<CefRequest> request_;
CefRefPtr<CefResponse> response_;
base::Closure destroy_callback_;
int cancel_ct_ = 0;
IMPLEMENT_REFCOUNTING(RequestRedirectSchemeHandlerOld);
DISALLOW_COPY_AND_ASSIGN(RequestRedirectSchemeHandlerOld);
};
class RequestRedirectSchemeHandler : public CefResourceHandler {
public:
RequestRedirectSchemeHandler(CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response,
const base::Closure& destroy_callback)
: request_(request),
response_(response),
destroy_callback_(destroy_callback) {}
~RequestRedirectSchemeHandler() override {
EXPECT_EQ(1, cancel_ct_);
destroy_callback_.Run();
}
bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
// Verify that the request was sent correctly.
TestRequestEqual(request_, request, true);
// Continue immediately.
handle_request = true;
return true;
}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
return false;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
EXPECT_IO_THREAD();
response->SetStatus(response_->GetStatus());
response->SetStatusText(response_->GetStatusText());
response->SetMimeType(response_->GetMimeType());
CefResponse::HeaderMap headerMap;
response_->GetHeaderMap(headerMap);
response->SetHeaderMap(headerMap);
response_length = 0;
}
bool Read(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
bytes_read = -1;
return false;
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
bytes_read = -2;
return false;
}
void Cancel() override {
EXPECT_IO_THREAD();
cancel_ct_++;
}
private: private:
CefRefPtr<CefRequest> request_; CefRefPtr<CefRequest> request_;
CefRefPtr<CefResponse> response_; CefRefPtr<CefResponse> response_;
@ -687,19 +863,20 @@ class RequestRedirectSchemeHandler : public CefResourceHandler {
int cancel_ct_ = 0; int cancel_ct_ = 0;
IMPLEMENT_REFCOUNTING(RequestRedirectSchemeHandler); IMPLEMENT_REFCOUNTING(RequestRedirectSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(RequestRedirectSchemeHandler);
}; };
// Resource handler implementation that never completes. Used to test // Resource handler implementation that never completes. Used to test
// destruction handling behavior for in-progress requests. // destruction handling behavior for in-progress requests.
class IncompleteSchemeHandler : public CefResourceHandler { class IncompleteSchemeHandlerOld : public CefResourceHandler {
public: public:
IncompleteSchemeHandler(RequestRunSettings* settings, IncompleteSchemeHandlerOld(RequestRunSettings* settings,
const base::Closure& destroy_callback) const base::Closure& destroy_callback)
: settings_(settings), destroy_callback_(destroy_callback) { : settings_(settings), destroy_callback_(destroy_callback) {
EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE); EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE);
} }
~IncompleteSchemeHandler() override { ~IncompleteSchemeHandlerOld() override {
EXPECT_EQ(1, process_request_ct_); EXPECT_EQ(1, process_request_ct_);
EXPECT_EQ(1, cancel_ct_); EXPECT_EQ(1, cancel_ct_);
@ -783,6 +960,120 @@ class IncompleteSchemeHandler : public CefResourceHandler {
CefRefPtr<CefCallback> incomplete_callback_; CefRefPtr<CefCallback> incomplete_callback_;
IMPLEMENT_REFCOUNTING(IncompleteSchemeHandlerOld);
DISALLOW_COPY_AND_ASSIGN(IncompleteSchemeHandlerOld);
};
class IncompleteSchemeHandler : public CefResourceHandler {
public:
IncompleteSchemeHandler(RequestRunSettings* settings,
const base::Closure& destroy_callback)
: settings_(settings), destroy_callback_(destroy_callback) {
EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE);
}
~IncompleteSchemeHandler() override {
EXPECT_EQ(1, open_ct_);
EXPECT_EQ(1, cancel_ct_);
if (settings_->incomplete_type ==
RequestRunSettings::INCOMPLETE_READ_RESPONSE) {
EXPECT_EQ(1, get_response_headers_ct_);
EXPECT_EQ(1, read_ct_);
} else {
EXPECT_EQ(0, get_response_headers_ct_);
EXPECT_EQ(0, read_ct_);
}
destroy_callback_.Run();
}
bool Open(CefRefPtr<CefRequest> request,
bool& handle_request,
CefRefPtr<CefCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
open_ct_++;
if (settings_->incomplete_type ==
RequestRunSettings::INCOMPLETE_PROCESS_REQUEST) {
// Never release or execute this callback.
incomplete_open_callback_ = callback;
} else {
// Continue immediately.
handle_request = true;
}
return true;
}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
return false;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
EXPECT_IO_THREAD();
EXPECT_EQ(settings_->incomplete_type,
RequestRunSettings::INCOMPLETE_READ_RESPONSE);
get_response_headers_ct_++;
response->SetStatus(settings_->response->GetStatus());
response->SetStatusText(settings_->response->GetStatusText());
response->SetMimeType(settings_->response->GetMimeType());
CefResponse::HeaderMap headerMap;
settings_->response->GetHeaderMap(headerMap);
settings_->response->SetHeaderMap(headerMap);
response_length = static_cast<int64>(settings_->response_data.size());
}
bool Read(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefResourceReadCallback> callback) override {
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
EXPECT_EQ(settings_->incomplete_type,
RequestRunSettings::INCOMPLETE_READ_RESPONSE);
read_ct_++;
// Never release or execute this callback.
incomplete_read_callback_ = callback;
bytes_read = 0;
return true;
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
EXPECT_TRUE(false); // Not reached.
bytes_read = -2;
return false;
}
void Cancel() override {
EXPECT_IO_THREAD();
cancel_ct_++;
}
private:
RequestRunSettings* const settings_;
const base::Closure destroy_callback_;
int open_ct_ = 0;
int get_response_headers_ct_ = 0;
int read_ct_ = 0;
int cancel_ct_ = 0;
CefRefPtr<CefCallback> incomplete_open_callback_;
CefRefPtr<CefResourceReadCallback> incomplete_read_callback_;
IMPLEMENT_REFCOUNTING(IncompleteSchemeHandler); IMPLEMENT_REFCOUNTING(IncompleteSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(IncompleteSchemeHandler); DISALLOW_COPY_AND_ASSIGN(IncompleteSchemeHandler);
}; };
@ -805,10 +1096,21 @@ class RequestSchemeHandlerFactory : public CefSchemeHandlerFactory {
if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) { if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) {
if (entry.settings->incomplete_type == if (entry.settings->incomplete_type ==
RequestRunSettings::INCOMPLETE_NONE) { RequestRunSettings::INCOMPLETE_NONE) {
if (TestOldResourceAPI()) {
return new RequestSchemeHandlerOld(entry.settings, destroy_callback);
}
return new RequestSchemeHandler(entry.settings, destroy_callback); return new RequestSchemeHandler(entry.settings, destroy_callback);
} }
if (TestOldResourceAPI()) {
return new IncompleteSchemeHandlerOld(entry.settings, destroy_callback);
}
return new IncompleteSchemeHandler(entry.settings, destroy_callback); return new IncompleteSchemeHandler(entry.settings, destroy_callback);
} else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) { } else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) {
if (TestOldResourceAPI()) {
return new RequestRedirectSchemeHandlerOld(
entry.redirect_request, entry.redirect_response, destroy_callback);
}
return new RequestRedirectSchemeHandler( return new RequestRedirectSchemeHandler(
entry.redirect_request, entry.redirect_response, destroy_callback); entry.redirect_request, entry.redirect_response, destroy_callback);
} }
@ -882,6 +1184,7 @@ class RequestSchemeHandlerFactory : public CefSchemeHandlerFactory {
base::Closure shutdown_callback_; base::Closure shutdown_callback_;
IMPLEMENT_REFCOUNTING(RequestSchemeHandlerFactory); IMPLEMENT_REFCOUNTING(RequestSchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandlerFactory);
}; };
// SERVER BACKEND // SERVER BACKEND