- Add MayBlock() method to stream classes which is used as a hint when determining the thread to access the stream from (issue #1187).

- In cases where MayBlock() returns true have CefStreamResourceReader perform the reads on the FILE thread (issue #1187).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1582 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2014-01-30 23:15:55 +00:00
parent 89a8832550
commit 2534b67365
23 changed files with 541 additions and 18 deletions

View File

@ -399,6 +399,7 @@
'tests/cefclient/client_app.h',
'tests/cefclient/client_switches.cpp',
'tests/cefclient/client_switches.h',
'tests/cefclient/resource_util.h',
'tests/cefclient/res/osr_test.html',
'tests/unittests/browser_info_map_unittest.cc',
'tests/unittests/command_line_unittest.cc',
@ -417,12 +418,12 @@
'tests/unittests/request_context_unittest.cc',
'tests/unittests/request_handler_unittest.cc',
'tests/unittests/request_unittest.cc',
'tests/cefclient/resource_util.h',
'tests/unittests/routing_test_handler.cc',
'tests/unittests/routing_test_handler.h',
'tests/unittests/run_all_unittests.cc',
'tests/unittests/scheme_handler_unittest.cc',
'tests/unittests/stream_unittest.cc',
'tests/unittests/stream_resource_handler_unittest.cc',
'tests/unittests/string_unittest.cc',
'tests/unittests/client_app_delegates.cc',
'tests/unittests/task_unittest.cc',
@ -920,6 +921,7 @@
'libcef/browser/download_item_impl.h',
'libcef/browser/download_manager_delegate.cc',
'libcef/browser/download_manager_delegate.h',
'libcef/browser/file_impl.cc',
'libcef/browser/frame_host_impl.cc',
'libcef/browser/frame_host_impl.h',
'libcef/browser/geolocation_impl.cc',

View File

@ -28,6 +28,7 @@
'include/cef_download_item.h',
'include/cef_drag_data.h',
'include/cef_drag_handler.h',
'include/cef_file.h',
'include/cef_focus_handler.h',
'include/cef_frame.h',
'include/cef_geolocation.h',
@ -80,6 +81,7 @@
'include/capi/cef_download_item_capi.h',
'include/capi/cef_drag_data_capi.h',
'include/capi/cef_drag_handler_capi.h',
'include/capi/cef_file_capi.h',
'include/capi/cef_focus_handler_capi.h',
'include/capi/cef_frame_capi.h',
'include/capi/cef_geolocation_capi.h',

View File

@ -77,6 +77,13 @@ typedef struct _cef_read_handler_t {
// Return non-zero if at end of file.
///
int (CEF_CALLBACK *eof)(struct _cef_read_handler_t* self);
///
// Return true (1) if this handler performs work like accessing the file
// system which may block. Used as a hint for determining the thread to access
// the handler from.
///
int (CEF_CALLBACK *may_block)(struct _cef_read_handler_t* self);
} cef_read_handler_t;
@ -112,6 +119,13 @@ typedef struct _cef_stream_reader_t {
// Return non-zero if at end of file.
///
int (CEF_CALLBACK *eof)(struct _cef_stream_reader_t* self);
///
// Returns true (1) if this reader performs work like accessing the file
// system which may block. Used as a hint for determining the thread to access
// the reader from.
///
int (CEF_CALLBACK *may_block)(struct _cef_stream_reader_t* self);
} cef_stream_reader_t;
@ -166,6 +180,13 @@ typedef struct _cef_write_handler_t {
// Flush the stream.
///
int (CEF_CALLBACK *flush)(struct _cef_write_handler_t* self);
///
// Return true (1) if this handler performs work like accessing the file
// system which may block. Used as a hint for determining the thread to access
// the handler from.
///
int (CEF_CALLBACK *may_block)(struct _cef_write_handler_t* self);
} cef_write_handler_t;
@ -201,6 +222,13 @@ typedef struct _cef_stream_writer_t {
// Flush the stream.
///
int (CEF_CALLBACK *flush)(struct _cef_stream_writer_t* self);
///
// Returns true (1) if this writer performs work like accessing the file
// system which may block. Used as a hint for determining the thread to access
// the writer from.
///
int (CEF_CALLBACK *may_block)(struct _cef_stream_writer_t* self);
} cef_stream_writer_t;

View File

@ -71,6 +71,14 @@ class CefReadHandler : public virtual CefBase {
///
/*--cef()--*/
virtual int Eof() =0;
///
// Return true if this handler performs work like accessing the file system
// which may block. Used as a hint for determining the thread to access the
// handler from.
///
/*--cef()--*/
virtual bool MayBlock() =0;
};
@ -123,6 +131,14 @@ class CefStreamReader : public virtual CefBase {
///
/*--cef()--*/
virtual int Eof() =0;
///
// Returns true if this reader performs work like accessing the file system
// which may block. Used as a hint for determining the thread to access the
// reader from.
///
/*--cef()--*/
virtual bool MayBlock() =0;
};
@ -158,6 +174,14 @@ class CefWriteHandler : public virtual CefBase {
///
/*--cef()--*/
virtual int Flush() =0;
///
// Return true if this handler performs work like accessing the file system
// which may block. Used as a hint for determining the thread to access the
// handler from.
///
/*--cef()--*/
virtual bool MayBlock() =0;
};
@ -205,6 +229,14 @@ class CefStreamWriter : public virtual CefBase {
///
/*--cef()--*/
virtual int Flush() =0;
///
// Returns true if this writer performs work like accessing the file system
// which may block. Used as a hint for determining the thread to access the
// writer from.
///
/*--cef()--*/
virtual bool MayBlock() =0;
};
#endif // CEF_INCLUDE_CEF_STREAM_H_

View File

@ -60,6 +60,7 @@ class CefByteReadHandler : public CefReadHandler {
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Eof() OVERRIDE;
virtual bool MayBlock() OVERRIDE { return false; }
private:
const unsigned char* bytes_;

View File

@ -57,11 +57,14 @@ class CefStreamResourceHandler : public CefResourceHandler {
// Create a new object with explicit response values.
///
CefStreamResourceHandler(int status_code,
const CefString& status_text,
const CefString& mime_type,
CefResponse::HeaderMap header_map,
CefRefPtr<CefStreamReader> stream);
// CefStreamResourceHandler methods.
virtual ~CefStreamResourceHandler();
// CefResourceHandler methods.
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) OVERRIDE;
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
@ -74,10 +77,23 @@ class CefStreamResourceHandler : public CefResourceHandler {
virtual void Cancel() OVERRIDE;
private:
int status_code_;
CefString mime_type_;
CefResponse::HeaderMap header_map_;
CefRefPtr<CefStreamReader> stream_;
void ReadOnFileThread(int bytes_to_read,
CefRefPtr<CefCallback> callback);
const int status_code_;
const CefString status_text_;
const CefString mime_type_;
const CefResponse::HeaderMap header_map_;
const CefRefPtr<CefStreamReader> stream_;
bool read_on_file_thread_;
class Buffer;
Buffer* buffer_;
#ifndef NDEBUG
// 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);
};

View File

@ -20,6 +20,7 @@ class CefFileReader : public CefStreamReader {
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Eof() OVERRIDE;
virtual bool MayBlock() OVERRIDE { return true; }
protected:
bool close_;
@ -39,6 +40,7 @@ class CefFileWriter : public CefStreamWriter {
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Flush() OVERRIDE;
virtual bool MayBlock() OVERRIDE { return true; }
protected:
FILE* file_;
@ -58,6 +60,7 @@ class CefBytesReader : public CefStreamReader {
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Eof() OVERRIDE;
virtual bool MayBlock() OVERRIDE { return false; }
void SetData(void* data, int64 datasize, bool copy);
@ -84,6 +87,7 @@ class CefBytesWriter : public CefStreamWriter {
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Flush() OVERRIDE;
virtual bool MayBlock() OVERRIDE { return false; }
void* GetData() { return data_; }
int64 GetDataSize() { return offset_; }
@ -119,6 +123,9 @@ class CefHandlerReader : public CefStreamReader {
virtual int Eof() OVERRIDE {
return handler_->Eof();
}
virtual bool MayBlock() OVERRIDE {
return handler_->MayBlock();
}
protected:
CefRefPtr<CefReadHandler> handler_;
@ -144,6 +151,9 @@ class CefHandlerWriter : public CefStreamWriter {
virtual int Flush() OVERRIDE {
return handler_->Flush();
}
virtual bool MayBlock() OVERRIDE {
return handler_->MayBlock();
}
protected:
CefRefPtr<CefWriteHandler> handler_;

View File

@ -28,6 +28,8 @@
#endif // !BUILDING_CEF_SHARED
#define CEF_REQUIRE_UI_THREAD() DCHECK(CefCurrentlyOn(TID_UI));
#define CEF_REQUIRE_IO_THREAD() DCHECK(CefCurrentlyOn(TID_IO));
#define CEF_REQUIRE_FILE_THREAD() DCHECK(CefCurrentlyOn(TID_FILE));
#define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER));
#endif // CEF_LIBCEF_DLL_CEF_LOGGING_H_

View File

@ -82,6 +82,20 @@ int CEF_CALLBACK read_handler_eof(struct _cef_read_handler_t* self) {
return _retval;
}
int CEF_CALLBACK read_handler_may_block(struct _cef_read_handler_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefReadHandlerCppToC::Get(self)->MayBlock();
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
@ -91,6 +105,7 @@ CefReadHandlerCppToC::CefReadHandlerCppToC(CefReadHandler* cls)
struct_.struct_.seek = read_handler_seek;
struct_.struct_.tell = read_handler_tell;
struct_.struct_.eof = read_handler_eof;
struct_.struct_.may_block = read_handler_may_block;
}
#ifndef NDEBUG

View File

@ -138,6 +138,20 @@ int CEF_CALLBACK stream_reader_eof(struct _cef_stream_reader_t* self) {
return _retval;
}
int CEF_CALLBACK stream_reader_may_block(struct _cef_stream_reader_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefStreamReaderCppToC::Get(self)->MayBlock();
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
@ -148,6 +162,7 @@ CefStreamReaderCppToC::CefStreamReaderCppToC(CefStreamReader* cls)
struct_.struct_.seek = stream_reader_seek;
struct_.struct_.tell = stream_reader_tell;
struct_.struct_.eof = stream_reader_eof;
struct_.struct_.may_block = stream_reader_may_block;
}
#ifndef NDEBUG

View File

@ -120,6 +120,20 @@ int CEF_CALLBACK stream_writer_flush(struct _cef_stream_writer_t* self) {
return _retval;
}
int CEF_CALLBACK stream_writer_may_block(struct _cef_stream_writer_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefStreamWriterCppToC::Get(self)->MayBlock();
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
@ -130,6 +144,7 @@ CefStreamWriterCppToC::CefStreamWriterCppToC(CefStreamWriter* cls)
struct_.struct_.seek = stream_writer_seek;
struct_.struct_.tell = stream_writer_tell;
struct_.struct_.flush = stream_writer_flush;
struct_.struct_.may_block = stream_writer_may_block;
}
#ifndef NDEBUG

View File

@ -82,6 +82,20 @@ int CEF_CALLBACK write_handler_flush(struct _cef_write_handler_t* self) {
return _retval;
}
int CEF_CALLBACK write_handler_may_block(struct _cef_write_handler_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefWriteHandlerCppToC::Get(self)->MayBlock();
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
@ -92,6 +106,7 @@ CefWriteHandlerCppToC::CefWriteHandlerCppToC(CefWriteHandler* cls)
struct_.struct_.seek = write_handler_seek;
struct_.struct_.tell = write_handler_tell;
struct_.struct_.flush = write_handler_flush;
struct_.struct_.may_block = write_handler_may_block;
}
#ifndef NDEBUG

View File

@ -77,6 +77,19 @@ int CefReadHandlerCToCpp::Eof() {
return _retval;
}
bool CefReadHandlerCToCpp::MayBlock() {
if (CEF_MEMBER_MISSING(struct_, may_block))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->may_block(struct_);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefReadHandlerCToCpp, CefReadHandler,

View File

@ -38,6 +38,7 @@ class CefReadHandlerCToCpp
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Eof() OVERRIDE;
virtual bool MayBlock() OVERRIDE;
};
#endif // BUILDING_CEF_SHARED

View File

@ -133,6 +133,19 @@ int CefStreamReaderCToCpp::Eof() {
return _retval;
}
bool CefStreamReaderCToCpp::MayBlock() {
if (CEF_MEMBER_MISSING(struct_, may_block))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->may_block(struct_);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefStreamReaderCToCpp, CefStreamReader,

View File

@ -38,6 +38,7 @@ class CefStreamReaderCToCpp
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Eof() OVERRIDE;
virtual bool MayBlock() OVERRIDE;
};
#endif // USING_CEF_SHARED

View File

@ -115,6 +115,19 @@ int CefStreamWriterCToCpp::Flush() {
return _retval;
}
bool CefStreamWriterCToCpp::MayBlock() {
if (CEF_MEMBER_MISSING(struct_, may_block))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->may_block(struct_);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefStreamWriterCToCpp, CefStreamWriter,

View File

@ -38,6 +38,7 @@ class CefStreamWriterCToCpp
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Flush() OVERRIDE;
virtual bool MayBlock() OVERRIDE;
};
#endif // USING_CEF_SHARED

View File

@ -77,6 +77,19 @@ int CefWriteHandlerCToCpp::Flush() {
return _retval;
}
bool CefWriteHandlerCToCpp::MayBlock() {
if (CEF_MEMBER_MISSING(struct_, may_block))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->may_block(struct_);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefWriteHandlerCToCpp, CefWriteHandler,

View File

@ -38,6 +38,7 @@ class CefWriteHandlerCToCpp
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Flush() OVERRIDE;
virtual bool MayBlock() OVERRIDE;
};
#endif // BUILDING_CEF_SHARED

View File

@ -3,32 +3,119 @@
// can be found in the LICENSE file.
#include "include/wrapper/cef_stream_resource_handler.h"
#include <algorithm>
#include "include/cef_callback.h"
#include "include/cef_request.h"
#include "include/cef_runnable.h"
#include "include/cef_stream.h"
#include "libcef_dll/cef_logging.h"
// Class that represents a readable/writable character buffer.
class CefStreamResourceHandler::Buffer {
public:
Buffer()
: buffer_(NULL),
size_(0),
bytes_requested_(0),
bytes_written_(0),
bytes_read_(0) {
}
~Buffer() {
if (buffer_)
delete [] buffer_;
}
void Reset(int new_size) {
if (size_ < new_size) {
if (buffer_)
delete [] buffer_;
size_ = new_size;
buffer_ = 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_ + 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_ + bytes_written_, 1,
bytes_requested_ - bytes_written_));
bytes_written_ += bytes_read;
} while (bytes_read != 0 && bytes_written_ < bytes_requested_);
return bytes_written_;
}
private:
char* buffer_;
int size_;
int bytes_requested_;
int bytes_written_;
int bytes_read_;
};
CefStreamResourceHandler::CefStreamResourceHandler(
const CefString& mime_type,
CefRefPtr<CefStreamReader> stream)
: status_code_(200),
status_text_("OK"),
mime_type_(mime_type),
stream_(stream) {
stream_(stream),
buffer_(NULL)
#ifndef NDEBUG
, buffer_owned_by_file_thread_(false)
#endif
{
DCHECK(!mime_type_.empty());
DCHECK(stream_.get());
read_on_file_thread_ = stream_->MayBlock();
}
CefStreamResourceHandler::CefStreamResourceHandler(
int status_code,
const CefString& status_text,
const CefString& mime_type,
CefResponse::HeaderMap header_map,
CefRefPtr<CefStreamReader> stream)
: status_code_(status_code),
status_text_(status_text),
mime_type_(mime_type),
header_map_(header_map),
stream_(stream) {
stream_(stream),
buffer_(NULL) {
DCHECK(!mime_type_.empty());
DCHECK(stream_.get());
read_on_file_thread_ = stream_->MayBlock();
}
CefStreamResourceHandler::~CefStreamResourceHandler() {
if (buffer_)
delete buffer_;
}
bool CefStreamResourceHandler::ProcessRequest(CefRefPtr<CefRequest> request,
@ -42,6 +129,7 @@ void CefStreamResourceHandler::GetResponseHeaders(
int64& response_length,
CefString& redirectUrl) {
response->SetStatus(status_code_);
response->SetStatusText(status_text_);
response->SetMimeType(mime_type_);
if (!header_map_.empty())
@ -54,9 +142,63 @@ bool CefStreamResourceHandler::ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) {
bytes_read = static_cast<int>(stream_->Read(data_out, 1, bytes_to_read));
return (bytes_read > 0);
DCHECK_GT(bytes_to_read, 0);
if (read_on_file_thread_) {
DCHECK(!buffer_owned_by_file_thread_);
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;
#ifndef NDEBUG
buffer_owned_by_file_thread_ = true;
#endif
CefPostTask(TID_FILE,
NewCefRunnableMethod(this, &CefStreamResourceHandler::ReadOnFileThread,
bytes_to_read, callback));
return true;
}
} else {
// 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);
}
}
void CefStreamResourceHandler::Cancel() {
}
void CefStreamResourceHandler::ReadOnFileThread(
int bytes_to_read,
CefRefPtr<CefCallback> callback) {
CEF_REQUIRE_FILE_THREAD();
DCHECK(buffer_owned_by_file_thread_);
if (!buffer_)
buffer_ = new Buffer();
buffer_->Reset(bytes_to_read);
buffer_->ReadFrom(stream_);
#ifndef NDEBUG
buffer_owned_by_file_thread_ = false;
#endif
callback->Continue();
}

View File

@ -0,0 +1,159 @@
// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include <algorithm>
#include <cstdlib>
#include <string>
#include "include/cef_stream.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "tests/unittests/routing_test_handler.h"
namespace {
const char kTestUrl[] = "http://tests-srh/test.html";
const size_t kReadBlockSize = 1024U; // 1k.
// The usual network buffer size is about 32k. Choose a value that's larger.
const size_t kReadDesiredSize = 100U * 1024U; // 100k
class ReadHandler : public CefReadHandler {
public:
explicit ReadHandler(bool may_block)
: may_block_(may_block),
offset_(0),
expected_result_(0) {
}
void CreateContent() {
// To verify that the data transers successfully we're going to make a big
// math problem.
content_.reserve(kReadDesiredSize + 50U);
content_ = "<html><body><script>var myratherlongvariablename=0;";
while (content_.size() < kReadDesiredSize) {
content_ += "myratherlongvariablename=myratherlongvariablename+1;";
expected_result_++;
}
content_ += "window.testQuery({request:myratherlongvariablename+''});"
"</script></body></html>";
}
int GetExpectedResult() const {
return expected_result_;
}
virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE {
EXPECT_EQ(1, size);
// Read the minimum of requested size, remaining size or kReadBlockSize.
const size_t read_bytes =
std::min(std::min(size * n, content_.size() - offset_), kReadBlockSize);
if (read_bytes > 0) {
memcpy(ptr, content_.c_str() + offset_, read_bytes);
offset_ += read_bytes;
}
return read_bytes;
}
virtual int Seek(int64 offset, int whence) OVERRIDE {
EXPECT_TRUE(false); // Not reached.
return 0;
}
virtual int64 Tell() OVERRIDE {
EXPECT_TRUE(false); // Not reached.
return 0;
}
virtual int Eof() OVERRIDE {
EXPECT_TRUE(false); // Not reached.
return 0;
}
virtual bool MayBlock() OVERRIDE {
return may_block_;
}
private:
const bool may_block_;
std::string content_;
size_t offset_;
int expected_result_;
IMPLEMENT_REFCOUNTING(StreamReader);
};
class ReadTestHandler : public RoutingTestHandler {
public:
explicit ReadTestHandler(bool may_block)
: may_block_(may_block),
expected_result_(0) {}
virtual void RunTest() OVERRIDE {
// Create the browser.
CreateBrowser(kTestUrl);
}
virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) OVERRIDE {
got_resource_handler_.yes();
const std::string& url = request->GetURL();
EXPECT_STREQ(kTestUrl, url.c_str());
CefRefPtr<ReadHandler> handler = new ReadHandler(may_block_);
handler->CreateContent();
expected_result_ = handler->GetExpectedResult();
CefRefPtr<CefStreamReader> stream =
CefStreamReader::CreateForHandler(handler.get());
return new CefStreamResourceHandler("text/html", stream);
}
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
got_on_query_.yes();
const int actual_result = atoi(request.ToString().c_str());
EXPECT_EQ(expected_result_, actual_result);
DestroyTest();
return true;
}
private:
virtual void DestroyTest() OVERRIDE {
EXPECT_TRUE(got_resource_handler_);
EXPECT_TRUE(got_on_query_);
RoutingTestHandler::DestroyTest();
}
const bool may_block_;
int expected_result_;
TrackCallback got_resource_handler_;
TrackCallback got_on_query_;
};
} // namespace
TEST(StreamResourceHandlerTest, ReadWillBlock) {
CefRefPtr<ReadTestHandler> handler = new ReadTestHandler(true);
handler->ExecuteTest();
}
TEST(StreamResourceHandlerTest, ReadWontBlock) {
CefRefPtr<ReadTestHandler> handler = new ReadTestHandler(false);
handler->ExecuteTest();
}

View File

@ -87,6 +87,7 @@ TEST(StreamTest, ReadFile) {
CefRefPtr<CefStreamReader> stream(
CefStreamReader::CreateForFile(fileNameStr));
ASSERT_TRUE(stream.get() != NULL);
ASSERT_TRUE(stream->MayBlock());
VerifyStreamReadBehavior(stream, contents);
// Release the file pointer
@ -109,6 +110,7 @@ TEST(StreamTest, ReadData) {
static_cast<void*>(const_cast<char*>(contents.c_str())),
contents.size()));
ASSERT_TRUE(stream.get() != NULL);
ASSERT_FALSE(stream->MayBlock());
VerifyStreamReadBehavior(stream, contents);
}
@ -121,6 +123,7 @@ TEST(StreamTest, WriteFile) {
CefRefPtr<CefStreamWriter> stream(
CefStreamWriter::CreateForFile(fileNameStr));
ASSERT_TRUE(stream.get() != NULL);
ASSERT_TRUE(stream->MayBlock());
VerifyStreamWriteBehavior(stream, contents);
// Release the file pointer
@ -173,7 +176,7 @@ class ReadHandlerTester : public CefReadHandler {
g_ReadHandlerTesterDeleted = true;
}
virtual size_t Read(void* ptr, size_t size, size_t n) {
virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE {
read_called_ = true;
read_ptr_ = ptr;
read_size_ = size;
@ -181,23 +184,27 @@ class ReadHandlerTester : public CefReadHandler {
return 10;
}
virtual int Seek(int64 offset, int whence) {
virtual int Seek(int64 offset, int whence) OVERRIDE {
seek_called_ = true;
seek_offset_ = offset;
seek_whence_ = whence;
return 10;
}
virtual int64 Tell() {
virtual int64 Tell() OVERRIDE {
tell_called_ = true;
return 10;
}
virtual int Eof() {
virtual int Eof() OVERRIDE {
eof_called_ = true;
return 10;
}
virtual bool MayBlock() OVERRIDE {
return false;
}
bool read_called_;
const void* read_ptr_;
size_t read_size_;
@ -220,6 +227,7 @@ TEST(StreamTest, ReadHandler) {
CefRefPtr<CefStreamReader> stream(CefStreamReader::CreateForHandler(handler));
ASSERT_TRUE(stream.get() != NULL);
ASSERT_FALSE(stream->MayBlock());
// CefReadHandler Read
const char* read_ptr = "My data";
@ -278,7 +286,7 @@ class WriteHandlerTester : public CefWriteHandler {
g_WriteHandlerTesterDeleted = true;
}
virtual size_t Write(const void* ptr, size_t size, size_t n) {
virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE {
write_called_ = true;
write_ptr_ = ptr;
write_size_ = size;
@ -286,23 +294,27 @@ class WriteHandlerTester : public CefWriteHandler {
return 10;
}
virtual int Seek(int64 offset, int whence) {
virtual int Seek(int64 offset, int whence) OVERRIDE {
seek_called_ = true;
seek_offset_ = offset;
seek_whence_ = whence;
return 10;
}
virtual int64 Tell() {
virtual int64 Tell() OVERRIDE {
tell_called_ = true;
return 10;
}
virtual int Flush() {
virtual int Flush() OVERRIDE {
flush_called_ = true;
return 10;
}
virtual bool MayBlock() OVERRIDE {
return false;
}
bool write_called_;
const void* write_ptr_;
size_t write_size_;
@ -325,6 +337,7 @@ TEST(StreamTest, WriteHandler) {
CefRefPtr<CefStreamWriter> stream(CefStreamWriter::CreateForHandler(handler));
ASSERT_TRUE(stream.get() != NULL);
ASSERT_FALSE(stream->MayBlock());
// CefWriteHandler Write
const char* write_ptr = "My data";