- 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:
parent
89a8832550
commit
2534b67365
4
cef.gyp
4
cef.gyp
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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";
|
||||
|
|
Loading…
Reference in New Issue