I need to use controlled http and https requests to edit their headers. For this purpose I use the function 'CefRegisterSchemeHandlerFactory' and classes derived from 'CefResourceHandler', 'CefURLRequestClient', 'CefSchemeHandlerFactory'.
When I open a webpage, for example https://google.com, then i see in debug that first big request is executed, than maybe a few requests with pictures executed, and then up to tens small requests executed and in this step i got error and application crashes.
Error: [1106/165830.779686:FATAL:url_fetcher_core.cc(587)] Check failed: is_chunked_upload_ || upload_content_set_.
(screenshot of application debug output: https://drive.google.com/open?id=1VhihY ... 49qKgw_oHA)
Is this means that something wrong with one of request? And what's wrong with him? I can not understand... Maybe you now?
The pieces of code associated with the implementation of this task:
- Code: Select all
// Cef App module
void SerfiumCefApp::OnContextInitialized() {
CEF_REQUIRE_UI_THREAD();
bool registerResult {CefRegisterSchemeHandlerFactory(CefString("https"),CefString(""),new SerfiumCefSchemeHandlerFactory())};
registerResult = CefRegisterSchemeHandlerFactory(CefString("http"),CefString(""),new SerfiumCefSchemeHandlerFactory());
}
// begin of my .h file for request handling
class QSerfiumCefManager;
class SerfiumCefURLRequestClient : public CefURLRequestClient {
public:
SerfiumCefURLRequestClient(CefRefPtr<CefCallback> callback);
~SerfiumCefURLRequestClient() OVERRIDE;
QByteArray getDownloadedData();
QByteArray cutDownloadedData(const int size);
int getDownloadedDataSize();
protected:
virtual void OnRequestComplete(CefRefPtr<CefURLRequest> request) OVERRIDE;
virtual void OnUploadProgress(CefRefPtr<CefURLRequest> request,
int64 current,
int64 total) OVERRIDE;
void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
int64 current,
int64 total) OVERRIDE;
void OnDownloadData(CefRefPtr<CefURLRequest> request,
const void* data,
size_t data_length) OVERRIDE;
bool GetAuthCredentials(bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) OVERRIDE;
protected:
QByteArray mData;
CefRefPtr<CefCallback> mCallback;
private:
IMPLEMENT_REFCOUNTING(SerfiumCefURLRequestClient);
DISALLOW_COPY_AND_ASSIGN(SerfiumCefURLRequestClient);
};
//------------------
// Implementation of the scheme handler for ... requests.
class SerfiumSchemeHandler : public CefResourceHandler {
public:
SerfiumSchemeHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame);
~SerfiumSchemeHandler() OVERRIDE {}
protected:
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) OVERRIDE;
void Cancel() OVERRIDE {CEF_REQUIRE_IO_THREAD();}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) OVERRIDE;
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) OVERRIDE;
virtual bool CanGetCookie(const CefCookie& cookie) OVERRIDE {}
virtual bool CanSetCookie(const CefCookie& cookie) OVERRIDE {}
protected:
CefRefPtr<SerfiumCefURLRequestClient> mUrlRequestClient = nullptr;
CefRefPtr<CefURLRequest> mUrlRequest = nullptr;
QSerfiumCefManager* mpSerfiumCefManager = nullptr;
private:
IMPLEMENT_REFCOUNTING(SerfiumSchemeHandler);
DISALLOW_COPY_AND_ASSIGN(SerfiumSchemeHandler);
};
//------------------
// Implementation of the factory for creating scheme handlers.
class SerfiumCefSchemeHandlerFactory : public CefSchemeHandlerFactory {
public:
SerfiumCefSchemeHandlerFactory() {}
~SerfiumCefSchemeHandlerFactory() OVERRIDE {}
protected:
// Return a new scheme handler instance to handle the request.
CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& scheme_name,
CefRefPtr<CefRequest> request) OVERRIDE;
protected:
QList<CefRefPtr<SerfiumSchemeHandler>> mSerfiumResourceHandlers;
private:
IMPLEMENT_REFCOUNTING(SerfiumCefSchemeHandlerFactory);
DISALLOW_COPY_AND_ASSIGN(SerfiumCefSchemeHandlerFactory);
};
//------------------
// begin of my .cpp file for request handling
static int requestsInActionCnt = 0;
SerfiumCefURLRequestClient::SerfiumCefURLRequestClient(CefRefPtr<CefCallback> callback) {
mCallback = callback;
}
//------------------
SerfiumCefURLRequestClient::~SerfiumCefURLRequestClient() {
mData.clear();
}
//------------------
QByteArray SerfiumCefURLRequestClient::getDownloadedData() {
return mData;
}
//------------------
QByteArray SerfiumCefURLRequestClient::cutDownloadedData(const int size) {
QByteArray result {mData.left(size)};
mData = mData.right(mData.length() - size);
return result;
}
//------------------
int SerfiumCefURLRequestClient::getDownloadedDataSize() {
return mData.size();
}
//------------------
void SerfiumCefURLRequestClient::OnRequestComplete(CefRefPtr<CefURLRequest> request) {
qDebug() << "requestsInActionCnt" << (requestsInActionCnt -= 1);
mCallback->Continue();
}
//------------------
void SerfiumCefURLRequestClient::OnUploadProgress(CefRefPtr<CefURLRequest> request,
int64 current,
int64 total) {
}
//------------------
void SerfiumCefURLRequestClient::OnDownloadProgress(CefRefPtr<CefURLRequest> request,
int64 current,
int64 total) {
}
//------------------
void SerfiumCefURLRequestClient::OnDownloadData(CefRefPtr<CefURLRequest> request,
const void* data,
size_t data_length) {
mData.append(static_cast<const char*>(data),static_cast<int>(data_length));
}
//------------------
bool SerfiumCefURLRequestClient::GetAuthCredentials(bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) {
}
//------------------
SerfiumSchemeHandler::SerfiumSchemeHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
CEF_REQUIRE_IO_THREAD();
// Thing from other modules of my project...
mpSerfiumCefManager = QSerfiumCefManager::getInstance();
if (nullptr == mpSerfiumCefManager) {
qDebug() << Q_FUNC_INFO;
qCritical() << SerfiumCefMisc::errors::pointerIsNull();
}
}
//------------------
bool SerfiumSchemeHandler::ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) {
CEF_REQUIRE_IO_THREAD();
CefRefPtr<CefRequestContext> requestContext;
mUrlRequestClient = new SerfiumCefURLRequestClient(callback);
mUrlRequest = CefURLRequest::Create(request,mUrlRequestClient,requestContext);
qDebug() << "requestsInActionCnt" << (requestsInActionCnt += 1);
return true;
}
//------------------
void SerfiumSchemeHandler::GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) {
response_length = mUrlRequestClient->getDownloadedDataSize();
}
//------------------
bool SerfiumSchemeHandler::ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) {
QByteArray amountOfData {mUrlRequestClient->cutDownloadedData(bytes_to_read)};
std::memcpy(data_out,amountOfData.data(),static_cast<std::size_t>(amountOfData.size()));
bytes_read = amountOfData.size();
callback->Continue();
return true;
}
//------------------
CefRefPtr<CefResourceHandler> SerfiumCefSchemeHandlerFactory::Create(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& scheme_name,
CefRefPtr<CefRequest> request) {
CEF_REQUIRE_IO_THREAD();
CefRefPtr<SerfiumSchemeHandler> result {nullptr};
if ((nullptr != browser) && (nullptr != frame)) {
result = new SerfiumSchemeHandler(browser,frame);
}
return result;
}
//------------------